Annotation of embedaddon/quagga/isisd/isis_misc.c, revision 1.1.1.2
1.1 misho 1: /*
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:
24: #include <zebra.h>
25:
26: #include "stream.h"
27: #include "vty.h"
28: #include "hash.h"
29: #include "if.h"
30: #include "command.h"
31:
32: #include "isisd/dict.h"
33: #include "isisd/isis_constants.h"
34: #include "isisd/isis_common.h"
1.1.1.2 ! misho 35: #include "isisd/isis_flags.h"
1.1 misho 36: #include "isisd/isis_circuit.h"
1.1.1.2 ! misho 37: #include "isisd/isis_csm.h"
1.1 misho 38: #include "isisd/isisd.h"
39: #include "isisd/isis_misc.h"
40:
41: #include "isisd/isis_tlv.h"
42: #include "isisd/isis_lsp.h"
43: #include "isisd/isis_constants.h"
44: #include "isisd/isis_adjacency.h"
1.1.1.2 ! misho 45: #include "isisd/isis_dynhn.h"
1.1 misho 46:
47: /* staticly assigned vars for printing purposes */
48: struct in_addr new_prefix;
49: /* len of xxxx.xxxx.xxxx + place for #0 termination */
50: char sysid[15];
51: /* len of xxxx.xxxx.xxxx + place for #0 termination */
52: char snpa[15];
53: /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
54: char isonet[51];
55: /* + place for #0 termination */
56: /* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
57: char lspid[21];
58: /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
59: char datestring[20];
60: char nlpidstring[30];
61:
62: /*
63: * This converts the isonet to its printable format
64: */
65: const char *
66: isonet_print (u_char * from, int len)
67: {
68: int i = 0;
69: char *pos = isonet;
70:
71: if (!from)
72: return "unknown";
73:
74: while (i < len)
75: {
76: if (i & 1)
77: {
78: sprintf (pos, "%02x", *(from + i));
79: pos += 2;
80: }
81: else
82: {
83: if (i == (len - 1))
84: { /* No dot at the end of address */
85: sprintf (pos, "%02x", *(from + i));
86: pos += 2;
87: }
88: else
89: {
90: sprintf (pos, "%02x.", *(from + i));
91: pos += 3;
92: }
93: }
94: i++;
95: }
96: *(pos) = '\0';
97: return isonet;
98: }
99:
100: /*
101: * Returns 0 on error, length of buff on ok
102: * extract dot from the dotted str, and insert all the number in a buff
103: */
104: int
1.1.1.2 ! misho 105: dotformat2buff (u_char * buff, const char * dotted)
1.1 misho 106: {
107: int dotlen, len = 0;
1.1.1.2 ! misho 108: const char *pos = dotted;
1.1 misho 109: u_char number[3];
110: int nextdotpos = 2;
111:
112: number[2] = '\0';
113: dotlen = strlen(dotted);
114: if (dotlen > 50)
115: {
116: /* this can't be an iso net, its too long */
117: return 0;
118: }
119:
120: while ((pos - dotted) < dotlen && len < 20)
121: {
122: if (*pos == '.')
123: {
124: /* we expect the . at 2, and than every 5 */
125: if ((pos - dotted) != nextdotpos)
126: {
127: len = 0;
128: break;
129: }
130: nextdotpos += 5;
131: pos++;
132: continue;
133: }
134: /* we must have at least two chars left here */
135: if (dotlen - (pos - dotted) < 2)
136: {
137: len = 0;
138: break;
139: }
140:
141: if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
142: {
143: memcpy (number, pos, 2);
144: pos += 2;
145: }
146: else
147: {
148: len = 0;
149: break;
150: }
151:
152: *(buff + len) = (char) strtol ((char *)number, NULL, 16);
153: len++;
154: }
155:
156: return len;
157: }
158:
159: /*
160: * conversion of XXXX.XXXX.XXXX to memory
161: */
162: int
1.1.1.2 ! misho 163: sysid2buff (u_char * buff, const char * dotted)
1.1 misho 164: {
165: int len = 0;
1.1.1.2 ! misho 166: const char *pos = dotted;
1.1 misho 167: u_char number[3];
168:
169: number[2] = '\0';
170: // surely not a sysid_string if not 14 length
171: if (strlen (dotted) != 14)
172: {
173: return 0;
174: }
175:
176: while (len < ISIS_SYS_ID_LEN)
177: {
178: if (*pos == '.')
179: {
180: /* the . is not positioned correctly */
181: if (((pos - dotted) != 4) && ((pos - dotted) != 9))
182: {
183: len = 0;
184: break;
185: }
186: pos++;
187: continue;
188: }
189: if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
190: {
191: memcpy (number, pos, 2);
192: pos += 2;
193: }
194: else
195: {
196: len = 0;
197: break;
198: }
199:
200: *(buff + len) = (char) strtol ((char *)number, NULL, 16);
201: len++;
202: }
203:
204: return len;
205:
206: }
207:
208: /*
209: * converts the nlpids struct (filled by TLV #129)
210: * into a string
211: */
212:
213: char *
214: nlpid2string (struct nlpids *nlpids)
215: {
216: char *pos = nlpidstring;
217: int i;
218:
219: for (i = 0; i < nlpids->count; i++)
220: {
221: switch (nlpids->nlpids[i])
222: {
223: case NLPID_IP:
224: pos += sprintf (pos, "IPv4");
225: break;
226: case NLPID_IPV6:
227: pos += sprintf (pos, "IPv6");
228: break;
229: case NLPID_SNAP:
230: pos += sprintf (pos, "SNAP");
231: break;
232: case NLPID_CLNP:
233: pos += sprintf (pos, "CLNP");
234: break;
235: case NLPID_ESIS:
236: pos += sprintf (pos, "ES-IS");
237: break;
238: default:
239: pos += sprintf (pos, "unknown");
240: break;
241: }
242: if (nlpids->count - i > 1)
243: pos += sprintf (pos, ", ");
244:
245: }
246:
247: *(pos) = '\0';
248:
249: return nlpidstring;
250: }
251:
252: /*
253: * supports the given af ?
254: */
255: int
256: speaks (struct nlpids *nlpids, int family)
257: {
258: int i, speaks = 0;
259:
260: if (nlpids == (struct nlpids *) NULL)
261: return speaks;
262: for (i = 0; i < nlpids->count; i++)
263: {
264: if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
265: speaks = 1;
266: if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
267: speaks = 1;
268: }
269:
270: return speaks;
271: }
272:
273: /*
274: * Returns 0 on error, IS-IS Circuit Type on ok
275: */
276: int
1.1.1.2 ! misho 277: string2circuit_t (const char * str)
1.1 misho 278: {
279:
280: if (!str)
281: return 0;
282:
283: if (!strcmp (str, "level-1"))
284: return IS_LEVEL_1;
285:
286: if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
287: return IS_LEVEL_2;
288:
289: if (!strcmp (str, "level-1-2"))
290: return IS_LEVEL_1_AND_2;
291:
292: return 0;
293: }
294:
295: const char *
1.1.1.2 ! misho 296: circuit_state2string (int state)
! 297: {
! 298:
! 299: switch (state)
! 300: {
! 301: case C_STATE_INIT:
! 302: return "Init";
! 303: case C_STATE_CONF:
! 304: return "Config";
! 305: case C_STATE_UP:
! 306: return "Up";
! 307: default:
! 308: return "Unknown";
! 309: }
! 310: return NULL;
! 311: }
! 312:
! 313: const char *
! 314: circuit_type2string (int type)
! 315: {
! 316:
! 317: switch (type)
! 318: {
! 319: case CIRCUIT_T_P2P:
! 320: return "p2p";
! 321: case CIRCUIT_T_BROADCAST:
! 322: return "lan";
! 323: case CIRCUIT_T_LOOPBACK:
! 324: return "loopback";
! 325: default:
! 326: return "Unknown";
! 327: }
! 328: return NULL;
! 329: }
! 330:
! 331: const char *
1.1 misho 332: circuit_t2string (int circuit_t)
333: {
334: switch (circuit_t)
335: {
336: case IS_LEVEL_1:
337: return "L1";
338: case IS_LEVEL_2:
339: return "L2";
340: case IS_LEVEL_1_AND_2:
341: return "L1L2";
342: default:
343: return "??";
344: }
345:
346: return NULL; /* not reached */
347: }
348:
349: const char *
350: syst2string (int type)
351: {
352: switch (type)
353: {
354: case ISIS_SYSTYPE_ES:
355: return "ES";
356: case ISIS_SYSTYPE_IS:
357: return "IS";
358: case ISIS_SYSTYPE_L1_IS:
359: return "1";
360: case ISIS_SYSTYPE_L2_IS:
361: return "2";
362: default:
363: return "??";
364: }
365:
366: return NULL; /* not reached */
367: }
368:
369: /*
370: * Print functions - we print to static vars
371: */
372: const char *
373: snpa_print (u_char * from)
374: {
375: int i = 0;
376: u_char *pos = (u_char *)snpa;
377:
378: if (!from)
379: return "unknown";
380:
381: while (i < ETH_ALEN - 1)
382: {
383: if (i & 1)
384: {
385: sprintf ((char *)pos, "%02x.", *(from + i));
386: pos += 3;
387: }
388: else
389: {
390: sprintf ((char *)pos, "%02x", *(from + i));
391: pos += 2;
392:
393: }
394: i++;
395: }
396:
397: sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
398: pos += 2;
399: *(pos) = '\0';
400:
401: return snpa;
402: }
403:
404: const char *
405: sysid_print (u_char * from)
406: {
407: int i = 0;
408: char *pos = sysid;
409:
410: if (!from)
411: return "unknown";
412:
413: while (i < ISIS_SYS_ID_LEN - 1)
414: {
415: if (i & 1)
416: {
417: sprintf (pos, "%02x.", *(from + i));
418: pos += 3;
419: }
420: else
421: {
422: sprintf (pos, "%02x", *(from + i));
423: pos += 2;
424:
425: }
426: i++;
427: }
428:
429: sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
430: pos += 2;
431: *(pos) = '\0';
432:
433: return sysid;
434: }
435:
436: const char *
437: rawlspid_print (u_char * from)
438: {
439: char *pos = lspid;
440: if (!from)
441: return "unknown";
442: memcpy (pos, sysid_print (from), 15);
443: pos += 14;
444: sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
445: pos += 3;
446: sprintf (pos, "-%02x", LSP_FRAGMENT (from));
447: pos += 3;
448:
449: *(pos) = '\0';
450:
451: return lspid;
452: }
453:
454: const char *
455: time2string (u_int32_t time)
456: {
457: char *pos = datestring;
458: u_int32_t rest;
459:
460: if (time == 0)
461: return "-";
462:
463: if (time / SECS_PER_YEAR)
464: pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
465: rest = time % SECS_PER_YEAR;
466: if (rest / SECS_PER_MONTH)
467: pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
468: rest = rest % SECS_PER_MONTH;
469: if (rest / SECS_PER_WEEK)
470: pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
471: rest = rest % SECS_PER_WEEK;
472: if (rest / SECS_PER_DAY)
473: pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
474: rest = rest % SECS_PER_DAY;
475: if (rest / SECS_PER_HOUR)
476: pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
477: rest = rest % SECS_PER_HOUR;
478: if (rest / SECS_PER_MINUTE)
479: pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
480: rest = rest % SECS_PER_MINUTE;
481: if (rest)
482: pos += sprintf (pos, "%us", rest);
483:
484: *(pos) = 0;
485:
486: return datestring;
487: }
488:
489: /*
490: * routine to decrement a timer by a random
491: * number
492: *
493: * first argument is the timer and the second is
494: * the jitter
495: */
496: unsigned long
497: isis_jitter (unsigned long timer, unsigned long jitter)
498: {
499: int j, k;
500:
501: if (jitter >= 100)
502: return timer;
503:
504: if (timer == 1)
505: return timer;
506: /*
507: * randomizing just the percent value provides
508: * no good random numbers - hence the spread
509: * to RANDOM_SPREAD (100000), which is ok as
510: * most IS-IS timers are no longer than 16 bit
511: */
512:
513: j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
514:
515: k = timer - (timer * (100 - jitter)) / 100;
516:
517: timer = timer - (k * j / RANDOM_SPREAD);
518:
519: return timer;
520: }
521:
522: struct in_addr
523: newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
524: {
525: memset (&new_prefix, 0, sizeof (new_prefix));
526: memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
527: ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
528: return new_prefix;
529: }
530:
531: /*
532: * Returns host.name if any, otherwise
533: * it returns the system hostname.
534: */
535: const char *
536: unix_hostname (void)
537: {
538: static struct utsname names;
539: const char *hostname;
540:
541: hostname = host.name;
542: if (!hostname)
543: {
544: uname (&names);
545: hostname = names.nodename;
546: }
547:
548: return hostname;
549: }
1.1.1.2 ! misho 550:
! 551: /*
! 552: * Returns the dynamic hostname associated with the passed system ID.
! 553: * If no dynamic hostname found then returns formatted system ID.
! 554: */
! 555: const char *
! 556: print_sys_hostname (u_char *sysid)
! 557: {
! 558: struct isis_dynhn *dyn;
! 559:
! 560: if (!sysid)
! 561: return "nullsysid";
! 562:
! 563: /* For our system ID return our host name */
! 564: if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
! 565: return unix_hostname();
! 566:
! 567: dyn = dynhn_find_by_id (sysid);
! 568: if (dyn)
! 569: return (const char *)dyn->name.name;
! 570:
! 571: return sysid_print (sysid);
! 572: }
! 573:
! 574: /*
! 575: * This function is a generic utility that logs data of given length.
! 576: * Move this to a shared lib so that any protocol can use it.
! 577: */
! 578: void
! 579: zlog_dump_data (void *data, int len)
! 580: {
! 581: int i;
! 582: unsigned char *p;
! 583: unsigned char c;
! 584: char bytestr[4];
! 585: char addrstr[10];
! 586: char hexstr[ 16*3 + 5];
! 587: char charstr[16*1 + 5];
! 588:
! 589: p = data;
! 590: memset (bytestr, 0, sizeof(bytestr));
! 591: memset (addrstr, 0, sizeof(addrstr));
! 592: memset (hexstr, 0, sizeof(hexstr));
! 593: memset (charstr, 0, sizeof(charstr));
! 594:
! 595: for (i = 1; i <= len; i++)
! 596: {
! 597: c = *p;
! 598: if (isalnum (c) == 0)
! 599: c = '.';
! 600:
! 601: /* store address for this line */
! 602: if ((i % 16) == 1)
! 603: snprintf (addrstr, sizeof(addrstr), "%p", p);
! 604:
! 605: /* store hex str (for left side) */
! 606: snprintf (bytestr, sizeof (bytestr), "%02X ", *p);
! 607: strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1);
! 608:
! 609: /* store char str (for right side) */
! 610: snprintf (bytestr, sizeof (bytestr), "%c", c);
! 611: strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1);
! 612:
! 613: if ((i % 16) == 0)
! 614: {
! 615: /* line completed */
! 616: zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
! 617: hexstr[0] = 0;
! 618: charstr[0] = 0;
! 619: }
! 620: else if ((i % 8) == 0)
! 621: {
! 622: /* half line: add whitespaces */
! 623: strncat (hexstr, " ", sizeof (hexstr) - strlen (hexstr) - 1);
! 624: strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1);
! 625: }
! 626: p++; /* next byte */
! 627: }
! 628:
! 629: /* print rest of buffer if not empty */
! 630: if (strlen (hexstr) > 0)
! 631: zlog_debug ("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
! 632: return;
! 633: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>