]>
git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_misc.c
2 * IS-IS Rout(e)ing protocol - isis_misc.h
3 * Miscellanous routines
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
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)
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
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
34 #include "isisd/isis_constants.h"
35 #include "isisd/isis_common.h"
36 #include "isisd/isis_flags.h"
37 #include "isisd/isis_circuit.h"
38 #include "isisd/isis_csm.h"
39 #include "isisd/isisd.h"
40 #include "isisd/isis_misc.h"
42 #include "isisd/isis_lsp.h"
43 #include "isisd/isis_constants.h"
44 #include "isisd/isis_adjacency.h"
45 #include "isisd/isis_dynhn.h"
47 /* staticly assigned vars for printing purposes */
48 struct in_addr new_prefix
;
49 /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
50 /* + place for #0 termination */
52 /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
57 * This converts the isonet to its printable format
59 const char *isonet_print(const uint8_t *from
, int len
)
70 snprintf(tbuf
, sizeof(tbuf
), "%02x", *(from
+ i
));
71 strlcat(isonet
, tbuf
, sizeof(isonet
));
73 if (i
== (len
- 1)) { /* No dot at the end of address */
74 snprintf(tbuf
, sizeof(tbuf
), "%02x",
76 strlcat(isonet
, tbuf
, sizeof(isonet
));
78 snprintf(tbuf
, sizeof(tbuf
), "%02x.",
80 strlcat(isonet
, tbuf
, sizeof(isonet
));
90 * Returns 0 on error, length of buff on ok
91 * extract dot from the dotted str, and insert all the number in a buff
93 int dotformat2buff(uint8_t *buff
, const char *dotted
)
96 const char *pos
= dotted
;
101 dotlen
= strlen(dotted
);
103 /* this can't be an iso net, its too long */
107 while ((pos
- dotted
) < dotlen
&& len
< 20) {
109 /* we expect the . at 2, and than every 5 */
110 if ((pos
- dotted
) != nextdotpos
) {
118 /* we must have at least two chars left here */
119 if (dotlen
- (pos
- dotted
) < 2) {
124 if ((isxdigit((unsigned char)*pos
)) &&
125 (isxdigit((unsigned char)*(pos
+ 1)))) {
126 memcpy(number
, pos
, 2);
133 *(buff
+ len
) = (char)strtol((char *)number
, NULL
, 16);
141 * conversion of XXXX.XXXX.XXXX to memory
143 int sysid2buff(uint8_t *buff
, const char *dotted
)
146 const char *pos
= dotted
;
150 // surely not a sysid_string if not 14 length
151 if (strlen(dotted
) != 14) {
155 while (len
< ISIS_SYS_ID_LEN
) {
157 /* the . is not positioned correctly */
158 if (((pos
- dotted
) != 4) && ((pos
- dotted
) != 9)) {
165 if ((isxdigit((unsigned char)*pos
)) &&
166 (isxdigit((unsigned char)*(pos
+ 1)))) {
167 memcpy(number
, pos
, 2);
174 *(buff
+ len
) = (char)strtol((char *)number
, NULL
, 16);
181 const char *nlpid2str(uint8_t nlpid
)
196 snprintf(buf
, sizeof(buf
), "%hhu", nlpid
);
202 * converts the nlpids struct (filled by TLV #129)
206 char *nlpid2string(struct nlpids
*nlpids
)
210 nlpidstring
[0] = '\0';
212 for (i
= 0; i
< nlpids
->count
; i
++) {
213 snprintf(tbuf
, sizeof(tbuf
), "%s",
214 nlpid2str(nlpids
->nlpids
[i
]));
215 strlcat(nlpidstring
, tbuf
, sizeof(nlpidstring
));
216 if (nlpids
->count
- i
> 1)
217 strlcat(nlpidstring
, ", ", sizeof(nlpidstring
));
224 * Returns 0 on error, IS-IS Circuit Type on ok
226 int string2circuit_t(const char *str
)
232 if (!strcmp(str
, "level-1"))
235 if (!strcmp(str
, "level-2-only") || !strcmp(str
, "level-2"))
238 if (!strcmp(str
, "level-1-2"))
239 return IS_LEVEL_1_AND_2
;
244 const char *circuit_state2string(int state
)
260 const char *circuit_type2string(int type
)
266 case CIRCUIT_T_BROADCAST
:
268 case CIRCUIT_T_LOOPBACK
:
276 const char *circuit_t2string(int circuit_t
)
283 case IS_LEVEL_1_AND_2
:
289 return NULL
; /* not reached */
292 const char *syst2string(int type
)
295 case ISIS_SYSTYPE_ES
:
297 case ISIS_SYSTYPE_IS
:
299 case ISIS_SYSTYPE_L1_IS
:
301 case ISIS_SYSTYPE_L2_IS
:
307 return NULL
; /* not reached */
311 * Print functions - we print to static vars
313 const char *snpa_print(const uint8_t *from
)
315 return isis_format_id(from
, ISIS_SYS_ID_LEN
);
318 const char *sysid_print(const uint8_t *from
)
320 return isis_format_id(from
, ISIS_SYS_ID_LEN
);
323 const char *rawlspid_print(const uint8_t *from
)
325 return isis_format_id(from
, 8);
328 #define FORMAT_ID_SIZE sizeof("0000.0000.0000.00-00")
329 const char *isis_format_id(const uint8_t *id
, size_t len
)
331 #define FORMAT_BUF_COUNT 4
332 static char buf_ring
[FORMAT_BUF_COUNT
][FORMAT_ID_SIZE
];
333 static size_t cur_buf
= 0;
338 if (cur_buf
>= FORMAT_BUF_COUNT
)
341 rv
= buf_ring
[cur_buf
];
344 snprintf(rv
, FORMAT_ID_SIZE
, "unknown");
349 snprintf(rv
, FORMAT_ID_SIZE
, "Short ID");
353 snprintf(rv
, FORMAT_ID_SIZE
, "%02x%02x.%02x%02x.%02x%02x", id
[0], id
[1],
354 id
[2], id
[3], id
[4], id
[5]);
357 snprintf(rv
+ 14, FORMAT_ID_SIZE
- 14, ".%02x", id
[6]);
359 snprintf(rv
+ 17, FORMAT_ID_SIZE
- 17, "-%02x", id
[7]);
364 const char *time2string(uint32_t time
)
368 datestring
[0] = '\0';
373 if (time
/ SECS_PER_YEAR
) {
374 snprintf(tbuf
, sizeof(tbuf
), "%uY", time
/ SECS_PER_YEAR
);
375 strlcat(datestring
, tbuf
, sizeof(datestring
));
377 rest
= time
% SECS_PER_YEAR
;
378 if (rest
/ SECS_PER_MONTH
) {
379 snprintf(tbuf
, sizeof(tbuf
), "%uM", rest
/ SECS_PER_MONTH
);
380 strlcat(datestring
, tbuf
, sizeof(datestring
));
382 rest
= rest
% SECS_PER_MONTH
;
383 if (rest
/ SECS_PER_WEEK
) {
384 snprintf(tbuf
, sizeof(tbuf
), "%uw", rest
/ SECS_PER_WEEK
);
385 strlcat(datestring
, tbuf
, sizeof(datestring
));
387 rest
= rest
% SECS_PER_WEEK
;
388 if (rest
/ SECS_PER_DAY
) {
389 snprintf(tbuf
, sizeof(tbuf
), "%ud", rest
/ SECS_PER_DAY
);
390 strlcat(datestring
, tbuf
, sizeof(datestring
));
392 rest
= rest
% SECS_PER_DAY
;
393 if (rest
/ SECS_PER_HOUR
) {
394 snprintf(tbuf
, sizeof(tbuf
), "%uh", rest
/ SECS_PER_HOUR
);
395 strlcat(datestring
, tbuf
, sizeof(datestring
));
397 rest
= rest
% SECS_PER_HOUR
;
398 if (rest
/ SECS_PER_MINUTE
) {
399 snprintf(tbuf
, sizeof(tbuf
), "%um", rest
/ SECS_PER_MINUTE
);
400 strlcat(datestring
, tbuf
, sizeof(datestring
));
402 rest
= rest
% SECS_PER_MINUTE
;
404 snprintf(tbuf
, sizeof(tbuf
), "%us", rest
);
405 strlcat(datestring
, tbuf
, sizeof(datestring
));
412 * routine to decrement a timer by a random
415 * first argument is the timer and the second is
418 unsigned long isis_jitter(unsigned long timer
, unsigned long jitter
)
428 * randomizing just the percent value provides
429 * no good random numbers - hence the spread
430 * to RANDOM_SPREAD (100000), which is ok as
431 * most IS-IS timers are no longer than 16 bit
434 j
= 1 + (int)((RANDOM_SPREAD
* frr_weak_random()) / (RAND_MAX
+ 1.0));
436 k
= timer
- (timer
* (100 - jitter
)) / 100;
438 timer
= timer
- (k
* j
/ RANDOM_SPREAD
);
443 struct in_addr
newprefix2inaddr(uint8_t *prefix_start
, uint8_t prefix_masklen
)
445 memset(&new_prefix
, 0, sizeof(new_prefix
));
446 memcpy(&new_prefix
, prefix_start
,
447 (prefix_masklen
& 0x3F)
448 ? ((((prefix_masklen
& 0x3F) - 1) >> 3) + 1)
454 * Returns the dynamic hostname associated with the passed system ID.
455 * If no dynamic hostname found then returns formatted system ID.
457 const char *print_sys_hostname(const uint8_t *sysid
)
459 struct isis_dynhn
*dyn
;
460 struct isis
*isis
= NULL
;
461 struct listnode
*node
;
466 /* For our system ID return our host name */
467 isis
= isis_lookup_by_sysid(sysid
);
468 if (isis
&& !CHECK_FLAG(im
->options
, F_ISIS_UNIT_TEST
))
469 return cmd_hostname_get();
471 for (ALL_LIST_ELEMENTS_RO(im
->isis
, node
, isis
)) {
472 dyn
= dynhn_find_by_id(isis
, sysid
);
474 return dyn
->hostname
;
477 return sysid_print(sysid
);
481 * This function is a generic utility that logs data of given length.
482 * Move this to a shared lib so that any protocol can use it.
484 void zlog_dump_data(void *data
, int len
)
491 char hexstr
[16 * 3 + 5];
492 char charstr
[16 * 1 + 5];
495 memset(bytestr
, 0, sizeof(bytestr
));
496 memset(addrstr
, 0, sizeof(addrstr
));
497 memset(hexstr
, 0, sizeof(hexstr
));
498 memset(charstr
, 0, sizeof(charstr
));
500 for (i
= 1; i
<= len
; i
++) {
505 /* store address for this line */
507 snprintf(addrstr
, sizeof(addrstr
), "%p", p
);
509 /* store hex str (for left side) */
510 snprintf(bytestr
, sizeof(bytestr
), "%02X ", *p
);
511 strncat(hexstr
, bytestr
, sizeof(hexstr
) - strlen(hexstr
) - 1);
513 /* store char str (for right side) */
514 snprintf(bytestr
, sizeof(bytestr
), "%c", c
);
515 strncat(charstr
, bytestr
,
516 sizeof(charstr
) - strlen(charstr
) - 1);
520 zlog_debug("[%8.8s] %-50.50s %s", addrstr
, hexstr
,
524 } else if ((i
% 8) == 0) {
525 /* half line: add whitespaces */
527 sizeof(hexstr
) - strlen(hexstr
) - 1);
528 strncat(charstr
, " ",
529 sizeof(charstr
) - strlen(charstr
) - 1);
534 /* print rest of buffer if not empty */
535 if (strlen(hexstr
) > 0)
536 zlog_debug("[%8.8s] %-50.50s %s", addrstr
, hexstr
, charstr
);
540 void log_multiline(int priority
, const char *prefix
, const char *format
, ...)
546 va_start(ap
, format
);
547 p
= vasnprintfrr(MTYPE_TMP
, shortbuf
, sizeof(shortbuf
), format
, ap
);
553 char *saveptr
= NULL
;
554 for (char *line
= strtok_r(p
, "\n", &saveptr
); line
;
555 line
= strtok_r(NULL
, "\n", &saveptr
)) {
556 zlog(priority
, "%s%s", prefix
, line
);
563 char *log_uptime(time_t uptime
, char *buf
, size_t nbuf
)
566 time_t difftime
= time(NULL
);
568 tm
= gmtime(&difftime
);
570 if (difftime
< ONE_DAY_SECOND
)
571 snprintf(buf
, nbuf
, "%02d:%02d:%02d", tm
->tm_hour
, tm
->tm_min
,
573 else if (difftime
< ONE_WEEK_SECOND
)
574 snprintf(buf
, nbuf
, "%dd%02dh%02dm", tm
->tm_yday
, tm
->tm_hour
,
577 snprintf(buf
, nbuf
, "%02dw%dd%02dh", tm
->tm_yday
/ 7,
578 tm
->tm_yday
- ((tm
->tm_yday
/ 7) * 7), tm
->tm_hour
);
583 void vty_multiline(struct vty
*vty
, const char *prefix
, const char *format
, ...)
589 va_start(ap
, format
);
590 p
= vasnprintfrr(MTYPE_TMP
, shortbuf
, sizeof(shortbuf
), format
, ap
);
596 char *saveptr
= NULL
;
597 for (char *line
= strtok_r(p
, "\n", &saveptr
); line
;
598 line
= strtok_r(NULL
, "\n", &saveptr
)) {
599 vty_out(vty
, "%s%s\n", prefix
, line
);
606 void vty_out_timestr(struct vty
*vty
, time_t uptime
)
608 time_t difftime
= time(NULL
);
609 char buf
[MONOTIME_STRLEN
];
613 frrtime_to_interval(difftime
, buf
, sizeof(buf
));
615 vty_out(vty
, "%s ago", buf
);