]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_misc.c
No warnings here any more.
[mirror_frr.git] / isisd / isis_misc.c
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 <stdlib.h>
25 #include <stdio.h>
26 #include <time.h>
27 #include <ctype.h>
28 #include <zebra.h>
29 #include <sys/utsname.h>
30
31 #include "stream.h"
32 #include "vty.h"
33 #include "hash.h"
34 #include "if.h"
35 #include "command.h"
36
37 #include "isisd/dict.h"
38 #include "isisd/isis_constants.h"
39 #include "isisd/isis_common.h"
40 #include "isisd/isis_circuit.h"
41 #include "isisd/isisd.h"
42 #include "isisd/isis_misc.h"
43
44 #include "isisd/isis_tlv.h"
45 #include "isisd/isis_lsp.h"
46 #include "isisd/isis_constants.h"
47 #include "isisd/isis_adjacency.h"
48
49 /* staticly assigned vars for printing purposes */
50 struct in_addr new_prefix;
51 /* len of xxxx.xxxx.xxxx + place for #0 termination */
52 char sysid[15];
53 /* len of xxxx.xxxx.xxxx + place for #0 termination */
54 char snpa[15];
55 /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
56 char isonet[51];
57 /* + place for #0 termination */
58 /* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
59 char lspid[21];
60 /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
61 char datestring[20];
62 char nlpidstring[30];
63
64 /*
65 * This converts the isonet to its printable format
66 */
67 const char *
68 isonet_print (u_char * from, int len)
69 {
70 int i = 0;
71 char *pos = isonet;
72
73 if (!from)
74 return "unknown";
75
76 while (i < len)
77 {
78 if (i & 1)
79 {
80 sprintf (pos, "%02x", *(from + i));
81 pos += 2;
82 }
83 else
84 {
85 if (i == (len - 1))
86 { /* No dot at the end of address */
87 sprintf (pos, "%02x", *(from + i));
88 pos += 2;
89 }
90 else
91 {
92 sprintf (pos, "%02x.", *(from + i));
93 pos += 3;
94 }
95 }
96 i++;
97 }
98 *(pos) = '\0';
99 return isonet;
100 }
101
102 /*
103 * Returns 0 on error, length of buff on ok
104 * extract dot from the dotted str, and insert all the number in a buff
105 */
106 int
107 dotformat2buff (u_char * buff, u_char * dotted)
108 {
109 int dotlen, len = 0;
110 u_char *pos = dotted;
111 u_char number[3];
112 int nextdotpos = 2;
113
114 number[2] = '\0';
115 dotlen = strlen ((char *)dotted);
116 if (dotlen > 50)
117 {
118 /* this can't be an iso net, its too long */
119 return 0;
120 }
121
122 while ((pos - dotted) < dotlen && len < 20)
123 {
124 if (*pos == '.')
125 {
126 /* we expect the . at 2, and than every 5 */
127 if ((pos - dotted) != nextdotpos)
128 {
129 len = 0;
130 break;
131 }
132 nextdotpos += 5;
133 pos++;
134 continue;
135 }
136 /* we must have at least two chars left here */
137 if (dotlen - (pos - dotted) < 2)
138 {
139 len = 0;
140 break;
141 }
142
143 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
144 {
145 memcpy (number, pos, 2);
146 pos += 2;
147 }
148 else
149 {
150 len = 0;
151 break;
152 }
153
154 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
155 len++;
156 }
157
158 return len;
159 }
160
161 /*
162 * conversion of XXXX.XXXX.XXXX to memory
163 */
164 int
165 sysid2buff (u_char * buff, u_char * dotted)
166 {
167 int len = 0;
168 u_char *pos = dotted;
169 u_char number[3];
170
171 number[2] = '\0';
172 // surely not a sysid_string if not 14 length
173 if (strlen ((char *)dotted) != 14)
174 {
175 return 0;
176 }
177
178 while (len < ISIS_SYS_ID_LEN)
179 {
180 if (*pos == '.')
181 {
182 /* the . is not positioned correctly */
183 if (((pos - dotted) != 4) && ((pos - dotted) != 9))
184 {
185 len = 0;
186 break;
187 }
188 pos++;
189 continue;
190 }
191 if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
192 {
193 memcpy (number, pos, 2);
194 pos += 2;
195 }
196 else
197 {
198 len = 0;
199 break;
200 }
201
202 *(buff + len) = (char) strtol ((char *)number, NULL, 16);
203 len++;
204 }
205
206 return len;
207
208 }
209
210 /*
211 * converts the nlpids struct (filled by TLV #129)
212 * into a string
213 */
214
215 char *
216 nlpid2string (struct nlpids *nlpids)
217 {
218 char *pos = nlpidstring;
219 int i;
220
221 for (i = 0; i < nlpids->count; i++)
222 {
223 switch (nlpids->nlpids[i])
224 {
225 case NLPID_IP:
226 pos += sprintf (pos, "IPv4");
227 break;
228 case NLPID_IPV6:
229 pos += sprintf (pos, "IPv6");
230 break;
231 case NLPID_SNAP:
232 pos += sprintf (pos, "SNAP");
233 break;
234 case NLPID_CLNP:
235 pos += sprintf (pos, "CLNP");
236 break;
237 case NLPID_ESIS:
238 pos += sprintf (pos, "ES-IS");
239 break;
240 default:
241 pos += sprintf (pos, "unknown");
242 break;
243 }
244 if (nlpids->count - i > 1)
245 pos += sprintf (pos, ", ");
246
247 }
248
249 *(pos) = '\0';
250
251 return nlpidstring;
252 }
253
254 /*
255 * supports the given af ?
256 */
257 int
258 speaks (struct nlpids *nlpids, int family)
259 {
260 int i, speaks = 0;
261
262 if (nlpids == (struct nlpids *) NULL)
263 return speaks;
264 for (i = 0; i < nlpids->count; i++)
265 {
266 if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
267 speaks = 1;
268 if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
269 speaks = 1;
270 }
271
272 return speaks;
273 }
274
275 /*
276 * Returns 0 on error, IS-IS Circuit Type on ok
277 */
278 int
279 string2circuit_t (u_char * str)
280 {
281
282 if (!str)
283 return 0;
284
285 if (!strcmp ((char *)str, "level-1"))
286 return IS_LEVEL_1;
287
288 if (!strcmp ((char *)str, "level-2-only") || !strcmp ((char *)str, "level-2"))
289 return IS_LEVEL_2;
290
291 if (!strcmp ((char *)str, "level-1-2"))
292 return IS_LEVEL_1_AND_2;
293
294 return 0;
295 }
296
297 const char *
298 circuit_t2string (int circuit_t)
299 {
300 switch (circuit_t)
301 {
302 case IS_LEVEL_1:
303 return "L1";
304 case IS_LEVEL_2:
305 return "L2";
306 case IS_LEVEL_1_AND_2:
307 return "L1L2";
308 default:
309 return "??";
310 }
311
312 return NULL; /* not reached */
313 }
314
315 const char *
316 syst2string (int type)
317 {
318 switch (type)
319 {
320 case ISIS_SYSTYPE_ES:
321 return "ES";
322 case ISIS_SYSTYPE_IS:
323 return "IS";
324 case ISIS_SYSTYPE_L1_IS:
325 return "1";
326 case ISIS_SYSTYPE_L2_IS:
327 return "2";
328 default:
329 return "??";
330 }
331
332 return NULL; /* not reached */
333 }
334
335 /*
336 * Print functions - we print to static vars
337 */
338 const char *
339 snpa_print (u_char * from)
340 {
341 int i = 0;
342 u_char *pos = (u_char *)snpa;
343
344 if (!from)
345 return "unknown";
346
347 while (i < ETH_ALEN - 1)
348 {
349 if (i & 1)
350 {
351 sprintf ((char *)pos, "%02x.", *(from + i));
352 pos += 3;
353 }
354 else
355 {
356 sprintf ((char *)pos, "%02x", *(from + i));
357 pos += 2;
358
359 }
360 i++;
361 }
362
363 sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
364 pos += 2;
365 *(pos) = '\0';
366
367 return snpa;
368 }
369
370 const char *
371 sysid_print (u_char * from)
372 {
373 int i = 0;
374 char *pos = sysid;
375
376 if (!from)
377 return "unknown";
378
379 while (i < ISIS_SYS_ID_LEN - 1)
380 {
381 if (i & 1)
382 {
383 sprintf (pos, "%02x.", *(from + i));
384 pos += 3;
385 }
386 else
387 {
388 sprintf (pos, "%02x", *(from + i));
389 pos += 2;
390
391 }
392 i++;
393 }
394
395 sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
396 pos += 2;
397 *(pos) = '\0';
398
399 return sysid;
400 }
401
402 const char *
403 rawlspid_print (u_char * from)
404 {
405 char *pos = lspid;
406 if (!from)
407 return "unknown";
408 memcpy (pos, sysid_print (from), 15);
409 pos += 14;
410 sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
411 pos += 3;
412 sprintf (pos, "-%02x", LSP_FRAGMENT (from));
413 pos += 3;
414
415 *(pos) = '\0';
416
417 return lspid;
418 }
419
420 const char *
421 time2string (u_int32_t time)
422 {
423 char *pos = datestring;
424 u_int32_t rest;
425
426 if (time == 0)
427 return "-";
428
429 if (time / SECS_PER_YEAR)
430 pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
431 rest = time % SECS_PER_YEAR;
432 if (rest / SECS_PER_MONTH)
433 pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
434 rest = rest % SECS_PER_MONTH;
435 if (rest / SECS_PER_WEEK)
436 pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
437 rest = rest % SECS_PER_WEEK;
438 if (rest / SECS_PER_DAY)
439 pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
440 rest = rest % SECS_PER_DAY;
441 if (rest / SECS_PER_HOUR)
442 pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
443 rest = rest % SECS_PER_HOUR;
444 if (rest / SECS_PER_MINUTE)
445 pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
446 rest = rest % SECS_PER_MINUTE;
447 if (rest)
448 pos += sprintf (pos, "%us", rest);
449
450 *(pos) = 0;
451
452 return datestring;
453 }
454
455 /*
456 * routine to decrement a timer by a random
457 * number
458 *
459 * first argument is the timer and the second is
460 * the jitter
461 */
462 unsigned long
463 isis_jitter (unsigned long timer, unsigned long jitter)
464 {
465 int j, k;
466
467 if (jitter >= 100)
468 return timer;
469
470 if (timer == 1)
471 return timer;
472 /*
473 * randomizing just the percent value provides
474 * no good random numbers - hence the spread
475 * to RANDOM_SPREAD (100000), which is ok as
476 * most IS-IS timers are no longer than 16 bit
477 */
478
479 j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0));
480
481 k = timer - (timer * (100 - jitter)) / 100;
482
483 timer = timer - (k * j / RANDOM_SPREAD);
484
485 return timer;
486 }
487
488 struct in_addr
489 newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
490 {
491 memset (&new_prefix, 0, sizeof (new_prefix));
492 memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
493 ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
494 return new_prefix;
495 }
496
497 /*
498 * Returns host.name if any, otherwise
499 * it returns the system hostname.
500 */
501 const char *
502 unix_hostname (void)
503 {
504 static struct utsname names;
505 const char *hostname;
506 extern struct host host;
507
508 hostname = host.name;
509 if (!hostname)
510 {
511 uname (&names);
512 hostname = names.nodename;
513 }
514
515 return hostname;
516 }