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