1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
7 #define FRR_DEFINE_DESC_TABLE
15 #include "lib_errors.h"
18 #include "frr_pthread.h"
21 #define UNW_LOCAL_ONLY
22 #include <libunwind.h>
27 * Looks up a message in a message list by key.
29 * If the message is not found, returns the provided error message.
31 * Terminates when it hits a struct message that's all zeros.
33 * @param mz the message list
34 * @param kz the message key
35 * @param nf the message to return if not found
38 const char *lookup_msg(const struct message
*mz
, int kz
, const char *nf
)
40 static struct message nt
= {0};
41 const char *rz
= nf
? nf
: "(no message found)";
42 const struct message
*pnt
;
43 for (pnt
= mz
; memcmp(pnt
, &nt
, sizeof(struct message
)); pnt
++)
45 rz
= pnt
->str
? pnt
->str
: rz
;
51 /* For time string format. */
52 size_t frr_timestamp(int timestamp_precision
, char *buf
, size_t buflen
)
61 gettimeofday(&clock
, NULL
);
63 /* first, we update the cache if the time has changed */
64 if (cache
.last
!= clock
.tv_sec
) {
66 cache
.last
= clock
.tv_sec
;
67 localtime_r(&cache
.last
, &tm
);
68 cache
.len
= strftime(cache
.buf
, sizeof(cache
.buf
),
69 "%Y/%m/%d %H:%M:%S", &tm
);
71 /* note: it's not worth caching the subsecond part, because
72 chances are that back-to-back calls are not sufficiently close
74 for the clock not to have ticked forward */
76 if (buflen
> cache
.len
) {
77 memcpy(buf
, cache
.buf
, cache
.len
);
78 if ((timestamp_precision
> 0)
79 && (buflen
> cache
.len
+ 1 + timestamp_precision
)) {
80 /* should we worry about locale issues? */
81 static const int divisor
[] = {0, 100000, 10000, 1000,
84 char *p
= buf
+ cache
.len
+ 1
85 + (prec
= timestamp_precision
);
88 /* this is unlikely to happen, but protect anyway */
93 clock
.tv_usec
/= divisor
[prec
];
95 *p
-- = '0' + (clock
.tv_usec
% 10);
99 return cache
.len
+ 1 + timestamp_precision
;
101 buf
[cache
.len
] = '\0';
112 * NB: only AS-Safe (async-signal) functions can be used here!
115 /* Note: the goal here is to use only async-signal-safe functions. */
116 void zlog_signal(int signo
, const char *action
, void *siginfo_v
,
117 void *program_counter
)
119 siginfo_t
*siginfo
= siginfo_v
;
121 char buf
[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")
123 struct fbuf fb
= { .buf
= buf
, .pos
= buf
, .len
= sizeof(buf
) };
127 bprintfrr(&fb
, "Received signal %d at %lld", signo
, (long long)now
);
129 bprintfrr(&fb
, " (si_addr 0x%tx, PC 0x%tx)",
130 (ptrdiff_t)siginfo
->si_addr
,
131 (ptrdiff_t)program_counter
);
133 bprintfrr(&fb
, " (si_addr 0x%tx)",
134 (ptrdiff_t)siginfo
->si_addr
);
135 bprintfrr(&fb
, "; %s\n", action
);
137 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
139 zlog_backtrace_sigsafe(LOG_CRIT
, program_counter
);
144 tc
= pthread_getspecific(thread_current
);
147 bprintfrr(&fb
, "no thread information available\n");
149 bprintfrr(&fb
, "in thread %s scheduled from %s:%d %s()\n",
150 tc
->xref
->funcname
, tc
->xref
->xref
.file
,
151 tc
->xref
->xref
.line
, tc
->xref
->xref
.func
);
153 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
156 /* Log a backtrace using only async-signal-safe functions.
157 Needs to be enhanced to support syslog logging. */
158 void zlog_backtrace_sigsafe(int priority
, void *program_counter
)
160 #ifdef HAVE_LIBUNWIND
162 struct fbuf fb
= { .buf
= buf
, .len
= sizeof(buf
) };
165 unw_word_t ip
, off
, sp
;
168 memset(&uc
, 0, sizeof(uc
));
169 memset(&cursor
, 0, sizeof(cursor
));
172 unw_init_local(&cursor
, &uc
);
173 while (unw_step(&cursor
) > 0) {
174 char name
[128] = "?";
176 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
177 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
179 if (!unw_get_proc_name(&cursor
, buf
, sizeof(buf
), &off
))
180 snprintfrr(name
, sizeof(name
), "%s+%#lx",
184 if (unw_is_signal_frame(&cursor
))
185 bprintfrr(&fb
, " ---- signal ----\n");
186 bprintfrr(&fb
, "%-30s %16lx %16lx", name
, (long)ip
, (long)sp
);
187 if (dladdr((void *)ip
, &dlinfo
))
188 bprintfrr(&fb
, " %s (mapped at %p)",
189 dlinfo
.dli_fname
, dlinfo
.dli_fbase
);
190 bprintfrr(&fb
, "\n");
191 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
193 #elif defined(HAVE_GLIBC_BACKTRACE)
197 struct fbuf fb
= { .buf
= buf
, .pos
= buf
, .len
= sizeof(buf
) };
200 size
= backtrace(array
, array_size(array
));
201 if (size
<= 0 || (size_t)size
> array_size(array
))
204 bprintfrr(&fb
, "Backtrace for %d stack frames:", size
);
205 zlog_sigsafe(fb
.pos
, fb
.buf
- fb
.pos
);
207 bt
= backtrace_symbols(array
, size
);
209 for (i
= 0; i
< size
; i
++) {
212 bprintfrr(&fb
, "%s", bt
[i
]);
214 bprintfrr(&fb
, "[bt %d] 0x%tx", i
,
215 (ptrdiff_t)(array
[i
]));
216 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
220 #endif /* HAVE_STRACK_TRACE */
223 void zlog_backtrace(int priority
)
225 #ifdef HAVE_LIBUNWIND
227 unw_cursor_t cursor
= {};
229 unw_word_t ip
, off
, sp
;
233 unw_init_local(&cursor
, &uc
);
234 zlog(priority
, "Backtrace:");
235 while (unw_step(&cursor
) > 0) {
236 char name
[128] = "?";
238 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
239 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
241 if (unw_is_signal_frame(&cursor
))
242 zlog(priority
, " ---- signal ----");
244 if (!unw_get_proc_name(&cursor
, buf
, sizeof(buf
), &off
))
245 snprintf(name
, sizeof(name
), "%s+%#lx",
248 if (dladdr((void *)ip
, &dlinfo
))
249 zlog(priority
, "%-30s %16lx %16lx %s (mapped at %p)",
250 name
, (long)ip
, (long)sp
,
251 dlinfo
.dli_fname
, dlinfo
.dli_fbase
);
253 zlog(priority
, "%-30s %16lx %16lx",
254 name
, (long)ip
, (long)sp
);
256 #elif defined(HAVE_GLIBC_BACKTRACE)
261 size
= backtrace(array
, array_size(array
));
262 if (size
<= 0 || (size_t)size
> array_size(array
)) {
265 "Cannot get backtrace, returned invalid # of frames %d (valid range is between 1 and %lu)",
266 size
, (unsigned long)(array_size(array
)));
269 zlog(priority
, "Backtrace for %d stack frames:", size
);
270 if (!(strings
= backtrace_symbols(array
, size
))) {
271 flog_err_sys(EC_LIB_SYSTEM_CALL
,
272 "Cannot get backtrace symbols (out of memory?)");
273 for (i
= 0; i
< size
; i
++)
274 zlog(priority
, "[bt %d] %p", i
, array
[i
]);
276 for (i
= 0; i
< size
; i
++)
277 zlog(priority
, "[bt %d] %s", i
, strings
[i
]);
280 #else /* !HAVE_GLIBC_BACKTRACE && !HAVE_LIBUNWIND */
281 zlog(priority
, "No backtrace available on this platform.");
285 void zlog_thread_info(int log_level
)
288 tc
= pthread_getspecific(thread_current
);
292 "Current thread function %s, scheduled from file %s, line %u in %s()",
293 tc
->xref
->funcname
, tc
->xref
->xref
.file
,
294 tc
->xref
->xref
.line
, tc
->xref
->xref
.func
);
296 zlog(log_level
, "Current thread not known/applicable");
299 void memory_oom(size_t size
, const char *name
)
302 "out of memory: failed to allocate %zu bytes for %s object",
304 zlog_backtrace(LOG_CRIT
);
305 log_memstats(stderr
, "log");
309 /* Wrapper around strerror to handle case where it returns NULL. */
310 const char *safe_strerror(int errnum
)
312 const char *s
= strerror(errnum
);
313 return (s
!= NULL
) ? s
: "Unknown error";
316 #define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' }
317 static const struct zebra_desc_table command_types
[] = {
318 DESC_ENTRY(ZEBRA_INTERFACE_ADD
),
319 DESC_ENTRY(ZEBRA_INTERFACE_DELETE
),
320 DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_ADD
),
321 DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_DELETE
),
322 DESC_ENTRY(ZEBRA_INTERFACE_UP
),
323 DESC_ENTRY(ZEBRA_INTERFACE_DOWN
),
324 DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER
),
325 DESC_ENTRY(ZEBRA_INTERFACE_SET_PROTODOWN
),
326 DESC_ENTRY(ZEBRA_ROUTE_ADD
),
327 DESC_ENTRY(ZEBRA_ROUTE_DELETE
),
328 DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER
),
329 DESC_ENTRY(ZEBRA_REDISTRIBUTE_ADD
),
330 DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE
),
331 DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
),
332 DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
),
333 DESC_ENTRY(ZEBRA_ROUTER_ID_ADD
),
334 DESC_ENTRY(ZEBRA_ROUTER_ID_DELETE
),
335 DESC_ENTRY(ZEBRA_ROUTER_ID_UPDATE
),
336 DESC_ENTRY(ZEBRA_HELLO
),
337 DESC_ENTRY(ZEBRA_CAPABILITIES
),
338 DESC_ENTRY(ZEBRA_NEXTHOP_REGISTER
),
339 DESC_ENTRY(ZEBRA_NEXTHOP_UNREGISTER
),
340 DESC_ENTRY(ZEBRA_NEXTHOP_UPDATE
),
341 DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_ADD
),
342 DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE
),
343 DESC_ENTRY(ZEBRA_INTERFACE_BFD_DEST_UPDATE
),
344 DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER
),
345 DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER
),
346 DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE
),
347 DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY
),
348 DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD
),
349 DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL
),
350 DESC_ENTRY(ZEBRA_VRF_UNREGISTER
),
351 DESC_ENTRY(ZEBRA_VRF_ADD
),
352 DESC_ENTRY(ZEBRA_VRF_DELETE
),
353 DESC_ENTRY(ZEBRA_VRF_LABEL
),
354 DESC_ENTRY(ZEBRA_INTERFACE_VRF_UPDATE
),
355 DESC_ENTRY(ZEBRA_BFD_CLIENT_REGISTER
),
356 DESC_ENTRY(ZEBRA_BFD_CLIENT_DEREGISTER
),
357 DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV
),
358 DESC_ENTRY(ZEBRA_INTERFACE_DISABLE_RADV
),
359 DESC_ENTRY(ZEBRA_NEXTHOP_LOOKUP_MRIB
),
360 DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS
),
361 DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD
),
362 DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE
),
363 DESC_ENTRY(ZEBRA_MPLS_LABELS_REPLACE
),
364 DESC_ENTRY(ZEBRA_SR_POLICY_SET
),
365 DESC_ENTRY(ZEBRA_SR_POLICY_DELETE
),
366 DESC_ENTRY(ZEBRA_SR_POLICY_NOTIFY_STATUS
),
367 DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS
),
368 DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT
),
369 DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC
),
370 DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK
),
371 DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK
),
372 DESC_ENTRY(ZEBRA_FEC_REGISTER
),
373 DESC_ENTRY(ZEBRA_FEC_UNREGISTER
),
374 DESC_ENTRY(ZEBRA_FEC_UPDATE
),
375 DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW
),
376 DESC_ENTRY(ZEBRA_ADVERTISE_SVI_MACIP
),
377 DESC_ENTRY(ZEBRA_ADVERTISE_SUBNET
),
378 DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI
),
379 DESC_ENTRY(ZEBRA_LOCAL_ES_ADD
),
380 DESC_ENTRY(ZEBRA_LOCAL_ES_DEL
),
381 DESC_ENTRY(ZEBRA_REMOTE_ES_VTEP_ADD
),
382 DESC_ENTRY(ZEBRA_REMOTE_ES_VTEP_DEL
),
383 DESC_ENTRY(ZEBRA_LOCAL_ES_EVI_ADD
),
384 DESC_ENTRY(ZEBRA_LOCAL_ES_EVI_DEL
),
385 DESC_ENTRY(ZEBRA_VNI_ADD
),
386 DESC_ENTRY(ZEBRA_VNI_DEL
),
387 DESC_ENTRY(ZEBRA_L3VNI_ADD
),
388 DESC_ENTRY(ZEBRA_L3VNI_DEL
),
389 DESC_ENTRY(ZEBRA_REMOTE_VTEP_ADD
),
390 DESC_ENTRY(ZEBRA_REMOTE_VTEP_DEL
),
391 DESC_ENTRY(ZEBRA_MACIP_ADD
),
392 DESC_ENTRY(ZEBRA_MACIP_DEL
),
393 DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_ADD
),
394 DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_DEL
),
395 DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD
),
396 DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL
),
397 DESC_ENTRY(ZEBRA_DUPLICATE_ADDR_DETECTION
),
398 DESC_ENTRY(ZEBRA_PW_ADD
),
399 DESC_ENTRY(ZEBRA_PW_DELETE
),
400 DESC_ENTRY(ZEBRA_PW_SET
),
401 DESC_ENTRY(ZEBRA_PW_UNSET
),
402 DESC_ENTRY(ZEBRA_PW_STATUS_UPDATE
),
403 DESC_ENTRY(ZEBRA_RULE_ADD
),
404 DESC_ENTRY(ZEBRA_RULE_DELETE
),
405 DESC_ENTRY(ZEBRA_RULE_NOTIFY_OWNER
),
406 DESC_ENTRY(ZEBRA_TABLE_MANAGER_CONNECT
),
407 DESC_ENTRY(ZEBRA_GET_TABLE_CHUNK
),
408 DESC_ENTRY(ZEBRA_RELEASE_TABLE_CHUNK
),
409 DESC_ENTRY(ZEBRA_IPSET_CREATE
),
410 DESC_ENTRY(ZEBRA_IPSET_DESTROY
),
411 DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD
),
412 DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE
),
413 DESC_ENTRY(ZEBRA_IPSET_NOTIFY_OWNER
),
414 DESC_ENTRY(ZEBRA_IPSET_ENTRY_NOTIFY_OWNER
),
415 DESC_ENTRY(ZEBRA_IPTABLE_ADD
),
416 DESC_ENTRY(ZEBRA_IPTABLE_DELETE
),
417 DESC_ENTRY(ZEBRA_IPTABLE_NOTIFY_OWNER
),
418 DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL
),
419 DESC_ENTRY(ZEBRA_VXLAN_SG_ADD
),
420 DESC_ENTRY(ZEBRA_VXLAN_SG_DEL
),
421 DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY
),
422 DESC_ENTRY(ZEBRA_MLAG_PROCESS_UP
),
423 DESC_ENTRY(ZEBRA_MLAG_PROCESS_DOWN
),
424 DESC_ENTRY(ZEBRA_MLAG_CLIENT_REGISTER
),
425 DESC_ENTRY(ZEBRA_MLAG_CLIENT_UNREGISTER
),
426 DESC_ENTRY(ZEBRA_MLAG_FORWARD_MSG
),
427 DESC_ENTRY(ZEBRA_NHG_ADD
),
428 DESC_ENTRY(ZEBRA_NHG_DEL
),
429 DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER
),
430 DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_ADD
),
431 DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL
),
432 DESC_ENTRY(ZEBRA_SRV6_LOCATOR_ADD
),
433 DESC_ENTRY(ZEBRA_SRV6_LOCATOR_DELETE
),
434 DESC_ENTRY(ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK
),
435 DESC_ENTRY(ZEBRA_SRV6_MANAGER_RELEASE_LOCATOR_CHUNK
),
436 DESC_ENTRY(ZEBRA_ERROR
),
437 DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES
),
438 DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE
),
439 DESC_ENTRY(ZEBRA_OPAQUE_REGISTER
),
440 DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER
),
441 DESC_ENTRY(ZEBRA_NEIGH_DISCOVER
),
442 DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST
),
443 DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY
),
444 DESC_ENTRY(ZEBRA_NHRP_NEIGH_ADDED
),
445 DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED
),
446 DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET
),
447 DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER
),
448 DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER
),
449 DESC_ENTRY(ZEBRA_NEIGH_IP_ADD
),
450 DESC_ENTRY(ZEBRA_NEIGH_IP_DEL
),
451 DESC_ENTRY(ZEBRA_CONFIGURE_ARP
),
452 DESC_ENTRY(ZEBRA_GRE_GET
),
453 DESC_ENTRY(ZEBRA_GRE_UPDATE
),
454 DESC_ENTRY(ZEBRA_GRE_SOURCE_SET
),
455 DESC_ENTRY(ZEBRA_TC_QDISC_INSTALL
),
456 DESC_ENTRY(ZEBRA_TC_QDISC_UNINSTALL
),
457 DESC_ENTRY(ZEBRA_TC_CLASS_ADD
),
458 DESC_ENTRY(ZEBRA_TC_CLASS_DELETE
),
459 DESC_ENTRY(ZEBRA_TC_FILTER_ADD
),
460 DESC_ENTRY(ZEBRA_TC_FILTER_DELETE
)};
463 static const struct zebra_desc_table unknown
= {0, "unknown", '?'};
465 static const struct zebra_desc_table
*zroute_lookup(unsigned int zroute
)
469 if (zroute
>= array_size(route_types
)) {
470 flog_err(EC_LIB_DEVELOPMENT
, "unknown zebra route type: %u",
474 if (zroute
== route_types
[zroute
].type
)
475 return &route_types
[zroute
];
476 for (i
= 0; i
< array_size(route_types
); i
++) {
477 if (zroute
== route_types
[i
].type
) {
479 "internal error: route type table out of order while searching for %u, please notify developers",
481 return &route_types
[i
];
484 flog_err(EC_LIB_DEVELOPMENT
,
485 "internal error: cannot find route type %u in table!", zroute
);
489 const char *zebra_route_string(unsigned int zroute
)
491 return zroute_lookup(zroute
)->string
;
494 char zebra_route_char(unsigned int zroute
)
496 return zroute_lookup(zroute
)->chr
;
499 const char *zserv_command_string(unsigned int command
)
501 if (command
>= array_size(command_types
)) {
502 flog_err(EC_LIB_DEVELOPMENT
, "unknown zserv command type: %u",
504 return unknown
.string
;
506 return command_types
[command
].string
;
509 int proto_name2num(const char *s
)
513 for (i
= 0; i
< array_size(route_types
); ++i
)
514 if (strcasecmp(s
, route_types
[i
].string
) == 0)
515 return route_types
[i
].type
;
519 int proto_redistnum(int afi
, const char *s
)
525 if (strmatch(s
, "kernel"))
526 return ZEBRA_ROUTE_KERNEL
;
527 else if (strmatch(s
, "connected"))
528 return ZEBRA_ROUTE_CONNECT
;
529 else if (strmatch(s
, "static"))
530 return ZEBRA_ROUTE_STATIC
;
531 else if (strmatch(s
, "rip"))
532 return ZEBRA_ROUTE_RIP
;
533 else if (strmatch(s
, "eigrp"))
534 return ZEBRA_ROUTE_EIGRP
;
535 else if (strmatch(s
, "ospf"))
536 return ZEBRA_ROUTE_OSPF
;
537 else if (strmatch(s
, "isis"))
538 return ZEBRA_ROUTE_ISIS
;
539 else if (strmatch(s
, "bgp"))
540 return ZEBRA_ROUTE_BGP
;
541 else if (strmatch(s
, "table"))
542 return ZEBRA_ROUTE_TABLE
;
543 else if (strmatch(s
, "vnc"))
544 return ZEBRA_ROUTE_VNC
;
545 else if (strmatch(s
, "vnc-direct"))
546 return ZEBRA_ROUTE_VNC_DIRECT
;
547 else if (strmatch(s
, "nhrp"))
548 return ZEBRA_ROUTE_NHRP
;
549 else if (strmatch(s
, "babel"))
550 return ZEBRA_ROUTE_BABEL
;
551 else if (strmatch(s
, "sharp"))
552 return ZEBRA_ROUTE_SHARP
;
553 else if (strmatch(s
, "openfabric"))
554 return ZEBRA_ROUTE_OPENFABRIC
;
556 if (afi
== AFI_IP6
) {
557 if (strmatch(s
, "kernel"))
558 return ZEBRA_ROUTE_KERNEL
;
559 else if (strmatch(s
, "connected"))
560 return ZEBRA_ROUTE_CONNECT
;
561 else if (strmatch(s
, "static"))
562 return ZEBRA_ROUTE_STATIC
;
563 else if (strmatch(s
, "ripng"))
564 return ZEBRA_ROUTE_RIPNG
;
565 else if (strmatch(s
, "ospf6"))
566 return ZEBRA_ROUTE_OSPF6
;
567 else if (strmatch(s
, "isis"))
568 return ZEBRA_ROUTE_ISIS
;
569 else if (strmatch(s
, "bgp"))
570 return ZEBRA_ROUTE_BGP
;
571 else if (strmatch(s
, "table"))
572 return ZEBRA_ROUTE_TABLE
;
573 else if (strmatch(s
, "vnc"))
574 return ZEBRA_ROUTE_VNC
;
575 else if (strmatch(s
, "vnc-direct"))
576 return ZEBRA_ROUTE_VNC_DIRECT
;
577 else if (strmatch(s
, "nhrp"))
578 return ZEBRA_ROUTE_NHRP
;
579 else if (strmatch(s
, "babel"))
580 return ZEBRA_ROUTE_BABEL
;
581 else if (strmatch(s
, "sharp"))
582 return ZEBRA_ROUTE_SHARP
;
583 else if (strmatch(s
, "openfabric"))
584 return ZEBRA_ROUTE_OPENFABRIC
;
589 void zlog_hexdump(const void *mem
, size_t len
)
592 const uint8_t *src
= mem
;
593 const uint8_t *end
= src
+ len
;
596 zlog_debug("%016lx: (zero length / no data)", (long)src
);
606 const uint8_t *lineend
= src
+ 8;
607 unsigned line_bytes
= 0;
609 bprintfrr(&fb
, "%016lx: ", (long)src
);
611 while (src
< lineend
&& src
< end
) {
612 bprintfrr(&fb
, "%02x ", *src
++);
616 bprintfrr(&fb
, "%*s", (8 - line_bytes
) * 3, "");
619 while (src
< lineend
&& src
< end
&& fb
.pos
< fb
.buf
+ fb
.len
) {
620 uint8_t byte
= *src
++;
628 zlog_debug("%.*s", (int)(fb
.pos
- fb
.buf
), fb
.buf
);
632 const char *zlog_sanitize(char *buf
, size_t bufsz
, const void *in
, size_t inlen
)
634 const char *inbuf
= in
;
635 char *pos
= buf
, *end
= buf
+ bufsz
;
636 const char *iend
= inbuf
+ inlen
;
638 memset(buf
, 0, bufsz
);
639 for (; inbuf
< iend
; inbuf
++) {
640 /* don't write partial escape sequence */
645 snprintf(pos
, end
- pos
, "\\n");
646 else if (*inbuf
== '\r')
647 snprintf(pos
, end
- pos
, "\\r");
648 else if (*inbuf
== '\t')
649 snprintf(pos
, end
- pos
, "\\t");
650 else if (*inbuf
< ' ' || *inbuf
== '"' || *inbuf
>= 127)
651 snprintf(pos
, end
- pos
, "\\x%02hhx", *inbuf
);