Annotation of embedaddon/quagga/isisd/isis_misc.c, revision 1.1.1.1
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"
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:
44: /* staticly assigned vars for printing purposes */
45: struct in_addr new_prefix;
46: /* len of xxxx.xxxx.xxxx + place for #0 termination */
47: char sysid[15];
48: /* len of xxxx.xxxx.xxxx + place for #0 termination */
49: char snpa[15];
50: /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
51: char isonet[51];
52: /* + place for #0 termination */
53: /* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
54: char lspid[21];
55: /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
56: char datestring[20];
57: char nlpidstring[30];
58:
59: /*
60: * This converts the isonet to its printable format
61: */
62: const char *
63: isonet_print (u_char * from, int len)
64: {
65: int i = 0;
66: char *pos = isonet;
67:
68: if (!from)
69: return "unknown";
70:
71: 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++;
92: }
93: *(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: */
101: int
102: dotformat2buff (u_char * buff, const u_char * dotted)
103: {
104: int dotlen, len = 0;
105: const u_char *pos = dotted;
106: u_char number[3];
107: int nextdotpos = 2;
108:
109: number[2] = '\0';
110: dotlen = strlen(dotted);
111: if (dotlen > 50)
112: {
113: /* this can't be an iso net, its too long */
114: return 0;
115: }
116:
117: 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:
149: *(buff + len) = (char) strtol ((char *)number, NULL, 16);
150: len++;
151: }
152:
153: return len;
154: }
155:
156: /*
157: * conversion of XXXX.XXXX.XXXX to memory
158: */
159: int
160: sysid2buff (u_char * buff, const u_char * dotted)
161: {
162: int len = 0;
163: const u_char *pos = dotted;
164: u_char number[3];
165:
166: number[2] = '\0';
167: // surely not a sysid_string if not 14 length
168: if (strlen (dotted) != 14)
169: {
170: return 0;
171: }
172:
173: 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:
197: *(buff + len) = (char) strtol ((char *)number, NULL, 16);
198: len++;
199: }
200:
201: return len;
202:
203: }
204:
205: /*
206: * converts the nlpids struct (filled by TLV #129)
207: * into a string
208: */
209:
210: char *
211: nlpid2string (struct nlpids *nlpids)
212: {
213: char *pos = nlpidstring;
214: int i;
215:
216: 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:
242: }
243:
244: *(pos) = '\0';
245:
246: return nlpidstring;
247: }
248:
249: /*
250: * supports the given af ?
251: */
252: int
253: speaks (struct nlpids *nlpids, int family)
254: {
255: int i, speaks = 0;
256:
257: if (nlpids == (struct nlpids *) NULL)
258: return speaks;
259: 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: }
266:
267: return speaks;
268: }
269:
270: /*
271: * Returns 0 on error, IS-IS Circuit Type on ok
272: */
273: int
274: string2circuit_t (const u_char * str)
275: {
276:
277: if (!str)
278: return 0;
279:
280: if (!strcmp (str, "level-1"))
281: return IS_LEVEL_1;
282:
283: if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
284: return IS_LEVEL_2;
285:
286: if (!strcmp (str, "level-1-2"))
287: return IS_LEVEL_1_AND_2;
288:
289: return 0;
290: }
291:
292: const char *
293: circuit_t2string (int circuit_t)
294: {
295: 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: }
306:
307: return NULL; /* not reached */
308: }
309:
310: const char *
311: syst2string (int type)
312: {
313: 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: }
326:
327: return NULL; /* not reached */
328: }
329:
330: /*
331: * Print functions - we print to static vars
332: */
333: const char *
334: snpa_print (u_char * from)
335: {
336: int i = 0;
337: u_char *pos = (u_char *)snpa;
338:
339: if (!from)
340: return "unknown";
341:
342: while (i < ETH_ALEN - 1)
343: {
344: if (i & 1)
345: {
346: sprintf ((char *)pos, "%02x.", *(from + i));
347: pos += 3;
348: }
349: else
350: {
351: sprintf ((char *)pos, "%02x", *(from + i));
352: pos += 2;
353:
354: }
355: i++;
356: }
357:
358: sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
359: pos += 2;
360: *(pos) = '\0';
361:
362: return snpa;
363: }
364:
365: const char *
366: sysid_print (u_char * from)
367: {
368: int i = 0;
369: char *pos = sysid;
370:
371: if (!from)
372: return "unknown";
373:
374: 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: }
389:
390: sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
391: pos += 2;
392: *(pos) = '\0';
393:
394: return sysid;
395: }
396:
397: const char *
398: rawlspid_print (u_char * from)
399: {
400: char *pos = lspid;
401: if (!from)
402: return "unknown";
403: memcpy (pos, sysid_print (from), 15);
404: pos += 14;
405: sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
406: pos += 3;
407: sprintf (pos, "-%02x", LSP_FRAGMENT (from));
408: pos += 3;
409:
410: *(pos) = '\0';
411:
412: return lspid;
413: }
414:
415: const char *
416: time2string (u_int32_t time)
417: {
418: char *pos = datestring;
419: u_int32_t rest;
420:
421: if (time == 0)
422: return "-";
423:
424: 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:
445: *(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: */
457: unsigned long
458: isis_jitter (unsigned long timer, unsigned long jitter)
459: {
460: int j, k;
461:
462: if (jitter >= 100)
463: 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:
474: j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
475:
476: k = timer - (timer * (100 - jitter)) / 100;
477:
478: timer = timer - (k * j / RANDOM_SPREAD);
479:
480: return timer;
481: }
482:
483: struct in_addr
484: newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
485: {
486: memset (&new_prefix, 0, sizeof (new_prefix));
487: memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
488: ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
489: return new_prefix;
490: }
491:
492: /*
493: * Returns host.name if any, otherwise
494: * it returns the system hostname.
495: */
496: const char *
497: unix_hostname (void)
498: {
499: static struct utsname names;
500: const char *hostname;
501: extern struct host host;
502:
503: hostname = host.name;
504: if (!hostname)
505: {
506: uname (&names);
507: hostname = names.nodename;
508: }
509:
510: return hostname;
511: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>