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