diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/command.c | 22 | ||||
| -rw-r--r-- | lib/command.h | 2 | ||||
| -rw-r--r-- | lib/distribute.c | 10 | ||||
| -rw-r--r-- | lib/ferr.c | 2 | ||||
| -rw-r--r-- | lib/hash.c | 4 | ||||
| -rw-r--r-- | lib/hash.h | 7 | ||||
| -rw-r--r-- | lib/if_rmap.c | 2 | ||||
| -rw-r--r-- | lib/log.c | 81 | ||||
| -rw-r--r-- | lib/qobj.c | 2 | ||||
| -rw-r--r-- | lib/routemap.c | 16 | ||||
| -rw-r--r-- | lib/subdir.am | 2 | ||||
| -rw-r--r-- | lib/table.c | 2 | ||||
| -rw-r--r-- | lib/thread.c | 4 | ||||
| -rw-r--r-- | lib/vrf.c | 2 | ||||
| -rw-r--r-- | lib/vty.c | 28 | ||||
| -rw-r--r-- | lib/vty.h | 7 |
16 files changed, 144 insertions, 49 deletions
diff --git a/lib/command.c b/lib/command.c index 60c5f4e75b..839c37b102 100644 --- a/lib/command.c +++ b/lib/command.c @@ -337,7 +337,7 @@ static unsigned int cmd_hash_key(void *p) return jhash(p, size, 0); } -static int cmd_hash_cmp(const void *a, const void *b) +static bool cmd_hash_cmp(const void *a, const void *b) { return a == b; } @@ -1281,7 +1281,8 @@ int cmd_execute(struct vty *vty, const char *cmd, * as to why no command could be executed. */ int command_config_read_one_line(struct vty *vty, - const struct cmd_element **cmd, int use_daemon) + const struct cmd_element **cmd, + uint32_t line_num, int use_daemon) { vector vline; int saved_node; @@ -1322,8 +1323,16 @@ int command_config_read_one_line(struct vty *vty, } } - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ); + if (ret != CMD_SUCCESS && ret != CMD_WARNING) { + struct vty_error *ve = XCALLOC(MTYPE_TMP, sizeof(*ve)); + + memcpy(ve->error_buf, vty->buf, VTY_BUFSIZ); + ve->line_num = line_num; + if (!vty->error) + vty->error = list_new(); + + listnode_add(vty->error, ve); + } cmd_free_strvec(vline); @@ -1337,10 +1346,9 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num) *line_num = 0; while (fgets(vty->buf, VTY_BUFSIZ, fp)) { - if (!error_ret) - ++(*line_num); + ++(*line_num); - ret = command_config_read_one_line(vty, NULL, 0); + ret = command_config_read_one_line(vty, NULL, *line_num, 0); if (ret != CMD_SUCCESS && ret != CMD_WARNING && ret != CMD_ERR_NOTHING_TODO) diff --git a/lib/command.h b/lib/command.h index 8e51641b88..fbff1e67f4 100644 --- a/lib/command.h +++ b/lib/command.h @@ -419,7 +419,7 @@ extern char **cmd_complete_command(vector, struct vty *, int *status); extern const char *cmd_prompt(enum node_type); extern int command_config_read_one_line(struct vty *vty, const struct cmd_element **, - int use_config_node); + uint32_t line_num, int use_config_node); extern int config_from_file(struct vty *, FILE *, unsigned int *line_num); extern enum node_type node_parent(enum node_type); /* diff --git a/lib/distribute.c b/lib/distribute.c index 25fcd92580..0f1d666aeb 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -140,15 +140,15 @@ static unsigned int distribute_hash_make(void *arg) /* If two distribute-list have same value then return 1 else return 0. This function is used by hash package. */ -static int distribute_cmp(const struct distribute *dist1, +static bool distribute_cmp(const struct distribute *dist1, const struct distribute *dist2) { if (dist1->ifname && dist2->ifname) if (strcmp(dist1->ifname, dist2->ifname) == 0) - return 1; + return true; if (!dist1->ifname && !dist2->ifname) - return 1; - return 0; + return true; + return false; } /* Set access-list name to the distribute list. */ @@ -521,7 +521,7 @@ void distribute_list_init(int node) { disthash = hash_create( distribute_hash_make, - (int (*)(const void *, const void *))distribute_cmp, NULL); + (bool (*)(const void *, const void *))distribute_cmp, NULL); /* vtysh command-extraction doesn't grok install_element(node, ) */ if (node == RIP_NODE) { diff --git a/lib/ferr.c b/lib/ferr.c index bf89cc7f46..e18597afb0 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -64,7 +64,7 @@ static void err_key_fini(void) pthread_mutex_t refs_mtx = PTHREAD_MUTEX_INITIALIZER; struct hash *refs; -static int ferr_hash_cmp(const void *a, const void *b) +static bool ferr_hash_cmp(const void *a, const void *b) { const struct log_ref *f_a = a; const struct log_ref *f_b = b; diff --git a/lib/hash.c b/lib/hash.c index 114522a75a..641c751368 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -38,7 +38,7 @@ static struct list *_hashes; struct hash *hash_create_size(unsigned int size, unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), + bool (*hash_cmp)(const void *, const void *), const char *name) { struct hash *hash; @@ -67,7 +67,7 @@ struct hash *hash_create_size(unsigned int size, } struct hash *hash_create(unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), + bool (*hash_cmp)(const void *, const void *), const char *name) { return hash_create_size(HASH_INITIAL_SIZE, hash_key, hash_cmp, name); diff --git a/lib/hash.h b/lib/hash.h index 2b4ea48f38..45ae6ce60a 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -73,7 +73,7 @@ struct hash { unsigned int (*hash_key)(void *); /* Data compare function. */ - int (*hash_cmp)(const void *, const void *); + bool (*hash_cmp)(const void *, const void *); /* Backet alloc. */ unsigned long count; @@ -115,7 +115,7 @@ struct hash { * a new hash table */ extern struct hash *hash_create(unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), + bool (*hash_cmp)(const void *, const void *), const char *name); /* @@ -150,7 +150,8 @@ extern struct hash *hash_create(unsigned int (*hash_key)(void *), */ extern struct hash * hash_create_size(unsigned int size, unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), const char *name); + bool (*hash_cmp)(const void *, const void *), + const char *name); /* * Retrieve or insert data from / into a hash table. diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 2c686ecb85..108ab7ec6b 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -117,7 +117,7 @@ static unsigned int if_rmap_hash_make(void *data) return string_hash_make(if_rmap->ifname); } -static int if_rmap_hash_cmp(const void *arg1, const void *arg2) +static bool if_rmap_hash_cmp(const void *arg1, const void *arg2) { const struct if_rmap *if_rmap1 = arg1; const struct if_rmap *if_rmap2 = arg2; @@ -38,6 +38,12 @@ #include <ucontext.h> #endif +#ifdef HAVE_LIBUNWIND +#define UNW_LOCAL_ONLY +#include <libunwind.h> +#include <dlfcn.h> +#endif + DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging") static int logfile_fd = -1; /* Used in signal handler. */ @@ -313,7 +319,9 @@ static char *num_append(char *s, int len, unsigned long x) return str_append(s, len, t); } -#if defined(SA_SIGINFO) || defined(HAVE_STACK_TRACE) +#if defined(SA_SIGINFO) \ + || defined(HAVE_PRINTSTACK) \ + || defined(HAVE_GLIBC_BACKTRACE) static char *hex_append(char *s, int len, unsigned long x) { char buf[30]; @@ -533,7 +541,37 @@ void zlog_signal(int signo, const char *action Needs to be enhanced to support syslog logging. */ void zlog_backtrace_sigsafe(int priority, void *program_counter) { -#ifdef HAVE_STACK_TRACE +#ifdef HAVE_LIBUNWIND + char buf[100]; + unw_cursor_t cursor; + unw_context_t uc; + unw_word_t ip, off, sp; + Dl_info dlinfo; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + while (unw_step(&cursor) > 0) { + char name[128] = "?"; + + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + + if (unw_is_signal_frame(&cursor)) + dprintf(2, " ---- signal ----\n"); + + if (!unw_get_proc_name(&cursor, buf, sizeof(buf), &off)) { + snprintf(name, sizeof(name), "%s+%#lx", + buf, (long)off); + } + dprintf(2, "%-30s %16lx %16lx", name, (long)ip, (long)sp); + if (dladdr((void *)ip, &dlinfo)) { + dprintf(2, " %s (mapped at %p)", + dlinfo.dli_fname, dlinfo.dli_fbase); + } + dprintf(2, "\n"); + + } +#elif defined(HAVE_GLIBC_BACKTRACE) || defined(HAVE_PRINTSTACK) static const char pclabel[] = "Program counter: "; void *array[64]; int size; @@ -624,9 +662,38 @@ void zlog_backtrace_sigsafe(int priority, void *program_counter) void zlog_backtrace(int priority) { -#ifndef HAVE_GLIBC_BACKTRACE - zlog(priority, "No backtrace available on this platform."); -#else +#ifdef HAVE_LIBUNWIND + char buf[100]; + unw_cursor_t cursor; + unw_context_t uc; + unw_word_t ip, off, sp; + Dl_info dlinfo; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + zlog(priority, "Backtrace:"); + while (unw_step(&cursor) > 0) { + char name[128] = "?"; + + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + + if (unw_is_signal_frame(&cursor)) + zlog(priority, " ---- signal ----"); + + if (!unw_get_proc_name(&cursor, buf, sizeof(buf), &off)) + snprintf(name, sizeof(name), "%s+%#lx", + buf, (long)off); + + if (dladdr((void *)ip, &dlinfo)) + zlog(priority, "%-30s %16lx %16lx %s (mapped at %p)", + name, (long)ip, (long)sp, + dlinfo.dli_fname, dlinfo.dli_fbase); + else + zlog(priority, "%-30s %16lx %16lx", + name, (long)ip, (long)sp); + } +#elif defined(HAVE_GLIBC_BACKTRACE) void *array[20]; int size, i; char **strings; @@ -651,7 +718,9 @@ void zlog_backtrace(int priority) zlog(priority, "[bt %d] %s", i, strings[i]); free(strings); } -#endif /* HAVE_GLIBC_BACKTRACE */ +#else /* !HAVE_GLIBC_BACKTRACE && !HAVE_LIBUNWIND */ + zlog(priority, "No backtrace available on this platform."); +#endif } void zlog(int priority, const char *format, ...) diff --git a/lib/qobj.c b/lib/qobj.c index c3f1a27c82..811645f3c3 100644 --- a/lib/qobj.c +++ b/lib/qobj.c @@ -36,7 +36,7 @@ static unsigned int qobj_key(void *data) return (unsigned int)node->nid; } -static int qobj_cmp(const void *a, const void *b) +static bool qobj_cmp(const void *a, const void *b) { const struct qobj_node *na = a, *nb = b; return na->nid == nb->nid; diff --git a/lib/routemap.c b/lib/routemap.c index 3a20ed5cda..5c6d106d83 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -631,7 +631,7 @@ static unsigned int route_map_hash_key_make(void *p) return string_hash_make(map->name); } -static int route_map_hash_cmp(const void *p1, const void *p2) +static bool route_map_hash_cmp(const void *p1, const void *p2) { const struct route_map *map1 = p1; const struct route_map *map2 = p2; @@ -639,14 +639,14 @@ static int route_map_hash_cmp(const void *p1, const void *p2) if (map1->deleted == map2->deleted) { if (map1->name && map2->name) { if (!strcmp(map1->name, map2->name)) { - return 1; + return true; } } else if (!map1->name && !map2->name) { - return 1; + return true; } } - return 0; + return false; } enum route_map_upd8_type { @@ -676,7 +676,6 @@ struct route_map_dep { struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX]; static unsigned int route_map_dep_hash_make_key(void *p); -static int route_map_dep_hash_cmp(const void *p1, const void *p2); static void route_map_clear_all_references(char *rmap_name); static void route_map_rule_delete(struct route_map_rule_list *, struct route_map_rule *); @@ -1624,12 +1623,12 @@ void route_map_event_hook(void (*func)(route_map_event_t, const char *)) } /* Routines for route map dependency lists and dependency processing */ -static int route_map_rmap_hash_cmp(const void *p1, const void *p2) +static bool route_map_rmap_hash_cmp(const void *p1, const void *p2) { return (strcmp((const char *)p1, (const char *)p2) == 0); } -static int route_map_dep_hash_cmp(const void *p1, const void *p2) +static bool route_map_dep_hash_cmp(const void *p1, const void *p2) { return (strcmp(((const struct route_map_dep *)p1)->dep_name, @@ -2251,7 +2250,8 @@ DEFUN(no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd, if (rmap_match_set_hook.no_match_ipv6_next_hop_type) return rmap_match_set_hook.no_match_ipv6_next_hop_type( - vty, index, "ipv6 next-hop type", argv[idx_word]->arg, + vty, index, "ipv6 next-hop type", + (argc <= idx_word) ? NULL : argv[idx_word]->arg, RMAP_EVENT_MATCH_DELETED); return CMD_SUCCESS; } diff --git a/lib/subdir.am b/lib/subdir.am index dd2731f74c..eef00a9086 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -3,7 +3,7 @@ # lib_LTLIBRARIES += lib/libfrr.la lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version -lib_libfrr_la_LIBADD = @LIBCAP@ +lib_libfrr_la_LIBADD = @LIBCAP@ $(UNWIND_LIBS) lib_libfrr_la_SOURCES = \ lib/agg_table.c \ diff --git a/lib/table.c b/lib/table.c index 3adb793891..0026b7692b 100644 --- a/lib/table.c +++ b/lib/table.c @@ -33,7 +33,7 @@ DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node") static void route_table_free(struct route_table *); -static int route_table_hash_cmp(const void *a, const void *b) +static bool route_table_hash_cmp(const void *a, const void *b) { const struct prefix *pa = a, *pb = b; return prefix_cmp(pa, pb) == 0; diff --git a/lib/thread.c b/lib/thread.c index 267dcd1cfc..d104c4f598 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -68,7 +68,7 @@ static unsigned int cpu_record_hash_key(struct cpu_thread_history *a) return jhash(&a->func, size, 0); } -static int cpu_record_hash_cmp(const struct cpu_thread_history *a, +static bool cpu_record_hash_cmp(const struct cpu_thread_history *a, const struct cpu_thread_history *b) { return a->func == b->func; @@ -434,7 +434,7 @@ struct thread_master *thread_master_create(const char *name) rv->cpu_record = hash_create_size( 8, (unsigned int (*)(void *))cpu_record_hash_key, - (int (*)(const void *, const void *))cpu_record_hash_cmp, + (bool (*)(const void *, const void *))cpu_record_hash_cmp, "Thread Hash"); @@ -366,7 +366,7 @@ static unsigned int vrf_hash_bitmap_key(void *data) return bit->vrf_id; } -static int vrf_hash_bitmap_cmp(const void *a, const void *b) +static bool vrf_hash_bitmap_cmp(const void *a, const void *b) { const struct vrf_bit_set *bit1 = a; const struct vrf_bit_set *bit2 = b; @@ -1695,7 +1695,6 @@ struct vty *vty_new() new->lbuf = buffer_new(0); new->obuf = buffer_new(0); /* Use default buffer size. */ new->buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); - new->error_buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); new->max = VTY_BUFSIZ; return new; @@ -2278,6 +2277,13 @@ void vty_serv_sock(const char *addr, unsigned short port, const char *path) #endif /* VTYSH */ } +static void vty_error_delete(void *arg) +{ + struct vty_error *ve = arg; + + XFREE(MTYPE_TMP, ve); +} + /* Close vty interface. Warning: call this only from functions that will be careful not to access the vty afterwards (since it has now been freed). This is safest from top-level functions (called @@ -2329,8 +2335,10 @@ void vty_close(struct vty *vty) if (vty->buf) XFREE(MTYPE_VTY, vty->buf); - if (vty->error_buf) - XFREE(MTYPE_VTY, vty->error_buf); + if (vty->error) { + vty->error->del = vty_error_delete; + list_delete(&vty->error); + } /* Check configure. */ vty_config_unlock(vty); @@ -2368,6 +2376,8 @@ static void vty_read_file(FILE *confp) { int ret; struct vty *vty; + struct vty_error *ve; + struct listnode *node; unsigned int line_num = 0; vty = vty_new(); @@ -2417,11 +2427,13 @@ static void vty_read_file(FILE *confp) break; } - nl = strchr(vty->error_buf, '\n'); - if (nl) - *nl = '\0'; - flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s", message, - line_num, vty->error_buf); + for (ALL_LIST_ELEMENTS_RO(vty->error, node, ve)) { + nl = strchr(ve->error_buf, '\n'); + if (nl) + *nl = '\0'; + flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s", + message, ve->line_num, ve->error_buf); + } } vty_close(vty); @@ -33,6 +33,11 @@ #define VTY_BUFSIZ 4096 #define VTY_MAXHIST 20 +struct vty_error { + char error_buf[VTY_BUFSIZ]; + uint32_t line_num; +}; + /* VTY struct. */ struct vty { /* File descripter of this vty. */ @@ -71,7 +76,7 @@ struct vty { char *buf; /* Command input error buffer */ - char *error_buf; + struct list *error; /* Command cursor point */ int cp; |
