blob: 6b565bcbe23a5b2b0659f8afa96e72e88b2883fc [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * IS-IS Rout(e)ing protocol - isis_misc.h
3 * Miscellanous routines
4 *
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
jardineb5d44e2003-12-23 08:09:43 +000024#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000025
26#include "stream.h"
27#include "vty.h"
28#include "hash.h"
29#include "if.h"
jardin9e867fe2003-12-23 08:56:18 +000030#include "command.h"
jardineb5d44e2003-12-23 08:09:43 +000031
32#include "isisd/dict.h"
33#include "isisd/isis_constants.h"
34#include "isisd/isis_common.h"
35#include "isisd/isis_circuit.h"
36#include "isisd/isisd.h"
37#include "isisd/isis_misc.h"
38
39#include "isisd/isis_tlv.h"
40#include "isisd/isis_lsp.h"
41#include "isisd/isis_constants.h"
42#include "isisd/isis_adjacency.h"
43
hasso73d1aea2004-09-24 10:45:28 +000044/* staticly assigned vars for printing purposes */
45struct in_addr new_prefix;
46/* len of xxxx.xxxx.xxxx + place for #0 termination */
47char sysid[15];
48/* len of xxxx.xxxx.xxxx + place for #0 termination */
49char snpa[15];
50/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
51char isonet[51];
52/* + place for #0 termination */
53/* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
54char lspid[21];
55/* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
56char datestring[20];
57char nlpidstring[30];
58
jardineb5d44e2003-12-23 08:09:43 +000059/*
60 * This converts the isonet to its printable format
61 */
hasso1cd80842004-10-07 20:07:40 +000062const char *
hassof390d2c2004-09-10 20:48:21 +000063isonet_print (u_char * from, int len)
64{
jardineb5d44e2003-12-23 08:09:43 +000065 int i = 0;
66 char *pos = isonet;
67
hassof390d2c2004-09-10 20:48:21 +000068 if (!from)
jardineb5d44e2003-12-23 08:09:43 +000069 return "unknown";
70
hassof390d2c2004-09-10 20:48:21 +000071 while (i < len)
72 {
73 if (i & 1)
74 {
75 sprintf (pos, "%02x", *(from + i));
76 pos += 2;
77 }
78 else
79 {
80 if (i == (len - 1))
81 { /* No dot at the end of address */
82 sprintf (pos, "%02x", *(from + i));
83 pos += 2;
84 }
85 else
86 {
87 sprintf (pos, "%02x.", *(from + i));
88 pos += 3;
89 }
90 }
91 i++;
jardineb5d44e2003-12-23 08:09:43 +000092 }
jardineb5d44e2003-12-23 08:09:43 +000093 *(pos) = '\0';
94 return isonet;
95}
96
97/*
98 * Returns 0 on error, length of buff on ok
99 * extract dot from the dotted str, and insert all the number in a buff
100 */
101int
Paul Jakma41b36e92006-12-08 01:09:50 +0000102dotformat2buff (u_char * buff, const u_char * dotted)
jardineb5d44e2003-12-23 08:09:43 +0000103{
104 int dotlen, len = 0;
Paul Jakma41b36e92006-12-08 01:09:50 +0000105 const u_char *pos = dotted;
jardineb5d44e2003-12-23 08:09:43 +0000106 u_char number[3];
107 int nextdotpos = 2;
108
109 number[2] = '\0';
Paul Jakma41b36e92006-12-08 01:09:50 +0000110 dotlen = strlen(dotted);
hassof390d2c2004-09-10 20:48:21 +0000111 if (dotlen > 50)
112 {
113 /* this can't be an iso net, its too long */
114 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000115 }
116
hassof390d2c2004-09-10 20:48:21 +0000117 while ((pos - dotted) < dotlen && len < 20)
118 {
119 if (*pos == '.')
120 {
121 /* we expect the . at 2, and than every 5 */
122 if ((pos - dotted) != nextdotpos)
123 {
124 len = 0;
125 break;
126 }
127 nextdotpos += 5;
128 pos++;
129 continue;
130 }
131 /* we must have at least two chars left here */
132 if (dotlen - (pos - dotted) < 2)
133 {
134 len = 0;
135 break;
136 }
137
138 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
139 {
140 memcpy (number, pos, 2);
141 pos += 2;
142 }
143 else
144 {
145 len = 0;
146 break;
147 }
148
hassof7c43dc2004-09-26 16:24:14 +0000149 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
hassof390d2c2004-09-10 20:48:21 +0000150 len++;
jardineb5d44e2003-12-23 08:09:43 +0000151 }
152
jardineb5d44e2003-12-23 08:09:43 +0000153 return len;
154}
hassof390d2c2004-09-10 20:48:21 +0000155
jardineb5d44e2003-12-23 08:09:43 +0000156/*
157 * conversion of XXXX.XXXX.XXXX to memory
158 */
159int
hasso56b24f42005-08-16 20:58:12 +0000160sysid2buff (u_char * buff, const u_char * dotted)
hassof390d2c2004-09-10 20:48:21 +0000161{
jardineb5d44e2003-12-23 08:09:43 +0000162 int len = 0;
hasso56b24f42005-08-16 20:58:12 +0000163 const u_char *pos = dotted;
jardineb5d44e2003-12-23 08:09:43 +0000164 u_char number[3];
165
166 number[2] = '\0';
167 // surely not a sysid_string if not 14 length
Paul Jakma41b36e92006-12-08 01:09:50 +0000168 if (strlen (dotted) != 14)
hassof390d2c2004-09-10 20:48:21 +0000169 {
170 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000171 }
172
hassof390d2c2004-09-10 20:48:21 +0000173 while (len < ISIS_SYS_ID_LEN)
174 {
175 if (*pos == '.')
176 {
177 /* the . is not positioned correctly */
178 if (((pos - dotted) != 4) && ((pos - dotted) != 9))
179 {
180 len = 0;
181 break;
182 }
183 pos++;
184 continue;
185 }
186 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
187 {
188 memcpy (number, pos, 2);
189 pos += 2;
190 }
191 else
192 {
193 len = 0;
194 break;
195 }
196
hassof7c43dc2004-09-26 16:24:14 +0000197 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
hassof390d2c2004-09-10 20:48:21 +0000198 len++;
199 }
jardineb5d44e2003-12-23 08:09:43 +0000200
201 return len;
202
203}
204
205/*
206 * converts the nlpids struct (filled by TLV #129)
207 * into a string
208 */
209
210char *
hassof390d2c2004-09-10 20:48:21 +0000211nlpid2string (struct nlpids *nlpids)
212{
jardineb5d44e2003-12-23 08:09:43 +0000213 char *pos = nlpidstring;
214 int i;
215
hassof390d2c2004-09-10 20:48:21 +0000216 for (i = 0; i < nlpids->count; i++)
217 {
218 switch (nlpids->nlpids[i])
219 {
220 case NLPID_IP:
221 pos += sprintf (pos, "IPv4");
222 break;
223 case NLPID_IPV6:
224 pos += sprintf (pos, "IPv6");
225 break;
226 case NLPID_SNAP:
227 pos += sprintf (pos, "SNAP");
228 break;
229 case NLPID_CLNP:
230 pos += sprintf (pos, "CLNP");
231 break;
232 case NLPID_ESIS:
233 pos += sprintf (pos, "ES-IS");
234 break;
235 default:
236 pos += sprintf (pos, "unknown");
237 break;
238 }
239 if (nlpids->count - i > 1)
240 pos += sprintf (pos, ", ");
241
jardineb5d44e2003-12-23 08:09:43 +0000242 }
jardineb5d44e2003-12-23 08:09:43 +0000243
244 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000245
jardineb5d44e2003-12-23 08:09:43 +0000246 return nlpidstring;
247}
248
249/*
250 * supports the given af ?
251 */
hassof390d2c2004-09-10 20:48:21 +0000252int
jardineb5d44e2003-12-23 08:09:43 +0000253speaks (struct nlpids *nlpids, int family)
254{
255 int i, speaks = 0;
hassof390d2c2004-09-10 20:48:21 +0000256
257 if (nlpids == (struct nlpids *) NULL)
jardineb5d44e2003-12-23 08:09:43 +0000258 return speaks;
hassof390d2c2004-09-10 20:48:21 +0000259 for (i = 0; i < nlpids->count; i++)
260 {
261 if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
262 speaks = 1;
263 if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
264 speaks = 1;
265 }
jardineb5d44e2003-12-23 08:09:43 +0000266
267 return speaks;
268}
269
jardineb5d44e2003-12-23 08:09:43 +0000270/*
271 * Returns 0 on error, IS-IS Circuit Type on ok
272 */
hassof390d2c2004-09-10 20:48:21 +0000273int
Paul Jakma41b36e92006-12-08 01:09:50 +0000274string2circuit_t (const u_char * str)
jardineb5d44e2003-12-23 08:09:43 +0000275{
hassof390d2c2004-09-10 20:48:21 +0000276
jardineb5d44e2003-12-23 08:09:43 +0000277 if (!str)
278 return 0;
hassof390d2c2004-09-10 20:48:21 +0000279
Paul Jakma41b36e92006-12-08 01:09:50 +0000280 if (!strcmp (str, "level-1"))
jardineb5d44e2003-12-23 08:09:43 +0000281 return IS_LEVEL_1;
282
Paul Jakma41b36e92006-12-08 01:09:50 +0000283 if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
jardineb5d44e2003-12-23 08:09:43 +0000284 return IS_LEVEL_2;
hassof390d2c2004-09-10 20:48:21 +0000285
Paul Jakma41b36e92006-12-08 01:09:50 +0000286 if (!strcmp (str, "level-1-2"))
jardineb5d44e2003-12-23 08:09:43 +0000287 return IS_LEVEL_1_AND_2;
288
289 return 0;
290}
291
292const char *
293circuit_t2string (int circuit_t)
294{
hassof390d2c2004-09-10 20:48:21 +0000295 switch (circuit_t)
296 {
297 case IS_LEVEL_1:
298 return "L1";
299 case IS_LEVEL_2:
300 return "L2";
301 case IS_LEVEL_1_AND_2:
302 return "L1L2";
303 default:
304 return "??";
305 }
jardineb5d44e2003-12-23 08:09:43 +0000306
hassof390d2c2004-09-10 20:48:21 +0000307 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000308}
309
310const char *
311syst2string (int type)
312{
hassof390d2c2004-09-10 20:48:21 +0000313 switch (type)
314 {
315 case ISIS_SYSTYPE_ES:
316 return "ES";
317 case ISIS_SYSTYPE_IS:
318 return "IS";
319 case ISIS_SYSTYPE_L1_IS:
320 return "1";
321 case ISIS_SYSTYPE_L2_IS:
322 return "2";
323 default:
324 return "??";
325 }
jardineb5d44e2003-12-23 08:09:43 +0000326
hassof390d2c2004-09-10 20:48:21 +0000327 return NULL; /* not reached */
jardineb5d44e2003-12-23 08:09:43 +0000328}
329
330/*
331 * Print functions - we print to static vars
332 */
hasso1cd80842004-10-07 20:07:40 +0000333const char *
hassof390d2c2004-09-10 20:48:21 +0000334snpa_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000335{
336 int i = 0;
hassof7c43dc2004-09-26 16:24:14 +0000337 u_char *pos = (u_char *)snpa;
jardineb5d44e2003-12-23 08:09:43 +0000338
hassof390d2c2004-09-10 20:48:21 +0000339 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000340 return "unknown";
jardineb5d44e2003-12-23 08:09:43 +0000341
hassof390d2c2004-09-10 20:48:21 +0000342 while (i < ETH_ALEN - 1)
343 {
344 if (i & 1)
345 {
hassof7c43dc2004-09-26 16:24:14 +0000346 sprintf ((char *)pos, "%02x.", *(from + i));
hassof390d2c2004-09-10 20:48:21 +0000347 pos += 3;
348 }
349 else
350 {
hassof7c43dc2004-09-26 16:24:14 +0000351 sprintf ((char *)pos, "%02x", *(from + i));
hassof390d2c2004-09-10 20:48:21 +0000352 pos += 2;
353
354 }
355 i++;
jardineb5d44e2003-12-23 08:09:43 +0000356 }
jardineb5d44e2003-12-23 08:09:43 +0000357
hassof7c43dc2004-09-26 16:24:14 +0000358 sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
jardineb5d44e2003-12-23 08:09:43 +0000359 pos += 2;
360 *(pos) = '\0';
361
362 return snpa;
363}
364
hasso1cd80842004-10-07 20:07:40 +0000365const char *
hassof390d2c2004-09-10 20:48:21 +0000366sysid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000367{
368 int i = 0;
369 char *pos = sysid;
370
hassof390d2c2004-09-10 20:48:21 +0000371 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000372 return "unknown";
373
hassof390d2c2004-09-10 20:48:21 +0000374 while (i < ISIS_SYS_ID_LEN - 1)
375 {
376 if (i & 1)
377 {
378 sprintf (pos, "%02x.", *(from + i));
379 pos += 3;
380 }
381 else
382 {
383 sprintf (pos, "%02x", *(from + i));
384 pos += 2;
385
386 }
387 i++;
388 }
jardineb5d44e2003-12-23 08:09:43 +0000389
390 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
391 pos += 2;
392 *(pos) = '\0';
hassof390d2c2004-09-10 20:48:21 +0000393
jardineb5d44e2003-12-23 08:09:43 +0000394 return sysid;
395}
396
hasso1cd80842004-10-07 20:07:40 +0000397const char *
hassof390d2c2004-09-10 20:48:21 +0000398rawlspid_print (u_char * from)
jardineb5d44e2003-12-23 08:09:43 +0000399{
400 char *pos = lspid;
hassof390d2c2004-09-10 20:48:21 +0000401 if (!from)
jardineb5d44e2003-12-23 08:09:43 +0000402 return "unknown";
hassof390d2c2004-09-10 20:48:21 +0000403 memcpy (pos, sysid_print (from), 15);
jardineb5d44e2003-12-23 08:09:43 +0000404 pos += 14;
hassof390d2c2004-09-10 20:48:21 +0000405 sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
jardineb5d44e2003-12-23 08:09:43 +0000406 pos += 3;
hassof390d2c2004-09-10 20:48:21 +0000407 sprintf (pos, "-%02x", LSP_FRAGMENT (from));
jardineb5d44e2003-12-23 08:09:43 +0000408 pos += 3;
409
410 *(pos) = '\0';
411
412 return lspid;
413}
414
hasso1cd80842004-10-07 20:07:40 +0000415const char *
hassof390d2c2004-09-10 20:48:21 +0000416time2string (u_int32_t time)
417{
418 char *pos = datestring;
jardineb5d44e2003-12-23 08:09:43 +0000419 u_int32_t rest;
420
hassof390d2c2004-09-10 20:48:21 +0000421 if (time == 0)
jardineb5d44e2003-12-23 08:09:43 +0000422 return "-";
423
hassof390d2c2004-09-10 20:48:21 +0000424 if (time / SECS_PER_YEAR)
425 pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
426 rest = time % SECS_PER_YEAR;
427 if (rest / SECS_PER_MONTH)
428 pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
429 rest = rest % SECS_PER_MONTH;
430 if (rest / SECS_PER_WEEK)
431 pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
432 rest = rest % SECS_PER_WEEK;
433 if (rest / SECS_PER_DAY)
434 pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
435 rest = rest % SECS_PER_DAY;
436 if (rest / SECS_PER_HOUR)
437 pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
438 rest = rest % SECS_PER_HOUR;
439 if (rest / SECS_PER_MINUTE)
440 pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
441 rest = rest % SECS_PER_MINUTE;
442 if (rest)
443 pos += sprintf (pos, "%us", rest);
444
jardineb5d44e2003-12-23 08:09:43 +0000445 *(pos) = 0;
446
447 return datestring;
448}
449
450/*
451 * routine to decrement a timer by a random
452 * number
453 *
454 * first argument is the timer and the second is
455 * the jitter
456 */
hassof390d2c2004-09-10 20:48:21 +0000457unsigned long
jardineb5d44e2003-12-23 08:09:43 +0000458isis_jitter (unsigned long timer, unsigned long jitter)
459{
hassof390d2c2004-09-10 20:48:21 +0000460 int j, k;
jardineb5d44e2003-12-23 08:09:43 +0000461
hassof390d2c2004-09-10 20:48:21 +0000462 if (jitter >= 100)
jardineb5d44e2003-12-23 08:09:43 +0000463 return timer;
464
465 if (timer == 1)
466 return timer;
467 /*
468 * randomizing just the percent value provides
469 * no good random numbers - hence the spread
470 * to RANDOM_SPREAD (100000), which is ok as
471 * most IS-IS timers are no longer than 16 bit
472 */
473
hassof390d2c2004-09-10 20:48:21 +0000474 j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
jardineb5d44e2003-12-23 08:09:43 +0000475
hassof390d2c2004-09-10 20:48:21 +0000476 k = timer - (timer * (100 - jitter)) / 100;
jardineb5d44e2003-12-23 08:09:43 +0000477
478 timer = timer - (k * j / RANDOM_SPREAD);
479
480 return timer;
481}
482
483struct in_addr
hassof390d2c2004-09-10 20:48:21 +0000484newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
jardineb5d44e2003-12-23 08:09:43 +0000485{
hassof390d2c2004-09-10 20:48:21 +0000486 memset (&new_prefix, 0, sizeof (new_prefix));
487 memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
488 ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
jardineb5d44e2003-12-23 08:09:43 +0000489 return new_prefix;
490}
491
jardin9e867fe2003-12-23 08:56:18 +0000492/*
493 * Returns host.name if any, otherwise
494 * it returns the system hostname.
495 */
496const char *
hassof390d2c2004-09-10 20:48:21 +0000497unix_hostname (void)
jardin9e867fe2003-12-23 08:56:18 +0000498{
499 static struct utsname names;
500 const char *hostname;
501 extern struct host host;
jardineb5d44e2003-12-23 08:09:43 +0000502
jardin9e867fe2003-12-23 08:56:18 +0000503 hostname = host.name;
hassof390d2c2004-09-10 20:48:21 +0000504 if (!hostname)
505 {
506 uname (&names);
507 hostname = names.nodename;
508 }
jardineb5d44e2003-12-23 08:09:43 +0000509
jardin9e867fe2003-12-23 08:56:18 +0000510 return hostname;
511}