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