summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--bgpd/subdir.am8
-rw-r--r--lib/agg_table.c2
-rw-r--r--lib/buffer.c6
-rw-r--r--lib/command_lex.l2
-rw-r--r--lib/filter.c8
-rw-r--r--lib/frrcu.c4
-rw-r--r--lib/frrcu.h2
-rw-r--r--lib/grammar_sandbox.c13
-rw-r--r--lib/if.c2
-rw-r--r--lib/linklist.c23
-rw-r--r--lib/linklist.h24
-rw-r--r--lib/memory.h23
-rw-r--r--lib/netns_linux.c7
-rw-r--r--lib/netns_other.c2
-rw-r--r--lib/nexthop_group.c2
-rw-r--r--lib/ns.h2
-rw-r--r--lib/prefix.c492
-rw-r--r--lib/prefix.h7
-rw-r--r--lib/routemap.c6
-rw-r--r--lib/sockopt.c15
-rw-r--r--lib/sockopt.h1
-rw-r--r--lib/systemd.c6
-rw-r--r--lib/systemd.h1
-rw-r--r--lib/vrf.c4
-rw-r--r--lib/vty.c2
-rw-r--r--lib/yang.c2
-rw-r--r--lib/yang.h3
-rw-r--r--tools/symalyzer.html347
-rwxr-xr-xtools/symalyzer.py383
30 files changed, 813 insertions, 590 deletions
diff --git a/.gitignore b/.gitignore
index 6cfe23e921..226dca09d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,10 @@
/Makefile
/Makefile.in
+/symalyzer_report.html
+/jquery-3.4.1.min.js
+/jquery-3.4.1.min.js.tmp
+
### autoconf/automake subdir stuff
.deps
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index b338fd4f3d..203cf779b9 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -199,14 +199,6 @@ bgpd_bgp_btoa_SOURCES = bgpd/bgp_btoa.c
bgpd_bgpd_CFLAGS = $(AM_CFLAGS)
bgpd_bgp_btoa_CFLAGS = $(AM_CFLAGS)
-if ENABLE_BGP_VNC
-bgpd_bgpd_SOURCES += bgpd/rfapi/rfapi_descriptor_rfp_utils.c
-bgpd_bgpd_CFLAGS += -Irfapi -I@top_srcdir@/$(RFPINC)
-
-bgpd_bgp_btoa_SOURCES += bgpd/rfapi/rfapi_descriptor_rfp_utils.c
-bgpd_bgp_btoa_CFLAGS += -Irfapi -I@top_srcdir@/$(RFPINC)
-endif
-
# RFPLDADD is set in bgpd/rfp-example/librfp/subdir.am
bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM)
bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM)
diff --git a/lib/agg_table.c b/lib/agg_table.c
index dad6a13d67..22b981e284 100644
--- a/lib/agg_table.c
+++ b/lib/agg_table.c
@@ -41,7 +41,7 @@ static void agg_node_destroy(route_table_delegate_t *delegate,
XFREE(MTYPE_TMP, anode);
}
-route_table_delegate_t agg_table_delegate = {
+static route_table_delegate_t agg_table_delegate = {
.create_node = agg_node_create,
.destroy_node = agg_node_destroy,
};
diff --git a/lib/buffer.c b/lib/buffer.c
index bb2cdb7e54..766b9791a5 100644
--- a/lib/buffer.c
+++ b/lib/buffer.c
@@ -114,12 +114,6 @@ char *buffer_getstr(struct buffer *b)
return s;
}
-/* Return 1 if buffer is empty. */
-int buffer_empty(struct buffer *b)
-{
- return (b->head == NULL);
-}
-
/* Clear and free all allocated data. */
void buffer_reset(struct buffer *b)
{
diff --git a/lib/command_lex.l b/lib/command_lex.l
index f361db78e9..0556605d63 100644
--- a/lib/command_lex.l
+++ b/lib/command_lex.l
@@ -85,7 +85,7 @@ RANGE \({NUMBER}[ ]?\-[ ]?{NUMBER}\)
. {return yytext[0];}
%%
-YY_BUFFER_STATE buffer;
+static YY_BUFFER_STATE buffer;
void set_lexer_string (yyscan_t *scn, const char *string)
{
diff --git a/lib/filter.c b/lib/filter.c
index ed3ffe9c67..31e25d6001 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -2498,8 +2498,8 @@ DEFUN (no_ipv6_access_list_remark_comment,
return no_ipv6_access_list_remark(self, vty, argc, argv);
}
-void config_write_access_zebra(struct vty *, struct filter *);
-void config_write_access_cisco(struct vty *, struct filter *);
+static void config_write_access_zebra(struct vty *, struct filter *);
+static void config_write_access_cisco(struct vty *, struct filter *);
/* show access-list command. */
static int filter_show(struct vty *vty, const char *name, afi_t afi)
@@ -2685,7 +2685,7 @@ DEFUN (show_ipv6_access_list_name,
return filter_show(vty, argv[idx_word]->arg, AFI_IP6);
}
-void config_write_access_cisco(struct vty *vty, struct filter *mfilter)
+static void config_write_access_cisco(struct vty *vty, struct filter *mfilter)
{
struct filter_cisco *filter;
@@ -2724,7 +2724,7 @@ void config_write_access_cisco(struct vty *vty, struct filter *mfilter)
}
}
-void config_write_access_zebra(struct vty *vty, struct filter *mfilter)
+static void config_write_access_zebra(struct vty *vty, struct filter *mfilter)
{
struct filter_zebra *filter;
struct prefix *p;
diff --git a/lib/frrcu.c b/lib/frrcu.c
index d65a4a98bf..7e6475b648 100644
--- a/lib/frrcu.c
+++ b/lib/frrcu.c
@@ -206,7 +206,7 @@ void rcu_thread_unprepare(struct rcu_thread *rt)
rcu_bump();
if (rt != &rcu_thread_main)
/* this free() happens after seqlock_release() below */
- rcu_free_internal(&_mt_RCU_THREAD, rt, rcu_head);
+ rcu_free_internal(MTYPE_RCU_THREAD, rt, rcu_head);
rcu_threads_del(&rcu_threads, rt);
seqlock_release(&rt->rcu);
@@ -269,7 +269,7 @@ static void rcu_bump(void)
* "last item is being deleted - start over" case, and then we may end
* up accessing old RCU queue items that are already free'd.
*/
- rcu_free_internal(&_mt_RCU_NEXT, rn, head_free);
+ rcu_free_internal(MTYPE_RCU_NEXT, rn, head_free);
/* Only allow the RCU sweeper to run after these 2 items are queued.
*
diff --git a/lib/frrcu.h b/lib/frrcu.h
index 8f789303cc..06d87c39f1 100644
--- a/lib/frrcu.h
+++ b/lib/frrcu.h
@@ -139,6 +139,8 @@ extern void rcu_enqueue(struct rcu_head *head, const struct rcu_action *action);
#define rcu_free(mtype, ptr, field) \
do { \
typeof(ptr) _ptr = (ptr); \
+ if (!_ptr) \
+ break; \
struct rcu_head *_rcu_head = &_ptr->field; \
static const struct rcu_action _rcu_action = { \
.type = RCUA_FREE, \
diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c
index a23874a517..8ccdbfcbc1 100644
--- a/lib/grammar_sandbox.c
+++ b/lib/grammar_sandbox.c
@@ -38,9 +38,9 @@ DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command desc")
/** headers **/
void grammar_sandbox_init(void);
-void pretty_print_graph(struct vty *vty, struct graph_node *, int, int,
- struct graph_node **, size_t);
-void init_cmdgraph(struct vty *, struct graph **);
+static void pretty_print_graph(struct vty *vty, struct graph_node *, int, int,
+ struct graph_node **, size_t);
+static void init_cmdgraph(struct vty *, struct graph **);
/** shim interface commands **/
static struct graph *nodegraph = NULL, *nodegraph_free = NULL;
@@ -491,8 +491,9 @@ void grammar_sandbox_init(void)
* @param start the node to take as the root
* @param level indent level for recursive calls, always pass 0
*/
-void pretty_print_graph(struct vty *vty, struct graph_node *start, int level,
- int desc, struct graph_node **stack, size_t stackpos)
+static void pretty_print_graph(struct vty *vty, struct graph_node *start,
+ int level, int desc, struct graph_node **stack,
+ size_t stackpos)
{
// print this node
char tokennum[32];
@@ -550,7 +551,7 @@ void pretty_print_graph(struct vty *vty, struct graph_node *start, int level,
}
/** stuff that should go in command.c + command.h */
-void init_cmdgraph(struct vty *vty, struct graph **graph)
+static void init_cmdgraph(struct vty *vty, struct graph **graph)
{
// initialize graph, add start noe
*graph = graph_new();
diff --git a/lib/if.c b/lib/if.c
index 31c1d9e8ba..c91407084e 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -58,7 +58,7 @@ DEFINE_QOBJ_TYPE(interface)
DEFINE_HOOK(if_add, (struct interface * ifp), (ifp))
DEFINE_KOOH(if_del, (struct interface * ifp), (ifp))
-struct interface_master{
+static struct interface_master{
int (*create_hook)(struct interface *ifp);
int (*up_hook)(struct interface *ifp);
int (*down_hook)(struct interface *ifp);
diff --git a/lib/linklist.c b/lib/linklist.c
index 0d1efdf3aa..272e153276 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -339,29 +339,6 @@ void list_delete_node(struct list *list, struct listnode *node)
listnode_free(node);
}
-void list_add_list(struct list *list, struct list *add)
-{
- struct listnode *n;
-
- for (n = listhead(add); n; n = listnextnode(n))
- listnode_add(list, n->data);
-}
-
-struct list *list_dup(struct list *list)
-{
- struct list *new = list_new();
- struct listnode *ln;
- void *data;
-
- new->cmp = list->cmp;
- new->del = list->del;
-
- for (ALL_LIST_ELEMENTS_RO(list, ln, data))
- listnode_add(new, data);
-
- return new;
-}
-
void list_sort(struct list *list, int (*cmp)(const void **, const void **))
{
struct listnode *ln, *nn;
diff --git a/lib/linklist.h b/lib/linklist.h
index ef914b965f..00cb9f8714 100644
--- a/lib/linklist.h
+++ b/lib/linklist.h
@@ -208,17 +208,6 @@ extern struct listnode *listnode_lookup(struct list *list, const void *data);
extern void *listnode_head(struct list *list);
/*
- * Duplicate a list.
- *
- * list
- * list to duplicate
- *
- * Returns:
- * copy of the list
- */
-extern struct list *list_dup(struct list *l);
-
-/*
* Sort a list in place.
*
* The sorting algorithm used is quicksort. Runtimes are equivalent to those of
@@ -296,19 +285,6 @@ extern void list_delete_all_node(struct list *list);
extern void list_delete_node(struct list *list, struct listnode *node);
/*
- * Append a list to an existing list.
- *
- * Runtime is O(N) where N = listcount(add).
- *
- * list
- * list to append to
- *
- * add
- * list to append
- */
-extern void list_add_list(struct list *list, struct list *add);
-
-/*
* Delete all nodes which satisfy a condition from a list.
* Deletes the node if cond function returns true for the node.
* If function ptr passed is NULL, it deletes all nodes
diff --git a/lib/memory.h b/lib/memory.h
index 8de5c4c2bf..44ea19b557 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -102,45 +102,42 @@ struct memgroup {
}
#define DECLARE_MTYPE(name) \
- extern struct memtype _mt_##name; \
- extern struct memtype *const MTYPE_##name; \
+ extern struct memtype MTYPE_##name[1]; \
/* end */
#define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \
- attr struct memtype _mt_##mname \
- __attribute__((section(".data.mtypes"))) = { \
+ attr struct memtype MTYPE_##mname[1] \
+ __attribute__((section(".data.mtypes"))) = { { \
.name = desc, \
.next = NULL, \
.n_alloc = 0, \
.size = 0, \
.ref = NULL, \
- }; \
+ } }; \
static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \
static void _mtinit_##mname(void) \
{ \
if (_mg_##group.insert == NULL) \
_mg_##group.insert = &_mg_##group.types; \
- _mt_##mname.ref = _mg_##group.insert; \
- *_mg_##group.insert = &_mt_##mname; \
- _mg_##group.insert = &_mt_##mname.next; \
+ MTYPE_##mname->ref = _mg_##group.insert; \
+ *_mg_##group.insert = MTYPE_##mname; \
+ _mg_##group.insert = &MTYPE_##mname->next; \
} \
static void _mtfini_##mname(void) __attribute__((_DESTRUCTOR(1001))); \
static void _mtfini_##mname(void) \
{ \
- if (_mt_##mname.next) \
- _mt_##mname.next->ref = _mt_##mname.ref; \
- *_mt_##mname.ref = _mt_##mname.next; \
+ if (MTYPE_##mname->next) \
+ MTYPE_##mname->next->ref = MTYPE_##mname->ref; \
+ *MTYPE_##mname->ref = MTYPE_##mname->next; \
} \
/* end */
#define DEFINE_MTYPE(group, name, desc) \
DEFINE_MTYPE_ATTR(group, name, , desc) \
- struct memtype *const MTYPE_##name = &_mt_##name; \
/* end */
#define DEFINE_MTYPE_STATIC(group, name, desc) \
DEFINE_MTYPE_ATTR(group, name, static, desc) \
- static struct memtype *const MTYPE_##name = &_mt_##name; \
/* end */
DECLARE_MGROUP(LIB)
diff --git a/lib/netns_linux.c b/lib/netns_linux.c
index 55c66fdc3d..d1a31ae35f 100644
--- a/lib/netns_linux.c
+++ b/lib/netns_linux.c
@@ -51,7 +51,7 @@ static struct ns *ns_lookup_name_internal(const char *name);
RB_GENERATE(ns_head, ns, entry, ns_compare)
-struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
+static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
static struct ns *default_ns;
static int ns_current_ns_fd;
@@ -74,7 +74,8 @@ static inline int ns_map_compare(const struct ns_map_nsid *a,
RB_HEAD(ns_map_nsid_head, ns_map_nsid);
RB_PROTOTYPE(ns_map_nsid_head, ns_map_nsid, id_entry, ns_map_compare);
RB_GENERATE(ns_map_nsid_head, ns_map_nsid, id_entry, ns_map_compare);
-struct ns_map_nsid_head ns_map_nsid_list = RB_INITIALIZER(&ns_map_nsid_list);
+static struct ns_map_nsid_head ns_map_nsid_list =
+ RB_INITIALIZER(&ns_map_nsid_list);
static ns_id_t ns_id_external_numbering;
@@ -123,7 +124,7 @@ static int have_netns(void)
}
/* Holding NS hooks */
-struct ns_master {
+static struct ns_master {
int (*ns_new_hook)(struct ns *ns);
int (*ns_delete_hook)(struct ns *ns);
int (*ns_enable_hook)(struct ns *ns);
diff --git a/lib/netns_other.c b/lib/netns_other.c
index b0aae4f8df..740d2b621e 100644
--- a/lib/netns_other.c
+++ b/lib/netns_other.c
@@ -34,7 +34,7 @@ static inline int ns_compare(const struct ns *ns, const struct ns *ns2);
RB_GENERATE(ns_head, ns, entry, ns_compare)
-struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
+static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
static inline int ns_compare(const struct ns *a, const struct ns *b)
{
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index 6d64c1ca11..0051cba625 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -797,7 +797,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
return CMD_SUCCESS;
}
-struct cmd_node nexthop_group_node = {
+static struct cmd_node nexthop_group_node = {
NH_GROUP_NODE,
"%s(config-nh-group)# ",
1
diff --git a/lib/ns.h b/lib/ns.h
index 1963b8a359..20e0a38e3b 100644
--- a/lib/ns.h
+++ b/lib/ns.h
@@ -71,8 +71,6 @@ struct ns {
RB_HEAD(ns_head, ns);
RB_PROTOTYPE(ns_head, ns, entry, ns_compare)
-extern struct ns_head ns_tree;
-
/*
* API for managing NETNS. eg from zebra daemon
* one want to manage the list of NETNS, etc...
diff --git a/lib/prefix.c b/lib/prefix.c
index e2bf3b949c..219f798dcc 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -37,394 +37,6 @@ DEFINE_MTYPE_STATIC(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec")
static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0,
0xf8, 0xfc, 0xfe, 0xff};
-static const struct in6_addr maskbytes6[] = {
- /* /0 */ {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /1 */
- {{{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /2 */
- {{{0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /3 */
- {{{0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /4 */
- {{{0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /5 */
- {{{0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /6 */
- {{{0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /7 */
- {{{0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /8 */
- {{{0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /9 */
- {{{0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /10 */
- {{{0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /11 */
- {{{0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /12 */
- {{{0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /13 */
- {{{0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /14 */
- {{{0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /15 */
- {{{0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /16 */
- {{{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /17 */
- {{{0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /18 */
- {{{0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /19 */
- {{{0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /20 */
- {{{0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /21 */
- {{{0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /22 */
- {{{0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /23 */
- {{{0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /24 */
- {{{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /25 */
- {{{0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /26 */
- {{{0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /27 */
- {{{0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /28 */
- {{{0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /29 */
- {{{0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /30 */
- {{{0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /31 */
- {{{0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /32 */
- {{{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /33 */
- {{{0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /34 */
- {{{0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /35 */
- {{{0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /36 */
- {{{0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /37 */
- {{{0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /38 */
- {{{0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /39 */
- {{{0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /40 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /41 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /42 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /43 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /44 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /45 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /46 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /47 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /48 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /49 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /50 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /51 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /52 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /53 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /54 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /55 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /56 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /57 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /58 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /59 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /60 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /61 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /62 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /63 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /64 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /65 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /66 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /67 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /68 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /69 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /70 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /71 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /72 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /73 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /74 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /75 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /76 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /77 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /78 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /79 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /80 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /81 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /82 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /83 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /84 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /85 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /86 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /87 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /88 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00, 0x00}}},
- /* /89 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x80, 0x00, 0x00, 0x00, 0x00}}},
- /* /90 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xc0, 0x00, 0x00, 0x00, 0x00}}},
- /* /91 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xe0, 0x00, 0x00, 0x00, 0x00}}},
- /* /92 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xf0, 0x00, 0x00, 0x00, 0x00}}},
- /* /93 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xf8, 0x00, 0x00, 0x00, 0x00}}},
- /* /94 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xfc, 0x00, 0x00, 0x00, 0x00}}},
- /* /95 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xfe, 0x00, 0x00, 0x00, 0x00}}},
- /* /96 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00}}},
- /* /97 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0x80, 0x00, 0x00, 0x00}}},
- /* /98 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xc0, 0x00, 0x00, 0x00}}},
- /* /99 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xe0, 0x00, 0x00, 0x00}}},
- /* /100 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf0, 0x00, 0x00, 0x00}}},
- /* /101 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xf8, 0x00, 0x00, 0x00}}},
- /* /102 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xfc, 0x00, 0x00, 0x00}}},
- /* /103 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xfe, 0x00, 0x00, 0x00}}},
- /* /104 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x00, 0x00, 0x00}}},
- /* /105 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x80, 0x00, 0x00}}},
- /* /106 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xc0, 0x00, 0x00}}},
- /* /107 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xe0, 0x00, 0x00}}},
- /* /108 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xf0, 0x00, 0x00}}},
- /* /109 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xf8, 0x00, 0x00}}},
- /* /110 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xfc, 0x00, 0x00}}},
- /* /111 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xfe, 0x00, 0x00}}},
- /* /112 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00}}},
- /* /113 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0x80, 0x00}}},
- /* /114 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xc0, 0x00}}},
- /* /115 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xe0, 0x00}}},
- /* /116 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf0, 0x00}}},
- /* /117 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xf8, 0x00}}},
- /* /118 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xfc, 0x00}}},
- /* /119 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xfe, 0x00}}},
- /* /120 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x00}}},
- /* /121 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x80}}},
- /* /122 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xc0}}},
- /* /123 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xe0}}},
- /* /124 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xf0}}},
- /* /125 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xf8}}},
- /* /126 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xfc}}},
- /* /127 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xfe}}},
- /* /128 */
- {{{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff}}}};
-
/* Number of bits in prefix type. */
#ifndef PNBBY
#define PNBBY 8
@@ -432,15 +44,6 @@ static const struct in6_addr maskbytes6[] = {
#define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff)
-void prefix_hexdump(const struct prefix *p)
-{
- char buf[PREFIX_STRLEN];
-
- zlog_debug("prefix: %s",
- prefix2str(p, buf, sizeof(buf)));
- zlog_hexdump(p, sizeof(struct prefix));
-}
-
int is_zero_mac(const struct ethaddr *mac)
{
int i = 0;
@@ -461,11 +64,6 @@ unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen)
return (prefix[offset] >> shift) & 1;
}
-unsigned int prefix6_bit(const struct in6_addr *prefix, const uint16_t prefixlen)
-{
- return prefix_bit((const uint8_t *)&prefix->s6_addr, prefixlen);
-}
-
int str2family(const char *string)
{
if (!strcmp("ipv4", string))
@@ -1121,31 +719,46 @@ int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p)
* FIXME return uint8_t as ip_maskleni() does. */
int ip6_masklen(struct in6_addr netmask)
{
- int len = 0;
- unsigned char val;
- unsigned char *pnt;
-
- pnt = (unsigned char *)&netmask;
-
- while ((*pnt == 0xff) && len < IPV6_MAX_BITLEN) {
- len += 8;
- pnt++;
- }
-
- if (len < IPV6_MAX_BITLEN) {
- val = *pnt;
- while (val) {
- len++;
- val <<= 1;
- }
- }
- return len;
+ if (netmask.s6_addr32[0] != 0xffffffffU)
+ return __builtin_clz(~ntohl(netmask.s6_addr32[0]));
+ if (netmask.s6_addr32[1] != 0xffffffffU)
+ return __builtin_clz(~ntohl(netmask.s6_addr32[1])) + 32;
+ if (netmask.s6_addr32[2] != 0xffffffffU)
+ return __builtin_clz(~ntohl(netmask.s6_addr32[2])) + 64;
+ if (netmask.s6_addr32[3] != 0xffffffffU)
+ return __builtin_clz(~ntohl(netmask.s6_addr32[3])) + 96;
+ /* note __builtin_clz(0) is undefined */
+ return 128;
}
void masklen2ip6(const int masklen, struct in6_addr *netmask)
{
assert(masklen >= 0 && masklen <= IPV6_MAX_BITLEN);
- memcpy(netmask, maskbytes6 + masklen, sizeof(struct in6_addr));
+
+ if (masklen == 0) {
+ /* note << 32 is undefined */
+ memset(netmask, 0, sizeof(*netmask));
+ } else if (masklen <= 32) {
+ netmask->s6_addr32[0] = htonl(0xffffffffU << (32 - masklen));
+ netmask->s6_addr32[1] = 0;
+ netmask->s6_addr32[2] = 0;
+ netmask->s6_addr32[3] = 0;
+ } else if (masklen <= 64) {
+ netmask->s6_addr32[0] = 0xffffffffU;
+ netmask->s6_addr32[1] = htonl(0xffffffffU << (64 - masklen));
+ netmask->s6_addr32[2] = 0;
+ netmask->s6_addr32[3] = 0;
+ } else if (masklen <= 96) {
+ netmask->s6_addr32[0] = 0xffffffffU;
+ netmask->s6_addr32[1] = 0xffffffffU;
+ netmask->s6_addr32[2] = htonl(0xffffffffU << (96 - masklen));
+ netmask->s6_addr32[3] = 0;
+ } else {
+ netmask->s6_addr32[0] = 0xffffffffU;
+ netmask->s6_addr32[1] = 0xffffffffU;
+ netmask->s6_addr32[2] = 0xffffffffU;
+ netmask->s6_addr32[3] = htonl(0xffffffffU << (128 - masklen));
+ }
}
void apply_mask_ipv6(struct prefix_ipv6 *p)
@@ -1183,33 +796,6 @@ void apply_mask(struct prefix *p)
return;
}
-/* Utility function of convert between struct prefix <=> union sockunion.
- * FIXME This function isn't used anywhere. */
-struct prefix *sockunion2prefix(const union sockunion *dest,
- const union sockunion *mask)
-{
- if (dest->sa.sa_family == AF_INET) {
- struct prefix_ipv4 *p;
-
- p = prefix_ipv4_new();
- p->family = AF_INET;
- p->prefix = dest->sin.sin_addr;
- p->prefixlen = ip_masklen(mask->sin.sin_addr);
- return (struct prefix *)p;
- }
- if (dest->sa.sa_family == AF_INET6) {
- struct prefix_ipv6 *p;
-
- p = prefix_ipv6_new();
- p->family = AF_INET6;
- p->prefixlen = ip6_masklen(mask->sin6.sin6_addr);
- memcpy(&p->prefix, &dest->sin6.sin6_addr,
- sizeof(struct in6_addr));
- return (struct prefix *)p;
- }
- return NULL;
-}
-
/* Utility function of convert between struct prefix <=> union sockunion. */
struct prefix *sockunion2hostprefix(const union sockunion *su,
struct prefix *prefix)
@@ -1521,14 +1107,6 @@ void apply_classful_mask_ipv4(struct prefix_ipv4 *p)
}
}
-in_addr_t ipv4_network_addr(in_addr_t hostaddr, int masklen)
-{
- struct in_addr mask;
-
- masklen2ip(masklen, &mask);
- return hostaddr & mask.s_addr;
-}
-
in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
{
struct in_addr mask;
diff --git a/lib/prefix.h b/lib/prefix.h
index 7a93c766a3..667627ddfe 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -392,8 +392,6 @@ extern const char *afi2str(afi_t afi);
/* Check bit of the prefix. */
extern unsigned int prefix_bit(const uint8_t *prefix, const uint16_t prefixlen);
-extern unsigned int prefix6_bit(const struct in6_addr *prefix,
- const uint16_t prefixlen);
extern struct prefix *prefix_new(void);
extern void prefix_free(struct prefix **p);
@@ -430,8 +428,6 @@ extern void apply_mask(struct prefix *);
#define prefix_copy(a, b) ({ memset(a, 0, sizeof(*a)); prefix_copy(a, b); })
#endif
-extern struct prefix *sockunion2prefix(const union sockunion *dest,
- const union sockunion *mask);
extern struct prefix *sockunion2hostprefix(const union sockunion *,
struct prefix *p);
extern void prefix2sockunion(const struct prefix *, union sockunion *);
@@ -453,8 +449,6 @@ extern void apply_classful_mask_ipv4(struct prefix_ipv4 *);
extern uint8_t ip_masklen(struct in_addr);
extern void masklen2ip(const int, struct in_addr *);
-/* returns the network portion of the host address */
-extern in_addr_t ipv4_network_addr(in_addr_t hostaddr, int masklen);
/* given the address of a host on a network and the network mask length,
* calculate the broadcast address for that network;
* special treatment for /31: returns the address of the other host
@@ -484,7 +478,6 @@ extern unsigned prefix_hash_key(const void *pp);
extern int str_to_esi(const char *str, esi_t *esi);
extern char *esi_to_str(const esi_t *esi, char *buf, int size);
-extern void prefix_hexdump(const struct prefix *p);
extern void prefix_evpn_hexdump(const struct prefix_evpn *p);
static inline int ipv6_martian(struct in6_addr *addr)
diff --git a/lib/routemap.c b/lib/routemap.c
index c0e01488b2..14fec0283c 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -221,7 +221,7 @@ struct route_map_match_set_hooks {
const char *command, const char *arg);
};
-struct route_map_match_set_hooks rmap_match_set_hook;
+static struct route_map_match_set_hooks rmap_match_set_hook;
/* match interface */
void route_map_match_interface_hook(int (*func)(
@@ -623,7 +623,7 @@ struct route_map_list {
/* Master list of route map. */
static struct route_map_list route_map_master = {NULL, NULL, NULL, NULL, NULL};
-struct hash *route_map_master_hash = NULL;
+static struct hash *route_map_master_hash = NULL;
static unsigned int route_map_hash_key_make(const void *p)
{
@@ -683,7 +683,7 @@ struct route_map_dep_data {
};
/* Hashes maintaining dependency between various sublists used by route maps */
-struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX];
+static struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX];
static unsigned int route_map_dep_hash_make_key(const void *p);
static void route_map_clear_all_references(char *rmap_name);
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 7726d74ff7..3b12d16cbc 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -122,21 +122,6 @@ int setsockopt_ipv6_pktinfo(int sock, int val)
}
/* Set multicast hops val to the socket. */
-int setsockopt_ipv6_checksum(int sock, int val)
-{
- int ret;
-
-#ifdef GNU_LINUX
- ret = setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
-#else
- ret = setsockopt(sock, IPPROTO_IPV6, IPV6_CHECKSUM, &val, sizeof(val));
-#endif /* GNU_LINUX */
- if (ret < 0)
- flog_err(EC_LIB_SOCKET, "can't setsockopt IPV6_CHECKSUM");
- return ret;
-}
-
-/* Set multicast hops val to the socket. */
int setsockopt_ipv6_multicast_hops(int sock, int val)
{
int ret;
diff --git a/lib/sockopt.h b/lib/sockopt.h
index f6b57b8e07..59d8a65964 100644
--- a/lib/sockopt.h
+++ b/lib/sockopt.h
@@ -33,7 +33,6 @@ extern int getsockopt_so_sendbuf(const int sock);
extern int getsockopt_so_recvbuf(const int sock);
extern int setsockopt_ipv6_pktinfo(int, int);
-extern int setsockopt_ipv6_checksum(int, int);
extern int setsockopt_ipv6_multicast_hops(int, int);
extern int setsockopt_ipv6_unicast_hops(int, int);
extern int setsockopt_ipv6_hoplimit(int, int);
diff --git a/lib/systemd.c b/lib/systemd.c
index 44db48d006..81b0400ab9 100644
--- a/lib/systemd.c
+++ b/lib/systemd.c
@@ -32,7 +32,7 @@
* Wrapper this silliness if we
* don't have systemd
*/
-void systemd_send_information(const char *info)
+static void systemd_send_information(const char *info)
{
#if defined HAVE_SYSTEMD
sd_notify(0, info);
@@ -93,8 +93,8 @@ void systemd_send_stopping(void)
/*
* How many seconds should we wait between watchdog sends
*/
-int wsecs = 0;
-struct thread_master *systemd_master = NULL;
+static int wsecs = 0;
+static struct thread_master *systemd_master = NULL;
static int systemd_send_watchdog(struct thread *t)
{
diff --git a/lib/systemd.h b/lib/systemd.h
index 1f730720ce..d9885c5d9c 100644
--- a/lib/systemd.h
+++ b/lib/systemd.h
@@ -32,7 +32,6 @@ extern "C" {
* To turn on systemd compilation, use --enable-systemd on
* configure run.
*/
-void systemd_send_information(const char *info);
void systemd_send_stopping(void);
/*
diff --git a/lib/vrf.c b/lib/vrf.c
index 2411cc3111..6ca6482e08 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -67,7 +67,7 @@ static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;
static int debug_vrf = 0;
/* Holding VRF hooks */
-struct vrf_master {
+static struct vrf_master {
int (*vrf_new_hook)(struct vrf *);
int (*vrf_delete_hook)(struct vrf *);
int (*vrf_enable_hook)(struct vrf *);
@@ -752,7 +752,7 @@ DEFUN (no_vrf,
}
-struct cmd_node vrf_node = {VRF_NODE, "%s(config-vrf)# ", 1};
+static struct cmd_node vrf_node = {VRF_NODE, "%s(config-vrf)# ", 1};
DEFUN_NOSH (vrf_netns,
vrf_netns_cmd,
diff --git a/lib/vty.c b/lib/vty.c
index c08e5e151a..40da8abcd7 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -89,7 +89,7 @@ static char *vty_ipv6_accesslist_name = NULL;
static vector Vvty_serv_thread;
/* Current directory. */
-char vty_cwd[MAXPATHLEN];
+static char vty_cwd[MAXPATHLEN];
/* Login password check. */
static int no_password_check = 0;
diff --git a/lib/yang.c b/lib/yang.c
index d153f75530..78ea7d0dd0 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -87,7 +87,7 @@ static inline int yang_module_compare(const struct yang_module *a,
}
RB_GENERATE(yang_modules, yang_module, entry, yang_module_compare)
-struct yang_modules yang_modules = RB_INITIALIZER(&yang_modules);
+static struct yang_modules yang_modules = RB_INITIALIZER(&yang_modules);
struct yang_module *yang_module_load(const char *module_name)
{
diff --git a/lib/yang.h b/lib/yang.h
index 6892e36019..ae3e782029 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -114,9 +114,6 @@ typedef int (*yang_iterate_cb)(const struct lys_node *snode, void *arg);
/* Global libyang context for native FRR models. */
extern struct ly_ctx *ly_native_ctx;
-/* Tree of all loaded YANG modules. */
-extern struct yang_modules yang_modules;
-
/*
* Create a new YANG module and load it using libyang. If the YANG module is not
* found in the YANG_MODELS_PATH directory, the program will exit with an error.
diff --git a/tools/symalyzer.html b/tools/symalyzer.html
new file mode 100644
index 0000000000..eefeee3b05
--- /dev/null
+++ b/tools/symalyzer.html
@@ -0,0 +1,347 @@
+<html>
+<!--
+ - 2019 by David Lamparter, placed in public domain
+ -->
+ <head>
+ <title>Symalyzer report</title>
+ <style type="text/css">
+html {
+ margin:auto;
+ max-width:70em;
+ font-family:Fira Sans, sans-serif;
+}
+dl {
+ display:grid;
+ grid-template-columns: 1.4em 1.4em 1fr 1fr;
+ grid-auto-rows: auto;
+}
+dt.dir {
+ background-color:#ff8;
+ color:#000;
+ border:1px solid #000;
+ border-bottom:2px solid #000;
+ font-size:14pt;
+ padding:2pt 15pt;
+ margin:0pt;
+ margin-top:10pt;
+ grid-column:1 / -1;
+}
+dt.file {
+ background-color:#ffa;
+ color:#000;
+ border-bottom:1px solid #000;
+ font-size:12pt;
+ padding:2pt 15pt;
+ margin:5pt 0pt;
+ grid-column:1 / -1;
+}
+dt.file.filehidden {
+ background-color:#ffc;
+ font-size:10pt;
+ padding:0.5pt 15pt;
+ margin-bottom:-5pt;
+}
+dd {
+ display:inline-block;
+ vertical-align:middle;
+ margin:0;
+}
+dd.symtype {
+ grid-column:1;
+
+ border:1px solid #666;
+ text-align:center;
+}
+dd.symklass {
+ grid-column:2;
+
+ border:1px solid #666;
+ text-align:center;
+}
+dd.symname {
+ grid-column:3;
+
+ font-family:monospace;
+ padding:0 0.5em;
+ padding-top:2px;
+ border-bottom:1px dashed #ccc;
+}
+dd.symloc {
+ grid-column:4;
+
+ padding:0 0.5em;
+ border-bottom:1px dashed #ccc;
+}
+.symloc-unknown {
+ font-style:italic;
+ color:#aaa;
+}
+
+.symtype.sym-static {
+ background-color:#cf4;
+ color:#000;
+}
+.symtype.sym-extrastatic {
+ background-color:#fe8;
+ color:#000;
+}
+.symtype.sym-liblocal {
+ background-color:#fc6;
+ color:#000;
+}
+
+.symklass.symk-T {
+ background-color:#ddd;
+ color:#000;
+}
+.symklass.symk-B,
+.symklass.symk-C,
+.symklass.symk-D {
+ background-color:#faa;
+ color:#000;
+}
+.symklass.symk-R {
+ background-color:#fd8;
+ color:#000;
+}
+
+.symtype.sym-api {
+ background-color:#d9f;
+ color:#000;
+}
+.symname.sym-api,
+.symloc.sym-api {
+ background-color:#f8e8ff;
+}
+
+dt.file.dirhidden,
+dd.dirhidden {
+ display:none;
+}
+dd.filehidden {
+ display:none;
+}
+dd.symhidden {
+ display:none;
+}
+
+ul {
+ font-size:10pt;
+}
+li {
+ margin-bottom:6pt;
+ text-indent:-2.5em;
+ margin-left:2.5em;
+}
+code {
+ background-color:#eee;
+ color:#060;
+ text-decoration:underline;
+}
+b.symtype,
+b.symklass {
+ display:inline-block;
+ text-align:center;
+ border:1px solid #666;
+ width:1.4em;
+ text-indent:0;
+}
+ </style>
+ <script src="jquery-3.4.1.min.js"></script>
+ <script>
+
+function dirtoggle(elem, visible) {
+ if (visible) {
+ elem.removeClass("dirhidden");
+ } else {
+ elem.addClass("dirhidden");
+ }
+
+ var next = elem.next();
+ while (next.is("dd") || next.is("dt.file")) {
+ if (visible) {
+ next.removeClass("dirhidden");
+ } else {
+ next.addClass("dirhidden");
+ }
+ next = next.next();
+ }
+}
+
+function filetoggle(elem, visible) {
+ if (visible) {
+ elem.removeClass("filehidden");
+ } else {
+ elem.addClass("filehidden");
+ }
+
+ var next = elem.next();
+ while (next.is("dd")) {
+ if (visible) {
+ next.removeClass("filehidden");
+ } else {
+ next.addClass("filehidden");
+ }
+ next = next.next();
+ }
+}
+
+function symtoggle(elem, visible) {
+ if (visible) {
+ elem.removeClass("symhidden");
+ } else {
+ elem.addClass("symhidden");
+ }
+
+ var next = elem.next();
+ while (next.is(".symklass") || next.is(".symname") || next.is(".symloc")) {
+ if (visible) {
+ next.removeClass("symhidden");
+ } else {
+ next.addClass("symhidden");
+ }
+ next = next.next();
+ }
+}
+
+
+$(document).ready(function(){
+ $("dt.dir").each(function(){
+ var elem = $(this);
+
+ elem.click(function(){
+ dirtoggle(elem, elem.is(".dirhidden"));
+ });
+
+ dirtoggle(elem, false);
+ });
+
+ $("dt.file").each(function(){
+ var elem = $(this);
+
+ elem.click(function(){
+ filetoggle(elem, elem.is(".filehidden"));
+ });
+
+ /* filetoggle(elem, false); */
+ });
+
+ $("#f_hide_all").click(function(){
+ $("dt.file").each(function(){
+ filetoggle($(this), false);
+ });
+ });
+ $("#f_show_all").click(function(){
+ $("dt.file").each(function(){
+ filetoggle($(this), true);
+ });
+ });
+
+ $("#s_show_all").click(function(){
+ $("dd.symtype").each(function(){
+ symtoggle($(this), true);
+ });
+ });
+ $("#s_hide_all").click(function(){
+ $("dd.symtype").each(function(){
+ symtoggle($(this), false);
+ });
+ });
+ $("#s_show_vars").click(function(){
+ $("dd.symtype").each(function(){
+ var elem_type = $(this);
+ if (elem_type.text() === "A") {
+ return;
+ }
+
+ var elem_klass = elem_type.next();
+
+ if ("BbCDdGgnRrSs".indexOf(elem_klass.text()) >= 0) {
+ symtoggle(elem_type, true);
+ }
+ });
+ });
+ $("#s_show_funcs").click(function(){
+ $("dd.symtype").each(function(){
+ var elem_type = $(this);
+ if (elem_type.text() === "A") {
+ return;
+ }
+
+ var elem_klass = elem_type.next();
+
+ if ("Tt".indexOf(elem_klass.text()) >= 0) {
+ symtoggle(elem_type, true);
+ }
+ });
+ });
+ $("#s_show_api").click(function(){
+ $("dd.sym-api").each(function(){
+ symtoggle($(this), true);
+ });
+ });
+
+ $("#jsbuttons").show();
+});
+ </script>
+ </head>
+ <body>
+ <table style="display:none" id="jsbuttons">
+ <tr><td>Files</td><td>
+ <button type="button" id="f_hide_all">Hide all</button>
+ <button type="button" id="f_show_all">Show all</button>
+ </td></tr>
+ <tr><td>Symbols</td><td>
+ <button type="button" id="s_hide_all">Hide all</button>
+ <button type="button" id="s_show_all">Show all</button><br>
+ <button type="button" id="s_show_vars">Show variables</button>
+ <button type="button" id="s_show_funcs">Show functions</button>
+ <button type="button" id="s_show_api">Show module/API usage</button>
+ </td></tr>
+ </table>
+ <div style="display:grid;grid-template-columns:1fr 1fr;">
+ <ul>
+ <li><b class="symtype sym-static">S</b> means the symbol is not used outside its own file.
+ It could either be completely unused or used locally. It might be appropriate to make it
+ <code>static</code>.</li>
+ <li><b class="symtype sym-extrastatic">Z</b> means the symbol is not used outside its own file,
+ and it's not visible to the outside of the library or daemon (i.e. ELF hidden linkage.)
+ It could still be completely unused, or used within the library. It might be appropriate to make it
+ <code>static</code>.</li>
+ <li><b class="symtype sym-liblocal">L</b> means the symbol is used from other files in the library,
+ but not from outside. It might be appropriate to make it <code>DSO_LOCAL</code>.</li>
+ <li><b class="symtype sym-api">A</b> means the symbol is used from some other file, most likely a
+ loadable module. Note this is only flagged for symbols in executable files, not libraries.</li>
+ </ul>
+ <ul>
+ <li><b class="symklass symk-T">T</b> are normal functions ("program <u>T</u>ext")</li>
+ <li style="text-indent:0;margin-left:0">
+ <b class="symklass symk-B">B</b> (<u>B</u>SS),<br>
+ <b class="symklass symk-C">C</b> (<u>C</u>ommon),<br>
+ <b class="symklass symk-D">D</b> (<u>D</u>ata)<br>
+ are various types of writable global variables</li>
+ <li><b class="symklass symk-R">R</b> are read-only global variables ("<u>R</u>odata")</li>
+ </ul>
+ </div>
+ <dl>
+ {%- for subdir, subreport in dirgroups.items()|sort %}
+ <dt class="dir">{{ subdir }}</dt>
+ {%- for obj, reports in subreport.items()|sort %}
+ <dt class="file">{{ obj }}</dt>
+ {%- for report in reports|sort %}
+ {#- <dd class="{{ report.idlong }}"> #}
+ <dd class="sym-{{ report.idlong }} symtype" title="{{ report.title }}">{{ report.idshort }}</dd>
+ <dd class="sym-{{ report.idlong }} symk-{{ report.sym.klass }} symklass" title="{{ klasses.get(report.sym.klass, '???') }}">{{ report.sym.klass }}</dd>
+ <dd class="sym-{{ report.idlong }} symname">{{ report.sym.name }}</dd>
+ {% if report.sym.loc %}
+ <dd class="sym-{{ report.idlong }} symloc">{{ report.sym.loc }}</dd>
+ {% else %}
+ <dd class="sym-{{ report.idlong }} symloc symloc-unknown">unknown</dd>
+ {% endif %}
+ {#- </dd> #}
+ {%- endfor %}
+ {%- endfor %}
+ {%- endfor %}
+ </dl>
+ </body>
+</html>
diff --git a/tools/symalyzer.py b/tools/symalyzer.py
new file mode 100755
index 0000000000..b3b5c4e567
--- /dev/null
+++ b/tools/symalyzer.py
@@ -0,0 +1,383 @@
+#!/usr/bin/python3
+#
+# 2019 by David Lamparter, placed in public domain
+#
+# This tool generates a report of possibly unused symbols in the build. It's
+# particularly useful for libfrr to find bitrotting functions that aren't even
+# used anywhere anymore.
+#
+# Note that the tool can't distinguish between "a symbol is completely unused"
+# and "a symbol is used only in its file" since file-internal references are
+# invisible in nm output. However, the compiler will warn you if a static
+# symbol is unused.
+#
+# This tool is only tested on Linux, it probably needs `nm` from GNU binutils
+# (as opposed to BSD `nm`). Could use pyelftools instead but that's a lot of
+# extra work.
+#
+# This is a developer tool, please don't put it in any packages :)
+
+import sys, os, subprocess
+import re
+from collections import namedtuple
+
+class MakeVars(object):
+ '''
+ makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile
+ '''
+ def __init__(self):
+ self._data = dict()
+
+ def getvars(self, varlist):
+ '''
+ get a batch list of variables from make. faster than individual calls.
+ '''
+ rdfd, wrfd = os.pipe()
+
+ shvars = ['shvar-%s' % s for s in varlist]
+ make = subprocess.Popen(['make', '-s', 'VARFD=%d' % wrfd] + shvars, pass_fds = [wrfd])
+ os.close(wrfd)
+ data = b''
+
+ rdf = os.fdopen(rdfd, 'rb')
+ while True:
+ rdata = rdf.read()
+ if len(rdata) == 0:
+ break
+ data += rdata
+
+ del rdf
+ make.wait()
+
+ data = data.decode('US-ASCII').strip().split('\n')
+ for row in data:
+ k, v = row.split('=', 1)
+ v = v[1:-1]
+ self._data[k] = v
+
+ def __getitem__(self, k):
+ if k not in self._data:
+ self.getvars([k])
+ return self._data[k]
+
+ def get(self, k, defval = None):
+ if k not in self._data:
+ self.getvars([k])
+ return self._data[k] or defval
+
+SymRowBase = namedtuple('SymRow', ['target', 'object', 'name', 'address', 'klass', 'typ', 'size', 'line', 'section', 'loc'])
+class SymRow(SymRowBase):
+ '''
+ wrapper around a line of `nm` output
+ '''
+ lib_re = re.compile(r'/lib[^/]+\.(so|la)$')
+ def is_global(self):
+ return self.klass.isupper() or self.klass in 'uvw'
+ def scope(self):
+ if self.lib_re.search(self.target) is None:
+ return self.target
+ # "global"
+ return None
+
+ def is_export(self):
+ '''
+ FRR-specific list of symbols which are considered "externally used"
+
+ e.g. hooks are by design APIs for external use, same for qobj_t_*
+ frr_inet_ntop is here because it's used through an ELF alias to
+ "inet_ntop()"
+ '''
+ if self.name in ['main', 'frr_inet_ntop', '_libfrr_version']:
+ return True
+ if self.name.startswith('_hook_'):
+ return True
+ if self.name.startswith('qobj_t_'):
+ return True
+ return False
+
+class Symbols(dict):
+ '''
+ dict of all symbols in all libs & executables
+ '''
+
+ from_re = re.compile(r'^Symbols from (.*?):$')
+ lt_re = re.compile(r'^(.*/)([^/]+)\.l[oa]$')
+
+ def __init__(self):
+ super().__init__()
+
+ class ReportSym(object):
+ def __init__(self, sym):
+ self.sym = sym
+ def __repr__(self):
+ return '<%-25s %-40s [%s]>' % (self.__class__.__name__ + ':', self.sym.name, self.sym.loc)
+ def __lt__(self, other):
+ return self.sym.name.__lt__(other.sym.name)
+
+ class ReportSymCouldBeStaticAlreadyLocal(ReportSym):
+ idshort = 'Z'
+ idlong = 'extrastatic'
+ title = "symbol is local to library, but only used in its source file (make static?)"
+ class ReportSymCouldBeStatic(ReportSym):
+ idshort = 'S'
+ idlong = 'static'
+ title = "symbol is only used in its source file (make static?)"
+ class ReportSymCouldBeLibLocal(ReportSym):
+ idshort = 'L'
+ idlong = 'liblocal'
+ title = "symbol is only used inside of library"
+ class ReportSymModuleAPI(ReportSym):
+ idshort = 'A'
+ idlong = 'api'
+ title = "symbol (in executable) is referenced externally from a module"
+
+ class Symbol(object):
+ def __init__(self, name):
+ super().__init__()
+ self.name = name
+ self.defs = {}
+ self.refs = []
+
+ def process(self, row):
+ scope = row.scope()
+ if row.section == '*UND*':
+ self.refs.append(row)
+ else:
+ self.defs.setdefault(scope, []).append(row)
+
+ def evaluate(self, out):
+ '''
+ generate output report
+
+ invoked after all object files have been read in, so it can look
+ at inter-object-file relationships
+ '''
+ if len(self.defs) == 0:
+ out.extsyms.add(self.name)
+ return
+
+ for scopename, symdefs in self.defs.items():
+ common_defs = [symdef for symdef in symdefs if symdef.section == '*COM*']
+ proper_defs = [symdef for symdef in symdefs if symdef.section != '*COM*']
+
+ if len(proper_defs) > 1:
+ print(self.name, ' DUPLICATE')
+ print('\tD: %s %s' % (scopename, '\n\t\t'.join([repr(s) for s in symdefs])))
+ for syms in self.refs:
+ print('\tR: %s' % (syms, ))
+ return
+
+ if len(proper_defs):
+ primary_def = proper_defs[0]
+ elif len(common_defs):
+ # "common" = global variables without initializer;
+ # they can occur in multiple .o files and the linker will
+ # merge them into one variable/storage location.
+ primary_def = common_defs[0]
+ else:
+ # undefined symbol, e.g. libc
+ continue
+
+ if scopename is not None and len(self.refs) > 0:
+ for ref in self.refs:
+ if ref.target != primary_def.target and ref.target.endswith('.la'):
+ outobj = out.report.setdefault(primary_def.object, [])
+ outobj.append(out.ReportSymModuleAPI(primary_def))
+ break
+
+ if len(self.refs) == 0:
+ if primary_def.is_export():
+ continue
+ outobj = out.report.setdefault(primary_def.object, [])
+ if primary_def.visible:
+ outobj.append(out.ReportSymCouldBeStatic(primary_def))
+ else:
+ outobj.append(out.ReportSymCouldBeStaticAlreadyLocal(primary_def))
+ continue
+
+ if scopename is None and primary_def.visible:
+ # lib symbol
+ for ref in self.refs:
+ if ref.target != primary_def.target:
+ break
+ else:
+ outobj = out.report.setdefault(primary_def.object, [])
+ outobj.append(out.ReportSymCouldBeLibLocal(primary_def))
+
+
+ def evaluate(self):
+ self.extsyms = set()
+ self.report = {}
+
+ for sym in self.values():
+ sym.evaluate(self)
+
+ def load(self, target, files):
+ def libtoolmustdie(fn):
+ m = self.lt_re.match(fn)
+ if m is None:
+ return fn
+ return m.group(1) + '.libs/' + m.group(2) + '.o'
+
+ def libtooltargetmustdie(fn):
+ m = self.lt_re.match(fn)
+ if m is None:
+ a, b = fn.rsplit('/', 1)
+ return '%s/.libs/%s' % (a, b)
+ return m.group(1) + '.libs/' + m.group(2) + '.so'
+
+ files = list(set([libtoolmustdie(fn) for fn in files]))
+
+ def parse_nm_output(text):
+ filename = None
+ path_rel_to = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+ for line in text.split('\n'):
+ if line.strip() == '':
+ continue
+ m = self.from_re.match(line)
+ if m is not None:
+ filename = m.group(1)
+ continue
+ if line.startswith('Name'):
+ continue
+
+ items = [i.strip() for i in line.split('|')]
+ loc = None
+ if '\t' in items[-1]:
+ items[-1], loc = items[-1].split('\t', 1)
+ fn, lno = loc.rsplit(':', 1)
+ fn = os.path.relpath(fn, path_rel_to)
+ loc = '%s:%s' % (fn, lno)
+
+ items[1] = int(items[1] if items[1] != '' else '0', 16)
+ items[4] = int(items[4] if items[4] != '' else '0', 16)
+ items.append(loc)
+ row = SymRow(target, filename, *items)
+
+ if row.section == '.group' or row.name == '_GLOBAL_OFFSET_TABLE_':
+ continue
+ if not row.is_global():
+ continue
+
+ yield row
+
+ visible_syms = set()
+
+ # the actual symbol report uses output from the individual object files
+ # (e.g. lib/.libs/foo.o), but we also read the linked binary (e.g.
+ # lib/.libs/libfrr.so) to determine which symbols are actually visible
+ # in the linked result (this covers ELF "hidden"/"internal" linkage)
+
+ libfile = libtooltargetmustdie(target)
+ nmlib = subprocess.Popen(['nm', '-l', '-g', '--defined-only', '-f', 'sysv', libfile], stdout = subprocess.PIPE)
+ out = nmlib.communicate()[0].decode('US-ASCII')
+
+ for row in parse_nm_output(out):
+ visible_syms.add(row.name)
+
+ nm = subprocess.Popen(['nm', '-l', '-f', 'sysv'] + files, stdout = subprocess.PIPE)
+ out = nm.communicate()[0].decode('US-ASCII')
+
+ for row in parse_nm_output(out):
+ row.visible = row.name in visible_syms
+ sym = self.setdefault(row.name, self.Symbol(row.name))
+ sym.process(row)
+
+
+def write_html_report(syms):
+ try:
+ import jinja2
+ except ImportError:
+ sys.stderr.write('jinja2 could not be imported, not writing HTML report!\n')
+ return
+
+ self_path = os.path.dirname(os.path.abspath(__file__))
+ jenv = jinja2.Environment(loader=jinja2.FileSystemLoader(self_path))
+ template = jenv.get_template('symalyzer.html')
+
+ dirgroups = {}
+ for fn, reports in syms.report.items():
+ dirname, filename = fn.replace('.libs/', '').rsplit('/', 1)
+ dirgroups.setdefault(dirname, {})[fn] = reports
+
+ klasses = {
+ 'T': 'code / plain old regular function (Text)',
+ 'D': 'global variable, read-write, with nonzero initializer (Data)',
+ 'B': 'global variable, read-write, with zero initializer (BSS)',
+ 'C': 'global variable, read-write, with zero initializer (Common)',
+ 'R': 'global variable, read-only (Rodata)',
+ }
+
+ with open('symalyzer_report.html.tmp', 'w') as fd:
+ fd.write(template.render(dirgroups = dirgroups, klasses = klasses))
+ os.rename('symalyzer_report.html.tmp', 'symalyzer_report.html')
+
+ if not os.path.exists('jquery-3.4.1.min.js'):
+ url = 'https://code.jquery.com/jquery-3.4.1.min.js'
+ sys.stderr.write(
+ 'trying to grab a copy of jquery from %s\nif this fails, please get it manually (the HTML output is done.)\n' % (url))
+ import requests
+ r = requests.get('https://code.jquery.com/jquery-3.4.1.min.js')
+ if r.status_code != 200:
+ sys.stderr.write('failed -- please download jquery-3.4.1.min.js and put it next to the HTML report\n')
+ else:
+ with open('jquery-3.4.1.min.js.tmp', 'w') as fd:
+ fd.write(r.text)
+ os.rename('jquery-3.4.1.min.js.tmp', 'jquery-3.4.1.min.js.tmp')
+ sys.stderr.write('done.\n')
+
+def automake_escape(s):
+ return s.replace('.', '_').replace('/', '_')
+
+if __name__ == '__main__':
+ mv = MakeVars()
+
+ if not (os.path.exists('config.version') and os.path.exists('lib/.libs/libfrr.so')):
+ sys.stderr.write('please execute this script in the root directory of an FRR build tree\n')
+ sys.stderr.write('./configure && make need to have completed successfully\n')
+ sys.exit(1)
+
+ amtargets = ['bin_PROGRAMS', 'sbin_PROGRAMS', 'lib_LTLIBRARIES', 'module_LTLIBRARIES']
+ targets = []
+
+ mv.getvars(amtargets)
+ for amtarget in amtargets:
+ targets.extend([item for item in mv[amtarget].strip().split() if item != 'tools/ssd'])
+
+ mv.getvars(['%s_LDADD' % automake_escape(t) for t in targets])
+ ldobjs = targets[:]
+ for t in targets:
+ ldadd = mv['%s_LDADD' % automake_escape(t)].strip().split()
+ for item in ldadd:
+ if item.startswith('-'):
+ continue
+ if item.endswith('.a'):
+ ldobjs.append(item)
+
+ mv.getvars(['%s_OBJECTS' % automake_escape(o) for o in ldobjs])
+
+ syms = Symbols()
+
+ for t in targets:
+ objs = mv['%s_OBJECTS' % automake_escape(t)].strip().split()
+ ldadd = mv['%s_LDADD' % automake_escape(t)].strip().split()
+ for item in ldadd:
+ if item.startswith('-'):
+ continue
+ if item.endswith('.a'):
+ objs.extend(mv['%s_OBJECTS' % automake_escape(item)].strip().split())
+
+ sys.stderr.write('processing %s...\n' % t)
+ sys.stderr.flush()
+ #print(t, '\n\t', objs)
+ syms.load(t, objs)
+
+ syms.evaluate()
+
+ for obj, reports in sorted(syms.report.items()):
+ print('%s:' % obj)
+ for report in reports:
+ print('\t%r' % report)
+
+ write_html_report(syms)