summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c22
-rw-r--r--lib/command.h2
-rw-r--r--lib/distribute.c10
-rw-r--r--lib/ferr.c2
-rw-r--r--lib/hash.c4
-rw-r--r--lib/hash.h7
-rw-r--r--lib/if_rmap.c2
-rw-r--r--lib/log.c81
-rw-r--r--lib/qobj.c2
-rw-r--r--lib/routemap.c16
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/table.c2
-rw-r--r--lib/thread.c4
-rw-r--r--lib/vrf.c2
-rw-r--r--lib/vty.c28
-rw-r--r--lib/vty.h7
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;
diff --git a/lib/log.c b/lib/log.c
index 10cb2cd8a4..5cc303daf0 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -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");
diff --git a/lib/vrf.c b/lib/vrf.c
index eca9913e1f..498aef4580 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -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;
diff --git a/lib/vty.c b/lib/vty.c
index f812dd4279..a73cc23b97 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -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);
diff --git a/lib/vty.h b/lib/vty.h
index b55abf2204..efe91a568b 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -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;