3 * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #define FRR_DEFINE_DESC_TABLE
30 #include "lib_errors.h"
33 #include "frr_pthread.h"
36 #define UNW_LOCAL_ONLY
37 #include <libunwind.h>
42 * Looks up a message in a message list by key.
44 * If the message is not found, returns the provided error message.
46 * Terminates when it hits a struct message that's all zeros.
48 * @param mz the message list
49 * @param kz the message key
50 * @param nf the message to return if not found
53 const char *lookup_msg(const struct message
*mz
, int kz
, const char *nf
)
55 static struct message nt
= {0};
56 const char *rz
= nf
? nf
: "(no message found)";
57 const struct message
*pnt
;
58 for (pnt
= mz
; memcmp(pnt
, &nt
, sizeof(struct message
)); pnt
++)
60 rz
= pnt
->str
? pnt
->str
: rz
;
66 /* For time string format. */
67 size_t frr_timestamp(int timestamp_precision
, char *buf
, size_t buflen
)
76 gettimeofday(&clock
, NULL
);
78 /* first, we update the cache if the time has changed */
79 if (cache
.last
!= clock
.tv_sec
) {
81 cache
.last
= clock
.tv_sec
;
82 localtime_r(&cache
.last
, &tm
);
83 cache
.len
= strftime(cache
.buf
, sizeof(cache
.buf
),
84 "%Y/%m/%d %H:%M:%S", &tm
);
86 /* note: it's not worth caching the subsecond part, because
87 chances are that back-to-back calls are not sufficiently close
89 for the clock not to have ticked forward */
91 if (buflen
> cache
.len
) {
92 memcpy(buf
, cache
.buf
, cache
.len
);
93 if ((timestamp_precision
> 0)
94 && (buflen
> cache
.len
+ 1 + timestamp_precision
)) {
95 /* should we worry about locale issues? */
96 static const int divisor
[] = {0, 100000, 10000, 1000,
99 char *p
= buf
+ cache
.len
+ 1
100 + (prec
= timestamp_precision
);
103 /* this is unlikely to happen, but protect anyway */
108 clock
.tv_usec
/= divisor
[prec
];
110 *p
-- = '0' + (clock
.tv_usec
% 10);
112 } while (--prec
> 0);
114 return cache
.len
+ 1 + timestamp_precision
;
116 buf
[cache
.len
] = '\0';
127 * NB: only AS-Safe (async-signal) functions can be used here!
130 /* Note: the goal here is to use only async-signal-safe functions. */
131 void zlog_signal(int signo
, const char *action
, void *siginfo_v
,
132 void *program_counter
)
134 siginfo_t
*siginfo
= siginfo_v
;
136 char buf
[sizeof("DEFAULT: Received signal S at T (si_addr 0xP, PC 0xP); aborting...")
138 struct fbuf fb
= { .buf
= buf
, .pos
= buf
, .len
= sizeof(buf
) };
142 bprintfrr(&fb
, "Received signal %d at %lld", signo
, (long long)now
);
144 bprintfrr(&fb
, " (si_addr 0x%tx, PC 0x%tx)",
145 (ptrdiff_t)siginfo
->si_addr
,
146 (ptrdiff_t)program_counter
);
148 bprintfrr(&fb
, " (si_addr 0x%tx)",
149 (ptrdiff_t)siginfo
->si_addr
);
150 bprintfrr(&fb
, "; %s\n", action
);
152 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
154 zlog_backtrace_sigsafe(LOG_CRIT
, program_counter
);
159 tc
= pthread_getspecific(thread_current
);
162 bprintfrr(&fb
, "no thread information available\n");
164 bprintfrr(&fb
, "in thread %s scheduled from %s:%d %s()\n",
165 tc
->xref
->funcname
, tc
->xref
->xref
.file
,
166 tc
->xref
->xref
.line
, tc
->xref
->xref
.func
);
168 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
171 /* Log a backtrace using only async-signal-safe functions.
172 Needs to be enhanced to support syslog logging. */
173 void zlog_backtrace_sigsafe(int priority
, void *program_counter
)
175 #ifdef HAVE_LIBUNWIND
177 struct fbuf fb
= { .buf
= buf
, .len
= sizeof(buf
) };
180 unw_word_t ip
, off
, sp
;
183 memset(&uc
, 0, sizeof(uc
));
184 memset(&cursor
, 0, sizeof(cursor
));
187 unw_init_local(&cursor
, &uc
);
188 while (unw_step(&cursor
) > 0) {
189 char name
[128] = "?";
191 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
192 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
194 if (!unw_get_proc_name(&cursor
, buf
, sizeof(buf
), &off
))
195 snprintfrr(name
, sizeof(name
), "%s+%#lx",
199 if (unw_is_signal_frame(&cursor
))
200 bprintfrr(&fb
, " ---- signal ----\n");
201 bprintfrr(&fb
, "%-30s %16lx %16lx", name
, (long)ip
, (long)sp
);
202 if (dladdr((void *)ip
, &dlinfo
))
203 bprintfrr(&fb
, " %s (mapped at %p)",
204 dlinfo
.dli_fname
, dlinfo
.dli_fbase
);
205 bprintfrr(&fb
, "\n");
206 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
208 #elif defined(HAVE_GLIBC_BACKTRACE)
212 struct fbuf fb
= { .buf
= buf
, .pos
= buf
, .len
= sizeof(buf
) };
215 size
= backtrace(array
, array_size(array
));
216 if (size
<= 0 || (size_t)size
> array_size(array
))
219 bprintfrr(&fb
, "Backtrace for %d stack frames:", size
);
220 zlog_sigsafe(fb
.pos
, fb
.buf
- fb
.pos
);
222 bt
= backtrace_symbols(array
, size
);
224 for (i
= 0; i
< size
; i
++) {
227 bprintfrr(&fb
, "%s", bt
[i
]);
229 bprintfrr(&fb
, "[bt %d] 0x%tx", i
,
230 (ptrdiff_t)(array
[i
]));
231 zlog_sigsafe(fb
.buf
, fb
.pos
- fb
.buf
);
235 #endif /* HAVE_STRACK_TRACE */
238 void zlog_backtrace(int priority
)
240 #ifdef HAVE_LIBUNWIND
244 unw_word_t ip
, off
, sp
;
248 unw_init_local(&cursor
, &uc
);
249 zlog(priority
, "Backtrace:");
250 while (unw_step(&cursor
) > 0) {
251 char name
[128] = "?";
253 unw_get_reg(&cursor
, UNW_REG_IP
, &ip
);
254 unw_get_reg(&cursor
, UNW_REG_SP
, &sp
);
256 if (unw_is_signal_frame(&cursor
))
257 zlog(priority
, " ---- signal ----");
259 if (!unw_get_proc_name(&cursor
, buf
, sizeof(buf
), &off
))
260 snprintf(name
, sizeof(name
), "%s+%#lx",
263 if (dladdr((void *)ip
, &dlinfo
))
264 zlog(priority
, "%-30s %16lx %16lx %s (mapped at %p)",
265 name
, (long)ip
, (long)sp
,
266 dlinfo
.dli_fname
, dlinfo
.dli_fbase
);
268 zlog(priority
, "%-30s %16lx %16lx",
269 name
, (long)ip
, (long)sp
);
271 #elif defined(HAVE_GLIBC_BACKTRACE)
276 size
= backtrace(array
, array_size(array
));
277 if (size
<= 0 || (size_t)size
> array_size(array
)) {
280 "Cannot get backtrace, returned invalid # of frames %d (valid range is between 1 and %lu)",
281 size
, (unsigned long)(array_size(array
)));
284 zlog(priority
, "Backtrace for %d stack frames:", size
);
285 if (!(strings
= backtrace_symbols(array
, size
))) {
286 flog_err_sys(EC_LIB_SYSTEM_CALL
,
287 "Cannot get backtrace symbols (out of memory?)");
288 for (i
= 0; i
< size
; i
++)
289 zlog(priority
, "[bt %d] %p", i
, array
[i
]);
291 for (i
= 0; i
< size
; i
++)
292 zlog(priority
, "[bt %d] %s", i
, strings
[i
]);
295 #else /* !HAVE_GLIBC_BACKTRACE && !HAVE_LIBUNWIND */
296 zlog(priority
, "No backtrace available on this platform.");
300 void zlog_thread_info(int log_level
)
303 tc
= pthread_getspecific(thread_current
);
307 "Current thread function %s, scheduled from file %s, line %u in %s()",
308 tc
->xref
->funcname
, tc
->xref
->xref
.file
,
309 tc
->xref
->xref
.line
, tc
->xref
->xref
.func
);
311 zlog(log_level
, "Current thread not known/applicable");
314 void memory_oom(size_t size
, const char *name
)
317 "out of memory: failed to allocate %zu bytes for %s object",
319 zlog_backtrace(LOG_CRIT
);
320 log_memstats(stderr
, "log");
324 /* Wrapper around strerror to handle case where it returns NULL. */
325 const char *safe_strerror(int errnum
)
327 const char *s
= strerror(errnum
);
328 return (s
!= NULL
) ? s
: "Unknown error";
331 #define DESC_ENTRY(T) [(T)] = { (T), (#T), '\0' }
332 static const struct zebra_desc_table command_types
[] = {
333 DESC_ENTRY(ZEBRA_INTERFACE_ADD
),
334 DESC_ENTRY(ZEBRA_INTERFACE_DELETE
),
335 DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_ADD
),
336 DESC_ENTRY(ZEBRA_INTERFACE_ADDRESS_DELETE
),
337 DESC_ENTRY(ZEBRA_INTERFACE_UP
),
338 DESC_ENTRY(ZEBRA_INTERFACE_DOWN
),
339 DESC_ENTRY(ZEBRA_INTERFACE_SET_MASTER
),
340 DESC_ENTRY(ZEBRA_ROUTE_ADD
),
341 DESC_ENTRY(ZEBRA_ROUTE_DELETE
),
342 DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER
),
343 DESC_ENTRY(ZEBRA_REDISTRIBUTE_ADD
),
344 DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE
),
345 DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
),
346 DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE
),
347 DESC_ENTRY(ZEBRA_ROUTER_ID_ADD
),
348 DESC_ENTRY(ZEBRA_ROUTER_ID_DELETE
),
349 DESC_ENTRY(ZEBRA_ROUTER_ID_UPDATE
),
350 DESC_ENTRY(ZEBRA_HELLO
),
351 DESC_ENTRY(ZEBRA_CAPABILITIES
),
352 DESC_ENTRY(ZEBRA_NEXTHOP_REGISTER
),
353 DESC_ENTRY(ZEBRA_NEXTHOP_UNREGISTER
),
354 DESC_ENTRY(ZEBRA_NEXTHOP_UPDATE
),
355 DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_ADD
),
356 DESC_ENTRY(ZEBRA_INTERFACE_NBR_ADDRESS_DELETE
),
357 DESC_ENTRY(ZEBRA_INTERFACE_BFD_DEST_UPDATE
),
358 DESC_ENTRY(ZEBRA_BFD_DEST_REGISTER
),
359 DESC_ENTRY(ZEBRA_BFD_DEST_DEREGISTER
),
360 DESC_ENTRY(ZEBRA_BFD_DEST_UPDATE
),
361 DESC_ENTRY(ZEBRA_BFD_DEST_REPLAY
),
362 DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_ADD
),
363 DESC_ENTRY(ZEBRA_REDISTRIBUTE_ROUTE_DEL
),
364 DESC_ENTRY(ZEBRA_VRF_UNREGISTER
),
365 DESC_ENTRY(ZEBRA_VRF_ADD
),
366 DESC_ENTRY(ZEBRA_VRF_DELETE
),
367 DESC_ENTRY(ZEBRA_VRF_LABEL
),
368 DESC_ENTRY(ZEBRA_INTERFACE_VRF_UPDATE
),
369 DESC_ENTRY(ZEBRA_BFD_CLIENT_REGISTER
),
370 DESC_ENTRY(ZEBRA_BFD_CLIENT_DEREGISTER
),
371 DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV
),
372 DESC_ENTRY(ZEBRA_INTERFACE_DISABLE_RADV
),
373 DESC_ENTRY(ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB
),
374 DESC_ENTRY(ZEBRA_INTERFACE_LINK_PARAMS
),
375 DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD
),
376 DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE
),
377 DESC_ENTRY(ZEBRA_MPLS_LABELS_REPLACE
),
378 DESC_ENTRY(ZEBRA_SR_POLICY_SET
),
379 DESC_ENTRY(ZEBRA_SR_POLICY_DELETE
),
380 DESC_ENTRY(ZEBRA_SR_POLICY_NOTIFY_STATUS
),
381 DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS
),
382 DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT
),
383 DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC
),
384 DESC_ENTRY(ZEBRA_GET_LABEL_CHUNK
),
385 DESC_ENTRY(ZEBRA_RELEASE_LABEL_CHUNK
),
386 DESC_ENTRY(ZEBRA_FEC_REGISTER
),
387 DESC_ENTRY(ZEBRA_FEC_UNREGISTER
),
388 DESC_ENTRY(ZEBRA_FEC_UPDATE
),
389 DESC_ENTRY(ZEBRA_ADVERTISE_ALL_VNI
),
390 DESC_ENTRY(ZEBRA_ADVERTISE_DEFAULT_GW
),
391 DESC_ENTRY(ZEBRA_ADVERTISE_SVI_MACIP
),
392 DESC_ENTRY(ZEBRA_ADVERTISE_SUBNET
),
393 DESC_ENTRY(ZEBRA_LOCAL_ES_ADD
),
394 DESC_ENTRY(ZEBRA_LOCAL_ES_DEL
),
395 DESC_ENTRY(ZEBRA_REMOTE_ES_VTEP_ADD
),
396 DESC_ENTRY(ZEBRA_REMOTE_ES_VTEP_DEL
),
397 DESC_ENTRY(ZEBRA_LOCAL_ES_EVI_ADD
),
398 DESC_ENTRY(ZEBRA_LOCAL_ES_EVI_DEL
),
399 DESC_ENTRY(ZEBRA_VNI_ADD
),
400 DESC_ENTRY(ZEBRA_VNI_DEL
),
401 DESC_ENTRY(ZEBRA_L3VNI_ADD
),
402 DESC_ENTRY(ZEBRA_L3VNI_DEL
),
403 DESC_ENTRY(ZEBRA_REMOTE_VTEP_ADD
),
404 DESC_ENTRY(ZEBRA_REMOTE_VTEP_DEL
),
405 DESC_ENTRY(ZEBRA_MACIP_ADD
),
406 DESC_ENTRY(ZEBRA_MACIP_DEL
),
407 DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_ADD
),
408 DESC_ENTRY(ZEBRA_IP_PREFIX_ROUTE_DEL
),
409 DESC_ENTRY(ZEBRA_REMOTE_MACIP_ADD
),
410 DESC_ENTRY(ZEBRA_REMOTE_MACIP_DEL
),
411 DESC_ENTRY(ZEBRA_DUPLICATE_ADDR_DETECTION
),
412 DESC_ENTRY(ZEBRA_PW_ADD
),
413 DESC_ENTRY(ZEBRA_PW_DELETE
),
414 DESC_ENTRY(ZEBRA_PW_SET
),
415 DESC_ENTRY(ZEBRA_PW_UNSET
),
416 DESC_ENTRY(ZEBRA_PW_STATUS_UPDATE
),
417 DESC_ENTRY(ZEBRA_RULE_ADD
),
418 DESC_ENTRY(ZEBRA_RULE_DELETE
),
419 DESC_ENTRY(ZEBRA_RULE_NOTIFY_OWNER
),
420 DESC_ENTRY(ZEBRA_TABLE_MANAGER_CONNECT
),
421 DESC_ENTRY(ZEBRA_GET_TABLE_CHUNK
),
422 DESC_ENTRY(ZEBRA_RELEASE_TABLE_CHUNK
),
423 DESC_ENTRY(ZEBRA_IPSET_CREATE
),
424 DESC_ENTRY(ZEBRA_IPSET_DESTROY
),
425 DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD
),
426 DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE
),
427 DESC_ENTRY(ZEBRA_IPSET_NOTIFY_OWNER
),
428 DESC_ENTRY(ZEBRA_IPSET_ENTRY_NOTIFY_OWNER
),
429 DESC_ENTRY(ZEBRA_IPTABLE_ADD
),
430 DESC_ENTRY(ZEBRA_IPTABLE_DELETE
),
431 DESC_ENTRY(ZEBRA_IPTABLE_NOTIFY_OWNER
),
432 DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL
),
433 DESC_ENTRY(ZEBRA_VXLAN_SG_ADD
),
434 DESC_ENTRY(ZEBRA_VXLAN_SG_DEL
),
435 DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY
),
436 DESC_ENTRY(ZEBRA_MLAG_PROCESS_UP
),
437 DESC_ENTRY(ZEBRA_MLAG_PROCESS_DOWN
),
438 DESC_ENTRY(ZEBRA_MLAG_CLIENT_REGISTER
),
439 DESC_ENTRY(ZEBRA_MLAG_CLIENT_UNREGISTER
),
440 DESC_ENTRY(ZEBRA_MLAG_FORWARD_MSG
),
441 DESC_ENTRY(ZEBRA_ERROR
),
442 DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES
),
443 DESC_ENTRY(ZEBRA_OPAQUE_MESSAGE
),
444 DESC_ENTRY(ZEBRA_OPAQUE_REGISTER
),
445 DESC_ENTRY(ZEBRA_OPAQUE_UNREGISTER
),
446 DESC_ENTRY(ZEBRA_NEIGH_DISCOVER
),
447 DESC_ENTRY(ZEBRA_NHG_ADD
),
448 DESC_ENTRY(ZEBRA_NHG_DEL
),
449 DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER
),
450 DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST
),
451 DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY
),
452 DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_ADD
),
453 DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL
),
454 DESC_ENTRY(ZEBRA_NHRP_NEIGH_ADDED
),
455 DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED
),
456 DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET
),
457 DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER
),
458 DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER
),
459 DESC_ENTRY(ZEBRA_NEIGH_IP_ADD
),
460 DESC_ENTRY(ZEBRA_NEIGH_IP_DEL
),
461 DESC_ENTRY(ZEBRA_CONFIGURE_ARP
),
462 DESC_ENTRY(ZEBRA_GRE_GET
),
463 DESC_ENTRY(ZEBRA_GRE_UPDATE
),
464 DESC_ENTRY(ZEBRA_GRE_SOURCE_SET
)};
467 static const struct zebra_desc_table unknown
= {0, "unknown", '?'};
469 static const struct zebra_desc_table
*zroute_lookup(unsigned int zroute
)
473 if (zroute
>= array_size(route_types
)) {
474 flog_err(EC_LIB_DEVELOPMENT
, "unknown zebra route type: %u",
478 if (zroute
== route_types
[zroute
].type
)
479 return &route_types
[zroute
];
480 for (i
= 0; i
< array_size(route_types
); i
++) {
481 if (zroute
== route_types
[i
].type
) {
483 "internal error: route type table out of order while searching for %u, please notify developers",
485 return &route_types
[i
];
488 flog_err(EC_LIB_DEVELOPMENT
,
489 "internal error: cannot find route type %u in table!", zroute
);
493 const char *zebra_route_string(unsigned int zroute
)
495 return zroute_lookup(zroute
)->string
;
498 char zebra_route_char(unsigned int zroute
)
500 return zroute_lookup(zroute
)->chr
;
503 const char *zserv_command_string(unsigned int command
)
505 if (command
>= array_size(command_types
)) {
506 flog_err(EC_LIB_DEVELOPMENT
, "unknown zserv command type: %u",
508 return unknown
.string
;
510 return command_types
[command
].string
;
513 int proto_name2num(const char *s
)
517 for (i
= 0; i
< array_size(route_types
); ++i
)
518 if (strcasecmp(s
, route_types
[i
].string
) == 0)
519 return route_types
[i
].type
;
523 int proto_redistnum(int afi
, const char *s
)
529 if (strmatch(s
, "kernel"))
530 return ZEBRA_ROUTE_KERNEL
;
531 else if (strmatch(s
, "connected"))
532 return ZEBRA_ROUTE_CONNECT
;
533 else if (strmatch(s
, "static"))
534 return ZEBRA_ROUTE_STATIC
;
535 else if (strmatch(s
, "rip"))
536 return ZEBRA_ROUTE_RIP
;
537 else if (strmatch(s
, "eigrp"))
538 return ZEBRA_ROUTE_EIGRP
;
539 else if (strmatch(s
, "ospf"))
540 return ZEBRA_ROUTE_OSPF
;
541 else if (strmatch(s
, "isis"))
542 return ZEBRA_ROUTE_ISIS
;
543 else if (strmatch(s
, "bgp"))
544 return ZEBRA_ROUTE_BGP
;
545 else if (strmatch(s
, "table"))
546 return ZEBRA_ROUTE_TABLE
;
547 else if (strmatch(s
, "vnc"))
548 return ZEBRA_ROUTE_VNC
;
549 else if (strmatch(s
, "vnc-direct"))
550 return ZEBRA_ROUTE_VNC_DIRECT
;
551 else if (strmatch(s
, "nhrp"))
552 return ZEBRA_ROUTE_NHRP
;
553 else if (strmatch(s
, "babel"))
554 return ZEBRA_ROUTE_BABEL
;
555 else if (strmatch(s
, "sharp"))
556 return ZEBRA_ROUTE_SHARP
;
557 else if (strmatch(s
, "openfabric"))
558 return ZEBRA_ROUTE_OPENFABRIC
;
560 if (afi
== AFI_IP6
) {
561 if (strmatch(s
, "kernel"))
562 return ZEBRA_ROUTE_KERNEL
;
563 else if (strmatch(s
, "connected"))
564 return ZEBRA_ROUTE_CONNECT
;
565 else if (strmatch(s
, "static"))
566 return ZEBRA_ROUTE_STATIC
;
567 else if (strmatch(s
, "ripng"))
568 return ZEBRA_ROUTE_RIPNG
;
569 else if (strmatch(s
, "ospf6"))
570 return ZEBRA_ROUTE_OSPF6
;
571 else if (strmatch(s
, "isis"))
572 return ZEBRA_ROUTE_ISIS
;
573 else if (strmatch(s
, "bgp"))
574 return ZEBRA_ROUTE_BGP
;
575 else if (strmatch(s
, "table"))
576 return ZEBRA_ROUTE_TABLE
;
577 else if (strmatch(s
, "vnc"))
578 return ZEBRA_ROUTE_VNC
;
579 else if (strmatch(s
, "vnc-direct"))
580 return ZEBRA_ROUTE_VNC_DIRECT
;
581 else if (strmatch(s
, "nhrp"))
582 return ZEBRA_ROUTE_NHRP
;
583 else if (strmatch(s
, "babel"))
584 return ZEBRA_ROUTE_BABEL
;
585 else if (strmatch(s
, "sharp"))
586 return ZEBRA_ROUTE_SHARP
;
587 else if (strmatch(s
, "openfabric"))
588 return ZEBRA_ROUTE_OPENFABRIC
;
593 void zlog_hexdump(const void *mem
, size_t len
)
596 const uint8_t *src
= mem
;
597 const uint8_t *end
= src
+ len
;
600 zlog_debug("%016lx: (zero length / no data)", (long)src
);
610 const uint8_t *lineend
= src
+ 8;
611 unsigned line_bytes
= 0;
613 bprintfrr(&fb
, "%016lx: ", (long)src
);
615 while (src
< lineend
&& src
< end
) {
616 bprintfrr(&fb
, "%02x ", *src
++);
620 bprintfrr(&fb
, "%*s", (8 - line_bytes
) * 3, "");
623 while (src
< lineend
&& src
< end
&& fb
.pos
< fb
.buf
+ fb
.len
) {
624 uint8_t byte
= *src
++;
632 zlog_debug("%.*s", (int)(fb
.pos
- fb
.buf
), fb
.buf
);
636 const char *zlog_sanitize(char *buf
, size_t bufsz
, const void *in
, size_t inlen
)
638 const char *inbuf
= in
;
639 char *pos
= buf
, *end
= buf
+ bufsz
;
640 const char *iend
= inbuf
+ inlen
;
642 memset(buf
, 0, bufsz
);
643 for (; inbuf
< iend
; inbuf
++) {
644 /* don't write partial escape sequence */
649 snprintf(pos
, end
- pos
, "\\n");
650 else if (*inbuf
== '\r')
651 snprintf(pos
, end
- pos
, "\\r");
652 else if (*inbuf
== '\t')
653 snprintf(pos
, end
- pos
, "\\t");
654 else if (*inbuf
< ' ' || *inbuf
== '"' || *inbuf
>= 127)
655 snprintf(pos
, end
- pos
, "\\x%02hhx", *inbuf
);