diff options
Diffstat (limited to 'lib')
119 files changed, 3283 insertions, 1602 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 14b7130c8a..a1b78d3c4d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -17,6 +17,7 @@ libfrr_la_SOURCES = \ network.c pid_output.c getopt.c getopt1.c \ checksum.c vector.c linklist.c vty.c \ graph.c command_parse.y command_lex.l command_match.c \ + command_graph.c \ command.c \ sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \ filter.c routemap.c distribute.c stream.c log.c plist.c \ @@ -32,8 +33,10 @@ libfrr_la_SOURCES = \ libfrr.c \ strlcpy.c \ strlcat.c \ + sha256.c \ module.c \ hook.c \ + frr_pthread.c \ # end BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h @@ -54,9 +57,11 @@ libfrrsnmp_la_SOURCES = \ #end pkginclude_HEADERS = \ + frratomic.h \ buffer.h checksum.h filter.h getopt.h hash.h \ if.h linklist.h log.h \ graph.h command_match.h \ + command_graph.h \ command.h \ memory.h network.h prefix.h routemap.h distribute.h sockunion.h \ stream.h table.h thread.h vector.h version.h vty.h zebra.h \ @@ -73,6 +78,9 @@ pkginclude_HEADERS = \ module.h \ hook.h \ libfrr.h \ + sha256.h \ + frr_pthread.h \ + vrf_int.h \ # end noinst_HEADERS = \ diff --git a/lib/agentx.c b/lib/agentx.c index 11d5c9385d..fda634bb86 100644 --- a/lib/agentx.c +++ b/lib/agentx.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -85,8 +84,11 @@ agentx_events_update(void) FD_ZERO (&fds); snmp_select_info (&maxfd, &fds, &timeout, &block); - if (!block) - timeout_thr = thread_add_timer_tv (agentx_tm, agentx_timeout, NULL, &timeout); + if (!block) { + timeout_thr = NULL; + thread_add_timer_tv(agentx_tm, agentx_timeout, NULL, &timeout, + &timeout_thr); + } ln = listhead (events); thr = ln ? listgetdata (ln) : NULL; @@ -114,7 +116,8 @@ agentx_events_update(void) else if (FD_ISSET (fd, &fds)) { struct listnode *newln; - thr = thread_add_read (agentx_tm, agentx_read, NULL, fd); + thr = NULL; + thread_add_read(agentx_tm, agentx_read, NULL, fd, &thr); newln = listnode_add_before (events, ln, thr); thr->arg = newln; } @@ -134,7 +137,8 @@ agentx_events_update(void) static struct cmd_node agentx_node = { SMUX_NODE, - "" /* AgentX has no interface. */ + "", /* AgentX has no interface. */ + 1 }; /* Logging NetSNMP messages */ @@ -165,7 +169,7 @@ config_write_agentx (struct vty *vty) { if (agentx_enabled) vty_out (vty, "agentx%s", VTY_NEWLINE); - return 0; + return 1; } DEFUN (agentx_enable, @@ -183,7 +187,7 @@ DEFUN (agentx_enable, return CMD_SUCCESS; } vty_out (vty, "SNMP AgentX already enabled%s", VTY_NEWLINE); - return CMD_WARNING; + return CMD_SUCCESS; } DEFUN (no_agentx, @@ -15,10 +15,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -15,10 +15,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_BFD_H diff --git a/lib/bitfield.h b/lib/bitfield.h index 7062796a99..4ff9c7fb2e 100644 --- a/lib/bitfield.h +++ b/lib/bitfield.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * A simple bit array implementation to allocate and free IDs. An example diff --git a/lib/buffer.c b/lib/buffer.c index 1dfcdb4732..649677fc93 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -8,16 +8,15 @@ * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your * option) any later version. - * + * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/buffer.h b/lib/buffer.h index 6c3dc76a1b..67ac71cad8 100644 --- a/lib/buffer.h +++ b/lib/buffer.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_BUFFER_H diff --git a/lib/command.c b/lib/command.c index ff921ff402..84d59f076c 100644 --- a/lib/command.c +++ b/lib/command.c @@ -19,10 +19,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -40,15 +39,13 @@ #include "workqueue.h" #include "vrf.h" #include "command_match.h" +#include "command_graph.h" #include "qobj.h" #include "defaults.h" DEFINE_MTYPE( LIB, HOST, "Host config") DEFINE_MTYPE( LIB, STRVEC, "String vector") -DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") -DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text") -DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help") -DEFINE_MTYPE( LIB, CMD_ARG, "Command Argument") +DEFINE_MTYPE( LIB, COMPLETION, "Completion item") /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -234,8 +231,8 @@ install_node (struct cmd_node *node, node->cmdgraph = graph_new (); node->cmd_vector = vector_init (VECTOR_MIN_SIZE); // add start node - struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (node->cmdgraph, token, (void (*)(void *)) &del_cmd_token); + struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node (node->cmdgraph, token, (void (*)(void *)) &cmd_token_del); node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp); } @@ -306,272 +303,6 @@ cmd_prompt (enum node_type node) return cnode->prompt; } -static bool -cmd_nodes_link (struct graph_node *from, struct graph_node *to) -{ - for (size_t i = 0; i < vector_active (from->to); i++) - if (vector_slot (from->to, i) == to) - return true; - return false; -} - -static bool cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb); - -/* returns a single node to be excluded as "next" from iteration - * - for JOIN_TKN, never continue back to the FORK_TKN - * - in all other cases, don't try the node itself (in case of "...") - */ -static inline struct graph_node * -cmd_loopstop(struct graph_node *gn) -{ - struct cmd_token *tok = gn->data; - if (tok->type == JOIN_TKN) - return tok->forkjoin; - else - return gn; -} - -static bool -cmd_subgraph_equal (struct graph_node *ga, struct graph_node *gb, - struct graph_node *a_join) -{ - size_t i, j; - struct graph_node *a_fork, *b_fork; - a_fork = cmd_loopstop (ga); - b_fork = cmd_loopstop (gb); - - if (vector_active (ga->to) != vector_active (gb->to)) - return false; - for (i = 0; i < vector_active (ga->to); i++) - { - struct graph_node *cga = vector_slot (ga->to, i); - - for (j = 0; j < vector_active (gb->to); j++) - { - struct graph_node *cgb = vector_slot (gb->to, i); - - if (cga == a_fork && cgb != b_fork) - continue; - if (cga == a_fork && cgb == b_fork) - break; - - if (cmd_nodes_equal (cga, cgb)) - { - if (cga == a_join) - break; - if (cmd_subgraph_equal (cga, cgb, a_join)) - break; - } - } - if (j == vector_active (gb->to)) - return false; - } - return true; -} - -/* deep compare -- for FORK_TKN, the entire subgraph is compared. - * this is what's needed since we're not currently trying to partially - * merge subgraphs */ -static bool -cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb) -{ - struct cmd_token *a = ga->data, *b = gb->data; - - if (a->type != b->type || a->allowrepeat != b->allowrepeat) - return false; - if (a->type < SPECIAL_TKN && strcmp (a->text, b->text)) - return false; - /* one a ..., the other not. */ - if (cmd_nodes_link (ga, ga) != cmd_nodes_link (gb, gb)) - return false; - - switch (a->type) - { - case RANGE_TKN: - return a->min == b->min && a->max == b->max; - - case FORK_TKN: - /* one is keywords, the other just option or selector ... */ - if (cmd_nodes_link (a->forkjoin, ga) != cmd_nodes_link (b->forkjoin, gb)) - return false; - if (cmd_nodes_link (ga, a->forkjoin) != cmd_nodes_link (gb, b->forkjoin)) - return false; - return cmd_subgraph_equal (ga, gb, a->forkjoin); - - default: - return true; - } -} - -static void -cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join, - u_char attr) -{ - size_t i; - struct cmd_token *tok = gn->data; - struct graph_node *stop = cmd_loopstop (gn); - - tok->attr = attr; - for (i = 0; i < vector_active (gn->to); i++) - { - struct graph_node *next = vector_slot (gn->to, i); - if (next == stop || next == join) - continue; - cmd_fork_bump_attr (next, join, attr); - } -} - -/* move an entire subtree from the temporary graph resulting from - * parse() into the permanent graph for the command node. - * - * this touches rather deeply into the graph code unfortunately. - */ -static void -cmd_reparent_tree (struct graph *fromgraph, struct graph *tograph, - struct graph_node *node) -{ - struct graph_node *stop = cmd_loopstop (node); - size_t i; - - for (i = 0; i < vector_active (fromgraph->nodes); i++) - if (vector_slot (fromgraph->nodes, i) == node) - { - /* agressive iteration punching through subgraphs - may hit some - * nodes twice. reparent only if found on old graph */ - vector_unset (fromgraph->nodes, i); - vector_set (tograph->nodes, node); - break; - } - - for (i = 0; i < vector_active (node->to); i++) - { - struct graph_node *next = vector_slot (node->to, i); - if (next != stop) - cmd_reparent_tree (fromgraph, tograph, next); - } -} - -static void -cmd_free_recur (struct graph *graph, struct graph_node *node, - struct graph_node *stop) -{ - struct graph_node *next, *nstop; - - for (size_t i = vector_active (node->to); i; i--) - { - next = vector_slot (node->to, i - 1); - if (next == stop) - continue; - nstop = cmd_loopstop (next); - if (nstop != next) - cmd_free_recur (graph, next, nstop); - cmd_free_recur (graph, nstop, stop); - } - graph_delete_node (graph, node); -} - -static void -cmd_free_node (struct graph *graph, struct graph_node *node) -{ - struct cmd_token *tok = node->data; - if (tok->type == JOIN_TKN) - cmd_free_recur (graph, tok->forkjoin, node); - graph_delete_node (graph, node); -} - -/* recursive graph merge. call with - * old ~= new - * (which holds true for old == START_TKN, new == START_TKN) - */ -static void -cmd_merge_nodes (struct graph *oldgraph, struct graph *newgraph, - struct graph_node *old, struct graph_node *new, - int direction) -{ - struct cmd_token *tok; - struct graph_node *old_skip, *new_skip; - old_skip = cmd_loopstop (old); - new_skip = cmd_loopstop (new); - - assert (direction == 1 || direction == -1); - - tok = old->data; - tok->refcnt += direction; - - size_t j, i; - for (j = 0; j < vector_active (new->to); j++) - { - struct graph_node *cnew = vector_slot (new->to, j); - if (cnew == new_skip) - continue; - - for (i = 0; i < vector_active (old->to); i++) - { - struct graph_node *cold = vector_slot (old->to, i); - if (cold == old_skip) - continue; - - if (cmd_nodes_equal (cold, cnew)) - { - struct cmd_token *told = cold->data, *tnew = cnew->data; - - if (told->type == END_TKN) - { - if (direction < 0) - { - graph_delete_node (oldgraph, vector_slot (cold->to, 0)); - graph_delete_node (oldgraph, cold); - } - else - /* force no-match handling to install END_TKN */ - i = vector_active (old->to); - break; - } - - /* the entire fork compared as equal, we continue after it. */ - if (told->type == FORK_TKN) - { - if (tnew->attr < told->attr && direction > 0) - cmd_fork_bump_attr (cold, told->forkjoin, tnew->attr); - /* XXX: no reverse bump on uninstall */ - told = (cold = told->forkjoin)->data; - tnew = (cnew = tnew->forkjoin)->data; - } - if (tnew->attr < told->attr) - told->attr = tnew->attr; - - cmd_merge_nodes (oldgraph, newgraph, cold, cnew, direction); - break; - } - } - /* nothing found => add new to old */ - if (i == vector_active (old->to) && direction > 0) - { - assert (vector_count (cnew->from) == - cmd_nodes_link (cnew, cnew) ? 2 : 1); - graph_remove_edge (new, cnew); - - cmd_reparent_tree (newgraph, oldgraph, cnew); - - graph_add_edge (old, cnew); - } - } - - if (!tok->refcnt) - cmd_free_node (oldgraph, old); -} - -void -cmd_merge_graphs (struct graph *old, struct graph *new, int direction) -{ - assert (vector_active (old->nodes) >= 1); - assert (vector_active (new->nodes) >= 1); - - cmd_merge_nodes (old, new, - vector_slot (old->nodes, 0), vector_slot (new->nodes, 0), - direction); -} - /* Install a command into a node. */ void install_element (enum node_type ntype, struct cmd_element *cmd) @@ -592,6 +323,7 @@ install_element (enum node_type ntype, struct cmd_element *cmd) { fprintf (stderr, "Command node %d doesn't exist, please check it\n", ntype); + fprintf (stderr, "Have you called install_node before this install_element?\n"); exit (EXIT_FAILURE); } @@ -606,11 +338,12 @@ install_element (enum node_type ntype, struct cmd_element *cmd) assert (hash_get (cnode->cmd_hash, cmd, hash_alloc_intern)); struct graph *graph = graph_new(); - struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token); + struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); - command_parse_format (graph, cmd); - cmd_merge_graphs (cnode->cmdgraph, graph, +1); + cmd_graph_parse (graph, cmd); + cmd_graph_names (graph); + cmd_graph_merge (cnode->cmdgraph, graph, +1); graph_delete_graph (graph); vector_set (cnode->cmd_vector, cmd); @@ -638,6 +371,7 @@ uninstall_element (enum node_type ntype, struct cmd_element *cmd) { fprintf (stderr, "Command node %d doesn't exist, please check it\n", ntype); + fprintf (stderr, "Have you called install_node before this install_element?\n"); exit (EXIT_FAILURE); } @@ -652,11 +386,12 @@ uninstall_element (enum node_type ntype, struct cmd_element *cmd) vector_unset_value (cnode->cmd_vector, cmd); struct graph *graph = graph_new(); - struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token); + struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); - command_parse_format (graph, cmd); - cmd_merge_graphs (cnode->cmdgraph, graph, -1); + cmd_graph_parse (graph, cmd); + cmd_graph_names (graph); + cmd_graph_merge (cnode->cmdgraph, graph, -1); graph_delete_graph (graph); if (ntype == VIEW_NODE) @@ -945,6 +680,86 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) return cmd_complete_command_real (vline, vty, status); } +static struct list *varhandlers = NULL; + +void +cmd_variable_complete (struct cmd_token *token, const char *arg, vector comps) +{ + struct listnode *ln; + const struct cmd_variable_handler *cvh; + size_t i, argsz; + vector tmpcomps; + + tmpcomps = arg ? vector_init (VECTOR_MIN_SIZE) : comps; + + for (ALL_LIST_ELEMENTS_RO(varhandlers, ln, cvh)) + { + if (cvh->tokenname && strcmp(cvh->tokenname, token->text)) + continue; + if (cvh->varname && (!token->varname || strcmp(cvh->varname, token->varname))) + continue; + cvh->completions(tmpcomps, token); + break; + } + + if (!arg) + return; + + argsz = strlen(arg); + for (i = vector_active(tmpcomps); i; i--) + { + char *item = vector_slot(tmpcomps, i - 1); + if (strlen(item) >= argsz + && !strncmp(item, arg, argsz)) + vector_set(comps, item); + else + XFREE(MTYPE_COMPLETION, item); + } + vector_free(tmpcomps); +} + +void +cmd_variable_handler_register (const struct cmd_variable_handler *cvh) +{ + if (!varhandlers) + return; + + for (; cvh->completions; cvh++) + listnode_add(varhandlers, (void *)cvh); +} + +DEFUN_HIDDEN (autocomplete, + autocomplete_cmd, + "autocomplete TYPE TEXT VARNAME", + "Autocompletion handler (internal, for vtysh)\n" + "cmd_token->type\n" + "cmd_token->text\n" + "cmd_token->varname\n") +{ + struct cmd_token tok; + vector comps = vector_init(32); + size_t i; + + memset(&tok, 0, sizeof(tok)); + tok.type = atoi(argv[1]->arg); + tok.text = argv[2]->arg; + tok.varname = argv[3]->arg; + if (!strcmp(tok.varname, "-")) + tok.varname = NULL; + + cmd_variable_complete(&tok, NULL, comps); + + for (i = 0; i < vector_active(comps); i++) + { + char *text = vector_slot(comps, i); + vty_out(vty, "%s\n", text); + XFREE(MTYPE_COMPLETION, text); + } + + vector_free(comps); + return CMD_SUCCESS; +} + /** * Generate possible tab-completions for the given input. This function only * returns results that would result in a valid command if used as Readline @@ -986,7 +801,12 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) { struct cmd_token *token = vector_slot (initial_comps, i); if (token->type == WORD_TKN) - vector_set (comps, token); + vector_set (comps, XSTRDUP (MTYPE_COMPLETION, token->text)); + else if (IS_VARYING_TOKEN(token->type)) + { + const char *ref = vector_lookup(vline, vector_active (vline) - 1); + cmd_variable_complete (token, ref, comps); + } } vector_free (initial_comps); @@ -1008,9 +828,7 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) unsigned int i; for (i = 0; i < vector_active (comps); i++) { - struct cmd_token *token = vector_slot (comps, i); - ret[i] = XSTRDUP (MTYPE_TMP, token->text); - vector_unset (comps, i); + ret[i] = vector_slot (comps, i); } // set the last element to NULL, because this array is used in // a Readline completion_generator function which expects NULL @@ -1055,9 +873,11 @@ node_parent ( enum node_type node ) case BGP_VNC_L2_GROUP_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: case BGP_IPV6_NODE: case BGP_IPV6M_NODE: case BGP_EVPN_NODE: + case BGP_IPV6L_NODE: ret = BGP_NODE; break; case KEYCHAIN_KEY_NODE: @@ -1399,6 +1219,7 @@ cmd_exit (struct vty *vty) case ZEBRA_NODE: case BGP_NODE: case RIP_NODE: + case EIGRP_NODE: case RIPNG_NODE: case OSPF_NODE: case OSPF6_NODE: @@ -1414,6 +1235,7 @@ cmd_exit (struct vty *vty) break; case BGP_IPV4_NODE: case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: case BGP_VPNV4_NODE: case BGP_VPNV6_NODE: case BGP_ENCAP_NODE: @@ -1425,6 +1247,7 @@ cmd_exit (struct vty *vty) case BGP_IPV6_NODE: case BGP_IPV6M_NODE: case BGP_EVPN_NODE: + case BGP_IPV6L_NODE: vty->node = BGP_NODE; break; case LDP_IPV4_NODE: @@ -1480,6 +1303,7 @@ DEFUN (config_end, case ZEBRA_NODE: case RIP_NODE: case RIPNG_NODE: + case EIGRP_NODE: case BGP_NODE: case BGP_ENCAP_NODE: case BGP_ENCAPV6_NODE: @@ -1491,9 +1315,11 @@ DEFUN (config_end, case BGP_VPNV6_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: case BGP_IPV6_NODE: case BGP_IPV6M_NODE: case BGP_EVPN_NODE: + case BGP_IPV6L_NODE: case RMAP_NODE: case OSPF_NODE: case OSPF6_NODE: @@ -1546,11 +1372,6 @@ DEFUN (frr_version_defaults, "set of configuration defaults used\n" "version string\n") { - if (vty->type == VTY_TERM || vty->type == VTY_SHELL) - /* only print this when the user tries to do run it */ - vty_out (vty, "%% NOTE: This command currently does nothing.%s" - "%% It is written to the configuration for future reference.%s", - VTY_NEWLINE, VTY_NEWLINE); return CMD_SUCCESS; } @@ -2109,16 +1930,8 @@ DEFUN (config_terminal_length, "Number of lines on screen (0 for no pausing)\n") { int idx_number = 2; - int lines; - char *endptr = NULL; - lines = strtol (argv[idx_number]->arg, &endptr, 10); - if (lines < 0 || lines > 512 || *endptr != '\0') - { - vty_out (vty, "length is malformed%s", VTY_NEWLINE); - return CMD_WARNING; - } - vty->lines = lines; + vty->lines = atoi (argv[idx_number]->arg); return CMD_SUCCESS; } @@ -2142,16 +1955,8 @@ DEFUN (service_terminal_length, "Number of lines of VTY (0 means no line control)\n") { int idx_number = 2; - int lines; - char *endptr = NULL; - lines = strtol (argv[idx_number]->arg, &endptr, 10); - if (lines < 0 || lines > 512 || *endptr != '\0') - { - vty_out (vty, "length is malformed%s", VTY_NEWLINE); - return CMD_WARNING; - } - host.lines = lines; + host.lines = atoi (argv[idx_number]->arg); return CMD_SUCCESS; } @@ -2657,6 +2462,8 @@ install_default (enum node_type node) install_element (node, &config_write_cmd); install_element (node, &show_running_config_cmd); + + install_element (node, &autocomplete_cmd); } /* Initialize command interface. Install basic nodes and commands. @@ -2669,6 +2476,8 @@ cmd_init (int terminal) { qobj_init (); + varhandlers = list_new (); + /* Allocate initial top vector of commands. */ cmdvec = vector_init (VECTOR_MIN_SIZE); @@ -2704,6 +2513,7 @@ cmd_init (int terminal) install_element (VIEW_NODE, &show_logging_cmd); install_element (VIEW_NODE, &show_commandtree_cmd); install_element (VIEW_NODE, &echo_cmd); + install_element (VIEW_NODE, &autocomplete_cmd); } if (terminal) @@ -2768,50 +2578,6 @@ cmd_init (int terminal) #endif } -struct cmd_token * -new_cmd_token (enum cmd_token_type type, u_char attr, - const char *text, const char *desc) -{ - struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token)); - token->type = type; - token->attr = attr; - token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL; - token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL; - token->refcnt = 1; - token->arg = NULL; - token->allowrepeat = false; - - return token; -} - -void -del_cmd_token (struct cmd_token *token) -{ - if (!token) return; - - if (token->text) - XFREE (MTYPE_CMD_TEXT, token->text); - if (token->desc) - XFREE (MTYPE_CMD_DESC, token->desc); - if (token->arg) - XFREE (MTYPE_CMD_ARG, token->arg); - - XFREE (MTYPE_CMD_TOKENS, token); -} - -struct cmd_token * -copy_cmd_token (struct cmd_token *token) -{ - struct cmd_token *copy = new_cmd_token (token->type, token->attr, NULL, NULL); - copy->max = token->max; - copy->min = token->min; - copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL; - copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL; - copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL; - - return copy; -} - void cmd_terminate () { diff --git a/lib/command.h b/lib/command.h index d62f7655ee..35fb20f8b0 100644 --- a/lib/command.h +++ b/lib/command.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_COMMAND_H @@ -29,9 +28,10 @@ #include "graph.h" #include "memory.h" #include "hash.h" +#include "command_graph.h" DECLARE_MTYPE(HOST) -DECLARE_MTYPE(CMD_ARG) +DECLARE_MTYPE(COMPLETION) /* for test-commands.c */ DECLARE_MTYPE(STRVEC) @@ -91,13 +91,16 @@ enum node_type TABLE_NODE, /* rtm_table selection node. */ RIP_NODE, /* RIP protocol mode node. */ RIPNG_NODE, /* RIPng protocol mode node. */ + EIGRP_NODE, /* EIGRP protocol mode node. */ BGP_NODE, /* BGP protocol mode which includes BGP4+ */ BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */ BGP_VPNV6_NODE, /* BGP MPLS-VPN PE exchange. */ BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */ BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */ + BGP_IPV4L_NODE, /* BGP IPv4 labeled unicast address family. */ BGP_IPV6_NODE, /* BGP IPv6 address family */ BGP_IPV6M_NODE, /* BGP IPv6 multicast address family. */ + BGP_IPV6L_NODE, /* BGP IPv6 labeled unicast address family. */ BGP_ENCAP_NODE, /* BGP ENCAP SAFI */ BGP_ENCAPV6_NODE, /* BGP ENCAP SAFI */ BGP_VRF_POLICY_NODE, /* BGP VRF policy */ @@ -162,69 +165,6 @@ struct cmd_node struct hash *cmd_hash; }; -/** - * Types for tokens. - * - * The type determines what kind of data the token can match (in the - * matching use case) or hold (in the argv use case). - */ -enum cmd_token_type -{ - WORD_TKN, // words - VARIABLE_TKN, // almost anything - RANGE_TKN, // integer range - IPV4_TKN, // IPV4 addresses - IPV4_PREFIX_TKN, // IPV4 network prefixes - IPV6_TKN, // IPV6 prefixes - IPV6_PREFIX_TKN, // IPV6 network prefixes - - /* plumbing types */ - FORK_TKN, // marks subgraph beginning - JOIN_TKN, // marks subgraph end - START_TKN, // first token in line - END_TKN, // last token in line - - SPECIAL_TKN = FORK_TKN, -}; - -/* Command attributes */ -enum -{ - CMD_ATTR_NORMAL, - CMD_ATTR_DEPRECATED, - CMD_ATTR_HIDDEN, -}; - -/* Comamand token struct. */ -struct cmd_token -{ - enum cmd_token_type type; // token type - u_char attr; // token attributes - bool allowrepeat; // matcher allowed to match token repetively? - uint32_t refcnt; - - char *text; // token text - char *desc; // token description - long long min, max; // for ranges - char *arg; // user input that matches this token - - struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK -}; - -/* Structure of command element. */ -struct cmd_element -{ - const char *string; /* Command specification by string. */ - const char *doc; /* Documentation of this command. */ - int daemon; /* Daemon to which this command belong. */ - u_char attr; /* Command attributes */ - - /* handler function for command */ - int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]); - - const char *name; /* symbol name for debugging */ -}; - /* Return value of the commands. */ #define CMD_SUCCESS 0 #define CMD_WARNING 1 @@ -356,6 +296,7 @@ struct cmd_element #define REDIST_STR "Redistribute information from another routing protocol\n" #define CLEAR_STR "Reset functions\n" #define RIP_STR "RIP information\n" +#define EIGRP_STR "EIGRP information\n" #define BGP_STR "BGP information\n" #define BGP_SOFT_STR "Soft reconfig inbound and outbound updates\n" #define BGP_SOFT_IN_STR "Send route-refresh unless using 'soft-reconfiguration inbound'\n" @@ -437,15 +378,7 @@ extern int cmd_hostname_set (const char *hostname); /* NOT safe for general use; call this only if DEV_BUILD! */ extern void grammar_sandbox_init (void); -/* memory management for cmd_token */ -extern struct cmd_token *new_cmd_token (enum cmd_token_type, u_char attr, - const char *text, const char *desc); -extern void del_cmd_token (struct cmd_token *); -extern struct cmd_token *copy_cmd_token (struct cmd_token *); - extern vector completions_to_vec (struct list *completions); -extern void cmd_merge_graphs (struct graph *old, struct graph *new, int direction); -extern void command_parse_format (struct graph *graph, struct cmd_element *cmd); /* Export typical functions. */ extern const char *host_config_get (void); @@ -458,7 +391,12 @@ extern int cmd_banner_motd_file (const char *); /* struct host global, ick */ extern struct host host; -/* text for <cr> command */ -#define CMD_CR_TEXT "<cr>" +struct cmd_variable_handler { + const char *tokenname, *varname; + void (*completions)(vector out, struct cmd_token *token); +}; + +extern void cmd_variable_complete (struct cmd_token *token, const char *arg, vector comps); +extern void cmd_variable_handler_register (const struct cmd_variable_handler *cvh); #endif /* _ZEBRA_COMMAND_H */ diff --git a/lib/command_graph.c b/lib/command_graph.c new file mode 100644 index 0000000000..8cfb333575 --- /dev/null +++ b/lib/command_graph.c @@ -0,0 +1,478 @@ +/* + * CLI graph handling + * + * -- + * Copyright (C) 2016 Cumulus Networks, Inc. + * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro + * Copyright (C) 2013 by Open Source Routing. + * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC") + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "command_graph.h" + +DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens") +DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text") +DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help") +DEFINE_MTYPE( LIB, CMD_ARG, "Command Argument") +DEFINE_MTYPE_STATIC(LIB, CMD_VAR, "Command Argument Name") + +struct cmd_token * +cmd_token_new (enum cmd_token_type type, u_char attr, + const char *text, const char *desc) +{ + struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token)); + token->type = type; + token->attr = attr; + token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL; + token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL; + token->refcnt = 1; + token->arg = NULL; + token->allowrepeat = false; + token->varname = NULL; + + return token; +} + +void +cmd_token_del (struct cmd_token *token) +{ + if (!token) return; + + XFREE (MTYPE_CMD_TEXT, token->text); + XFREE (MTYPE_CMD_DESC, token->desc); + XFREE (MTYPE_CMD_ARG, token->arg); + XFREE (MTYPE_CMD_VAR, token->varname); + + XFREE (MTYPE_CMD_TOKENS, token); +} + +struct cmd_token * +cmd_token_dup (struct cmd_token *token) +{ + struct cmd_token *copy = cmd_token_new (token->type, token->attr, NULL, NULL); + copy->max = token->max; + copy->min = token->min; + copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL; + copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL; + copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL; + copy->varname = token->varname ? XSTRDUP (MTYPE_CMD_VAR, token->varname) : NULL; + + return copy; +} + +void cmd_token_varname_set(struct cmd_token *token, const char *varname) +{ + XFREE (MTYPE_CMD_VAR, token->varname); + if (!varname) + { + token->varname = NULL; + return; + } + + size_t len = strlen (varname), i; + token->varname = XMALLOC (MTYPE_CMD_VAR, len + 1); + + for (i = 0; i < len; i++) + switch (varname[i]) + { + case '-': + case '+': + case '*': + case ':': + token->varname[i] = '_'; + break; + default: + token->varname[i] = tolower (varname[i]); + } + token->varname[len] = '\0'; +} + +static bool +cmd_nodes_link (struct graph_node *from, struct graph_node *to) +{ + for (size_t i = 0; i < vector_active (from->to); i++) + if (vector_slot (from->to, i) == to) + return true; + return false; +} + +static bool cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb); + +/* returns a single node to be excluded as "next" from iteration + * - for JOIN_TKN, never continue back to the FORK_TKN + * - in all other cases, don't try the node itself (in case of "...") + */ +static inline struct graph_node * +cmd_loopstop(struct graph_node *gn) +{ + struct cmd_token *tok = gn->data; + if (tok->type == JOIN_TKN) + return tok->forkjoin; + else + return gn; +} + +static bool +cmd_subgraph_equal (struct graph_node *ga, struct graph_node *gb, + struct graph_node *a_join) +{ + size_t i, j; + struct graph_node *a_fork, *b_fork; + a_fork = cmd_loopstop (ga); + b_fork = cmd_loopstop (gb); + + if (vector_active (ga->to) != vector_active (gb->to)) + return false; + for (i = 0; i < vector_active (ga->to); i++) + { + struct graph_node *cga = vector_slot (ga->to, i); + + for (j = 0; j < vector_active (gb->to); j++) + { + struct graph_node *cgb = vector_slot (gb->to, i); + + if (cga == a_fork && cgb != b_fork) + continue; + if (cga == a_fork && cgb == b_fork) + break; + + if (cmd_nodes_equal (cga, cgb)) + { + if (cga == a_join) + break; + if (cmd_subgraph_equal (cga, cgb, a_join)) + break; + } + } + if (j == vector_active (gb->to)) + return false; + } + return true; +} + +/* deep compare -- for FORK_TKN, the entire subgraph is compared. + * this is what's needed since we're not currently trying to partially + * merge subgraphs */ +static bool +cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb) +{ + struct cmd_token *a = ga->data, *b = gb->data; + + if (a->type != b->type || a->allowrepeat != b->allowrepeat) + return false; + if (a->type < SPECIAL_TKN && strcmp (a->text, b->text)) + return false; + /* one a ..., the other not. */ + if (cmd_nodes_link (ga, ga) != cmd_nodes_link (gb, gb)) + return false; + if (!a->varname != !b->varname) + return false; + if (a->varname && strcmp (a->varname, b->varname)) + return false; + + switch (a->type) + { + case RANGE_TKN: + return a->min == b->min && a->max == b->max; + + case FORK_TKN: + /* one is keywords, the other just option or selector ... */ + if (cmd_nodes_link (a->forkjoin, ga) != cmd_nodes_link (b->forkjoin, gb)) + return false; + if (cmd_nodes_link (ga, a->forkjoin) != cmd_nodes_link (gb, b->forkjoin)) + return false; + return cmd_subgraph_equal (ga, gb, a->forkjoin); + + default: + return true; + } +} + +static void +cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join, + u_char attr) +{ + size_t i; + struct cmd_token *tok = gn->data; + struct graph_node *stop = cmd_loopstop (gn); + + tok->attr = attr; + for (i = 0; i < vector_active (gn->to); i++) + { + struct graph_node *next = vector_slot (gn->to, i); + if (next == stop || next == join) + continue; + cmd_fork_bump_attr (next, join, attr); + } +} + +/* move an entire subtree from the temporary graph resulting from + * parse() into the permanent graph for the command node. + * + * this touches rather deeply into the graph code unfortunately. + */ +static void +cmd_reparent_tree (struct graph *fromgraph, struct graph *tograph, + struct graph_node *node) +{ + struct graph_node *stop = cmd_loopstop (node); + size_t i; + + for (i = 0; i < vector_active (fromgraph->nodes); i++) + if (vector_slot (fromgraph->nodes, i) == node) + { + /* agressive iteration punching through subgraphs - may hit some + * nodes twice. reparent only if found on old graph */ + vector_unset (fromgraph->nodes, i); + vector_set (tograph->nodes, node); + break; + } + + for (i = 0; i < vector_active (node->to); i++) + { + struct graph_node *next = vector_slot (node->to, i); + if (next != stop) + cmd_reparent_tree (fromgraph, tograph, next); + } +} + +static void +cmd_free_recur (struct graph *graph, struct graph_node *node, + struct graph_node *stop) +{ + struct graph_node *next, *nstop; + + for (size_t i = vector_active (node->to); i; i--) + { + next = vector_slot (node->to, i - 1); + if (next == stop) + continue; + nstop = cmd_loopstop (next); + if (nstop != next) + cmd_free_recur (graph, next, nstop); + cmd_free_recur (graph, nstop, stop); + } + graph_delete_node (graph, node); +} + +static void +cmd_free_node (struct graph *graph, struct graph_node *node) +{ + struct cmd_token *tok = node->data; + if (tok->type == JOIN_TKN) + cmd_free_recur (graph, tok->forkjoin, node); + graph_delete_node (graph, node); +} + +/* recursive graph merge. call with + * old ~= new + * (which holds true for old == START_TKN, new == START_TKN) + */ +static void +cmd_merge_nodes (struct graph *oldgraph, struct graph *newgraph, + struct graph_node *old, struct graph_node *new, + int direction) +{ + struct cmd_token *tok; + struct graph_node *old_skip, *new_skip; + old_skip = cmd_loopstop (old); + new_skip = cmd_loopstop (new); + + assert (direction == 1 || direction == -1); + + tok = old->data; + tok->refcnt += direction; + + size_t j, i; + for (j = 0; j < vector_active (new->to); j++) + { + struct graph_node *cnew = vector_slot (new->to, j); + if (cnew == new_skip) + continue; + + for (i = 0; i < vector_active (old->to); i++) + { + struct graph_node *cold = vector_slot (old->to, i); + if (cold == old_skip) + continue; + + if (cmd_nodes_equal (cold, cnew)) + { + struct cmd_token *told = cold->data, *tnew = cnew->data; + + if (told->type == END_TKN) + { + if (direction < 0) + { + graph_delete_node (oldgraph, vector_slot (cold->to, 0)); + graph_delete_node (oldgraph, cold); + } + else + /* force no-match handling to install END_TKN */ + i = vector_active (old->to); + break; + } + + /* the entire fork compared as equal, we continue after it. */ + if (told->type == FORK_TKN) + { + if (tnew->attr < told->attr && direction > 0) + cmd_fork_bump_attr (cold, told->forkjoin, tnew->attr); + /* XXX: no reverse bump on uninstall */ + told = (cold = told->forkjoin)->data; + tnew = (cnew = tnew->forkjoin)->data; + } + if (tnew->attr < told->attr) + told->attr = tnew->attr; + + cmd_merge_nodes (oldgraph, newgraph, cold, cnew, direction); + break; + } + } + /* nothing found => add new to old */ + if (i == vector_active (old->to) && direction > 0) + { + assert (vector_count (cnew->from) == + cmd_nodes_link (cnew, cnew) ? 2 : 1); + graph_remove_edge (new, cnew); + + cmd_reparent_tree (newgraph, oldgraph, cnew); + + graph_add_edge (old, cnew); + } + } + + if (!tok->refcnt) + cmd_free_node (oldgraph, old); +} + +void +cmd_graph_merge (struct graph *old, struct graph *new, int direction) +{ + assert (vector_active (old->nodes) >= 1); + assert (vector_active (new->nodes) >= 1); + + cmd_merge_nodes (old, new, + vector_slot (old->nodes, 0), vector_slot (new->nodes, 0), + direction); +} + +static void +cmd_node_names (struct graph_node *gn, struct graph_node *join, + const char *prevname) +{ + size_t i; + struct cmd_token *tok = gn->data, *jointok; + struct graph_node *stop = cmd_loopstop (gn); + + switch (tok->type) + { + case WORD_TKN: + prevname = tok->text; + break; + + case VARIABLE_TKN: + if (!tok->varname + && strcmp (tok->text, "WORD") + && strcmp (tok->text, "NAME")) + cmd_token_varname_set (tok, tok->text); + /* fallthrough */ + case RANGE_TKN: + case IPV4_TKN: + case IPV4_PREFIX_TKN: + case IPV6_TKN: + case IPV6_PREFIX_TKN: + if (!tok->varname && prevname) + cmd_token_varname_set (tok, prevname); + prevname = NULL; + break; + + case START_TKN: + case END_TKN: + case JOIN_TKN: + /* "<foo|bar> WORD" -> word is not "bar" or "foo" */ + prevname = NULL; + break; + + case FORK_TKN: + /* apply "<A.B.C.D|X:X::X:X>$name" */ + jointok = tok->forkjoin->data; + if (!jointok->varname) + break; + for (i = 0; i < vector_active (tok->forkjoin->from); i++) + { + struct graph_node *tail = vector_slot (tok->forkjoin->from, i); + struct cmd_token *tailtok = tail->data; + if (tail == gn || tailtok->varname) + continue; + cmd_token_varname_set (tailtok, jointok->varname); + } + break; + } + + for (i = 0; i < vector_active (gn->to); i++) + { + struct graph_node *next = vector_slot (gn->to, i); + if (next == stop || next == join) + continue; + cmd_node_names (next, join, prevname); + } + + if (tok->type == FORK_TKN && tok->forkjoin != join) + cmd_node_names (tok->forkjoin, join, NULL); +} + +void +cmd_graph_names (struct graph *graph) +{ + struct graph_node *start; + + assert (vector_active (graph->nodes) >= 1); + start = vector_slot (graph->nodes, 0); + + /* apply varname on initial "[no]" */ + do + { + if (vector_active (start->to) != 1) + break; + + struct graph_node *first = vector_slot (start->to, 0); + struct cmd_token *tok = first->data; + /* looking for an option with 2 choices, nothing or "no" */ + if (tok->type != FORK_TKN || vector_active (first->to) != 2) + break; + + struct graph_node *next0 = vector_slot (first->to, 0); + struct graph_node *next1 = vector_slot (first->to, 1); + /* one needs to be empty */ + if (next0 != tok->forkjoin && next1 != tok->forkjoin) + break; + + struct cmd_token *tok0 = next0->data; + struct cmd_token *tok1 = next1->data; + /* the other one needs to be "no" (only one will match here) */ + if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no"))) + cmd_token_varname_set (tok0, "no"); + if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no"))) + cmd_token_varname_set (tok1, "no"); + } + while (0); + + cmd_node_names (start, NULL, NULL); +} diff --git a/lib/command_graph.h b/lib/command_graph.h new file mode 100644 index 0000000000..a7a34a0598 --- /dev/null +++ b/lib/command_graph.h @@ -0,0 +1,119 @@ +/* + * CLI graph handling + * + * -- + * Copyright (C) 2016 Cumulus Networks, Inc. + * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro + * Copyright (C) 2013 by Open Source Routing. + * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC") + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_COMMAND_GRAPH_H +#define _FRR_COMMAND_GRAPH_H + +#include <stdbool.h> +#include <stdint.h> + +#include "memory.h" +#include "vector.h" +#include "graph.h" + +DECLARE_MTYPE(CMD_ARG) + +struct vty; + +/** + * Types for tokens. + * + * The type determines what kind of data the token can match (in the + * matching use case) or hold (in the argv use case). + */ +enum cmd_token_type +{ + WORD_TKN, // words + VARIABLE_TKN, // almost anything + RANGE_TKN, // integer range + IPV4_TKN, // IPV4 addresses + IPV4_PREFIX_TKN, // IPV4 network prefixes + IPV6_TKN, // IPV6 prefixes + IPV6_PREFIX_TKN, // IPV6 network prefixes + + /* plumbing types */ + FORK_TKN, // marks subgraph beginning + JOIN_TKN, // marks subgraph end + START_TKN, // first token in line + END_TKN, // last token in line + + SPECIAL_TKN = FORK_TKN, +}; + +#define IS_VARYING_TOKEN(x) ((x) >= VARIABLE_TKN && (x) < FORK_TKN) + +/* Command attributes */ +enum +{ + CMD_ATTR_NORMAL, + CMD_ATTR_DEPRECATED, + CMD_ATTR_HIDDEN, +}; + +/* Comamand token struct. */ +struct cmd_token +{ + enum cmd_token_type type; // token type + uint8_t attr; // token attributes + bool allowrepeat; // matcher allowed to match token repetively? + uint32_t refcnt; + + char *text; // token text + char *desc; // token description + long long min, max; // for ranges + char *arg; // user input that matches this token + char *varname; + + struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK +}; + +/* Structure of command element. */ +struct cmd_element +{ + const char *string; /* Command specification by string. */ + const char *doc; /* Documentation of this command. */ + int daemon; /* Daemon to which this command belong. */ + uint8_t attr; /* Command attributes */ + + /* handler function for command */ + int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]); + + const char *name; /* symbol name for debugging */ +}; + +/* text for <cr> command */ +#define CMD_CR_TEXT "<cr>" + +/* memory management for cmd_token */ +extern struct cmd_token *cmd_token_new (enum cmd_token_type, uint8_t attr, + const char *text, const char *desc); +extern struct cmd_token *cmd_token_dup (struct cmd_token *); +extern void cmd_token_del (struct cmd_token *); +extern void cmd_token_varname_set(struct cmd_token *token, const char *varname); + +extern void cmd_graph_parse (struct graph *graph, struct cmd_element *cmd); +extern void cmd_graph_names (struct graph *graph); +extern void cmd_graph_merge (struct graph *old, struct graph *new, int direction); + +#endif /* _FRR_COMMAND_GRAPH_H */ diff --git a/lib/command_lex.l b/lib/command_lex.l index deec1757c2..c020d193a1 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -23,6 +23,9 @@ */ %{ +/* ignore harmless bug in old versions of flex */ +#pragma GCC diagnostic ignored "-Wsign-compare" + #include "command_parse.h" #define YY_USER_ACTION yylloc->last_column += yyleng; diff --git a/lib/command_match.c b/lib/command_match.c index bbd9cd091d..75d8fdc3d3 100644 --- a/lib/command_match.c +++ b/lib/command_match.c @@ -16,10 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -78,10 +77,7 @@ static enum match_type match_ipv4_prefix (const char *); static enum match_type -match_ipv6 (const char *); - -static enum match_type -match_ipv6_prefix (const char *); +match_ipv6_prefix (const char *, bool); static enum match_type match_range (struct cmd_token *, const char *); @@ -117,7 +113,7 @@ command_match (struct graph *cmdgraph, struct listnode *tail = listtail (*argv); // delete dummy start node - del_cmd_token ((struct cmd_token *) head->data); + cmd_token_del ((struct cmd_token *) head->data); list_delete_node (*argv, head); // get cmd_element out of list tail @@ -281,7 +277,7 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n, // manually deleted struct cmd_element *el = leaf->data; listnode_add (currbest, el); - currbest->del = (void (*)(void *)) &del_cmd_token; + currbest->del = (void (*)(void *)) &cmd_token_del; // do not break immediately; continue walking through the follow set // to ensure that there is exactly one END_TKN } @@ -320,7 +316,7 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n, { // copy token, set arg and prepend to currbest struct cmd_token *token = start->data; - struct cmd_token *copy = copy_cmd_token (token); + struct cmd_token *copy = cmd_token_dup (token); copy->arg = XSTRDUP (MTYPE_CMD_ARG, input_token); listnode_add_before (currbest, currbest->head, copy); matcher_rv = MATCHER_OK; @@ -677,9 +673,9 @@ match_token (struct cmd_token *token, char *input_token) case IPV4_PREFIX_TKN: return match_ipv4_prefix (input_token); case IPV6_TKN: - return match_ipv6 (input_token); + return match_ipv6_prefix (input_token, false); case IPV6_PREFIX_TKN: - return match_ipv6_prefix (input_token); + return match_ipv6_prefix (input_token, true); case RANGE_TKN: return match_range (token, input_token); case VARIABLE_TKN: @@ -835,35 +831,18 @@ match_ipv4_prefix (const char *str) #define STATE_MASK 7 static enum match_type -match_ipv6 (const char *str) -{ - struct sockaddr_in6 sin6_dummy; - int ret; - - if (strspn (str, IPV6_ADDR_STR) != strlen (str)) - return no_match; - - ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr); - - if (ret == 1) - return exact_match; - - return no_match; -} - -static enum match_type -match_ipv6_prefix (const char *str) +match_ipv6_prefix (const char *str, bool prefix) { int state = STATE_START; int colons = 0, nums = 0, double_colon = 0; int mask; - const char *sp = NULL; + const char *sp = NULL, *start = str; char *endptr = NULL; if (str == NULL) return partly_match; - if (strspn (str, IPV6_PREFIX_STR) != strlen (str)) + if (strspn (str, prefix ? IPV6_PREFIX_STR : IPV6_ADDR_STR) != strlen (str)) return no_match; while (*str != '\0' && state != STATE_MASK) @@ -966,6 +945,13 @@ match_ipv6_prefix (const char *str) str++; } + if (!prefix) + { + struct sockaddr_in6 sin6_dummy; + int ret = inet_pton(AF_INET6, start, &sin6_dummy.sin6_addr); + return ret == 1 ? exact_match : partly_match; + } + if (state < STATE_MASK) return partly_match; diff --git a/lib/command_match.h b/lib/command_match.h index 9e18b8d905..a04f60f0d8 100644 --- a/lib/command_match.h +++ b/lib/command_match.h @@ -16,10 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_COMMAND_MATCH_H diff --git a/lib/command_parse.y b/lib/command_parse.y index 0c415af3aa..466e3d3f1f 100644 --- a/lib/command_parse.y +++ b/lib/command_parse.y @@ -44,12 +44,12 @@ * struct parser_ctx is needed for the bison forward decls. */ %code requires { - #include "stdlib.h" - #include "string.h" - #include "memory.h" - #include "command.h" + #include <stdlib.h> + #include <string.h> + #include <ctype.h> + + #include "command_graph.h" #include "log.h" - #include "graph.h" DECLARE_MTYPE(LEX) @@ -104,12 +104,15 @@ %type <node> start %type <node> literal_token %type <node> placeholder_token +%type <node> placeholder_token_real %type <node> simple_token %type <subgraph> selector %type <subgraph> selector_token %type <subgraph> selector_token_seq %type <subgraph> selector_seq_seq +%type <string> varname_token + %code { /* bison declarations */ @@ -184,6 +187,16 @@ start: } ; +varname_token: '$' WORD +{ + $$ = XSTRDUP (MTYPE_LEX, $2); +} +| /* empty */ +{ + $$ = NULL; +} +; + cmd_token_seq: /* empty */ | cmd_token_seq cmd_token @@ -207,14 +220,16 @@ simple_token: | placeholder_token ; -literal_token: WORD +literal_token: WORD varname_token { $$ = new_token_node (ctx, WORD_TKN, $1, doc_next(ctx)); + cmd_token_varname_set ($$->data, $2); + XFREE (MTYPE_LEX, $2); XFREE (MTYPE_LEX, $1); } ; -placeholder_token: +placeholder_token_real: IPV4 { $$ = new_token_node (ctx, IPV4_TKN, $1, doc_next(ctx)); @@ -257,10 +272,22 @@ placeholder_token: XFREE (MTYPE_LEX, $1); } +placeholder_token: + placeholder_token_real varname_token +{ + struct cmd_token *token = $$->data; + $$ = $1; + cmd_token_varname_set (token, $2); + XFREE (MTYPE_LEX, $2); +}; + + /* <selector|set> productions */ -selector: '<' selector_seq_seq '>' +selector: '<' selector_seq_seq '>' varname_token { $$ = $2; + cmd_token_varname_set ($2.end->data, $4); + XFREE (MTYPE_LEX, $4); }; selector_seq_seq: @@ -283,7 +310,7 @@ selector_seq_seq: ; /* {keyword} productions */ -selector: '{' selector_seq_seq '}' +selector: '{' selector_seq_seq '}' varname_token { $$ = $2; graph_add_edge ($$.end, $$.start); @@ -293,6 +320,9 @@ selector: '{' selector_seq_seq '}' * loop-avoidal fails to handle * just use [{a|b}] if neccessary, that will work perfectly fine, and reason * #1 is good enough to keep it this way. */ + + cmd_token_varname_set ($2.end->data, $4); + XFREE (MTYPE_LEX, $4); }; @@ -315,10 +345,12 @@ selector_token_seq: ; /* [option] productions */ -selector: '[' selector_seq_seq ']' +selector: '[' selector_seq_seq ']' varname_token { $$ = $2; graph_add_edge ($$.start, $$.end); + cmd_token_varname_set ($2.end->data, $4); + XFREE (MTYPE_LEX, $4); } ; @@ -329,7 +361,7 @@ selector: '[' selector_seq_seq ']' DEFINE_MTYPE(LIB, LEX, "Lexer token (temporary)") void -command_parse_format (struct graph *graph, struct cmd_element *cmd) +cmd_graph_parse (struct graph *graph, struct cmd_element *cmd) { struct parser_ctx ctx = { .graph = graph, .el = cmd }; @@ -430,6 +462,6 @@ static struct graph_node * new_token_node (struct parser_ctx *ctx, enum cmd_token_type type, const char *text, const char *doc) { - struct cmd_token *token = new_cmd_token (type, ctx->el->attr, text, doc); - return graph_new_node (ctx->graph, token, (void (*)(void *)) &del_cmd_token); + struct cmd_token *token = cmd_token_new (type, ctx->el->attr, text, doc); + return graph_new_node (ctx->graph, token, (void (*)(void *)) &cmd_token_del); } @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdio.h> #include <stdlib.h> @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CSV_H__ diff --git a/lib/distribute.c b/lib/distribute.c index f85994c9a8..7b7d49d1d6 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/distribute.h b/lib/distribute.h index e9625a3548..23d7cac577 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_DISTRIBUTE_H diff --git a/lib/event_counter.c b/lib/event_counter.c index e94aa4c0f6..0acd0a1f7a 100644 --- a/lib/event_counter.c +++ b/lib/event_counter.c @@ -35,10 +35,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/event_counter.h b/lib/event_counter.h index f40c6cde63..8c11e10287 100644 --- a/lib/event_counter.h +++ b/lib/event_counter.h @@ -35,10 +35,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_EVENT_COUNTER_H diff --git a/lib/fifo.h b/lib/fifo.h index 6be75b7611..631556e78e 100644 --- a/lib/fifo.h +++ b/lib/fifo.h @@ -1,22 +1,22 @@ /* FIFO common header. - Copyright (C) 2015 Kunihiro Ishiguro - -This file is part of Quagga. - -Quagga is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -Quagga is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + * Copyright (C) 2015 Kunihiro Ishiguro + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef __LIB_FIFO_H__ #define __LIB_FIFO_H__ diff --git a/lib/filter.c b/lib/filter.c index fd73d4de73..93aac31b4f 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/filter.h b/lib/filter.h index 6b5ccb52ec..2c70018112 100644 --- a/lib/filter.h +++ b/lib/filter.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_FILTER_H diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c new file mode 100644 index 0000000000..17bc82f5da --- /dev/null +++ b/lib/frr_pthread.c @@ -0,0 +1,183 @@ +/* + * Utilities and interfaces for managing POSIX threads + * Copyright (C) 2017 Cumulus Networks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> +#include <pthread.h> + +#include "frr_pthread.h" +#include "memory.h" +#include "hash.h" + +DEFINE_MTYPE_STATIC(LIB, FRR_PTHREAD, "FRR POSIX Thread"); + +static unsigned int next_id = 0; + +/* Hash table of all frr_pthreads along with synchronization primitive(s) and + * hash table callbacks. + * ------------------------------------------------------------------------ */ +static struct hash *pthread_table; +static pthread_mutex_t pthread_table_mtx = PTHREAD_MUTEX_INITIALIZER; + +/* pthread_table->hash_cmp */ +static int pthread_table_hash_cmp(const void *value1, const void *value2) +{ + const struct frr_pthread *tq1 = value1; + const struct frr_pthread *tq2 = value2; + + return (tq1->id == tq2->id); +} + +/* pthread_table->hash_key */ +static unsigned int pthread_table_hash_key(void *value) +{ + return ((struct frr_pthread *)value)->id; +} +/* ------------------------------------------------------------------------ */ + +void frr_pthread_init() +{ + pthread_mutex_lock(&pthread_table_mtx); + { + pthread_table = + hash_create(pthread_table_hash_key, pthread_table_hash_cmp); + } + pthread_mutex_unlock(&pthread_table_mtx); +} + +void frr_pthread_finish() +{ + pthread_mutex_lock(&pthread_table_mtx); + { + hash_clean(pthread_table, (void (*)(void *))frr_pthread_destroy); + hash_free(pthread_table); + } + pthread_mutex_unlock(&pthread_table_mtx); +} + +struct frr_pthread *frr_pthread_new(const char *name, unsigned int id, + void *(*start_routine) (void *), + int (*stop_routine) (void **, struct frr_pthread *)) +{ + static struct frr_pthread holder = { 0 }; + struct frr_pthread *fpt = NULL; + + pthread_mutex_lock(&pthread_table_mtx); + { + holder.id = id; + + if (!hash_lookup(pthread_table, &holder)) { + struct frr_pthread *fpt = + XCALLOC(MTYPE_FRR_PTHREAD, + sizeof(struct frr_pthread)); + fpt->id = id; + fpt->master = thread_master_create(); + fpt->start_routine = start_routine; + fpt->stop_routine = stop_routine; + fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name); + + hash_get(pthread_table, fpt, hash_alloc_intern); + } + } + pthread_mutex_unlock(&pthread_table_mtx); + + return fpt; +} + +void frr_pthread_destroy(struct frr_pthread *fpt) +{ + thread_master_free(fpt->master); + XFREE(MTYPE_FRR_PTHREAD, fpt->name); + XFREE(MTYPE_FRR_PTHREAD, fpt); +} + +struct frr_pthread *frr_pthread_get(unsigned int id) +{ + static struct frr_pthread holder = { 0 }; + struct frr_pthread *fpt; + + pthread_mutex_lock(&pthread_table_mtx); + { + holder.id = id; + fpt = hash_lookup(pthread_table, &holder); + } + pthread_mutex_unlock(&pthread_table_mtx); + + return fpt; +} + +int frr_pthread_run(unsigned int id, const pthread_attr_t * attr, void *arg) +{ + struct frr_pthread *fpt = frr_pthread_get(id); + int ret; + + if (!fpt) + return -1; + + ret = pthread_create(&fpt->thread, attr, fpt->start_routine, arg); + + /* Per pthread_create(3), the contents of fpt->thread are undefined if + * pthread_create() did not succeed. Reset this value to zero. */ + if (ret < 0) + memset(&fpt->thread, 0x00, sizeof(fpt->thread)); + + return ret; +} + +/** + * Calls the stop routine for the frr_pthread and resets any relevant fields. + * + * @param fpt - the frr_pthread to stop + * @param result - pointer to result pointer + * @return the return code from the stop routine + */ +static int frr_pthread_stop_actual(struct frr_pthread *fpt, void **result) +{ + int ret = (*fpt->stop_routine) (result, fpt); + memset(&fpt->thread, 0x00, sizeof(fpt->thread)); + return ret; +} + +int frr_pthread_stop(unsigned int id, void **result) +{ + struct frr_pthread *fpt = frr_pthread_get(id); + return frr_pthread_stop_actual(fpt, result); +} + +/** + * Callback for hash_iterate to stop all frr_pthread's. + */ +static void frr_pthread_stop_all_iter(struct hash_backet *hb, void *arg) +{ + struct frr_pthread *fpt = hb->data; + frr_pthread_stop_actual(fpt, NULL); +} + +void frr_pthread_stop_all() +{ + pthread_mutex_lock(&pthread_table_mtx); + { + hash_iterate(pthread_table, frr_pthread_stop_all_iter, NULL); + } + pthread_mutex_unlock(&pthread_table_mtx); +} + +unsigned int frr_pthread_get_id() +{ + return next_id++; +} diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h new file mode 100644 index 0000000000..1a390b1e45 --- /dev/null +++ b/lib/frr_pthread.h @@ -0,0 +1,144 @@ +/* + * Utilities and interfaces for managing POSIX threads + * Copyright (C) 2017 Cumulus Networks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_PTHREAD_H +#define _FRR_PTHREAD_H + +#include <pthread.h> +#include "thread.h" + +struct frr_pthread { + + /* pthread id */ + pthread_t thread; + + /* frr thread identifier */ + unsigned int id; + + /* thread master for this pthread's thread.c event loop */ + struct thread_master *master; + + /* start routine */ + void *(*start_routine) (void *); + + /* stop routine */ + int (*stop_routine) (void **, struct frr_pthread *); + + /* the (hopefully descriptive) name of this thread */ + char *name; +}; + +/* Initializes this module. + * + * Must be called before using any of the other functions. + */ +void frr_pthread_init(void); + +/* Uninitializes this module. + * + * Destroys all registered frr_pthread's and internal data structures. + * + * It is safe to call frr_pthread_init() after this function to reinitialize + * the module. + */ +void frr_pthread_finish(void); + +/* Creates a new frr_pthread. + * + * If the provided ID is already assigned to an existing frr_pthread, the + * return value will be NULL. + * + * @param name - the name of the thread. Doesn't have to be unique, but it + * probably should be. This value is copied and may be safely free'd upon + * return. + * + * @param id - the integral ID of the thread. MUST be unique. The caller may + * use this id to retrieve the thread. + * + * @param start_routine - start routine for the pthread, will be passed to + * pthread_create (see those docs for details) + * + * @param stop_routine - stop routine for the pthread, called to terminate the + * thread. This function should gracefully stop the pthread and clean up any + * thread-specific resources. The passed pointer is used to return a data + * result. + * + * @return the created frr_pthread upon success, or NULL upon failure + */ +struct frr_pthread *frr_pthread_new(const char *name, unsigned int id, + void *(*start_routine) (void *), + int (*stop_routine) (void **, struct frr_pthread *)); + +/* Destroys an frr_pthread. + * + * Assumes that the associated pthread, if any, has already terminated. + * + * @param fpt - the frr_pthread to destroy + */ +void frr_pthread_destroy(struct frr_pthread *fpt); + +/* Gets an existing frr_pthread by its id. + * + * @return frr_thread associated with the provided id, or NULL on error + */ +struct frr_pthread *frr_pthread_get(unsigned int id); + +/* Creates a new pthread and binds it to a frr_pthread. + * + * This function is a wrapper for pthread_create. The first parameter is the + * frr_pthread to bind the created pthread to. All subsequent arguments are + * passed unmodified to pthread_create(). + * + * This function returns the same code as pthread_create(). If the value is + * zero, the provided frr_pthread is bound to a running POSIX thread. If the + * value is less than zero, the provided frr_pthread is guaranteed to be a + * clean instance that may be susbsequently passed to frr_pthread_run(). + * + * @param id - frr_pthread to bind the created pthread to + * @param attr - see pthread_create(3) + * @param arg - see pthread_create(3) + * + * @return see pthread_create(3) + */ +int frr_pthread_run(unsigned int id, const pthread_attr_t * attr, void *arg); + +/* Stops an frr_pthread with a result. + * + * @param id - frr_pthread to stop + * @param result - where to store the thread's result, if any. May be NULL if a + * result is not needed. + */ +int frr_pthread_stop(unsigned int id, void **result); + +/* Stops all frr_pthread's. */ +void frr_pthread_stop_all(void); + +/* Returns a unique identifier for use with frr_pthread_new(). + * + * Internally, this is an integer that increments after each call to this + * function. Because the number of pthreads created should never exceed INT_MAX + * during the life of the program, there is no overflow protection. If by + * chance this function returns an ID which is already in use, + * frr_pthread_new() will fail when it is provided. + * + * @return unique identifier + */ +unsigned int frr_pthread_get_id(void); + +#endif /* _FRR_PTHREAD_H */ diff --git a/lib/frratomic.h b/lib/frratomic.h new file mode 100644 index 0000000000..183790aeb0 --- /dev/null +++ b/lib/frratomic.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _FRRATOMIC_H +#define _FRRATOMIC_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef FRR_AUTOCONF_ATOMIC +#error autoconf checks for atomic functions were not properly run +#endif + +/* ISO C11 */ +#ifdef HAVE_STDATOMIC_H +#include <stdatomic.h> + +/* gcc 4.7 and newer */ +#elif defined(HAVE___ATOMIC) + +#define _Atomic volatile + +#define memory_order_relaxed __ATOMIC_RELAXED +#define memory_order_consume __ATOMIC_CONSUME +#define memory_order_acquire __ATOMIC_ACQUIRE +#define memory_order_release __ATOMIC_RELEASE +#define memory_order_acq_rel __ATOMIC_ACQ_REL +#define memory_order_seq_cst __ATOMIC_SEQ_CST + +#define atomic_load_explicit __atomic_load_n +#define atomic_store_explicit __atomic_store_n +#define atomic_exchange_explicit __atomic_exchange_n +#define atomic_fetch_add_explicit __atomic_fetch_add +#define atomic_fetch_sub_explicit __atomic_fetch_sub + +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ + __atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2) + +/* gcc 4.1 and newer, + * clang 3.3 (possibly older) + * + * __sync_swap isn't in gcc's documentation, but clang has it + * + * note __sync_synchronize() + */ +#elif defined(HAVE___SYNC) + +#define _Atomic volatile + +#define memory_order_relaxed 0 +#define memory_order_consume 0 +#define memory_order_acquire 0 +#define memory_order_release 0 +#define memory_order_acq_rel 0 +#define memory_order_seq_cst 0 + +#define atomic_load_explicit(ptr, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \ + __sync_synchronize(); rval; }) +#define atomic_store_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + *(ptr) = (val); \ + __sync_synchronize(); (void)0; }) +#ifdef HAVE___SYNC_SWAP +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_swap((ptr, val), 0); \ + __sync_synchronize(); rval; }) +#else /* !HAVE___SYNC_SWAP */ +#define atomic_exchange_explicit(ptr, val, mem) \ + ({ typeof(ptr) _ptr = (ptr); typeof(val) _val = (val); \ + __sync_synchronize(); \ + typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \ + do { \ + old1 = old2; \ + old2 = __sync_val_compare_and_swap (_ptr, old1, _val); \ + } while (old1 != old2); \ + __sync_synchronize(); \ + old2; \ + }) +#endif /* !HAVE___SYNC_SWAP */ +#define atomic_fetch_add_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \ + __sync_synchronize(); rval; }) +#define atomic_fetch_sub_explicit(ptr, val, mem) \ + ({ __sync_synchronize(); \ + typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \ + __sync_synchronize(); rval; }) + +#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \ + ({ typeof(atom) _atom = (atom); typeof(expect) _expect = (expect); \ + typeof(desire) _desire = (desire); \ + __sync_synchronize(); \ + typeof(*atom) rval = __sync_val_compare_and_swap(_atom, *_expect, _desire); \ + __sync_synchronize(); \ + bool ret = (rval == *_expect); *_expect = rval; ret; }) + +#else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */ +#error no atomic functions... +#endif + +#endif /* _FRRATOMIC_H */ diff --git a/lib/getopt.c b/lib/getopt.c index 7a58a8a8cc..d0ee43510b 100644 --- a/lib/getopt.c +++ b/lib/getopt.c @@ -1,28 +1,28 @@ /* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to drepper@gnu.org - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 - Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@gnu.org. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ + * NOTE: getopt is now part of the C library, so if you don't know what + * "Keep this file name-space clean" means, talk to drepper@gnu.org + * before changing it! + * + * Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98 + * Free Software Foundation, Inc. + * + * NOTE: The canonical source of this file is maintained with the GNU C Library. + * Bugs can be reported to bug-glibc@gnu.org. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. Ditto for AIX 3.2 and <stdlib.h>. */ diff --git a/lib/getopt.h b/lib/getopt.h index b359a47beb..cc38a45c23 100644 --- a/lib/getopt.h +++ b/lib/getopt.h @@ -1,23 +1,23 @@ /* Declarations for getopt. - Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@gnu.org. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ + * Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. + * + * NOTE: The canonical source of this file is maintained with the GNU C Library. + * Bugs can be reported to bug-glibc@gnu.org. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _GETOPT_H #define _GETOPT_H 1 diff --git a/lib/getopt1.c b/lib/getopt1.c index bd3099e799..1873a197e1 100644 --- a/lib/getopt1.c +++ b/lib/getopt1.c @@ -1,24 +1,24 @@ /* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 - Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@gnu.org. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ + * Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 + * Free Software Foundation, Inc. + * + * NOTE: The canonical source of this file is maintained with the GNU C Library. + * Bugs can be reported to bug-glibc@gnu.org. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include <zebra.h> #include "getopt.h" diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index 0da7981fc1..cfc3fb7982 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -18,10 +18,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" @@ -70,11 +69,11 @@ DEFUN (grammar_test, // parse the command and install it into the command graph struct graph *graph = graph_new(); - struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); - graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token); + struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL); + graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del); - command_parse_format (graph, cmd); - cmd_merge_graphs (nodegraph, graph, +1); + cmd_graph_parse (graph, cmd); + cmd_graph_merge (nodegraph, graph, +1); return CMD_SUCCESS; } @@ -123,7 +122,7 @@ DEFUN (grammar_test_complete, } for (i = 0; i < vector_active (comps); i++) - del_cmd_token ((struct cmd_token *) vector_slot (comps, i)); + cmd_token_del ((struct cmd_token *) vector_slot (comps, i)); vector_free (comps); } else @@ -229,7 +228,7 @@ DEFUN (grammar_test_doc, cmd->func = NULL; // parse element - command_parse_format (nodegraph, cmd); + cmd_graph_parse (nodegraph, cmd); return CMD_SUCCESS; } @@ -526,6 +525,8 @@ pretty_print_graph (struct vty *vty, struct graph_node *start, int level, vty_out(vty, "%s", LOOKUP_DEF(tokennames, tok->type, tokennum)); if (tok->text) vty_out(vty, ":\"%s\"", tok->text); + if (tok->varname) + vty_out(vty, " => %s", tok->varname); if (desc) vty_out(vty, " ?'%s'", tok->desc); vty_out(vty, " "); @@ -647,8 +648,8 @@ init_cmdgraph (struct vty *vty, struct graph **graph) // initialize graph, add start noe *graph = graph_new (); nodegraph_free = *graph; - struct cmd_token *token = new_cmd_token (START_TKN, 0, NULL, NULL); - graph_new_node (*graph, token, (void (*)(void *)) &del_cmd_token); + struct cmd_token *token = cmd_token_new (START_TKN, 0, NULL, NULL); + graph_new_node (*graph, token, (void (*)(void *)) &cmd_token_del); if (vty) vty_out (vty, "initialized graph%s", VTY_NEWLINE); } diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c index 681d4da440..3bf0e268cf 100644 --- a/lib/grammar_sandbox_main.c +++ b/lib/grammar_sandbox_main.c @@ -19,8 +19,8 @@ * details. * * You should have received a copy of the GNU General Public License along - * with FRR; see the file COPYING. If not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "command.h" diff --git a/lib/graph.c b/lib/graph.c index 0992059ef1..6173b2084b 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -16,10 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> #include "graph.h" diff --git a/lib/graph.h b/lib/graph.h index 8d8aa3823b..d3973d4b02 100644 --- a/lib/graph.h +++ b/lib/graph.h @@ -16,10 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_COMMAND_GRAPH_H diff --git a/lib/hash.c b/lib/hash.c index cb8531fccf..553a137eb6 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/hash.h b/lib/hash.h index 11ecf75ec9..bafb35a2a3 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -1,22 +1,22 @@ /* Hash routine. - Copyright (C) 1998 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published -by the Free Software Foundation; either version 2, or (at your -option) any later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + * Copyright (C) 1998 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _ZEBRA_HASH_H #define _ZEBRA_HASH_H @@ -1,10 +1,9 @@ - /* * Interface functions. * Copyright (C) 1997, 98 Kunihiro Ishiguro * * This file is part of GNU Zebra. - * + * * GNU Zebra is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your @@ -15,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -1126,6 +1124,36 @@ ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex) } #endif /* ifaddr_ipv4_table */ +static void if_autocomplete(vector comps, struct cmd_token *token) +{ + struct interface *ifp; + struct listnode *ln; + struct vrf *vrf = NULL; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + { + for (ALL_LIST_ELEMENTS_RO(vrf->iflist, ln, ifp)) + vector_set (comps, XSTRDUP (MTYPE_COMPLETION, ifp->name)); + } + +} + +static const struct cmd_variable_handler if_var_handlers[] = { + { + /* "interface NAME" */ + .varname = "interface", + .completions = if_autocomplete + }, { + .tokenname = "IFNAME", + .completions = if_autocomplete + }, { + .tokenname = "INTERFACE", + .completions = if_autocomplete + }, { + .completions = NULL + } +}; + /* Initialize interface list. */ void if_init (struct list **intf_list) @@ -1136,6 +1164,8 @@ if_init (struct list **intf_list) #endif /* ifaddr_ipv4_table */ (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func; + + cmd_variable_handler_register(if_var_handlers); } void @@ -1,22 +1,22 @@ /* Interface related header. - Copyright (C) 1997, 98, 99 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published -by the Free Software Foundation; either version 2, or (at your -option) any later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _ZEBRA_IF_H #define _ZEBRA_IF_H diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 2afb08c7ca..fa9b17f2ae 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/if_rmap.h b/lib/if_rmap.h index e6c2966ff8..e38b5f7f73 100644 --- a/lib/if_rmap.h +++ b/lib/if_rmap.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_IF_RMAP_H diff --git a/lib/json.c b/lib/json.c index ccbecb726a..186efc9f48 100644 --- a/lib/json.c +++ b/lib/json.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/json.h b/lib/json.h index 7e98614280..5faaaa841a 100644 --- a/lib/json.h +++ b/lib/json.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _QUAGGA_JSON_H diff --git a/lib/keychain.c b/lib/keychain.c index 95a2c8e599..1aa6edb4bd 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -1,22 +1,22 @@ /* key-chain for authentication. - Copyright (C) 2000 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published -by the Free Software Foundation; either version 2, or (at your -option) any later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + * Copyright (C) 2000 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include <zebra.h> diff --git a/lib/keychain.h b/lib/keychain.h index d3f9168a0f..e6bdcc6f06 100644 --- a/lib/keychain.h +++ b/lib/keychain.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_KEYCHAIN_H diff --git a/lib/libfrr.c b/lib/libfrr.c index de83e14f0e..16681fe578 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -13,9 +13,9 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/libfrr.h b/lib/libfrr.h index 0cc7ad564b..6bd92d8bea 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -13,9 +13,9 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_FRR_H diff --git a/lib/libospf.h b/lib/libospf.h index a1ff9c24a2..c9483a4c65 100644 --- a/lib/libospf.h +++ b/lib/libospf.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LIBOSPFD_H diff --git a/lib/linklist.c b/lib/linklist.c index 6fe91c75fc..0aee54d44c 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/linklist.h b/lib/linklist.h index cd6e2f13aa..37ba396a76 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_LINKLIST_H @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define FRR_DEFINE_DESC_TABLE @@ -734,6 +733,17 @@ openzlog (const char *progname, const char *protoname, u_short instance, openlog (progname, syslog_flags, zl->facility); zlog_default = zl; + +#ifdef HAVE_GLIBC_BACKTRACE + /* work around backtrace() using lazily resolved dynamically linked + * symbols, which will otherwise cause funny breakage in the SEGV handler. + * (particularly, the dynamic linker can call malloc(), which uses locks + * in programs linked with -pthread, thus can deadlock.) */ + void *bt[4]; + backtrace (bt, array_size(bt)); + free (backtrace_symbols (bt, 0)); + backtrace_symbols_fd (bt, 0, 0); +#endif } void @@ -1047,6 +1057,8 @@ proto_redistnum(int afi, const char *s) return ZEBRA_ROUTE_STATIC; else if (strmatch (s, "rip")) return ZEBRA_ROUTE_RIP; + else if (strmatch (s, "eigrp")) + return ZEBRA_ROUTE_EIGRP; else if (strmatch (s, "ospf")) return ZEBRA_ROUTE_OSPF; else if (strmatch (s, "isis")) @@ -14,16 +14,16 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_LOG_H #define _ZEBRA_LOG_H #include <syslog.h> +#include <stdint.h> #include <stdio.h> /* Here is some guidance on logging levels to use: @@ -64,7 +64,7 @@ struct message /* Open zlog function */ extern void openzlog (const char *progname, const char *protoname, - u_short instance, int syslog_options, int syslog_facility); + uint16_t instance, int syslog_options, int syslog_facility); /* Close zlog function. */ extern void closezlog (void); diff --git a/lib/log_int.h b/lib/log_int.h index c21d723ac6..7c93381cbc 100644 --- a/lib/log_int.h +++ b/lib/log_int.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_LOG_PRIVATE_H diff --git a/lib/memory.c b/lib/memory.c index ad55366f64..c6207adb98 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -27,119 +27,107 @@ struct memgroup **mg_insert = &mg_first; DEFINE_MGROUP(LIB, "libfrr") DEFINE_MTYPE(LIB, TMP, "Temporary memory") -static inline void -mt_count_alloc (struct memtype *mt, size_t size) +static inline void mt_count_alloc(struct memtype *mt, size_t size) { - mt->n_alloc++; + size_t oldsize; - if (mt->size == 0) - mt->size = size; - else if (mt->size != size) - mt->size = SIZE_VAR; + atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed); + + oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed); + if (oldsize == 0) + oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed); + if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR) + atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed); } -static inline void -mt_count_free (struct memtype *mt) +static inline void mt_count_free(struct memtype *mt) { - assert(mt->n_alloc); - mt->n_alloc--; + assert(mt->n_alloc); + atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed); } -static inline void * -mt_checkalloc (struct memtype *mt, void *ptr, size_t size) +static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size) { - if (__builtin_expect(ptr == NULL, 0)) - { - memory_oom (size, mt->name); - return NULL; - } - mt_count_alloc (mt, size); - return ptr; + if (__builtin_expect(ptr == NULL, 0)) { + memory_oom(size, mt->name); + return NULL; + } + mt_count_alloc(mt, size); + return ptr; } -void * -qmalloc (struct memtype *mt, size_t size) +void *qmalloc(struct memtype *mt, size_t size) { - return mt_checkalloc (mt, malloc (size), size); + return mt_checkalloc(mt, malloc(size), size); } -void * -qcalloc (struct memtype *mt, size_t size) +void *qcalloc(struct memtype *mt, size_t size) { - return mt_checkalloc (mt, calloc (size, 1), size); + return mt_checkalloc(mt, calloc(size, 1), size); } -void * -qrealloc (struct memtype *mt, void *ptr, size_t size) +void *qrealloc(struct memtype *mt, void *ptr, size_t size) { - if (ptr) - mt_count_free (mt); - return mt_checkalloc (mt, ptr ? realloc (ptr, size) : malloc (size), size); + if (ptr) + mt_count_free(mt); + return mt_checkalloc(mt, ptr ? realloc(ptr, size) : malloc(size), size); } -void * -qstrdup (struct memtype *mt, const char *str) +void *qstrdup(struct memtype *mt, const char *str) { - return mt_checkalloc (mt, strdup (str), strlen (str) + 1); + return mt_checkalloc(mt, strdup(str), strlen(str) + 1); } -void -qfree (struct memtype *mt, void *ptr) +void qfree(struct memtype *mt, void *ptr) { - if (ptr) - mt_count_free (mt); - free (ptr); + if (ptr) + mt_count_free(mt); + free(ptr); } -int -qmem_walk (qmem_walk_fn *func, void *arg) +int qmem_walk(qmem_walk_fn *func, void *arg) { - struct memgroup *mg; - struct memtype *mt; - int rv; - - for (mg = mg_first; mg; mg = mg->next) - { - if ((rv = func (arg, mg, NULL))) - return rv; - for (mt = mg->types; mt; mt = mt->next) - if ((rv = func (arg, mg, mt))) - return rv; - } - return 0; + struct memgroup *mg; + struct memtype *mt; + int rv; + + for (mg = mg_first; mg; mg = mg->next) { + if ((rv = func(arg, mg, NULL))) + return rv; + for (mt = mg->types; mt; mt = mt->next) + if ((rv = func(arg, mg, mt))) + return rv; + } + return 0; } -struct exit_dump_args -{ - const char *prefix; - int error; +struct exit_dump_args { + const char *prefix; + int error; }; -static int -qmem_exit_walker (void *arg, struct memgroup *mg, struct memtype *mt) +static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt) { - struct exit_dump_args *eda = arg; - - if (!mt) - { - fprintf (stderr, "%s: showing active allocations in memory group %s\n", - eda->prefix, mg->name); - } - else if (mt->n_alloc) - { - char size[32]; - eda->error++; - snprintf (size, sizeof (size), "%10zu", mt->size); - fprintf (stderr, "%s: memstats: %-30s: %6zu * %s\n", - eda->prefix, mt->name, mt->n_alloc, - mt->size == SIZE_VAR ? "(variably sized)" : size); - } - return 0; + struct exit_dump_args *eda = arg; + + if (!mt) { + fprintf(stderr, "%s: showing active allocations in " + "memory group %s\n", + eda->prefix, mg->name); + + } else if (mt->n_alloc) { + char size[32]; + eda->error++; + snprintf(size, sizeof(size), "%10zu", mt->size); + fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n", + eda->prefix, mt->name, mt->n_alloc, + mt->size == SIZE_VAR ? "(variably sized)" : size); + } + return 0; } -void -log_memstats_stderr (const char *prefix) +void log_memstats_stderr(const char *prefix) { - struct exit_dump_args eda = { .prefix = prefix, .error = 0 }; - qmem_walk (qmem_exit_walker, &eda); + struct exit_dump_args eda = { .prefix = prefix, .error = 0 }; + qmem_walk(qmem_exit_walker, &eda); } diff --git a/lib/memory.h b/lib/memory.h index 477a6162dc..9e8803a8b2 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -18,23 +18,22 @@ #define _QUAGGA_MEMORY_H #include <stdlib.h> +#include <frratomic.h> #define array_size(ar) (sizeof(ar) / sizeof(ar[0])) #define SIZE_VAR ~0UL -struct memtype -{ - struct memtype *next, **ref; - const char *name; - size_t n_alloc; - size_t size; +struct memtype { + struct memtype *next, **ref; + const char *name; + _Atomic size_t n_alloc; + _Atomic size_t size; }; -struct memgroup -{ - struct memgroup *next, **ref; - struct memtype *types, **insert; - const char *name; +struct memgroup { + struct memgroup *next, **ref; + struct memtype *types, **insert; + const char *name; }; #if defined(__clang__) @@ -82,14 +81,14 @@ struct memgroup * DEFINE_MGROUP(MYDAEMON, "my daemon memory") * DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON, * "this mtype is used in multiple files in mydaemon") - * foo = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*foo)) + * foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo)) * * mydaemon_io.c - * bar = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*bar)) + * bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar)) * * DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO, * "this mtype is used only in this file") - * baz = qmalloc (MTYPE_MYDAEMON_IO, sizeof (*baz)) + * baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz)) * * Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced * by not having these as part of the macro arguments) @@ -155,15 +154,15 @@ DECLARE_MGROUP(LIB) DECLARE_MTYPE(TMP) -extern void *qmalloc (struct memtype *mt, size_t size) +extern void *qmalloc(struct memtype *mt, size_t size) __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); -extern void *qcalloc (struct memtype *mt, size_t size) +extern void *qcalloc(struct memtype *mt, size_t size) __attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL)); -extern void *qrealloc (struct memtype *mt, void *ptr, size_t size) +extern void *qrealloc(struct memtype *mt, void *ptr, size_t size) __attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL)); extern void *qstrdup (struct memtype *mt, const char *str) __attribute__ ((malloc, nonnull (1) _RET_NONNULL)); -extern void qfree (struct memtype *mt, void *ptr) +extern void qfree(struct memtype *mt, void *ptr) __attribute__ ((nonnull (1))); #define XMALLOC(mtype, size) qmalloc(mtype, size) @@ -183,10 +182,10 @@ static inline size_t mtype_stats_alloc(struct memtype *mt) * * return value: 0: continue, !0: abort walk. qmem_walk will return the * last value from qmem_walk_fn. */ -typedef int qmem_walk_fn (void *arg, struct memgroup *mg, struct memtype *mt); -extern int qmem_walk (qmem_walk_fn *func, void *arg); -extern void log_memstats_stderr (const char *); +typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt); +extern int qmem_walk(qmem_walk_fn *func, void *arg); +extern void log_memstats_stderr(const char *); -extern void memory_oom (size_t size, const char *name); +extern void memory_oom(size_t size, const char *name); #endif /* _QUAGGA_MEMORY_H */ diff --git a/lib/memory_vty.c b/lib/memory_vty.c index 6d63bc2d53..27254cfa5b 100644 --- a/lib/memory_vty.c +++ b/lib/memory_vty.c @@ -14,9 +14,9 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/memory_vty.h b/lib/memory_vty.h index 565a75aa98..a47c5d51b8 100644 --- a/lib/memory_vty.h +++ b/lib/memory_vty.h @@ -1,22 +1,22 @@ /* Memory management routine - Copyright (C) 1998 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + * Copyright (C) 1998 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _ZEBRA_MEMORY_VTY_H #define _ZEBRA_MEMORY_VTY_H diff --git a/lib/mpls.h b/lib/mpls.h index 13a46e1012..6cf0142755 100644 --- a/lib/mpls.h +++ b/lib/mpls.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _QUAGGA_MPLS_H @@ -85,7 +84,8 @@ enum lsp_types_t { ZEBRA_LSP_NONE = 0, /* No LSP. */ ZEBRA_LSP_STATIC = 1, /* Static LSP. */ - ZEBRA_LSP_LDP = 2 /* LDP LSP. */ + ZEBRA_LSP_LDP = 2, /* LDP LSP. */ + ZEBRA_LSP_BGP = 3 /* BGP LSP. */ }; /* Functions for basic label operations. */ @@ -122,6 +122,11 @@ mpls_lse_decode (mpls_lse_t lse, mpls_label_t *label, *ttl = MPLS_LABEL_TTL(local_lse); } +/* Invalid label index value (when used with BGP Prefix-SID). Should + * match the BGP definition. + */ +#define MPLS_INVALID_LABEL_INDEX 0xFFFFFFFF + /* Printable string for labels (with consideration for reserved values). */ static inline char * diff --git a/lib/network.c b/lib/network.c index 2b6f2fbab5..3d2c63c89d 100644 --- a/lib/network.c +++ b/lib/network.c @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/network.h b/lib/network.h index a9126caf7f..a6b8ed1e17 100644 --- a/lib/network.h +++ b/lib/network.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_NETWORK_H diff --git a/lib/nexthop.c b/lib/nexthop.c index 7b8ac95e83..725b52c052 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -92,6 +91,28 @@ nexthop_type_to_str (enum nexthop_types_t nh_type) return desc[nh_type]; } +/* + * Check if the labels match for the 2 nexthops specified. + */ +int +nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2) +{ + struct nexthop_label *nhl1, *nhl2; + + nhl1 = nh1->nh_label; + nhl2 = nh2->nh_label; + if ((nhl1 && !nhl2) || (!nhl1 && nhl2)) + return 0; + + if (nhl1->num_labels != nhl2->num_labels) + return 0; + + if (memcmp (nhl1->label, nhl2->label, nhl1->num_labels)) + return 0; + + return 1; +} + struct nexthop * nexthop_new (void) { diff --git a/lib/nexthop.h b/lib/nexthop.h index e66e0eee20..8c9c801c91 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -15,10 +15,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LIB_NEXTHOP_H @@ -117,6 +116,7 @@ void nexthop_del_labels (struct nexthop *); extern const char *nexthop_type_to_str (enum nexthop_types_t nh_type); extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2); +extern int nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2); extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size); #endif /*_LIB_NEXTHOP_H */ @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_NS_H diff --git a/lib/pid_output.c b/lib/pid_output.c index ba1f37476e..7369e23c20 100644 --- a/lib/pid_output.c +++ b/lib/pid_output.c @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/plist.c b/lib/plist.c index 3714969696..8091429e31 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -3157,6 +3156,40 @@ config_write_prefix_ipv4 (struct vty *vty) } static void +plist_autocomplete_afi (afi_t afi, vector comps, struct cmd_token *token) +{ + struct prefix_list *plist; + struct prefix_master *master; + + master = prefix_master_get (afi, 0); + if (master == NULL) + return; + + for (plist = master->str.head; plist; plist = plist->next) + vector_set (comps, XSTRDUP (MTYPE_COMPLETION, plist->name)); + for (plist = master->num.head; plist; plist = plist->next) + vector_set (comps, XSTRDUP (MTYPE_COMPLETION, plist->name)); +} + +static void +plist_autocomplete(vector comps, struct cmd_token *token) +{ + plist_autocomplete_afi (AFI_IP, comps, token); + plist_autocomplete_afi (AFI_IP6, comps, token); +} + +static const struct cmd_variable_handler plist_var_handlers[] = { + { + /* "prefix-list WORD" */ + .varname = "prefix_list", + .completions = plist_autocomplete + }, { + .completions = NULL + } +}; + + +static void prefix_list_init_ipv4 (void) { install_node (&prefix_node, config_write_prefix_ipv4); @@ -3275,6 +3308,8 @@ prefix_list_init_ipv6 (void) void prefix_list_init () { + cmd_variable_handler_register(plist_var_handlers); + prefix_list_init_ipv4 (); prefix_list_init_ipv6 (); } diff --git a/lib/plist.h b/lib/plist.h index 89d9a874f0..0f397ff01a 100644 --- a/lib/plist.h +++ b/lib/plist.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _QUAGGA_PLIST_H diff --git a/lib/plist_int.h b/lib/plist_int.h index e6e5901dbf..e711d12564 100644 --- a/lib/plist_int.h +++ b/lib/plist_int.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _QUAGGA_PLIST_INT_H diff --git a/lib/pqueue.c b/lib/pqueue.c index 0f870564da..2d9127b88e 100644 --- a/lib/pqueue.c +++ b/lib/pqueue.c @@ -1,22 +1,22 @@ /* Priority queue functions. - Copyright (C) 2003 Yasuhiro Ohara - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published -by the Free Software Foundation; either version 2, or (at your -option) any later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + * Copyright (C) 2003 Yasuhiro Ohara + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include <zebra.h> @@ -188,3 +188,11 @@ pqueue_remove_at (int index, struct pqueue *queue) trickle_down (index, queue); } } + +void +pqueue_remove (void *data, struct pqueue *queue) +{ + for (int i = 0; i < queue->size; i++) + if (queue->array[i] == data) + pqueue_remove_at (i, queue); +} diff --git a/lib/pqueue.h b/lib/pqueue.h index 8bb6961d86..d87d91fdc5 100644 --- a/lib/pqueue.h +++ b/lib/pqueue.h @@ -1,22 +1,22 @@ /* Priority queue functions. - Copyright (C) 2003 Yasuhiro Ohara - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published -by the Free Software Foundation; either version 2, or (at your -option) any later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + * Copyright (C) 2003 Yasuhiro Ohara + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _ZEBRA_PQUEUE_H #define _ZEBRA_PQUEUE_H @@ -39,6 +39,7 @@ extern void pqueue_delete (struct pqueue *queue); extern void pqueue_enqueue (void *data, struct pqueue *queue); extern void *pqueue_dequeue (struct pqueue *queue); extern void pqueue_remove_at (int index, struct pqueue *queue); +extern void pqueue_remove (void *data, struct pqueue *queue); extern void trickle_down (int index, struct pqueue *queue); extern void trickle_up (int index, struct pqueue *queue); diff --git a/lib/prefix.c b/lib/prefix.c index 0cc759bb7c..9c228cf954 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -252,12 +251,14 @@ safi2str(safi_t safi) return "unicast"; case SAFI_MULTICAST: return "multicast"; - case SAFI_ENCAP: - return "encap"; case SAFI_MPLS_VPN: return "vpn"; + case SAFI_ENCAP: + return "encap"; case SAFI_EVPN: return "evpn"; + case SAFI_LABELED_UNICAST: + return "labeled-unicast"; } return NULL; } diff --git a/lib/prefix.h b/lib/prefix.h index eb3ae3dafb..09cb0cab87 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_PREFIX_H @@ -244,6 +243,8 @@ union prefixconstptr /* Count prefix size from mask length */ #define PSIZE(a) (((a) + 7) / (8)) +#define BSIZE(a) ((a) * (8)) + /* Prefix's family member. */ #define PREFIX_FAMILY(p) ((p)->family) diff --git a/lib/privs.c b/lib/privs.c index decd4bb7db..3a66382191 100644 --- a/lib/privs.c +++ b/lib/privs.c @@ -16,10 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> #include "log.h" @@ -769,6 +768,7 @@ zprivs_init(struct zebra_privs_t *zprivs) } } + zprivs_state.zsuid = geteuid(); /* initial uid */ /* add groups only if we changed uid - otherwise skip */ if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid)) { diff --git a/lib/privs.h b/lib/privs.h index 46d614e008..9a5eb3bd6c 100644 --- a/lib/privs.h +++ b/lib/privs.h @@ -15,10 +15,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_PRIVS_H diff --git a/lib/ptm_lib.c b/lib/ptm_lib.c index a93d7b8476..7181e2d89d 100644 --- a/lib/ptm_lib.c +++ b/lib/ptm_lib.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdio.h> #include <stdlib.h> diff --git a/lib/ptm_lib.h b/lib/ptm_lib.h index be4170bb37..747ce349ad 100644 --- a/lib/ptm_lib.h +++ b/lib/ptm_lib.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PTM_LIB_H__ #define __PTM_LIB_H__ diff --git a/lib/qobj.c b/lib/qobj.c index 8a386d2486..fd7b4c8c5b 100644 --- a/lib/qobj.c +++ b/lib/qobj.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/route_types.txt b/lib/route_types.txt index 5cb06ffb7f..7625d1f690 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -52,6 +52,7 @@ ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, "OSPFv3" ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, "IS-IS" ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP" ZEBRA_ROUTE_PIM, pim, pimd, 'P', 1, 0, "PIM" +ZEBRA_ROUTE_EIGRP, eigrp, eigrpd, 'E', 1, 0, "EIGRP" ZEBRA_ROUTE_NHRP, nhrp, nhrpd, 'N', 1, 1, "NHRP" # HSLS and OLSR both are AFI independent (so: 1, 1), however # we want to disable for them for general Quagga distribution. @@ -86,6 +87,7 @@ ZEBRA_ROUTE_OSPF6, "Open Shortest Path First (IPv6) (OSPFv3)" ZEBRA_ROUTE_ISIS, "Intermediate System to Intermediate System (IS-IS)" ZEBRA_ROUTE_BGP, "Border Gateway Protocol (BGP)" ZEBRA_ROUTE_PIM, "Protocol Independent Multicast (PIM)" +ZEBRA_ROUTE_EIGRP, "Enhanced Interior Gateway Routing Protocol (EIGRP)" ZEBRA_ROUTE_NHRP, "Next Hop Resolution Protocol (NHRP)" ZEBRA_ROUTE_HSLS, "Hazy-Sighted Link State Protocol (HSLS)" ZEBRA_ROUTE_VNC, "Virtual Network Control (VNC)" diff --git a/lib/routemap.c b/lib/routemap.c index cd34ffaae5..44b3c2bf9f 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1,22 +1,22 @@ /* Route map function. - Copyright (C) 1998, 1999 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + * Copyright (C) 1998, 1999 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include <zebra.h> @@ -2001,7 +2001,7 @@ DEFUN (match_interface, DEFUN (no_match_interface, no_match_interface_cmd, - "no match interface [INTERFACE]", + "no match interface [WORD]", NO_STR MATCH_STR "Match first hop interface of route\n" @@ -2958,6 +2958,30 @@ route_map_finish (void) route_map_master_hash = NULL; } +static void rmap_autocomplete(vector comps, struct cmd_token *token) +{ + struct route_map *map; + + for (map = route_map_master.head; map; map = map->next) + vector_set (comps, XSTRDUP (MTYPE_COMPLETION, map->name)); +} + +static const struct cmd_variable_handler rmap_var_handlers[] = { + { + /* "route-map WORD" */ + .varname = "route_map", + .completions = rmap_autocomplete + }, { + .tokenname = "ROUTEMAP_NAME", + .completions = rmap_autocomplete + }, { + .tokenname = "RMAP_NAME", + .completions = rmap_autocomplete + }, { + .completions = NULL + } +}; + /* Initialization of route map vector. */ void route_map_init (void) @@ -2973,6 +2997,8 @@ route_map_init (void) route_map_dep_hash[i] = hash_create(route_map_dep_hash_make_key, route_map_dep_hash_cmp); + cmd_variable_handler_register(rmap_var_handlers); + /* Install route map top node. */ install_node (&rmap_node, route_map_config_write); diff --git a/lib/routemap.h b/lib/routemap.h index b378c64eae..f1937ac403 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_ROUTEMAP_H diff --git a/lib/sha256.c b/lib/sha256.c new file mode 100644 index 0000000000..f98a758821 --- /dev/null +++ b/lib/sha256.c @@ -0,0 +1,433 @@ +/*- + * Copyright 2005,2007,2009 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <zebra.h> +#include "sha256.h" + +#if !HAVE_DECL_BE32DEC +static inline uint32_t +be32dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); +} +#else +#include <sys/endian.h> +#endif + +#if !HAVE_DECL_BE32ENC +static inline void +be32enc(void *pp, uint32_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[3] = x & 0xff; + p[2] = (x >> 8) & 0xff; + p[1] = (x >> 16) & 0xff; + p[0] = (x >> 24) & 0xff; +} +#else +#include <sys/endian.h> +#endif + +/* + * Encode a length len/4 vector of (uint32_t) into a length len vector of + * (unsigned char) in big-endian form. Assumes len is a multiple of 4. + */ +static void +be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) +{ + size_t i; + + for (i = 0; i < len / 4; i++) + be32enc(dst + i * 4, src[i]); +} + +/* + * Decode a big-endian length len vector of (unsigned char) into a length + * len/4 vector of (uint32_t). Assumes len is a multiple of 4. + */ +static void +be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) +{ + size_t i; + + for (i = 0; i < len / 4; i++) + dst[i] = be32dec(src + i * 4); +} + +/* Elementary functions used by SHA256 */ +#define Ch(x, y, z) ((x & (y ^ z)) ^ z) +#define Maj(x, y, z) ((x & (y | z)) | (y & z)) +#define SHR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << (32 - n))) +#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) +#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) + +/* SHA256 round function */ +#define RND(a, b, c, d, e, f, g, h, k) \ + t0 = h + S1(e) + Ch(e, f, g) + k; \ + t1 = S0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + +/* Adjusted round function for rotating state */ +#define RNDr(S, W, i, k) \ + RND(S[(64 - i) % 8], S[(65 - i) % 8], \ + S[(66 - i) % 8], S[(67 - i) % 8], \ + S[(68 - i) % 8], S[(69 - i) % 8], \ + S[(70 - i) % 8], S[(71 - i) % 8], \ + W[i] + k) + +/* + * SHA256 block compression function. The 256-bit state is transformed via + * the 512-bit input block to produce a new state. + */ +static void +SHA256_Transform(uint32_t * state, const unsigned char block[64]) +{ + uint32_t W[64]; + uint32_t S[8]; + uint32_t t0, t1; + int i; + + /* 1. Prepare message schedule W. */ + be32dec_vect(W, block, 64); + for (i = 16; i < 64; i++) + W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; + + /* 2. Initialize working variables. */ + memcpy(S, state, 32); + + /* 3. Mix. */ + RNDr(S, W, 0, 0x428a2f98); + RNDr(S, W, 1, 0x71374491); + RNDr(S, W, 2, 0xb5c0fbcf); + RNDr(S, W, 3, 0xe9b5dba5); + RNDr(S, W, 4, 0x3956c25b); + RNDr(S, W, 5, 0x59f111f1); + RNDr(S, W, 6, 0x923f82a4); + RNDr(S, W, 7, 0xab1c5ed5); + RNDr(S, W, 8, 0xd807aa98); + RNDr(S, W, 9, 0x12835b01); + RNDr(S, W, 10, 0x243185be); + RNDr(S, W, 11, 0x550c7dc3); + RNDr(S, W, 12, 0x72be5d74); + RNDr(S, W, 13, 0x80deb1fe); + RNDr(S, W, 14, 0x9bdc06a7); + RNDr(S, W, 15, 0xc19bf174); + RNDr(S, W, 16, 0xe49b69c1); + RNDr(S, W, 17, 0xefbe4786); + RNDr(S, W, 18, 0x0fc19dc6); + RNDr(S, W, 19, 0x240ca1cc); + RNDr(S, W, 20, 0x2de92c6f); + RNDr(S, W, 21, 0x4a7484aa); + RNDr(S, W, 22, 0x5cb0a9dc); + RNDr(S, W, 23, 0x76f988da); + RNDr(S, W, 24, 0x983e5152); + RNDr(S, W, 25, 0xa831c66d); + RNDr(S, W, 26, 0xb00327c8); + RNDr(S, W, 27, 0xbf597fc7); + RNDr(S, W, 28, 0xc6e00bf3); + RNDr(S, W, 29, 0xd5a79147); + RNDr(S, W, 30, 0x06ca6351); + RNDr(S, W, 31, 0x14292967); + RNDr(S, W, 32, 0x27b70a85); + RNDr(S, W, 33, 0x2e1b2138); + RNDr(S, W, 34, 0x4d2c6dfc); + RNDr(S, W, 35, 0x53380d13); + RNDr(S, W, 36, 0x650a7354); + RNDr(S, W, 37, 0x766a0abb); + RNDr(S, W, 38, 0x81c2c92e); + RNDr(S, W, 39, 0x92722c85); + RNDr(S, W, 40, 0xa2bfe8a1); + RNDr(S, W, 41, 0xa81a664b); + RNDr(S, W, 42, 0xc24b8b70); + RNDr(S, W, 43, 0xc76c51a3); + RNDr(S, W, 44, 0xd192e819); + RNDr(S, W, 45, 0xd6990624); + RNDr(S, W, 46, 0xf40e3585); + RNDr(S, W, 47, 0x106aa070); + RNDr(S, W, 48, 0x19a4c116); + RNDr(S, W, 49, 0x1e376c08); + RNDr(S, W, 50, 0x2748774c); + RNDr(S, W, 51, 0x34b0bcb5); + RNDr(S, W, 52, 0x391c0cb3); + RNDr(S, W, 53, 0x4ed8aa4a); + RNDr(S, W, 54, 0x5b9cca4f); + RNDr(S, W, 55, 0x682e6ff3); + RNDr(S, W, 56, 0x748f82ee); + RNDr(S, W, 57, 0x78a5636f); + RNDr(S, W, 58, 0x84c87814); + RNDr(S, W, 59, 0x8cc70208); + RNDr(S, W, 60, 0x90befffa); + RNDr(S, W, 61, 0xa4506ceb); + RNDr(S, W, 62, 0xbef9a3f7); + RNDr(S, W, 63, 0xc67178f2); + + /* 4. Mix local working variables into global state */ + for (i = 0; i < 8; i++) + state[i] += S[i]; + + /* Clean the stack. */ + memset(W, 0, 256); + memset(S, 0, 32); + t0 = t1 = 0; +} + +static unsigned char PAD[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* Add padding and terminating bit-count. */ +static void +SHA256_Pad(SHA256_CTX * ctx) +{ + unsigned char len[8]; + uint32_t r, plen; + + /* + * Convert length to a vector of bytes -- we do this now rather + * than later because the length will change after we pad. + */ + be32enc_vect(len, ctx->count, 8); + + /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ + r = (ctx->count[1] >> 3) & 0x3f; + plen = (r < 56) ? (56 - r) : (120 - r); + SHA256_Update(ctx, PAD, (size_t)plen); + + /* Add the terminating bit-count */ + SHA256_Update(ctx, len, 8); +} + +/* SHA-256 initialization. Begins a SHA-256 operation. */ +void +SHA256_Init(SHA256_CTX * ctx) +{ + + /* Zero bits processed so far */ + ctx->count[0] = ctx->count[1] = 0; + + /* Magic initialization constants */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; +} + +/* Add bytes into the hash */ +void +SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len) +{ + uint32_t bitlen[2]; + uint32_t r; + const unsigned char *src = in; + + /* Number of bytes left in the buffer from previous updates */ + r = (ctx->count[1] >> 3) & 0x3f; + + /* Convert the length into a number of bits */ + bitlen[1] = ((uint32_t)len) << 3; + bitlen[0] = (uint32_t)(len >> 29); + + /* Update number of bits */ + if ((ctx->count[1] += bitlen[1]) < bitlen[1]) + ctx->count[0]++; + ctx->count[0] += bitlen[0]; + + /* Handle the case where we don't need to perform any transforms */ + if (len < 64 - r) { + memcpy(&ctx->buf[r], src, len); + return; + } + + /* Finish the current block */ + memcpy(&ctx->buf[r], src, 64 - r); + SHA256_Transform(ctx->state, ctx->buf); + src += 64 - r; + len -= 64 - r; + + /* Perform complete blocks */ + while (len >= 64) { + SHA256_Transform(ctx->state, src); + src += 64; + len -= 64; + } + + /* Copy left over data into buffer */ + memcpy(ctx->buf, src, len); +} + +/* + * SHA-256 finalization. Pads the input data, exports the hash value, + * and clears the context state. + */ +void +SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx) +{ + + /* Add padding */ + SHA256_Pad(ctx); + + /* Write the hash */ + be32enc_vect(digest, ctx->state, 32); + + /* Clear the context state */ + memset((void *)ctx, 0, sizeof(*ctx)); +} + +/* Initialize an HMAC-SHA256 operation with the given key. */ +void +HMAC__SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) +{ + unsigned char pad[64]; + unsigned char khash[32]; + const unsigned char * K = _K; + size_t i; + + /* If Klen > 64, the key is really SHA256(K). */ + if (Klen > 64) { + SHA256_Init(&ctx->ictx); + SHA256_Update(&ctx->ictx, K, Klen); + SHA256_Final(khash, &ctx->ictx); + K = khash; + Klen = 32; + } + + /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ + SHA256_Init(&ctx->ictx); + memset(pad, 0x36, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->ictx, pad, 64); + + /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ + SHA256_Init(&ctx->octx); + memset(pad, 0x5c, 64); + for (i = 0; i < Klen; i++) + pad[i] ^= K[i]; + SHA256_Update(&ctx->octx, pad, 64); + + /* Clean the stack. */ + memset(khash, 0, 32); +} + +/* Add bytes to the HMAC-SHA256 operation. */ +void +HMAC__SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) +{ + + /* Feed data to the inner SHA256 operation. */ + SHA256_Update(&ctx->ictx, in, len); +} + +/* Finish an HMAC-SHA256 operation. */ +void +HMAC__SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) +{ + unsigned char ihash[32]; + + /* Finish the inner SHA256 operation. */ + SHA256_Final(ihash, &ctx->ictx); + + /* Feed the inner hash to the outer SHA256 operation. */ + SHA256_Update(&ctx->octx, ihash, 32); + + /* Finish the outer SHA256 operation. */ + SHA256_Final(digest, &ctx->octx); + + /* Clean the stack. */ + memset(ihash, 0, 32); +} + +/** + * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): + * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and + * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). + */ +void +PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, + size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) +{ + HMAC_SHA256_CTX PShctx, hctx; + size_t i; + uint8_t ivec[4]; + uint8_t U[32]; + uint8_t T[32]; + uint64_t j; + int k; + size_t clen; + + /* Compute HMAC state after processing P and S. */ + HMAC__SHA256_Init(&PShctx, passwd, passwdlen); + HMAC__SHA256_Update(&PShctx, salt, saltlen); + + /* Iterate through the blocks. */ + for (i = 0; i * 32 < dkLen; i++) { + /* Generate INT(i + 1). */ + be32enc(ivec, (uint32_t)(i + 1)); + + /* Compute U_1 = PRF(P, S || INT(i)). */ + memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); + HMAC__SHA256_Update(&hctx, ivec, 4); + HMAC__SHA256_Final(U, &hctx); + + /* T_i = U_1 ... */ + memcpy(T, U, 32); + + for (j = 2; j <= c; j++) { + /* Compute U_j. */ + HMAC__SHA256_Init(&hctx, passwd, passwdlen); + HMAC__SHA256_Update(&hctx, U, 32); + HMAC__SHA256_Final(U, &hctx); + + /* ... xor U_j ... */ + for (k = 0; k < 32; k++) + T[k] ^= U[k]; + } + + /* Copy as many bytes as necessary into buf. */ + clen = dkLen - i * 32; + if (clen > 32) + clen = 32; + memcpy(&buf[i * 32], T, clen); + } + + /* Clean PShctx, since we never called _Final on it. */ + memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); +} diff --git a/lib/sha256.h b/lib/sha256.h new file mode 100644 index 0000000000..502f3fc224 --- /dev/null +++ b/lib/sha256.h @@ -0,0 +1,58 @@ +/*- + * Copyright 2005,2007,2009 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $ + */ + +#ifndef _SHA256_H_ +#define _SHA256_H_ + +typedef struct SHA256Context { + uint32_t state[8]; + uint32_t count[2]; + unsigned char buf[64]; +} SHA256_CTX; + +typedef struct HMAC_SHA256Context { + SHA256_CTX ictx; + SHA256_CTX octx; +} HMAC_SHA256_CTX; + +void SHA256_Init(SHA256_CTX *); +void SHA256_Update(SHA256_CTX *, const void *, size_t); +void SHA256_Final(unsigned char [32], SHA256_CTX *); +void HMAC__SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); +void HMAC__SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); +void HMAC__SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *); + +/** + * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): + * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and + * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). + */ +void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, + uint64_t, uint8_t *, size_t); + +#endif /* !_SHA256_H_ */ diff --git a/lib/sigevent.c b/lib/sigevent.c index 09f07180ce..e8c722b987 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -132,8 +131,9 @@ quagga_signal_timer (struct thread *t) int i; sigm = THREAD_ARG (t); - sigm->t = thread_add_timer (sigm->t->master, quagga_signal_timer, &sigmaster, - QUAGGA_SIGNAL_TIMER_INTERVAL); + sigm->t = NULL; + thread_add_timer(sigm->t->master, quagga_signal_timer, &sigmaster, QUAGGA_SIGNAL_TIMER_INTERVAL, + &sigm->t); return quagga_sigevent_process (); } #endif /* SIGEVENT_SCHEDULE_THREAD */ @@ -233,6 +233,18 @@ core_handler(int signo #endif ) { + /* make sure we don't hang in here. default for SIGALRM is terminate. + * - if we're in backtrace for more than a second, abort. */ + struct sigaction sa_default = { .sa_handler = SIG_DFL }; + sigaction (SIGALRM, &sa_default, NULL); + + sigset_t sigset; + sigemptyset (&sigset); + sigaddset (&sigset, SIGALRM); + sigprocmask (SIG_UNBLOCK, &sigset, NULL); + + alarm (1); + zlog_signal(signo, "aborting..." #ifdef SA_SIGINFO , siginfo, program_counter(context) @@ -327,6 +339,11 @@ trap_default_signals(void) act.sa_handler = sigmap[i].handler; act.sa_flags = 0; #endif +#ifdef SA_RESETHAND + /* don't try to print backtraces recursively */ + if (sigmap[i].handler == core_handler) + act.sa_flags |= SA_RESETHAND; +#endif } if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0) zlog_warn("Unable to set signal handler for signal %d: %s", @@ -361,8 +378,8 @@ signal_init (struct thread_master *m, int sigc, sigmaster.signals = signals; #ifdef SIGEVENT_SCHEDULE_THREAD - sigmaster.t = - thread_add_timer (m, quagga_signal_timer, &sigmaster, - QUAGGA_SIGNAL_TIMER_INTERVAL); + sigmaster.t = NULL; + thread_add_timer(m, quagga_signal_timer, &sigmaster, QUAGGA_SIGNAL_TIMER_INTERVAL, + &sigmaster.t); #endif /* SIGEVENT_SCHEDULE_THREAD */ } diff --git a/lib/sigevent.h b/lib/sigevent.h index 248fa2c058..08eb1ca412 100644 --- a/lib/sigevent.h +++ b/lib/sigevent.h @@ -15,10 +15,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _QUAGGA_SIGNAL_H diff --git a/lib/smux.c b/lib/smux.c index 370b8f138e..032801f6df 100644 --- a/lib/smux.c +++ b/lib/smux.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -1197,13 +1196,18 @@ smux_event (enum smux_event event, int sock) switch (event) { case SMUX_SCHEDULE: - smux_connect_thread = thread_add_event (smux_master, smux_connect, NULL, 0); + smux_connect_thread = NULL; + thread_add_event(smux_master, smux_connect, NULL, 0, + &smux_connect_thread); break; case SMUX_CONNECT: - smux_connect_thread = thread_add_timer (smux_master, smux_connect, NULL, 10); + smux_connect_thread = NULL; + thread_add_timer(smux_master, smux_connect, NULL, 10, + &smux_connect_thread); break; case SMUX_READ: - smux_read_thread = thread_add_read (smux_master, smux_read, NULL, sock); + smux_read_thread = NULL; + thread_add_read(smux_master, smux_read, NULL, sock, &smux_read_thread); break; default: break; diff --git a/lib/smux.h b/lib/smux.h index dc91cac71a..e94a7a9cc9 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_SNMP_H diff --git a/lib/snmp.c b/lib/snmp.c index 1cbd41c720..7eb86e9412 100644 --- a/lib/snmp.c +++ b/lib/snmp.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/sockopt.c b/lib/sockopt.c index 2a9f907cb3..83ea574833 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/sockopt.h b/lib/sockopt.h index 1b7be1e49f..d31fcaa411 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_SOCKOPT_H diff --git a/lib/sockunion.c b/lib/sockunion.c index 9ba2ce82f6..423ad20441 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/sockunion.h b/lib/sockunion.h index bed68e1ee1..98c3e0adef 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_SOCKUNION_H diff --git a/lib/spf_backoff.c b/lib/spf_backoff.c index e923f232b8..7e34947344 100644 --- a/lib/spf_backoff.c +++ b/lib/spf_backoff.c @@ -19,10 +19,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with FRR; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -169,21 +168,19 @@ long spf_backoff_schedule(struct spf_backoff *backoff) { case SPF_BACKOFF_QUIET: backoff->state = SPF_BACKOFF_SHORT_WAIT; - THREAD_TIMER_MSEC_ON(backoff->m, backoff->t_timetolearn, - spf_backoff_timetolearn_elapsed, backoff, - backoff->timetolearn); - THREAD_TIMER_MSEC_ON(backoff->m, backoff->t_holddown, - spf_backoff_holddown_elapsed, backoff, - backoff->holddown); + thread_add_timer_msec(backoff->m, spf_backoff_timetolearn_elapsed, + backoff, backoff->timetolearn, + &backoff->t_timetolearn); + thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff, + backoff->holddown, &backoff->t_holddown); backoff->first_event_time = now; rv = backoff->init_delay; break; case SPF_BACKOFF_SHORT_WAIT: case SPF_BACKOFF_LONG_WAIT: THREAD_TIMER_OFF(backoff->t_holddown); - THREAD_TIMER_MSEC_ON(backoff->m, backoff->t_holddown, - spf_backoff_holddown_elapsed, backoff, - backoff->holddown); + thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff, + backoff->holddown, &backoff->t_holddown); if (backoff->state == SPF_BACKOFF_SHORT_WAIT) rv = backoff->short_delay; else diff --git a/lib/spf_backoff.h b/lib/spf_backoff.h index 552ca4ae41..92bd46506a 100644 --- a/lib/spf_backoff.h +++ b/lib/spf_backoff.h @@ -19,10 +19,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with FRR; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_SPF_BACKOFF_H #define _ZEBRA_SPF_BACKOFF_H diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c index 04c9eff79a..383cf00d4f 100644 --- a/lib/srcdest_table.c +++ b/lib/srcdest_table.c @@ -16,10 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with FRR; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/srcdest_table.h b/lib/srcdest_table.h index 207f5d121d..0d858d11ab 100644 --- a/lib/srcdest_table.h +++ b/lib/srcdest_table.h @@ -16,10 +16,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with FRR; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_SRC_DEST_TABLE_H diff --git a/lib/stream.c b/lib/stream.c index 301ebc6275..e8320a8fa1 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -1,4 +1,4 @@ - /* +/* * Packet interface * Copyright (C) 1999 Kunihiro Ishiguro * @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -919,6 +918,31 @@ stream_put_prefix (struct stream *s, struct prefix *p) return stream_put_prefix_addpath (s, p, 0, 0); } +/* Put NLRI with label */ +int +stream_put_labeled_prefix (struct stream *s, struct prefix *p, u_char *label) +{ + size_t psize; + + STREAM_VERIFY_SANE(s); + + psize = PSIZE (p->prefixlen); + + if (STREAM_WRITEABLE (s) < (psize + 3)) + { + STREAM_BOUND_WARN (s, "put"); + return 0; + } + + stream_putc (s, (p->prefixlen + 24)); + stream_putc(s, label[0]); + stream_putc(s, label[1]); + stream_putc(s, label[2]); + memcpy (s->data + s->endp, &p->u.prefix, psize); + s->endp += psize; + + return (psize + 3); +} /* Read size from fd. */ int diff --git a/lib/stream.h b/lib/stream.h index 1e2bc89b32..dd6aae677d 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_STREAM_H @@ -181,7 +180,8 @@ extern int stream_put_prefix_addpath (struct stream *, struct prefix *, int addpath_encode, u_int32_t addpath_tx_id); extern int stream_put_prefix (struct stream *, struct prefix *); - +extern int stream_put_labeled_prefix (struct stream *, struct prefix *, + u_char *); extern void stream_get (void *, struct stream *, size_t); extern void stream_get_from (void *, struct stream *, size_t, size_t); extern u_char stream_getc (struct stream *); diff --git a/lib/strlcat.c b/lib/strlcat.c index 1d04b43d95..6fdb2a4a37 100644 --- a/lib/strlcat.c +++ b/lib/strlcat.c @@ -1,20 +1,21 @@ /* Append a null-terminated string to another string, with length checking. - Copyright (C) 2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ + * Copyright (C) 2016 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + */ /* adapted for Quagga from glibc patch submission originally from * Florian Weimer <fweimer@redhat.com>, 2016-05-18 */ diff --git a/lib/strlcpy.c b/lib/strlcpy.c index 41bab97ea7..112c8180b9 100644 --- a/lib/strlcpy.c +++ b/lib/strlcpy.c @@ -1,20 +1,21 @@ /* Copy a null-terminated string to a fixed-size buffer, with length checking. - Copyright (C) 2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ + * Copyright (C) 2016 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + */ /* adapted for Quagga from glibc patch submission originally from * Florian Weimer <fweimer@redhat.com>, 2016-05-18 */ diff --git a/lib/systemd.c b/lib/systemd.c index 4c78cf328c..341de9eabe 100644 --- a/lib/systemd.c +++ b/lib/systemd.c @@ -1,23 +1,23 @@ /* lib/systemd Code - Copyright (C) 2016 Cumulus Networks, Inc. - Donald Sharp - -This file is part of Quagga. - -Quagga is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -Quagga is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quagga; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #include <zebra.h> @@ -104,7 +104,7 @@ systemd_send_watchdog (struct thread *t) { systemd_send_information ("WATCHDOG=1"); - thread_add_timer (systemd_master, systemd_send_watchdog, NULL, wsecs); + thread_add_timer(systemd_master, systemd_send_watchdog, NULL, wsecs, NULL); return 1; } @@ -119,5 +119,5 @@ systemd_send_started (struct thread_master *m, int the_process) systemd_send_information ("READY=1"); if (wsecs != 0) - thread_add_timer (m, systemd_send_watchdog, m, wsecs); + thread_add_timer(m, systemd_send_watchdog, m, wsecs, NULL); } diff --git a/lib/systemd.h b/lib/systemd.h index 685f3d9a77..c048797cf2 100644 --- a/lib/systemd.h +++ b/lib/systemd.h @@ -1,23 +1,23 @@ /* lib/systemd Code - Copyright (C) 2016 Cumulus Networks, Inc. - Donald Sharp - -This file is part of Quagga. - -Quagga is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -Quagga is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Quagga; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + * Copyright (C) 2016 Cumulus Networks, Inc. + * Donald Sharp + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ /* * Wrapper functions to systemd calls. diff --git a/lib/table.c b/lib/table.c index 7f789dd3cd..1461bb81a4 100644 --- a/lib/table.c +++ b/lib/table.c @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/table.h b/lib/table.h index 1691a8e20a..00131b29c6 100644 --- a/lib/table.h +++ b/lib/table.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_TABLE_H diff --git a/lib/thread.c b/lib/thread.c index dbdd91dd24..2843a9211e 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* #define DEBUG */ @@ -41,7 +40,7 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") #include <mach/mach_time.h> #endif -/* Relative time, since startup */ +static pthread_mutex_t cpu_record_mtx = PTHREAD_MUTEX_INITIALIZER; static struct hash *cpu_record = NULL; static unsigned long @@ -137,9 +136,14 @@ cpu_record_print(struct vty *vty, thread_type filter) vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs"); vty_out(vty, " Avg uSec Max uSecs"); vty_out(vty, " Type Thread%s", VTY_NEWLINE); - hash_iterate(cpu_record, - (void(*)(struct hash_backet*,void*))cpu_record_hash_print, - args); + + pthread_mutex_lock (&cpu_record_mtx); + { + hash_iterate(cpu_record, + (void(*)(struct hash_backet*,void*))cpu_record_hash_print, + args); + } + pthread_mutex_unlock (&cpu_record_mtx); if (tmp.total_calls > 0) vty_out_cpu_thread_history(vty, &tmp); @@ -216,16 +220,25 @@ cpu_record_hash_clear (struct hash_backet *bucket, if ( !(a->types & *filter) ) return; - hash_release (cpu_record, bucket->data); + pthread_mutex_lock (&cpu_record_mtx); + { + hash_release (cpu_record, bucket->data); + } + pthread_mutex_unlock (&cpu_record_mtx); } static void cpu_record_clear (thread_type filter) { thread_type *tmp = &filter; - hash_iterate (cpu_record, - (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear, - tmp); + + pthread_mutex_lock (&cpu_record_mtx); + { + hash_iterate (cpu_record, + (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear, + tmp); + } + pthread_mutex_unlock (&cpu_record_mtx); } DEFUN (clear_thread_cpu, @@ -326,16 +339,20 @@ thread_master_create (void) getrlimit(RLIMIT_NOFILE, &limit); - if (cpu_record == NULL) - cpu_record - = hash_create ((unsigned int (*) (void *))cpu_record_hash_key, - (int (*) (const void *, const void *))cpu_record_hash_cmp); + pthread_mutex_lock (&cpu_record_mtx); + { + if (cpu_record == NULL) + cpu_record = hash_create ((unsigned int (*) (void *))cpu_record_hash_key, + (int (*) (const void *, const void *)) + cpu_record_hash_cmp); + } + pthread_mutex_unlock (&cpu_record_mtx); rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master)); if (rv == NULL) - { - return NULL; - } + return NULL; + + pthread_mutex_init (&rv->mtx, NULL); rv->fd_limit = (int)limit.rlim_cur; rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit); @@ -358,6 +375,8 @@ thread_master_create (void) rv->background = pqueue_create(); rv->timer->cmp = rv->background->cmp = thread_timer_cmp; rv->timer->update = rv->background->update = thread_timer_update; + rv->spin = true; + rv->handle_signals = true; #if defined(HAVE_POLL_CALL) rv->handler.pfdsize = rv->fd_limit; @@ -434,6 +453,7 @@ thread_add_unuse (struct thread_master *m, struct thread *thread) assert (m != NULL && thread != NULL); assert (thread->next == NULL); assert (thread->prev == NULL); + thread->ref = NULL; thread->type = THREAD_UNUSED; thread->hist->total_active--; @@ -498,11 +518,16 @@ thread_queue_free (struct thread_master *m, struct pqueue *queue) void thread_master_free_unused (struct thread_master *m) { - struct thread *t; - while ((t = thread_trim_head(&m->unuse)) != NULL) - { - XFREE(MTYPE_THREAD, t); - } + pthread_mutex_lock (&m->mtx); + { + struct thread *t; + while ((t = thread_trim_head(&m->unuse)) != NULL) + { + pthread_mutex_destroy (&t->mtx); + XFREE(MTYPE_THREAD, t); + } + } + pthread_mutex_unlock (&m->mtx); } /* Stop thread scheduler. */ @@ -516,25 +541,37 @@ thread_master_free (struct thread_master *m) thread_list_free (m, &m->ready); thread_list_free (m, &m->unuse); thread_queue_free (m, m->background); + pthread_mutex_destroy (&m->mtx); #if defined(HAVE_POLL_CALL) XFREE (MTYPE_THREAD_MASTER, m->handler.pfds); #endif XFREE (MTYPE_THREAD_MASTER, m); - if (cpu_record) - { - hash_clean (cpu_record, cpu_record_hash_free); - hash_free (cpu_record); - cpu_record = NULL; - } + pthread_mutex_lock (&cpu_record_mtx); + { + if (cpu_record) + { + hash_clean (cpu_record, cpu_record_hash_free); + hash_free (cpu_record); + cpu_record = NULL; + } + } + pthread_mutex_unlock (&cpu_record_mtx); } /* Return remain time in second. */ unsigned long thread_timer_remain_second (struct thread *thread) { - int64_t remain = monotime_until(&thread->u.sands, NULL) / 1000000LL; + int64_t remain; + + pthread_mutex_lock (&thread->mtx); + { + remain = monotime_until(&thread->u.sands, NULL) / 1000000LL; + } + pthread_mutex_unlock (&thread->mtx); + return remain < 0 ? 0 : remain; } @@ -545,7 +582,11 @@ struct timeval thread_timer_remain(struct thread *thread) { struct timeval remain; - monotime_until(&thread->u.sands, &remain); + pthread_mutex_lock (&thread->mtx); + { + monotime_until(&thread->u.sands, &remain); + } + pthread_mutex_unlock (&thread->mtx); return remain; } @@ -560,14 +601,18 @@ thread_get (struct thread_master *m, u_char type, if (! thread) { thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread)); + /* mutex only needs to be initialized at struct creation. */ + pthread_mutex_init (&thread->mtx, NULL); m->alloc++; } + thread->type = type; thread->add_type = type; thread->master = m; thread->arg = arg; thread->index = -1; thread->yield = THREAD_YIELD_TIME_SLOT; /* default */ + thread->ref = NULL; /* * So if the passed in funcname is not what we have @@ -584,8 +629,12 @@ thread_get (struct thread_master *m, u_char type, { tmp.func = func; tmp.funcname = funcname; - thread->hist = hash_get (cpu_record, &tmp, - (void * (*) (void *))cpu_record_hash_alloc); + pthread_mutex_lock (&cpu_record_mtx); + { + thread->hist = hash_get (cpu_record, &tmp, + (void * (*) (void *))cpu_record_hash_alloc); + } + pthread_mutex_unlock (&cpu_record_mtx); } thread->hist->total_active++; thread->func = func; @@ -650,15 +699,46 @@ static int fd_select (struct thread_master *m, int size, thread_fd_set *read, thread_fd_set *write, thread_fd_set *except, struct timeval *timer_wait) { int num; + + /* If timer_wait is null here, that means either select() or poll() should + * block indefinitely, unless the thread_master has overriden it. select() + * and poll() differ in the timeout values they interpret as an indefinite + * block; select() requires a null pointer, while poll takes a millisecond + * value of -1. + * + * The thread_master owner has the option of overriding the default behavior + * by setting ->selectpoll_timeout. If the value is positive, it specifies + * the maximum number of milliseconds to wait. If the timeout is -1, it + * specifies that we should never wait and always return immediately even if + * no event is detected. If the value is zero, the behavior is default. + */ + #if defined(HAVE_POLL_CALL) - /* recalc timeout for poll. Attention NULL pointer is no timeout with - select, where with poll no timeount is -1 */ int timeout = -1; - if (timer_wait != NULL) + + if (timer_wait != NULL && m->selectpoll_timeout == 0) // use the default value timeout = (timer_wait->tv_sec*1000) + (timer_wait->tv_usec/1000); + else if (m->selectpoll_timeout > 0) // use the user's timeout + timeout = m->selectpoll_timeout; + else if (m->selectpoll_timeout < 0) // effect a poll (return immediately) + timeout = 0; num = poll (m->handler.pfds, m->handler.pfdcount + m->handler.pfdcountsnmp, timeout); #else + struct timeval timeout; + + if (m->selectpoll_timeout > 0) // use the user's timeout + { + timeout.tv_sec = m->selectpoll_timeout / 1000; + timeout.tv_usec = (m->selectpoll_timeout % 1000) * 1000; + timer_wait = &timeout; + } + else if (m->selectpoll_timeout < 0) // effect a poll (return immediately) + { + timeout.tv_sec = 0; + timeout.tv_usec = 0; + timer_wait = &timeout; + } num = select (size, read, write, except, timer_wait); #endif @@ -698,52 +778,74 @@ fd_clear_read_write (struct thread *thread) /* Add new read thread. */ struct thread * funcname_thread_add_read_write (int dir, struct thread_master *m, - int (*func) (struct thread *), void *arg, int fd, - debugargdef) + int (*func) (struct thread *), void *arg, int fd, struct thread **t_ptr, + debugargdef) { struct thread *thread = NULL; -#if !defined(HAVE_POLL_CALL) - thread_fd_set *fdset = NULL; - if (dir == THREAD_READ) - fdset = &m->handler.readfd; - else - fdset = &m->handler.writefd; -#endif + pthread_mutex_lock (&m->mtx); + { + if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock (&m->mtx); + return NULL; + } #if defined (HAVE_POLL_CALL) - thread = generic_thread_add(m, func, arg, fd, dir, debugargpass); - - if (thread == NULL) - return NULL; + thread = generic_thread_add(m, func, arg, fd, dir, debugargpass); #else - if (FD_ISSET (fd, fdset)) - { - zlog_warn ("There is already %s fd [%d]", - (dir == THREAD_READ) ? "read" : "write", fd); - return NULL; - } + if (fd >= FD_SETSIZE) + { + zlog_err ("File descriptor %d is >= FD_SETSIZE (%d). Please recompile" + "with --enable-poll=yes", fd, FD_SETSIZE); + assert (fd < FD_SETSIZE && !"fd >= FD_SETSIZE"); + } + thread_fd_set *fdset = NULL; + if (dir == THREAD_READ) + fdset = &m->handler.readfd; + else + fdset = &m->handler.writefd; - FD_SET (fd, fdset); - thread = thread_get (m, dir, func, arg, debugargpass); + if (FD_ISSET (fd, fdset)) + { + zlog_warn ("There is already %s fd [%d]", + (dir == THREAD_READ) ? "read" : "write", fd); + } + else + { + FD_SET (fd, fdset); + thread = thread_get (m, dir, func, arg, debugargpass); + } #endif - thread->u.fd = fd; - if (dir == THREAD_READ) - thread_add_fd (m->read, thread); - else - thread_add_fd (m->write, thread); + if (thread) + { + pthread_mutex_lock (&thread->mtx); + { + thread->u.fd = fd; + if (dir == THREAD_READ) + thread_add_fd (m->read, thread); + else + thread_add_fd (m->write, thread); + } + pthread_mutex_unlock (&thread->mtx); + + if (t_ptr) + { + *t_ptr = thread; + thread->ref = t_ptr; + } + } + } + pthread_mutex_unlock (&m->mtx); return thread; } static struct thread * funcname_thread_add_timer_timeval (struct thread_master *m, - int (*func) (struct thread *), - int type, - void *arg, - struct timeval *time_relative, - debugargdef) + int (*func) (struct thread *), int type, void *arg, + struct timeval *time_relative, struct thread **t_ptr, debugargdef) { struct thread *thread; struct pqueue *queue; @@ -753,13 +855,32 @@ funcname_thread_add_timer_timeval (struct thread_master *m, assert (type == THREAD_TIMER || type == THREAD_BACKGROUND); assert (time_relative); - queue = ((type == THREAD_TIMER) ? m->timer : m->background); - thread = thread_get (m, type, func, arg, debugargpass); + pthread_mutex_lock (&m->mtx); + { + if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock (&m->mtx); + return NULL; + } - monotime(&thread->u.sands); - timeradd(&thread->u.sands, time_relative, &thread->u.sands); + queue = ((type == THREAD_TIMER) ? m->timer : m->background); + thread = thread_get (m, type, func, arg, debugargpass); + + pthread_mutex_lock (&thread->mtx); + { + monotime(&thread->u.sands); + timeradd(&thread->u.sands, time_relative, &thread->u.sands); + pqueue_enqueue(thread, queue); + if (t_ptr) + { + *t_ptr = thread; + thread->ref = t_ptr; + } + } + pthread_mutex_unlock (&thread->mtx); + } + pthread_mutex_unlock (&m->mtx); - pqueue_enqueue(thread, queue); return thread; } @@ -767,9 +888,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m, /* Add timer event thread. */ struct thread * funcname_thread_add_timer (struct thread_master *m, - int (*func) (struct thread *), - void *arg, long timer, - debugargdef) + int (*func) (struct thread *), void *arg, long timer, + struct thread **t_ptr, debugargdef) { struct timeval trel; @@ -778,16 +898,15 @@ funcname_thread_add_timer (struct thread_master *m, trel.tv_sec = timer; trel.tv_usec = 0; - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, - &trel, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, + t_ptr, debugargpass); } /* Add timer event thread with "millisecond" resolution */ struct thread * funcname_thread_add_timer_msec (struct thread_master *m, - int (*func) (struct thread *), - void *arg, long timer, - debugargdef) + int (*func) (struct thread *), void *arg, long timer, + struct thread **t_ptr, debugargdef) { struct timeval trel; @@ -796,27 +915,25 @@ funcname_thread_add_timer_msec (struct thread_master *m, trel.tv_sec = timer / 1000; trel.tv_usec = 1000*(timer % 1000); - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, - arg, &trel, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel, + t_ptr, debugargpass); } /* Add timer event thread with "millisecond" resolution */ struct thread * funcname_thread_add_timer_tv (struct thread_master *m, - int (*func) (struct thread *), - void *arg, struct timeval *tv, - debugargdef) + int (*func) (struct thread *), void *arg, struct timeval *tv, + struct thread **t_ptr, debugargdef) { - return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, - arg, tv, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, tv, + t_ptr, debugargpass); } /* Add a background thread, with an optional millisec delay */ struct thread * funcname_thread_add_background (struct thread_master *m, - int (*func) (struct thread *), - void *arg, long delay, - debugargdef) + int (*func) (struct thread *), void *arg, long delay, + struct thread **t_ptr, debugargdef) { struct timeval trel; @@ -833,23 +950,43 @@ funcname_thread_add_background (struct thread_master *m, trel.tv_usec = 0; } - return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND, - arg, &trel, debugargpass); + return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND, arg, &trel, + t_ptr, debugargpass); } /* Add simple event thread. */ struct thread * funcname_thread_add_event (struct thread_master *m, - int (*func) (struct thread *), void *arg, int val, - debugargdef) + int (*func) (struct thread *), void *arg, int val, + struct thread **t_ptr, debugargdef) { struct thread *thread; assert (m != NULL); - thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass); - thread->u.val = val; - thread_list_add (&m->event, thread); + pthread_mutex_lock (&m->mtx); + { + if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule + { + pthread_mutex_unlock (&m->mtx); + return NULL; + } + + thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass); + pthread_mutex_lock (&thread->mtx); + { + thread->u.val = val; + thread_list_add (&m->event, thread); + } + pthread_mutex_unlock (&thread->mtx); + + if (t_ptr) + { + *t_ptr = thread; + thread->ref = t_ptr; + } + } + pthread_mutex_unlock (&m->mtx); return thread; } @@ -880,14 +1017,22 @@ thread_cancel_read_or_write (struct thread *thread, short int state) fd_clear_read_write (thread); } -/* Cancel thread from scheduler. */ +/** + * Cancel thread from scheduler. + * + * This function is *NOT* MT-safe. DO NOT call it from any other pthread except + * the one which owns thread->master. + */ void thread_cancel (struct thread *thread) { struct thread_list *list = NULL; struct pqueue *queue = NULL; struct thread **thread_array = NULL; - + + pthread_mutex_lock (&thread->master->mtx); + pthread_mutex_lock (&thread->mtx); + switch (thread->type) { case THREAD_READ: @@ -919,15 +1064,14 @@ thread_cancel (struct thread *thread) queue = thread->master->background; break; default: - return; + goto done; break; } if (queue) { assert(thread->index >= 0); - assert(thread == queue->array[thread->index]); - pqueue_remove_at(thread->index, queue); + pqueue_remove (thread, queue); } else if (list) { @@ -942,7 +1086,14 @@ thread_cancel (struct thread *thread) assert(!"Thread should be either in queue or list or array!"); } + if (thread->ref) + *thread->ref = NULL; + thread_add_unuse (thread->master, thread); + +done: + pthread_mutex_unlock (&thread->mtx); + pthread_mutex_unlock (&thread->master->mtx); } /* Delete all events which has argument value arg. */ @@ -951,39 +1102,52 @@ thread_cancel_event (struct thread_master *m, void *arg) { unsigned int ret = 0; struct thread *thread; + struct thread *t; - thread = m->event.head; - while (thread) - { - struct thread *t; - - t = thread; - thread = t->next; - - if (t->arg == arg) + pthread_mutex_lock (&m->mtx); + { + thread = m->event.head; + while (thread) + { + t = thread; + pthread_mutex_lock (&t->mtx); { - ret++; - thread_list_delete (&m->event, t); - thread_add_unuse (m, t); + thread = t->next; + + if (t->arg == arg) + { + ret++; + thread_list_delete (&m->event, t); + if (t->ref) + *t->ref = NULL; + thread_add_unuse (m, t); + } } - } - - /* thread can be on the ready list too */ - thread = m->ready.head; - while (thread) - { - struct thread *t; - - t = thread; - thread = t->next; + pthread_mutex_unlock (&t->mtx); + } - if (t->arg == arg) + /* thread can be on the ready list too */ + thread = m->ready.head; + while (thread) + { + t = thread; + pthread_mutex_lock (&t->mtx); { - ret++; - thread_list_delete (&m->ready, t); - thread_add_unuse (m, t); + thread = t->next; + + if (t->arg == arg) + { + ret++; + thread_list_delete (&m->ready, t); + if (t->ref) + *t->ref = NULL; + thread_add_unuse (m, t); + } } - } + pthread_mutex_unlock (&t->mtx); + } + } + pthread_mutex_unlock (&m->mtx); return ret; } @@ -1142,18 +1306,26 @@ thread_fetch (struct thread_master *m, struct thread *fetch) struct timeval *timer_wait = &timer_val; struct timeval *timer_wait_bg; - while (1) + do { int num = 0; /* Signals pre-empt everything */ - quagga_sigevent_process (); + if (m->handle_signals) + quagga_sigevent_process (); + pthread_mutex_lock (&m->mtx); /* Drain the ready queue of already scheduled jobs, before scheduling * more. */ if ((thread = thread_trim_head (&m->ready)) != NULL) - return thread_run (m, thread, fetch); + { + fetch = thread_run (m, thread, fetch); + if (fetch->ref) + *fetch->ref = NULL; + pthread_mutex_unlock (&m->mtx); + return fetch; + } /* To be fair to all kinds of threads, and avoid starvation, we * need to be careful to consider all thread types for scheduling @@ -1193,8 +1365,12 @@ thread_fetch (struct thread_master *m, struct thread *fetch) if (num < 0) { if (errno == EINTR) - continue; /* signal received - process it */ + { + pthread_mutex_unlock (&m->mtx); + continue; /* signal received - process it */ + } zlog_warn ("select() error: %s", safe_strerror (errno)); + pthread_mutex_unlock (&m->mtx); return NULL; } @@ -1214,15 +1390,32 @@ thread_fetch (struct thread_master *m, struct thread *fetch) list at this time. If this is code is uncommented, then background timer threads will not run unless there is nothing else to do. */ if ((thread = thread_trim_head (&m->ready)) != NULL) - return thread_run (m, thread, fetch); + { + fetch = thread_run (m, thread, fetch); + if (fetch->ref) + *fetch->ref = NULL; + pthread_mutex_unlock (&m->mtx); + return fetch; + } #endif /* Background timer/events, lowest priority */ thread_timer_process (m->background, &now); if ((thread = thread_trim_head (&m->ready)) != NULL) - return thread_run (m, thread, fetch); - } + { + fetch = thread_run (m, thread, fetch); + if (fetch->ref) + *fetch->ref = NULL; + pthread_mutex_unlock (&m->mtx); + return fetch; + } + + pthread_mutex_unlock (&m->mtx); + + } while (m->spin); + + return NULL; } unsigned long @@ -1247,13 +1440,23 @@ thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime) int thread_should_yield (struct thread *thread) { - return monotime_since(&thread->real, NULL) > (int64_t)thread->yield; + int result; + pthread_mutex_lock (&thread->mtx); + { + result = monotime_since(&thread->real, NULL) > (int64_t)thread->yield; + } + pthread_mutex_unlock (&thread->mtx); + return result; } void thread_set_yield_time (struct thread *thread, unsigned long yield_time) { - thread->yield = yield_time; + pthread_mutex_lock (&thread->mtx); + { + thread->yield = yield_time; + } + pthread_mutex_unlock (&thread->mtx); } void @@ -1311,7 +1514,7 @@ thread_call (struct thread *thread) } /* Execute thread */ -struct thread * +void funcname_thread_execute (struct thread_master *m, int (*func)(struct thread *), void *arg, @@ -1323,6 +1526,7 @@ funcname_thread_execute (struct thread_master *m, memset (&dummy, 0, sizeof (struct thread)); + pthread_mutex_init (&dummy.mtx, NULL); dummy.type = THREAD_EVENT; dummy.add_type = THREAD_EXECUTE; dummy.master = NULL; @@ -1331,13 +1535,15 @@ funcname_thread_execute (struct thread_master *m, tmp.func = dummy.func = func; tmp.funcname = dummy.funcname = funcname; - dummy.hist = hash_get (cpu_record, &tmp, - (void * (*) (void *))cpu_record_hash_alloc); + pthread_mutex_lock (&cpu_record_mtx); + { + dummy.hist = hash_get (cpu_record, &tmp, + (void * (*) (void *))cpu_record_hash_alloc); + } + pthread_mutex_unlock (&cpu_record_mtx); dummy.schedfrom = schedfrom; dummy.schedfrom_line = fromln; thread_call (&dummy); - - return NULL; } diff --git a/lib/thread.h b/lib/thread.h index 6cb7896e7d..218672c7bf 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_THREAD_H @@ -24,6 +23,7 @@ #include <zebra.h> #include "monotime.h" +#include <pthread.h> struct rusage_t { @@ -84,6 +84,10 @@ struct thread_master int fd_limit; struct fd_handler handler; unsigned long alloc; + long selectpoll_timeout; + bool spin; + bool handle_signals; + pthread_mutex_t mtx; }; typedef unsigned char thread_type; @@ -91,25 +95,27 @@ typedef unsigned char thread_type; /* Thread itself. */ struct thread { - thread_type type; /* thread type */ - thread_type add_type; /* thread type */ - struct thread *next; /* next pointer of the thread */ - struct thread *prev; /* previous pointer of the thread */ - struct thread_master *master; /* pointer to the struct thread_master. */ - int (*func) (struct thread *); /* event function */ - void *arg; /* event argument */ + thread_type type; /* thread type */ + thread_type add_type; /* thread type */ + struct thread *next; /* next pointer of the thread */ + struct thread *prev; /* previous pointer of the thread */ + struct thread **ref; /* external reference (if given) */ + struct thread_master *master; /* pointer to the struct thread_master */ + int (*func) (struct thread *); /* event function */ + void *arg; /* event argument */ union { - int val; /* second argument of the event. */ - int fd; /* file descriptor in case of read/write. */ - struct timeval sands; /* rest of time sands value. */ + int val; /* second argument of the event. */ + int fd; /* file descriptor in case of r/w */ + struct timeval sands; /* rest of time sands value. */ } u; - int index; /* used for timers to store position in queue */ + int index; /* queue position for timers */ struct timeval real; - struct cpu_thread_history *hist; /* cache pointer to cpu_history */ - unsigned long yield; /* yield time in us */ - const char *funcname; - const char *schedfrom; - int schedfrom_line; + struct cpu_thread_history *hist; /* cache pointer to cpu_history */ + unsigned long yield; /* yield time in microseconds */ + const char *funcname; /* name of thread function */ + const char *schedfrom; /* source file thread was scheduled from */ + int schedfrom_line; /* line number of source file */ + pthread_mutex_t mtx; /* mutex for thread.c functions */ }; struct cpu_thread_history @@ -147,30 +153,6 @@ struct cpu_thread_history #define THREAD_FD(X) ((X)->u.fd) #define THREAD_VAL(X) ((X)->u.val) -#define THREAD_READ_ON(master,thread,func,arg,sock) \ - do { \ - if (! thread) \ - thread = thread_add_read (master, func, arg, sock); \ - } while (0) - -#define THREAD_WRITE_ON(master,thread,func,arg,sock) \ - do { \ - if (! thread) \ - thread = thread_add_write (master, func, arg, sock); \ - } while (0) - -#define THREAD_TIMER_ON(master,thread,func,arg,time) \ - do { \ - if (! thread) \ - thread = thread_add_timer (master, func, arg, time); \ - } while (0) - -#define THREAD_TIMER_MSEC_ON(master,thread,func,arg,time) \ - do { \ - if (! thread) \ - thread = thread_add_timer_msec (master, func, arg, time); \ - } while (0) - #define THREAD_OFF(thread) \ do { \ if (thread) \ @@ -186,46 +168,42 @@ struct cpu_thread_history #define debugargdef const char *funcname, const char *schedfrom, int fromln -#define thread_add_read(m,f,a,v) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,#f,__FILE__,__LINE__) -#define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f,__FILE__,__LINE__) -#define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__) -#define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__) -#define thread_add_timer_tv(m,f,a,v) funcname_thread_add_timer_tv(m,f,a,v,#f,__FILE__,__LINE__) -#define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__) +#define thread_add_read(m,f,a,v,t) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,t,#f,__FILE__,__LINE__) +#define thread_add_write(m,f,a,v,t) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,t,#f,__FILE__,__LINE__) +#define thread_add_timer(m,f,a,v,t) funcname_thread_add_timer(m,f,a,v,t,#f,__FILE__,__LINE__) +#define thread_add_timer_msec(m,f,a,v,t) funcname_thread_add_timer_msec(m,f,a,v,t,#f,__FILE__,__LINE__) +#define thread_add_timer_tv(m,f,a,v,t) funcname_thread_add_timer_tv(m,f,a,v,t,#f,__FILE__,__LINE__) +#define thread_add_event(m,f,a,v,t) funcname_thread_add_event(m,f,a,v,t,#f,__FILE__,__LINE__) #define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__) /* The 4th arg to thread_add_background is the # of milliseconds to delay. */ -#define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f,__FILE__,__LINE__) +#define thread_add_background(m,f,a,v,t) funcname_thread_add_background(m,f,a,v,t,#f,__FILE__,__LINE__) /* Prototypes. */ extern struct thread_master *thread_master_create (void); extern void thread_master_free (struct thread_master *); extern void thread_master_free_unused(struct thread_master *); -extern struct thread *funcname_thread_add_read_write (int dir, struct thread_master *, - int (*)(struct thread *), - void *, int, debugargdef); -extern struct thread *funcname_thread_add_timer (struct thread_master *, - int (*)(struct thread *), - void *, long, debugargdef); -extern struct thread *funcname_thread_add_timer_msec (struct thread_master *, - int (*)(struct thread *), - void *, long, debugargdef); -extern struct thread *funcname_thread_add_timer_tv (struct thread_master *, - int (*)(struct thread *), - void *, struct timeval *, - debugargdef); -extern struct thread *funcname_thread_add_event (struct thread_master *, - int (*)(struct thread *), - void *, int, debugargdef); -extern struct thread *funcname_thread_add_background (struct thread_master *, - int (*func)(struct thread *), - void *arg, - long milliseconds_to_delay, - debugargdef); -extern struct thread *funcname_thread_execute (struct thread_master *, - int (*)(struct thread *), - void *, int, debugargdef); +extern struct thread * funcname_thread_add_read_write (int dir, struct thread_master *, + int (*)(struct thread *), void *, int, struct thread **, debugargdef); + +extern struct thread * funcname_thread_add_timer (struct thread_master *, + int (*)(struct thread *), void *, long, struct thread **, debugargdef); + +extern struct thread * funcname_thread_add_timer_msec (struct thread_master *, + int (*)(struct thread *), void *, long, struct thread **, debugargdef); + +extern struct thread * funcname_thread_add_timer_tv (struct thread_master *, + int (*)(struct thread *), void *, struct timeval *, struct thread **, debugargdef); + +extern struct thread * funcname_thread_add_event (struct thread_master *, + int (*)(struct thread *), void *, int, struct thread **, debugargdef); + +extern struct thread * funcname_thread_add_background (struct thread_master *, + int (*)(struct thread *), void *, long, struct thread **, debugargdef); + +extern void funcname_thread_execute (struct thread_master *, + int (*)(struct thread *), void *, int, debugargdef); #undef debugargdef extern void thread_cancel (struct thread *); diff --git a/lib/vector.c b/lib/vector.c index e16fcf5315..110cd2915c 100644 --- a/lib/vector.c +++ b/lib/vector.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> diff --git a/lib/vector.h b/lib/vector.h index f57f28bbd0..ab1d1e6aac 100644 --- a/lib/vector.h +++ b/lib/vector.h @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_VECTOR_H @@ -14,16 +14,16 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> #include "if.h" #include "vrf.h" +#include "vrf_int.h" #include "prefix.h" #include "table.h" #include "log.h" @@ -237,33 +237,6 @@ vrf_disable (struct vrf *vrf) (*vrf_master.vrf_disable_hook) (vrf); } - -/* Add a VRF hook. Please add hooks before calling vrf_init(). */ -void -vrf_add_hook (int type, int (*func)(struct vrf *)) -{ - if (debug_vrf) - zlog_debug ("%s: Add Hook %d to function %p", __PRETTY_FUNCTION__, - type, func); - - switch (type) { - case VRF_NEW_HOOK: - vrf_master.vrf_new_hook = func; - break; - case VRF_DELETE_HOOK: - vrf_master.vrf_delete_hook = func; - break; - case VRF_ENABLE_HOOK: - vrf_master.vrf_enable_hook = func; - break; - case VRF_DISABLE_HOOK: - vrf_master.vrf_disable_hook = func; - break; - default: - break; - } -} - vrf_id_t vrf_name_to_id (const char *name) { @@ -309,24 +282,6 @@ vrf_iflist_get (vrf_id_t vrf_id) return vrf->iflist; } -/* Create the interface list for the specified VRF, if needed. */ -void -vrf_iflist_create (vrf_id_t vrf_id) -{ - struct vrf * vrf = vrf_lookup_by_id (vrf_id); - if (vrf && !vrf->iflist) - if_init (&vrf->iflist); -} - -/* Free the interface list of the specified VRF. */ -void -vrf_iflist_terminate (vrf_id_t vrf_id) -{ - struct vrf * vrf = vrf_lookup_by_id (vrf_id); - if (vrf && vrf->iflist) - if_terminate (&vrf->iflist); -} - /* * VRF bit-map */ @@ -424,13 +379,21 @@ vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id) /* Initialize VRF module. */ void -vrf_init (void) +vrf_init (int (*create)(struct vrf *), + int (*enable)(struct vrf *), + int (*disable)(struct vrf *), + int (*delete)(struct vrf *)) { struct vrf *default_vrf; if (debug_vrf) zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__); + vrf_master.vrf_new_hook = create; + vrf_master.vrf_enable_hook = enable; + vrf_master.vrf_disable_hook = disable; + vrf_master.vrf_delete_hook = delete; + /* The default VRF always exists. */ default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME); if (!default_vrf) @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_VRF_H @@ -57,15 +56,6 @@ enum { #define VRF_CMD_HELP_STR "Specify the VRF\nThe VRF name\n" #define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n" -/* - * VRF hooks - */ - -#define VRF_NEW_HOOK 0 /* a new VRF is just created */ -#define VRF_DELETE_HOOK 1 /* a VRF is to be deleted */ -#define VRF_ENABLE_HOOK 2 /* a VRF is ready to use */ -#define VRF_DISABLE_HOOK 3 /* a VRF is to be unusable */ - struct vrf { RB_ENTRY(vrf) id_entry, name_entry; @@ -98,21 +88,9 @@ DECLARE_QOBJ_TYPE(vrf) extern struct vrf_id_head vrfs_by_id; extern struct vrf_name_head vrfs_by_name; -/* - * Add a specific hook to VRF module. - * @param1: hook type - * @param2: the callback function - * - param 1: the VRF ID - * - param 2: the address of the user data pointer (the user data - * can be stored in or freed from there) - */ -extern void vrf_add_hook (int, int (*)(struct vrf *)); - extern struct vrf *vrf_lookup_by_id (vrf_id_t); extern struct vrf *vrf_lookup_by_name (const char *); extern struct vrf *vrf_get (vrf_id_t, const char *); -extern void vrf_delete (struct vrf *); -extern int vrf_enable (struct vrf *); extern vrf_id_t vrf_name_to_id (const char *); #define VRF_GET_ID(V,NAME) \ @@ -148,10 +126,6 @@ extern void *vrf_info_lookup (vrf_id_t); extern struct list *vrf_iflist (vrf_id_t); /* Get the interface list of the specified VRF. Create one if not find. */ extern struct list *vrf_iflist_get (vrf_id_t); -/* Create the interface list for the specified VRF, if needed. */ -extern void vrf_iflist_create (vrf_id_t vrf_id); -/* Free the interface list of the specified VRF. */ -extern void vrf_iflist_terminate (vrf_id_t vrf_id); /* * VRF bit-map: maintaining flags, one bit per VRF ID @@ -168,9 +142,31 @@ extern int vrf_bitmap_check (vrf_bitmap_t, vrf_id_t); /* * VRF initializer/destructor + * + * create -> Called back when a new VRF is created. This + * can be either through these 3 options: + * 1) CLI mentions a vrf before OS knows about it + * 2) OS calls zebra and we create the vrf from OS + * callback + * 3) zebra calls individual protocols to notify + * about the new vrf + * + * enable -> Called back when a VRF is actually usable from + * an OS perspective ( 2 and 3 above ) + * + * disable -> Called back when a VRF is being deleted from + * the system ( 2 and 3 ) above + * + * delete -> Called back when a vrf is being deleted from + * the system ( 2 and 3 ) above. + */ +extern void vrf_init (int (*create)(struct vrf *), + int (*enable)(struct vrf *), + int (*disable)(struct vrf *), + int (*delete)(struct vrf *)); +/* + * Call vrf_terminate when the protocol is being shutdown */ -/* Please add hooks before calling vrf_init(). */ -extern void vrf_init (void); extern void vrf_terminate (void); extern void vrf_cmd_init (int (*writefunc)(struct vty *vty)); diff --git a/lib/vrf_int.h b/lib/vrf_int.h new file mode 100644 index 0000000000..f0301b7670 --- /dev/null +++ b/lib/vrf_int.h @@ -0,0 +1,56 @@ +/* + * VRF Internal Header + * Copyright (C) 2017 Cumulus Networks, Inc. + * Donald Sharp + * + * This file is part of FRR. + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef __LIB_VRF_PRIVATE_H__ +#define __LIB_VRF_PRIVATE_H__ + +#include "vrf.h" + +/* + * These functions should only be called by: + * zebra/if_netlink.c -> The interface from OS into Zebra + * lib/zclient.c -> The interface from Zebra to each daemon + * + * Why you ask? Well because these are the turn on/off + * functions and the only place we can really turn a + * vrf on properly is in the call up from the os -> zebra + * and the pass through of this informatoin from zebra -> protocols + */ + +/* + * vrf_enable + * + * Given a newly running vrf enable it to be used + * by interested routing protocols + */ +extern int vrf_enable (struct vrf *); + +/* + * vrf_delete + * + * Given a vrf that is being deleted, delete it + * from interested parties + */ +extern void vrf_delete (struct vrf *); + +#endif + @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -734,6 +733,7 @@ vty_end_config (struct vty *vty) case ZEBRA_NODE: case RIP_NODE: case RIPNG_NODE: + case EIGRP_NODE: case BGP_NODE: case BGP_VPNV4_NODE: case BGP_VPNV6_NODE: @@ -745,9 +745,11 @@ vty_end_config (struct vty *vty) case BGP_VNC_L2_GROUP_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: + case BGP_IPV4L_NODE: case BGP_IPV6_NODE: case BGP_IPV6M_NODE: case BGP_EVPN_NODE: + case BGP_IPV6L_NODE: case RMAP_NODE: case OSPF_NODE: case OSPF6_NODE: @@ -952,14 +954,14 @@ vty_complete_command (struct vty *vty) vty_backward_pure_word (vty); vty_insert_word_overwrite (vty, matched[0]); vty_self_insert (vty, ' '); - XFREE (MTYPE_TMP, matched[0]); + XFREE (MTYPE_COMPLETION, matched[0]); break; case CMD_COMPLETE_MATCH: vty_prompt (vty); vty_redraw_line (vty); vty_backward_pure_word (vty); vty_insert_word_overwrite (vty, matched[0]); - XFREE (MTYPE_TMP, matched[0]); + XFREE (MTYPE_COMPLETION, matched[0]); break; case CMD_COMPLETE_LIST_MATCH: for (i = 0; matched[i] != NULL; i++) @@ -967,7 +969,7 @@ vty_complete_command (struct vty *vty) if (i != 0 && ((i % 6) == 0)) vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "%-10s ", matched[i]); - XFREE (MTYPE_TMP, matched[i]); + XFREE (MTYPE_COMPLETION, matched[i]); } vty_out (vty, "%s", VTY_NEWLINE); @@ -1106,6 +1108,26 @@ vty_describe_command (struct vty *vty) else vty_describe_fold (vty, width, desc_width, token); + if (IS_VARYING_TOKEN(token->type)) + { + const char *ref = vector_slot(vline, vector_active(vline) - 1); + + vector varcomps = vector_init (VECTOR_MIN_SIZE); + cmd_variable_complete (token, ref, varcomps); + + if (vector_active(varcomps) > 0) + { + vty_out(vty, " "); + for (size_t j = 0; j < vector_active (varcomps); j++) + { + char *item = vector_slot (varcomps, j); + vty_out(vty, " %s", item); + XFREE(MTYPE_COMPLETION, item); + } + vty_out(vty, "%s", VTY_NEWLINE); + } + vector_free(varcomps); + } #if 0 vty_out (vty, " %-*s %s%s", width desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, @@ -1161,6 +1183,7 @@ vty_stop_input (struct vty *vty) case ZEBRA_NODE: case RIP_NODE: case RIPNG_NODE: + case EIGRP_NODE: case BGP_NODE: case RMAP_NODE: case OSPF_NODE: @@ -2609,41 +2632,44 @@ static struct thread_master *vty_master; static void vty_event (enum event event, int sock, struct vty *vty) { - struct thread *vty_serv_thread; + struct thread *vty_serv_thread = NULL; switch (event) { case VTY_SERV: - vty_serv_thread = thread_add_read (vty_master, vty_accept, vty, sock); + vty_serv_thread = thread_add_read(vty_master, vty_accept, vty, sock, NULL); vector_set_index (Vvty_serv_thread, sock, vty_serv_thread); break; #ifdef VTYSH case VTYSH_SERV: - vty_serv_thread = thread_add_read (vty_master, vtysh_accept, vty, sock); + vty_serv_thread = thread_add_read(vty_master, vtysh_accept, vty, sock, NULL); vector_set_index (Vvty_serv_thread, sock, vty_serv_thread); break; case VTYSH_READ: - vty->t_read = thread_add_read (vty_master, vtysh_read, vty, sock); + vty->t_read = NULL; + thread_add_read(vty_master, vtysh_read, vty, sock, &vty->t_read); break; case VTYSH_WRITE: - vty->t_write = thread_add_write (vty_master, vtysh_write, vty, sock); + vty->t_write = NULL; + thread_add_write(vty_master, vtysh_write, vty, sock, &vty->t_write); break; #endif /* VTYSH */ case VTY_READ: - vty->t_read = thread_add_read (vty_master, vty_read, vty, sock); + vty->t_read = NULL; + thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read); /* Time out treatment. */ if (vty->v_timeout) { if (vty->t_timeout) thread_cancel (vty->t_timeout); - vty->t_timeout = - thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout); + vty->t_timeout = NULL; + thread_add_timer(vty_master, vty_timeout, vty, vty->v_timeout, + &vty->t_timeout); } break; case VTY_WRITE: - if (! vty->t_write) - vty->t_write = thread_add_write (vty_master, vty_flush, vty, sock); + thread_add_write(vty_master, vty_flush, vty, sock, &vty->t_write); break; case VTY_TIMEOUT_RESET: if (vty->t_timeout) @@ -2653,8 +2679,9 @@ vty_event (enum event event, int sock, struct vty *vty) } if (vty->v_timeout) { - vty->t_timeout = - thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout); + vty->t_timeout = NULL; + thread_add_timer(vty_master, vty_timeout, vty, vty->v_timeout, + &vty->t_timeout); } break; } @@ -1,22 +1,22 @@ /* Virtual terminal [aka TeletYpe] interface routine - Copyright (C) 1997 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + * Copyright (C) 1997 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _ZEBRA_VTY_H #define _ZEBRA_VTY_H diff --git a/lib/wheel.c b/lib/wheel.c index fe53dea299..f273a29262 100644 --- a/lib/wheel.c +++ b/lib/wheel.c @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "zebra.h" #include "linklist.h" @@ -60,9 +59,8 @@ wheel_timer_thread (struct thread *t) slots_to_skip++; wheel->slots_to_skip = slots_to_skip; - THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer, - wheel_timer_thread, wheel, - wheel->nexttime * slots_to_skip); + thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, + wheel->nexttime * slots_to_skip, &wheel->timer); return 0; } @@ -91,9 +89,8 @@ wheel_init (struct thread_master *master, int period, size_t slots, for (i = 0; i < slots; i++) wheel->wheel_slot_lists[i] = list_new (); - THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer, - wheel_timer_thread, wheel, - wheel->nexttime); + thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, + wheel->nexttime, &wheel->timer); return wheel; } @@ -124,9 +121,8 @@ int wheel_start (struct timer_wheel *wheel) { if (!wheel->timer) - THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer, - wheel_timer_thread, wheel, - wheel->nexttime); + thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel, + wheel->nexttime, &wheel->timer); return 0; } diff --git a/lib/wheel.h b/lib/wheel.h index 79d21e124b..07be79bf26 100644 --- a/lib/wheel.h +++ b/lib/wheel.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __WHEEL_H__ #define __WHEEL_H__ diff --git a/lib/workqueue.c b/lib/workqueue.c index 51017b34ea..f992588399 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -15,10 +15,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -126,8 +125,9 @@ work_queue_schedule (struct work_queue *wq, unsigned int delay) && (wq->thread == NULL) && (listcount (wq->items) > 0) ) { - wq->thread = thread_add_background (wq->master, work_queue_run, - wq, delay); + wq->thread = NULL; + thread_add_background(wq->master, work_queue_run, wq, delay, + &wq->thread); /* set thread yield time, if needed */ if (wq->thread && wq->spec.yield != THREAD_YIELD_TIME_SLOT) thread_set_yield_time (wq->thread, wq->spec.yield); diff --git a/lib/workqueue.h b/lib/workqueue.h index 548f96d8b0..45f02afc63 100644 --- a/lib/workqueue.h +++ b/lib/workqueue.h @@ -15,10 +15,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _QUAGGA_WORK_QUEUE_H diff --git a/lib/zassert.h b/lib/zassert.h index bf0a851ba8..082ad67897 100644 --- a/lib/zassert.h +++ b/lib/zassert.h @@ -13,10 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Quagga; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _QUAGGA_ASSERT_H diff --git a/lib/zclient.c b/lib/zclient.c index d2a5186315..9823bc8d99 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -14,10 +14,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> @@ -26,6 +25,8 @@ #include "stream.h" #include "buffer.h" #include "network.h" +#include "vrf.h" +#include "vrf_int.h" #include "if.h" #include "log.h" #include "thread.h" @@ -310,8 +311,9 @@ zclient_flush_data(struct thread *thread) return zclient_failed(zclient); break; case BUFFER_PENDING: - zclient->t_write = thread_add_write(zclient->master, zclient_flush_data, - zclient, zclient->sock); + zclient->t_write = NULL; + thread_add_write(zclient->master, zclient_flush_data, zclient, zclient->sock, + &zclient->t_write); break; case BUFFER_EMPTY: break; @@ -336,8 +338,8 @@ zclient_send_message(struct zclient *zclient) THREAD_OFF(zclient->t_write); break; case BUFFER_PENDING: - THREAD_WRITE_ON(zclient->master, zclient->t_write, - zclient_flush_data, zclient, zclient->sock); + thread_add_write(zclient->master, zclient_flush_data, zclient, + zclient->sock, &zclient->t_write); break; } return 0; @@ -733,6 +735,18 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, s = zclient->obuf; stream_reset (s); + /* Some checks for labeled-unicast. The current expectation is that each + * nexthop is accompanied by a label in the case of labeled-unicast. + */ + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) && + CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) + { + /* We expect prefixes installed with labels and the number to match + * the number of nexthops. + */ + assert (api->label_num == api->nexthop_num); + } + zclient_create_header (s, cmd, api->vrf_id); /* Put type and nexthop. */ @@ -749,7 +763,7 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, /* Nexthop, ifindex, distance and metric information. */ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) - { + { /* traditional 32-bit data units */ if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE)) { @@ -765,6 +779,9 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, { stream_putc (s, NEXTHOP_TYPE_IPV4); stream_put_in_addr (s, api->nexthop[i]); + /* For labeled-unicast, each nexthop is followed by label. */ + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) + stream_putl (s, api->label[i]); } for (i = 0; i < api->ifindex_num; i++) { @@ -800,6 +817,18 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, s = zclient->obuf; stream_reset (s); + /* Some checks for labeled-unicast. The current expectation is that each + * nexthop is accompanied by a label in the case of labeled-unicast. + */ + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) && + CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) + { + /* We expect prefixes installed with labels and the number to match + * the number of nexthops. + */ + assert (api->label_num == api->nexthop_num); + } + zclient_create_header (s, cmd, api->vrf_id); /* Put type and nexthop. */ @@ -831,6 +860,9 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient, { stream_putc (s, NEXTHOP_TYPE_IPV6); stream_write (s, (u_char *)api->nexthop[i], 16); + /* For labeled-unicast, each nexthop is followed by label. */ + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) + stream_putl (s, api->label[i]); } for (i = 0; i < api->ifindex_num; i++) { @@ -869,6 +901,18 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, s = zclient->obuf; stream_reset (s); + /* Some checks for labeled-unicast. The current expectation is that each + * nexthop is accompanied by a label in the case of labeled-unicast. + */ + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) && + CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP)) + { + /* We expect prefixes installed with labels and the number to match + * the number of nexthops. + */ + assert (api->label_num == api->nexthop_num); + } + zclient_create_header (s, cmd, api->vrf_id); /* Put type and nexthop. */ @@ -907,6 +951,9 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p, { stream_putc (s, NEXTHOP_TYPE_IPV6); stream_write (s, (u_char *)api->nexthop[i], 16); + /* For labeled-unicast, each nexthop is followed by label. */ + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL)) + stream_putl (s, api->label[i]); } for (i = 0; i < api->ifindex_num; i++) { @@ -1879,6 +1926,12 @@ zclient_read (struct thread *thread) if (zclient->interface_link_params) (*zclient->interface_link_params) (command, zclient, length); break; + case ZEBRA_FEC_UPDATE: + if (zclient_debug) + zlog_debug("zclient rcvd fec update\n"); + if (zclient->fec_update) + (*zclient->fec_update) (command, zclient, length); + break; default: break; } @@ -1961,22 +2014,20 @@ zclient_event (enum event event, struct zclient *zclient) switch (event) { case ZCLIENT_SCHEDULE: - if (! zclient->t_connect) - zclient->t_connect = - thread_add_event (zclient->master, zclient_connect, zclient, 0); + thread_add_event(zclient->master, zclient_connect, zclient, 0, + &zclient->t_connect); break; case ZCLIENT_CONNECT: if (zclient_debug) zlog_debug ("zclient connect failures: %d schedule interval is now %d", zclient->fail, zclient->fail < 3 ? 10 : 60); - if (! zclient->t_connect) - zclient->t_connect = - thread_add_timer (zclient->master, zclient_connect, zclient, - zclient->fail < 3 ? 10 : 60); + thread_add_timer(zclient->master, zclient_connect, zclient, + zclient->fail < 3 ? 10 : 60, &zclient->t_connect); break; case ZCLIENT_READ: - zclient->t_read = - thread_add_read (zclient->master, zclient_read, zclient, zclient->sock); + zclient->t_read = NULL; + thread_add_read(zclient->master, zclient_read, zclient, zclient->sock, + &zclient->t_read); break; } } diff --git a/lib/zclient.h b/lib/zclient.h index d3d0a202c5..847ac3b671 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -7,16 +7,15 @@ * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. - * + * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _ZEBRA_ZCLIENT_H @@ -94,6 +93,9 @@ typedef enum { ZEBRA_LABEL_MANAGER_CONNECT, ZEBRA_GET_LABEL_CHUNK, ZEBRA_RELEASE_LABEL_CHUNK, + ZEBRA_FEC_REGISTER, + ZEBRA_FEC_UNREGISTER, + ZEBRA_FEC_UPDATE, } zebra_message_types_t; struct redist_proto @@ -164,6 +166,7 @@ struct zclient int (*redistribute_route_ipv4_del) (int, struct zclient *, uint16_t, vrf_id_t); int (*redistribute_route_ipv6_add) (int, struct zclient *, uint16_t, vrf_id_t); int (*redistribute_route_ipv6_del) (int, struct zclient *, uint16_t, vrf_id_t); + int (*fec_update) (int, struct zclient *, uint16_t); }; /* Zebra API message flag. */ @@ -174,6 +177,7 @@ struct zclient #define ZAPI_MESSAGE_TAG 0x10 #define ZAPI_MESSAGE_MTU 0x20 #define ZAPI_MESSAGE_SRCPFX 0x40 +#define ZAPI_MESSAGE_LABEL 0x80 /* Zserv protocol message header */ struct zserv_header @@ -206,6 +210,9 @@ struct zapi_ipv4 u_char ifindex_num; ifindex_t *ifindex; + u_char label_num; + unsigned int *label; + u_char distance; u_int32_t metric; @@ -297,6 +304,9 @@ struct zapi_ipv6 u_char ifindex_num; ifindex_t *ifindex; + u_char label_num; + unsigned int *label; + u_char distance; u_int32_t metric; diff --git a/lib/zebra.h b/lib/zebra.h index 760264d752..0a61c433d9 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -1,22 +1,22 @@ /* Zebra common header. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Kunihiro Ishiguro - -This file is part of GNU Zebra. - -GNU Zebra is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -GNU Zebra is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Zebra; see the file COPYING. If not, write to the Free -Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef _ZEBRA_H #define _ZEBRA_H @@ -393,6 +393,9 @@ extern const char *zserv_command_string (unsigned int command); #define ZEBRA_FLAG_SCOPE_LINK 0x100 #define ZEBRA_FLAG_FIB_OVERRIDE 0x200 +/* Zebra FEC flags. */ +#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1 + #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */ #endif @@ -401,8 +404,8 @@ extern const char *zserv_command_string (unsigned int command); typedef enum { AFI_IP = 1, AFI_IP6 = 2, - AFI_L2VPN = 4, - AFI_MAX = 5 + AFI_L2VPN = 3, + AFI_MAX = 4 } afi_t; /* Subsequent Address Family Identifier. */ @@ -413,11 +416,13 @@ typedef enum { #define SAFI_ENCAP 5 #define SAFI_RESERVED_5 5 #define SAFI_EVPN 6 -#define SAFI_MAX 7 +#define SAFI_LABELED_UNICAST 7 +#define SAFI_MAX 8 #define IANA_SAFI_RESERVED 0 #define IANA_SAFI_UNICAST 1 #define IANA_SAFI_MULTICAST 2 +#define IANA_SAFI_LABELED_UNICAST 4 #define IANA_SAFI_ENCAP 7 #define IANA_SAFI_MPLS_VPN 128 @@ -512,6 +517,8 @@ static inline safi_t safi_iana2int (safi_t safi) return SAFI_ENCAP; if (safi == IANA_SAFI_EVPN) return SAFI_EVPN; + if (safi == IANA_SAFI_LABELED_UNICAST) + return SAFI_LABELED_UNICAST; return SAFI_MAX; } @@ -527,6 +534,8 @@ static inline safi_t safi_int2iana (safi_t safi) return IANA_SAFI_ENCAP; if (safi == SAFI_EVPN) return IANA_SAFI_EVPN; + if (safi == SAFI_LABELED_UNICAST) + return IANA_SAFI_LABELED_UNICAST; return IANA_SAFI_RESERVED; } |
