diff options
66 files changed, 807 insertions, 427 deletions
diff --git a/babeld/babel_main.c b/babeld/babel_main.c index 239ab71f06..48f6994d82 100644 --- a/babeld/babel_main.c +++ b/babeld/babel_main.c @@ -84,7 +84,7 @@ static zebra_capabilities_t _caps_p [] = ZCAP_BIND }; -static struct zebra_privs_t babeld_privs = +struct zebra_privs_t babeld_privs = { #if defined(FRR_USER) .user = FRR_USER, diff --git a/babeld/babel_zebra.c b/babeld/babel_zebra.c index 337b7b3927..e7c27e8e21 100644 --- a/babeld/babel_zebra.c +++ b/babeld/babel_zebra.c @@ -238,7 +238,7 @@ babel_zebra_connected (struct zclient *zclient) void babelz_zebra_init(void) { zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0); + zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs); zclient->zebra_connected = babel_zebra_connected; zclient->interface_add = babel_interface_add; diff --git a/babeld/babeld.h b/babeld/babeld.h index 899b4f175c..bc284c1e96 100644 --- a/babeld/babeld.h +++ b/babeld/babeld.h @@ -113,6 +113,8 @@ struct babel struct thread *t_update; /* timers */ }; +extern struct zebra_privs_t babeld_privs; + extern void babeld_quagga_init(void); extern int input_filter(const unsigned char *id, const unsigned char *prefix, unsigned short plen, diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 6de9ba3cc6..1fb930fdef 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -1587,6 +1587,7 @@ DEFUN (no_debug_bgp, TERM_DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS); TERM_DEBUG_OFF(zebra, ZEBRA); TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS); + TERM_DEBUG_OFF(nht, NHT); vty_out(vty, "All possible debugging has been turned off\n"); return CMD_SUCCESS; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 70299ea456..101e0e62bb 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -675,7 +675,7 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen) return ret; } - ret = listen(sock, 3); + ret = listen(sock, SOMAXCONN); if (ret < 0) { zlog_err("listen: %s", safe_strerror(errno)); return ret; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index ddf461f1b1..0d1d768294 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1105,12 +1105,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, ->ifindex; if (!ifindex) { - if (mpinfo->peer->conf_if - || mpinfo->peer->ifname) + if (mpinfo->peer->conf_if) + ifindex = mpinfo->peer->ifp->ifindex; + else if (mpinfo->peer->ifname) ifindex = ifname2ifindex( - mpinfo->peer->conf_if - ? mpinfo->peer->conf_if - : mpinfo->peer->ifname, + mpinfo->peer->ifname, bgp->vrf_id); else if (mpinfo->peer->nexthop.ifp) ifindex = mpinfo->peer->nexthop.ifp @@ -1749,13 +1748,15 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); } +extern struct zebra_privs_t bgpd_privs; + void bgp_zebra_init(struct thread_master *master) { zclient_num_connects = 0; /* Set default values. */ zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_BGP, 0); + zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs); zclient->zebra_connected = bgp_zebra_connected; zclient->router_id_update = bgp_router_id_update; zclient->interface_add = bgp_interface_add; diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index b8058cf1e5..478d3b5ac7 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -883,6 +883,7 @@ int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type) return CMD_SUCCESS; } +extern struct zebra_privs_t bgpd_privs; /* * Modeled after bgp_zebra.c'bgp_zebra_init() @@ -892,7 +893,7 @@ void vnc_zebra_init(struct thread_master *master) { /* Set default values. */ zclient_vnc = zclient_new(master); - zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0); + zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs); zclient_vnc->redistribute_route_add = vnc_zebra_read_route; zclient_vnc->redistribute_route_del = vnc_zebra_read_route; diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index 56327f1205..21413bf446 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -38,8 +38,6 @@ #include "table.h" #include "vty.h" -extern struct zebra_privs_t eigrpd_privs; - #include "eigrpd/eigrp_structs.h" #include "eigrpd/eigrpd.h" #include "eigrpd/eigrp_interface.h" diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h index 4441f5d004..324181c21e 100644 --- a/eigrpd/eigrp_structs.h +++ b/eigrpd/eigrp_structs.h @@ -100,7 +100,7 @@ struct eigrp { struct route_table *networks; /* EIGRP config networks. */ - struct list *topology_table; + struct route_table *topology_table; uint64_t serno; /* Global serial number counter for topology entry changes*/ diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 94775622d9..7d352b8bed 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -51,9 +51,6 @@ #include "eigrpd/eigrp_fsm.h" #include "eigrpd/eigrp_memory.h" -static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *, - struct eigrp_prefix_entry *); -static void eigrp_prefix_entry_del(struct eigrp_prefix_entry *); static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *, struct eigrp_nexthop_entry *); @@ -63,45 +60,9 @@ static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *, * del - assigned function executed before deleting topology node by list * function */ -struct list *eigrp_topology_new() +struct route_table *eigrp_topology_new() { - struct list *new = list_new(); - new->cmp = (int (*)(void *, void *))eigrp_prefix_entry_cmp; - new->del = (void (*)(void *))eigrp_prefix_entry_del; - - return new; -} - -/* - * Topology node comparison - */ - -static int eigrp_prefix_entry_cmp(struct eigrp_prefix_entry *node1, - struct eigrp_prefix_entry *node2) -{ - if (node1->af == AF_INET) { - if (node2->af == AF_INET) { - if (node1->destination->u.prefix4.s_addr - < node2->destination->u.prefix4.s_addr) - return -1; - if (node1->destination->u.prefix4.s_addr - > node2->destination->u.prefix4.s_addr) - return 1; - else - return 0; - } else - return 1; - } else - return 1; -} - -/* - * Topology node delete - */ - -static void eigrp_prefix_entry_del(struct eigrp_prefix_entry *node) -{ - list_delete_and_null(&node->entries); + return route_table_init(); } /* @@ -155,30 +116,41 @@ struct eigrp_nexthop_entry *eigrp_nexthop_entry_new() /* * Freeing topology table list */ -void eigrp_topology_free(struct list *list) +void eigrp_topology_free(struct route_table *table) { - list_delete_and_null(&list); + route_table_finish(table); } /* * Deleting all topology nodes in table */ -void eigrp_topology_cleanup(struct list *topology) +void eigrp_topology_cleanup(struct route_table *table) { - assert(topology); - - eigrp_topology_delete_all(topology); + eigrp_topology_delete_all(table); } /* * Adding topology node to topology table */ -void eigrp_prefix_entry_add(struct list *topology, - struct eigrp_prefix_entry *node) +void eigrp_prefix_entry_add(struct route_table *topology, + struct eigrp_prefix_entry *pe) { - if (listnode_lookup(topology, node) == NULL) { - listnode_add_sort(topology, node); + struct route_node *rn; + + rn = route_node_get(topology, pe->destination); + if (rn->info) { + if (IS_DEBUG_EIGRP_EVENT) { + char buf[PREFIX_STRLEN]; + + zlog_debug("%s: %s Should we have found this entry in the topo table?", + __PRETTY_FUNCTION__, + prefix2str(pe->destination, buf, + sizeof(buf))); + } } + + rn->info = pe; + route_lock_node(rn); } /* @@ -204,24 +176,30 @@ void eigrp_nexthop_entry_add(struct eigrp_prefix_entry *node, /* * Deleting topology node from topology table */ -void eigrp_prefix_entry_delete(struct list *topology, - struct eigrp_prefix_entry *node) +void eigrp_prefix_entry_delete(struct route_table *table, + struct eigrp_prefix_entry *pe) { struct eigrp *eigrp = eigrp_lookup(); + struct route_node *rn; + + rn = route_node_lookup(table, pe->destination); + if (!rn) + return; /* * Emergency removal of the node from this list. * Whatever it is. */ - listnode_delete(eigrp->topology_changes_internalIPV4, node); + listnode_delete(eigrp->topology_changes_internalIPV4, pe); - if (listnode_lookup(topology, node) != NULL) { - list_delete_and_null(&node->entries); - list_delete_and_null(&node->rij); - listnode_delete(topology, node); - eigrp_zebra_route_delete(node->destination); - XFREE(MTYPE_EIGRP_PREFIX_ENTRY, node); - } + list_delete_and_null(&pe->entries); + list_delete_and_null(&pe->rij); + eigrp_zebra_route_delete(pe->destination); + + rn->info = NULL; + route_unlock_node(rn); //Lookup above + route_unlock_node(rn); //Initial creation + XFREE(MTYPE_EIGRP_PREFIX_ENTRY, pe); } /* @@ -240,9 +218,19 @@ void eigrp_nexthop_entry_delete(struct eigrp_prefix_entry *node, /* * Deleting all nodes from topology table */ -void eigrp_topology_delete_all(struct list *topology) +void eigrp_topology_delete_all(struct route_table *topology) { - list_delete_all_node(topology); + struct route_node *rn; + struct eigrp_prefix_entry *pe; + + for (rn = route_top(topology); rn; rn = route_next(rn)) { + pe = rn->info; + + if (!pe) + continue; + + eigrp_prefix_entry_delete(topology, pe); + } } /* @@ -258,17 +246,21 @@ unsigned int eigrp_topology_table_isempty(struct list *topology) } struct eigrp_prefix_entry * -eigrp_topology_table_lookup_ipv4(struct list *topology_table, +eigrp_topology_table_lookup_ipv4(struct route_table *table, struct prefix *address) { - struct eigrp_prefix_entry *data; - struct listnode *node; - for (ALL_LIST_ELEMENTS_RO(topology_table, node, data)) { - if (prefix_same(data->destination, address)) - return data; - } + struct eigrp_prefix_entry *pe; + struct route_node *rn; - return NULL; + rn = route_node_lookup(table, address); + if (!rn) + return NULL; + + pe = rn->info; + + route_unlock_node(rn); + + return pe; } /* @@ -337,20 +329,24 @@ eigrp_prefix_entry_lookup(struct list *entries, struct eigrp_neighbor *nbr) struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *eigrp, struct eigrp_neighbor *nbr) { - struct listnode *node1, *node11, *node2, *node22; - struct eigrp_prefix_entry *prefix; + struct listnode *node2, *node22; struct eigrp_nexthop_entry *entry; + struct eigrp_prefix_entry *pe; + struct route_node *rn; /* create new empty list for prefixes storage */ struct list *prefixes = list_new(); /* iterate over all prefixes in topology table */ - for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { + for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + pe = rn->info; /* iterate over all neighbor entry in prefix */ - for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { + for (ALL_LIST_ELEMENTS(pe->entries, node2, node22, entry)) { /* if entry is from specified neighbor, add to list */ if (entry->adv_router == nbr) { - listnode_add(prefixes, prefix); + listnode_add(prefixes, pe); } } } @@ -426,11 +422,16 @@ enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action_messag void eigrp_topology_update_all_node_flags(struct eigrp *eigrp) { - struct list *table = eigrp->topology_table; - struct eigrp_prefix_entry *data; - struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS(table, node, nnode, data)) { - eigrp_topology_update_node_flags(data); + struct eigrp_prefix_entry *pe; + struct route_node *rn; + + for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { + pe = rn->info; + + if (!pe) + continue; + + eigrp_topology_update_node_flags(pe); } } @@ -484,12 +485,18 @@ void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix) void eigrp_topology_neighbor_down(struct eigrp *eigrp, struct eigrp_neighbor *nbr) { - struct listnode *node1, *node11, *node2, *node22; - struct eigrp_prefix_entry *prefix; + struct listnode *node2, *node22; + struct eigrp_prefix_entry *pe; struct eigrp_nexthop_entry *entry; + struct route_node *rn; + + for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { + pe = rn->info; + + if (!pe) + continue; - for (ALL_LIST_ELEMENTS(eigrp->topology_table, node1, node11, prefix)) { - for (ALL_LIST_ELEMENTS(prefix->entries, node2, node22, entry)) { + for (ALL_LIST_ELEMENTS(pe->entries, node2, node22, entry)) { struct eigrp_fsm_action_message msg; if (entry->adv_router != nbr) @@ -501,7 +508,7 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, msg.data_type = EIGRP_INT; msg.adv_router = nbr; msg.entry = entry; - msg.prefix = prefix; + msg.prefix = pe; eigrp_fsm_event(&msg); } } @@ -510,7 +517,7 @@ void eigrp_topology_neighbor_down(struct eigrp *eigrp, eigrp_update_send_all(eigrp, nbr->ei); } -void eigrp_update_topology_table_prefix(struct list *table, +void eigrp_update_topology_table_prefix(struct route_table *table, struct eigrp_prefix_entry *prefix) { struct listnode *node1, *node2; diff --git a/eigrpd/eigrp_topology.h b/eigrpd/eigrp_topology.h index ef5b32d5bf..c8772c8c3a 100644 --- a/eigrpd/eigrp_topology.h +++ b/eigrpd/eigrp_topology.h @@ -33,23 +33,25 @@ #define _ZEBRA_EIGRP_TOPOLOGY_H /* EIGRP Topology table related functions. */ -extern struct list *eigrp_topology_new(void); -extern void eigrp_topology_init(struct list *); +extern struct route_table *eigrp_topology_new(void); +extern void eigrp_topology_init(struct route_table *table); extern struct eigrp_prefix_entry *eigrp_prefix_entry_new(void); extern struct eigrp_nexthop_entry *eigrp_nexthop_entry_new(void); -extern void eigrp_topology_free(struct list *); -extern void eigrp_topology_cleanup(struct list *); -extern void eigrp_prefix_entry_add(struct list *, struct eigrp_prefix_entry *); +extern void eigrp_topology_free(struct route_table *table); +extern void eigrp_topology_cleanup(struct route_table *table); +extern void eigrp_prefix_entry_add(struct route_table *table, + struct eigrp_prefix_entry *pe); extern void eigrp_nexthop_entry_add(struct eigrp_prefix_entry *, struct eigrp_nexthop_entry *); -extern void eigrp_prefix_entry_delete(struct list *, - struct eigrp_prefix_entry *); +extern void eigrp_prefix_entry_delete(struct route_table *table, + struct eigrp_prefix_entry *pe); extern void eigrp_nexthop_entry_delete(struct eigrp_prefix_entry *, struct eigrp_nexthop_entry *); -extern void eigrp_topology_delete_all(struct list *); +extern void eigrp_topology_delete_all(struct route_table *table); extern unsigned int eigrp_topology_table_isempty(struct list *); extern struct eigrp_prefix_entry * -eigrp_topology_table_lookup_ipv4(struct list *, struct prefix *); +eigrp_topology_table_lookup_ipv4(struct route_table *table, + struct prefix *p); extern struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *); extern struct list * eigrp_topology_get_successor_max(struct eigrp_prefix_entry *pe, @@ -64,7 +66,7 @@ extern enum metric_change eigrp_topology_update_distance(struct eigrp_fsm_action extern void eigrp_update_routing_table(struct eigrp_prefix_entry *); extern void eigrp_topology_neighbor_down(struct eigrp *, struct eigrp_neighbor *); -extern void eigrp_update_topology_table_prefix(struct list *, - struct eigrp_prefix_entry *); +extern void eigrp_update_topology_table_prefix(struct route_table *table, + struct eigrp_prefix_entry *pe); #endif diff --git a/eigrpd/eigrp_update.c b/eigrpd/eigrp_update.c index 4a86b48944..b4d1c58870 100644 --- a/eigrpd/eigrp_update.c +++ b/eigrpd/eigrp_update.c @@ -530,13 +530,15 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) u_int16_t length = EIGRP_HEADER_LEN; struct eigrp_nexthop_entry *te; struct eigrp_prefix_entry *pe; - struct listnode *node, *node2, *nnode, *nnode2; + struct listnode *node2, *nnode2; struct eigrp_interface *ei = nbr->ei; struct eigrp *eigrp = ei->eigrp; struct prefix *dest_addr; u_int32_t seq_no = eigrp->sequence_number; + u_int16_t mtu = ei->ifp->mtu; + struct route_node *rn; - ep = eigrp_packet_new(ei->ifp->mtu, nbr); + ep = eigrp_packet_new(mtu, nbr); /* Prepare EIGRP EOT UPDATE header */ eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp, @@ -549,20 +551,26 @@ void eigrp_update_send_EOT(struct eigrp_neighbor *nbr) length += eigrp_add_authTLV_MD5_to_stream(ep->s,ei); } - for (ALL_LIST_ELEMENTS(eigrp->topology_table, node, nnode, pe)) { + for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + pe = rn->info; for (ALL_LIST_ELEMENTS(pe->entries, node2, nnode2, te)) { if (eigrp_nbr_split_horizon_check(te, ei)) continue; - if ((length + 0x001D) > (u_int16_t)ei->ifp->mtu) { + if ((length + 0x001D) > mtu) { eigrp_update_place_on_nbr_queue (nbr, ep, seq_no, length); seq_no++; length = EIGRP_HEADER_LEN; - ep = eigrp_packet_new(ei->ifp->mtu, nbr); - eigrp_packet_header_init(EIGRP_OPC_UPDATE, eigrp, + ep = eigrp_packet_new(mtu, nbr); + eigrp_packet_header_init(EIGRP_OPC_UPDATE, + nbr->ei->eigrp, ep->s, EIGRP_EOT_FLAG, - seq_no, nbr->recv_sequence_number); + seq_no, + nbr->recv_sequence_number); if((ei->params.auth_type == EIGRP_AUTH_TYPE_MD5) && (ei->params.auth_keychain != NULL)) @@ -736,7 +744,6 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) { struct eigrp_packet *ep; u_int16_t length = EIGRP_HEADER_LEN; - struct listnode *node, *nnode; struct eigrp_prefix_entry *pe; struct prefix *dest_addr; struct eigrp_interface *ei = nbr->ei; @@ -744,6 +751,7 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) struct list *prefixes; u_int32_t flags; unsigned int send_prefixes; + struct route_node *rn; /* get prefixes to send to neighbor */ prefixes = nbr->nbr_gr_prefixes_send; @@ -795,7 +803,11 @@ static void eigrp_update_send_GR_part(struct eigrp_neighbor *nbr) length += eigrp_add_authTLV_MD5_to_stream(ep->s, ei); } - for (ALL_LIST_ELEMENTS(eigrp->topology_table, node, nnode, pe)) { + for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + pe = rn->info; /* * Filtering */ @@ -945,35 +957,40 @@ void eigrp_update_send_GR(struct eigrp_neighbor *nbr, enum GR_type gr_type, struct vty *vty) { struct eigrp_prefix_entry *pe2; - struct listnode *node2, *nnode2; struct list *prefixes; + struct route_node *rn; + struct eigrp_interface *ei = nbr->ei; + struct eigrp *eigrp = ei->eigrp; if (gr_type == EIGRP_GR_FILTER) { /* function was called after applying filtration */ zlog_info( "Neighbor %s (%s) is resync: route configuration changed", inet_ntoa(nbr->src), - ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + ifindex2ifname(ei->ifp->ifindex, VRF_DEFAULT)); } else if (gr_type == EIGRP_GR_MANUAL) { /* Graceful restart was called manually */ zlog_info("Neighbor %s (%s) is resync: manually cleared", inet_ntoa(nbr->src), - ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT)); + ifindex2ifname(ei->ifp->ifindex, VRF_DEFAULT)); if (vty != NULL) { vty_time_print(vty, 0); vty_out(vty, "Neighbor %s (%s) is resync: manually cleared\n", inet_ntoa(nbr->src), - ifindex2ifname(nbr->ei->ifp->ifindex, + ifindex2ifname(ei->ifp->ifindex, VRF_DEFAULT)); } } prefixes = list_new(); /* add all prefixes from topology table to list */ - for (ALL_LIST_ELEMENTS(nbr->ei->eigrp->topology_table, node2, nnode2, - pe2)) { + for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + pe2 = rn->info; listnode_add(prefixes, pe2); } diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index d93abbb8b7..34a07f5fe3 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -466,9 +466,10 @@ DEFUN (show_ip_eigrp_topology, "Show all links in topology table\n") { struct eigrp *eigrp; - struct listnode *node, *node2; + struct listnode *node; struct eigrp_prefix_entry *tn; struct eigrp_nexthop_entry *te; + struct route_node *rn; int first; eigrp = eigrp_lookup(); @@ -479,9 +480,13 @@ DEFUN (show_ip_eigrp_topology, show_ip_eigrp_topology_header(vty, eigrp); - for (ALL_LIST_ELEMENTS_RO(eigrp->topology_table, node, tn)) { + for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + tn = rn->info; first = 1; - for (ALL_LIST_ELEMENTS_RO(tn->entries, node2, te)) { + for (ALL_LIST_ELEMENTS_RO(tn->entries, node, te)) { if (argc == 5 || (((te->flags & EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG) diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 28d2f29811..9076a50f57 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -103,7 +103,7 @@ void eigrp_zebra_init(void) { zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0); + zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs); zclient->zebra_connected = eigrp_zebra_connected; zclient->router_id_update = eigrp_router_id_update_zebra; zclient->interface_add = eigrp_interface_add; diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index a8173f4efd..42d398458e 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -158,7 +158,7 @@ static struct eigrp *eigrp_new(const char *AS) /* init internal data structures */ eigrp->eiflist = list_new(); eigrp->passive_interface_default = EIGRP_IF_ACTIVE; - eigrp->networks = route_table_init(); + eigrp->networks = eigrp_topology_new(); if ((eigrp_socket = eigrp_sock_init()) < 0) { zlog_err( @@ -181,7 +181,7 @@ static struct eigrp *eigrp_new(const char *AS) thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); eigrp->oi_write_q = list_new(); - eigrp->topology_table = eigrp_topology_new(); + eigrp->topology_table = route_table_init(); eigrp->neighbor_self = eigrp_nbr_new(NULL); eigrp->neighbor_self->src.s_addr = INADDR_ANY; diff --git a/eigrpd/eigrpd.h b/eigrpd/eigrpd.h index 5ec6c8e1f7..de7c881ac0 100644 --- a/eigrpd/eigrpd.h +++ b/eigrpd/eigrpd.h @@ -41,6 +41,7 @@ extern struct zclient *zclient; extern struct thread_master *master; extern struct eigrp_master *eigrp_om; +extern struct zebra_privs_t eigrpd_privs; /* Prototypes */ extern void eigrp_master_init(void); diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 2c8b126088..591af3b8ed 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -45,8 +45,6 @@ #include "privs.h" -extern struct zebra_privs_t isisd_privs; - struct bpf_insn llcfilter[] = { /* check first byte */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, ETH_ALEN), diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c index 7ac8b54fa4..ccde4fbbe1 100644 --- a/isisd/isis_dlpi.c +++ b/isisd/isis_dlpi.c @@ -47,8 +47,6 @@ #include "privs.h" -extern struct zebra_privs_t isisd_privs; - static t_uscalar_t dlpi_ctl[1024]; /* DLPI control messages */ /* diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index e24901b0de..974d2b78cf 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -44,8 +44,6 @@ #include "privs.h" -extern struct zebra_privs_t isisd_privs; - /* tcpdump -i eth0 'isis' -dd */ static struct sock_filter isisfilter[] = { diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 387f99938e..c186dd56ad 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -412,7 +412,7 @@ static void isis_zebra_connected(struct zclient *zclient) void isis_zebra_init(struct thread_master *master) { zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_ISIS, 0); + zclient_init(zclient, ZEBRA_ROUTE_ISIS, 0, &isisd_privs); zclient->zebra_connected = isis_zebra_connected; zclient->router_id_update = isis_router_id_update_zebra; zclient->interface_add = isis_zebra_if_add; diff --git a/isisd/isisd.h b/isisd/isisd.h index a10748fd45..427d314df6 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -33,6 +33,8 @@ #include "isis_memory.h" #include "qobj.h" +extern struct zebra_privs_t isisd_privs; + /* uncomment if you are a developer in bug hunt */ /* #define EXTREME_DEBUG */ /* #define EXTREME_DICT_DEBUG */ diff --git a/ldpd/lde.c b/ldpd/lde.c index a7f933bbe5..8122b88cca 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -77,7 +77,7 @@ struct thread_master *master; /* lde privileges */ static zebra_capabilities_t _caps_p [] = { - /* none */ + ZCAP_NET_ADMIN }; static struct zebra_privs_t lde_privs = @@ -1622,6 +1622,8 @@ zclient_sync_init(u_short instance) zclient_sync->sock = -1; zclient_sync->redist_default = ZEBRA_ROUTE_LDP; zclient_sync->instance = instance; + zclient_sync->privs = &lde_privs; + while (zclient_socket_connect(zclient_sync) < 0) { log_warnx("Error connecting synchronous zclient!"); sleep(1); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 7f68f0b694..8fe51cb9d1 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -507,12 +507,14 @@ ldp_zebra_connected(struct zclient *zclient) ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); } +extern struct zebra_privs_t ldpd_privs; + void ldp_zebra_init(struct thread_master *master) { /* Set default values. */ zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_LDP, 0); + zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs); /* set callbacks */ zclient->zebra_connected = ldp_zebra_connected; diff --git a/lib/buffer.c b/lib/buffer.c index a7c4fe4f2f..191fbf875a 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -482,12 +482,14 @@ buffer_status_t buffer_write(struct buffer *b, int fd, const void *p, ssize_t nbytes; #if 0 - /* Should we attempt to drain any previously buffered data? This could help - reduce latency in pushing out the data if we are stuck in a long-running - thread that is preventing the main select loop from calling the flush - thread... */ - if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR)) - return BUFFER_ERROR; + /* + * Should we attempt to drain any previously buffered data? + * This could help reduce latency in pushing out the data if + * we are stuck in a long-running thread that is preventing + * the main select loop from calling the flush thread... + */ + if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR)) + return BUFFER_ERROR; #endif if (b->head) /* Buffer is not empty, so do not attempt to write the new data. diff --git a/lib/zclient.c b/lib/zclient.c index ad5c30584c..d23e5fbd79 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -35,6 +35,7 @@ #include "table.h" #include "nexthop.h" #include "mpls.h" +#include "sockopt.h" DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient") DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs") @@ -180,7 +181,8 @@ void zclient_reset(struct zclient *zclient) &zclient->mi_redist[afi][zclient->redist_default], zclient->instance); - zclient_init(zclient, zclient->redist_default, zclient->instance); + zclient_init(zclient, zclient->redist_default, + zclient->instance, zclient->privs); } /** @@ -202,6 +204,10 @@ int zclient_socket_connect(struct zclient *zclient) set_cloexec(sock); + zclient->privs->change(ZPRIVS_RAISE); + setsockopt_so_sendbuf(sock, 1048576); + zclient->privs->change(ZPRIVS_LOWER); + /* Connect to zebra. */ ret = connect(sock, (struct sockaddr *)&zclient_addr, zclient_addr_len); @@ -543,12 +549,14 @@ int zclient_start(struct zclient *zclient) /* Initialize zebra client. Argument redist_default is unwanted redistribute route type. */ -void zclient_init(struct zclient *zclient, int redist_default, u_short instance) +void zclient_init(struct zclient *zclient, int redist_default, + u_short instance, struct zebra_privs_t *privs) { int afi, i; /* Set -1 to the default socket value. */ zclient->sock = -1; + zclient->privs = privs; /* Clear redistribution flags. */ for (afi = AFI_IP; afi < AFI_MAX; afi++) diff --git a/lib/zclient.h b/lib/zclient.h index 288951eb1a..23fe0e41f4 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -134,6 +134,9 @@ struct zclient { /* The thread master we schedule ourselves on */ struct thread_master *master; + /* Priviledges to change socket values */ + struct zebra_privs_t *privs; + /* Socket to zebra daemon. */ int sock; @@ -315,7 +318,7 @@ struct zapi_pw_status { /* Prototypes of zebra client service functions. */ extern struct zclient *zclient_new(struct thread_master *); -extern void zclient_init(struct zclient *, int, u_short); +extern void zclient_init(struct zclient *, int, u_short, struct zebra_privs_t *privs); extern int zclient_start(struct zclient *); extern void zclient_stop(struct zclient *); extern void zclient_reset(struct zclient *); diff --git a/nhrpd/nhrp_main.c b/nhrpd/nhrp_main.c index 3a7186c1d7..767907aa53 100644 --- a/nhrpd/nhrp_main.c +++ b/nhrpd/nhrp_main.c @@ -43,7 +43,7 @@ static zebra_capabilities_t _caps_p [] = { ZCAP_DAC_OVERRIDE, /* for now needed to write to /proc/sys/net/ipv4/<if>/send_redirect */ }; -static struct zebra_privs_t nhrpd_privs = { +struct zebra_privs_t nhrpd_privs = { #if defined(FRR_USER) && defined(FRR_GROUP) .user = FRR_USER, .group = FRR_GROUP, diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 495e226f15..7701dcbb88 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -325,7 +325,7 @@ void nhrp_zebra_init(void) zclient->redistribute_route_add = nhrp_route_read; zclient->redistribute_route_del = nhrp_route_read; - zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0); + zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs); } void nhrp_zebra_terminate(void) diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h index 3071371969..2ab40a4d39 100644 --- a/nhrpd/nhrpd.h +++ b/nhrpd/nhrpd.h @@ -303,6 +303,8 @@ struct nhrp_interface { } afi[AFI_MAX]; }; +extern struct zebra_privs_t nhrpd_privs; + int sock_open_unix(const char *path); void nhrp_interface_init(void); diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index b126786246..6bbab46ad8 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -234,6 +234,7 @@ struct ospf6_area *ospf6_area_create(u_int32_t area_id, struct ospf6 *o, int df) oa->summary_prefix->scope = oa; oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS); oa->summary_router->scope = oa; + oa->router_lsa_size_limit = 1024 + 256; /* set default options */ if (CHECK_FLAG(o->flag, OSPF6_STUB_ROUTER)) { diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index a2caeccb86..b5a0a9209b 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -52,6 +52,7 @@ unsigned char conf_debug_ospf6_brouter = 0; u_int32_t conf_debug_ospf6_brouter_specific_router_id; u_int32_t conf_debug_ospf6_brouter_specific_area_id; +#define MAX_LSA_PAYLOAD (1024 + 256) /******************************/ /* RFC2740 3.4.3.1 Router-LSA */ /******************************/ @@ -214,8 +215,7 @@ int ospf6_router_lsa_originate(struct thread *thread) ospf6_router_lsa_options_set(oa, router_lsa); /* describe links for each interfaces */ - lsdesc = (struct ospf6_router_lsdesc - *)((caddr_t)router_lsa + lsdesc = (struct ospf6_router_lsdesc *)((caddr_t)router_lsa + sizeof(struct ospf6_router_lsa)); for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) { @@ -248,6 +248,41 @@ int ospf6_router_lsa_originate(struct thread *thread) return 0; } + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_ROUTER); + lsa_header->id = htonl(link_state_id); + lsa_header->adv_router = oa->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, + lsa_header->id, + lsa_header->adv_router, oa->lsdb); + lsa_header->length = + htons((caddr_t)lsdesc - (caddr_t)buffer); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_area(lsa, oa); + + /* Reset Buffer to fill next Router LSA */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + router_lsa = + (struct ospf6_router_lsa *)((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + + ospf6_router_lsa_options_set(oa, router_lsa); + + /* describe links for each interfaces */ + lsdesc = (struct ospf6_router_lsdesc *) + ((caddr_t)router_lsa + + sizeof(struct ospf6_router_lsa)); + link_state_id++; } @@ -861,7 +896,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) char buffer[OSPF6_MAX_LSASIZE]; struct ospf6_lsa_header *lsa_header; - struct ospf6_lsa *old, *lsa; + struct ospf6_lsa *old, *lsa, *old_next = NULL; struct ospf6_intra_prefix_lsa *intra_prefix_lsa; struct ospf6_interface *oi; @@ -873,6 +908,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) unsigned short prefix_num = 0; char buf[PREFIX2STR_BUFFER]; struct ospf6_route_table *route_advertise; + int ls_id = 0; oa = (struct ospf6_area *)THREAD_ARG(thread); oa->thread_intra_prefix_lsa = NULL; @@ -882,8 +918,22 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) oa->ospf6->router_id, oa->lsdb); if (!IS_AREA_ENABLED(oa)) { - if (old) + if (old) { ospf6_lsa_purge(old); + /* find previous LSA */ + old_next = ospf6_lsdb_lookup( + htons(OSPF6_LSTYPE_INTRA_PREFIX), + htonl(++ls_id), + oa->ospf6->router_id, oa->lsdb); + + while (old_next) { + ospf6_lsa_purge(old_next); + old_next = ospf6_lsdb_lookup( + htons(OSPF6_LSTYPE_INTRA_PREFIX), + htonl(++ls_id), + oa->ospf6->router_id, oa->lsdb); + } + } return 0; } @@ -895,8 +945,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) /* prepare buffer */ memset(buffer, 0, sizeof(buffer)); lsa_header = (struct ospf6_lsa_header *)buffer; - intra_prefix_lsa = (struct ospf6_intra_prefix_lsa - *)((caddr_t)lsa_header + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)((caddr_t)lsa_header + sizeof(struct ospf6_lsa_header)); /* Fill Intra-Area-Prefix-LSA */ @@ -945,8 +994,23 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) } if (route_advertise->count == 0) { - if (old) + if (old) { + ls_id = 0; ospf6_lsa_purge(old); + /* find previous LSA */ + old_next = ospf6_lsdb_lookup( + htons(OSPF6_LSTYPE_INTRA_PREFIX), + htonl(++ls_id), + oa->ospf6->router_id, oa->lsdb); + + while (old_next) { + ospf6_lsa_purge(old_next); + old_next = ospf6_lsdb_lookup( + htons(OSPF6_LSTYPE_INTRA_PREFIX), + htonl(++ls_id), + oa->ospf6->router_id, oa->lsdb); + } + } ospf6_route_table_delete(route_advertise); return 0; } @@ -957,13 +1021,58 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) + sizeof(struct ospf6_intra_prefix_lsa)); for (route = ospf6_route_head(route_advertise); route; route = ospf6_route_best_next(route)) { + if (((caddr_t)op - (caddr_t)lsa_header) > MAX_LSA_PAYLOAD) { + + intra_prefix_lsa->prefix_num = htons(prefix_num); + + /* Fill LSA Header */ + lsa_header->age = 0; + lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX); + lsa_header->id = htonl(ls_id++); + lsa_header->adv_router = oa->ospf6->router_id; + lsa_header->seqnum = + ospf6_new_ls_seqnum(lsa_header->type, + lsa_header->id, + lsa_header->adv_router, + oa->lsdb); + lsa_header->length = htons((caddr_t)op - + (caddr_t)lsa_header); + + /* LSA checksum */ + ospf6_lsa_checksum(lsa_header); + + /* Create LSA */ + lsa = ospf6_lsa_create(lsa_header); + + /* Originate */ + ospf6_lsa_originate_area(lsa, oa); + + /* Prepare next buffer */ + memset(buffer, 0, sizeof(buffer)); + lsa_header = (struct ospf6_lsa_header *)buffer; + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) + ((caddr_t)lsa_header + + sizeof(struct ospf6_lsa_header)); + + /* Fill Intra-Area-Prefix-LSA */ + intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER); + intra_prefix_lsa->ref_id = htonl(0); + intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id; + + /* Put next set of prefixes to advertise */ + prefix_num = 0; + op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa + + sizeof(struct ospf6_intra_prefix_lsa)); + } + op->prefix_length = route->prefix.prefixlen; op->prefix_options = route->path.prefix_options; op->prefix_metric = htons(route->path.cost); memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6, OSPF6_PREFIX_SPACE(op->prefix_length)); - op = OSPF6_PREFIX_NEXT(op); prefix_num++; + + op = OSPF6_PREFIX_NEXT(op); } ospf6_route_table_delete(route_advertise); @@ -980,7 +1089,7 @@ int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread) /* Fill LSA Header */ lsa_header->age = 0; lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX); - lsa_header->id = htonl(0); + lsa_header->id = htonl(ls_id++); lsa_header->adv_router = oa->ospf6->router_id; lsa_header->seqnum = ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id, diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c index 4d9c259443..9f81bb89fb 100644 --- a/ospf6d/ospf6_network.c +++ b/ospf6d/ospf6_network.c @@ -29,8 +29,7 @@ #include "libospf.h" #include "ospf6_proto.h" #include "ospf6_network.h" - -extern struct zebra_privs_t ospf6d_privs; +#include "ospf6d.h" int ospf6_sock; struct in6_addr allspfrouters6; diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index b032bd7a79..022b913168 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -584,7 +584,7 @@ void ospf6_zebra_init(struct thread_master *master) { /* Allocate zebra structure. */ zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0); + zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs); zclient->zebra_connected = ospf6_zebra_connected; zclient->router_id_update = ospf6_router_id_update_zebra; zclient->interface_add = ospf6_zebra_if_add; diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h index 77a40eac63..f95381084d 100644 --- a/ospf6d/ospf6d.h +++ b/ospf6d/ospf6d.h @@ -94,6 +94,7 @@ extern struct thread_master *master; return CMD_SUCCESS; \ } +extern struct zebra_privs_t ospf6d_privs; /* Function Prototypes */ extern struct route_node *route_prev(struct route_node *node); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 34a1e6f6d6..e8700e7eb0 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -453,6 +453,15 @@ struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf, return match; } +static void ospf_if_reset_stats(struct ospf_interface *oi) +{ + oi->hello_in = oi->hello_out = 0; + oi->db_desc_in = oi->db_desc_out = 0; + oi->ls_req_in = oi->ls_req_out = 0; + oi->ls_upd_in = oi->ls_upd_out = 0; + oi->ls_ack_in = oi->ls_ack_out = 0; +} + void ospf_if_stream_set(struct ospf_interface *oi) { /* set output fifo queue. */ @@ -468,6 +477,9 @@ void ospf_if_stream_unset(struct ospf_interface *oi) ospf_fifo_free(oi->obuf); oi->obuf = NULL; + /*reset protocol stats */ + ospf_if_reset_stats(oi); + if (oi->on_write_q) { listnode_delete(ospf->oi_write_q, oi); if (list_isempty(ospf->oi_write_q)) diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 699f2341d5..519e3f9cf4 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -30,8 +30,6 @@ #include "sockopt.h" #include "privs.h" -extern struct zebra_privs_t ospfd_privs; - #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" #include "ospfd/ospf_interface.h" diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 47f5ee76d2..633c3deeaf 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -825,6 +825,26 @@ static int ospf_write(struct thread *thread) "-----------------------------------------------------"); } + switch (type) { + case OSPF_MSG_HELLO: + oi->hello_out++; + break; + case OSPF_MSG_DB_DESC: + oi->db_desc_out++; + break; + case OSPF_MSG_LS_REQ: + oi->ls_req_out++; + break; + case OSPF_MSG_LS_UPD: + oi->ls_upd_out++; + break; + case OSPF_MSG_LS_ACK: + oi->ls_ack_out++; + break; + default: + break; + } + /* Now delete packet from queue. */ ospf_packet_delete(oi); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 70e0da1158..df3cd16c1c 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3666,6 +3666,154 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, return CMD_SUCCESS; } +static void show_ip_ospf_interface_traffic_sub(struct vty *vty, + struct ospf_interface *oi, + json_object *json_interface_sub, + u_char use_json) +{ + if (use_json) { + json_object_int_add(json_interface_sub, + "ifIndex", + oi->ifp->ifindex); + json_object_int_add(json_interface_sub, + "helloIn", + oi->hello_in); + json_object_int_add(json_interface_sub, + "helloOut", + oi->hello_out); + json_object_int_add(json_interface_sub, + "dbDescIn", + oi->db_desc_in); + json_object_int_add(json_interface_sub, + "dbDescOut", + oi->db_desc_out); + json_object_int_add(json_interface_sub, + "lsReqIn", + oi->ls_req_in); + json_object_int_add(json_interface_sub, + "lsReqOut", + oi->ls_req_out); + json_object_int_add(json_interface_sub, + "lsUpdIn", + oi->ls_upd_in); + json_object_int_add(json_interface_sub, + "lsUpdOut", + oi->ls_upd_out); + json_object_int_add(json_interface_sub, + "lsAckIn", + oi->ls_ack_in); + json_object_int_add(json_interface_sub, + "lsAckOut", + oi->ls_ack_out); + } else { + vty_out(vty, + "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n", + oi->ifp->name, oi->hello_in, + oi->hello_out, + oi->db_desc_in, oi->db_desc_out, + oi->ls_req_in, oi->ls_req_out, + oi->ls_upd_in, oi->ls_upd_out, + oi->ls_ack_in, oi->ls_ack_out); + } +} + +/* OSPFv2 Packet Counters */ +static int show_ip_ospf_interface_traffic_common(struct vty *vty, + struct ospf *ospf, + char *intf_name, + int display_once, + u_char use_json) +{ + struct vrf *vrf = NULL; + struct interface *ifp = NULL; + json_object *json = NULL; + json_object *json_interface_sub = NULL; + + if (!use_json && !display_once) { + vty_out(vty, "\n"); + vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", + "Interface", " HELLO", " DB-Desc", " LS-Req", + " LS-Update", " LS-Ack"); + vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "", + " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx"); + vty_out(vty, + "--------------------------------------------------------------------------------------------\n"); + } else if (use_json) { + json = json_object_new_object(); + } + + if (intf_name == NULL) { + vrf = vrf_lookup_by_id(ospf->vrf_id); + FOR_ALL_INTERFACES (vrf, ifp) { + struct route_node *rn; + struct ospf_interface *oi; + + if (ospf_oi_count(ifp) == 0) + continue; + + for (rn = route_top(IF_OIFS(ifp)); rn; + rn = route_next(rn)) { + oi = rn->info; + + if (oi == NULL) + continue; + + if (use_json) { + json_interface_sub = + json_object_new_object(); + } + + show_ip_ospf_interface_traffic_sub(vty, oi, + json_interface_sub, + use_json); + if (use_json) { + json_object_object_add(json, ifp->name, + json_interface_sub); + } + } + } + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name(intf_name, ospf->vrf_id); + if (ifp != NULL) { + struct route_node *rn; + struct ospf_interface *oi; + + if (ospf_oi_count(ifp) == 0) { + vty_out(vty, " OSPF not enabled on this interface %s\n", + ifp->name); + return CMD_SUCCESS; + } + + for (rn = route_top(IF_OIFS(ifp)); rn; + rn = route_next(rn)) { + oi = rn->info; + + if (use_json) { + json_interface_sub = + json_object_new_object(); + } + + show_ip_ospf_interface_traffic_sub(vty, oi, + json_interface_sub, + use_json); + if (use_json) { + json_object_object_add(json, ifp->name, + json_interface_sub); + } + } + } + } + + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + + return CMD_SUCCESS; +} + DEFUN (show_ip_ospf_interface, show_ip_ospf_interface_cmd, "show ip ospf [vrf <NAME|all>] interface [INTERFACE] [json]", @@ -3753,6 +3901,71 @@ DEFUN (show_ip_ospf_instance_interface, return show_ip_ospf_interface_common(vty, ospf, argc, argv, 5, uj); } +DEFUN (show_ip_ospf_interface_traffic, + show_ip_ospf_interface_traffic_cmd, + "show ip ospf [vrf <NAME|all>] interface traffic [INTERFACE] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Interface information\n" + "Protocol Packet counters\n" + "Interface name\n" + JSON_STR) +{ + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL, *intf_name = NULL; + bool all_vrf = FALSE; + int inst = 0; + int idx_vrf = 0, idx_intf = 0; + u_char uj = use_json(argc, argv); + int ret = CMD_SUCCESS; + int display_once = 0; + + if (uj) + argc--; + + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (argv_find(argv, argc, "INTERFACE", &idx_intf)) + intf_name = argv[idx_intf]->arg; + + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ret = show_ip_ospf_interface_traffic_common(vty, + ospf, intf_name, + display_once, + uj); + display_once = 1; + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_interface_traffic_common(vty, ospf, + intf_name, + display_once, uj); + } else { + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_interface_traffic_common(vty, ospf, + intf_name, + display_once, uj); + } + + return ret; +} + + static void show_ip_ospf_neighbour_header(struct vty *vty) { vty_out(vty, "\n%-15s %3s %-15s %9s %-15s %-20s %5s %5s %5s\n", @@ -9484,6 +9697,8 @@ void ospf_vty_show_init(void) install_element(VIEW_NODE, &show_ip_ospf_interface_cmd); install_element(VIEW_NODE, &show_ip_ospf_instance_interface_cmd); + /* "show ip ospf interface traffic */ + install_element(VIEW_NODE, &show_ip_ospf_interface_traffic_cmd); /* "show ip ospf neighbor" commands. */ install_element(VIEW_NODE, &show_ip_ospf_neighbor_int_detail_cmd); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 7e6146e0d3..76fa6fa6dd 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -1472,7 +1472,7 @@ void ospf_zebra_init(struct thread_master *master, u_short instance) { /* Allocate zebra structure. */ zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance); + zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs); zclient->zebra_connected = ospf_zebra_connected; zclient->router_id_update = ospf_router_id_update_zebra; zclient->interface_add = ospf_interface_add; diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 8ee32289c1..3771f94630 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -67,7 +67,6 @@ struct ospf_master *om; extern struct zclient *zclient; extern struct in_addr router_id_zebra; -extern struct zebra_privs_t ospfd_privs; static void ospf_remove_vls_through_area(struct ospf *, struct ospf_area *); diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 4b0ebc8eb8..4c5bb756f6 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -502,6 +502,7 @@ extern const int ospf_redistributed_proto_max; extern struct zclient *zclient; extern struct thread_master *master; extern int ospf_zlog; +extern struct zebra_privs_t ospfd_privs; /* Prototypes. */ extern const char *ospf_redist_string(u_int route_type); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index db11e5f171..8c90ccbed1 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -753,7 +753,7 @@ void pim_zebra_init(void) zclient->interface_address_delete = pim_zebra_if_address_del; zclient->nexthop_update = pim_parse_nexthop_update; - zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); + zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs); if (PIM_DEBUG_PIM_TRACE) { zlog_info("zclient_init cleared redistribution request"); } diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index df8ad4e428..fd75a699b3 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -128,6 +128,7 @@ void zclient_lookup_new(void) zlookup->sock = -1; zlookup->t_connect = NULL; + zlookup->privs = &pimd_privs; zclient_lookup_sched_now(zlookup); diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md index c05331256a..2de64b8f40 100644 --- a/redhat/README.rpm_build.md +++ b/redhat/README.rpm_build.md @@ -9,11 +9,10 @@ Building your own FRRouting RPM Newer automake/autoconf/bison is only needed to build the rpm and is **not** needed to install the binary rpm package -2. Install the following packages to build the RPMs: +2. Install the build packages as documented in doc/Building_on_xxxxx.md + and the following additional packages: - yum install git autoconf automake libtool make gawk readline-devel \ - texinfo net-snmp-devel groff pkgconfig rpm-build json-c-devel \ - pam-devel texi2html bison libcap-devel flex + yum install rpm-build net-snmp-devel pam-devel Additionally, on systems with systemd (CentOS 7, Fedora) @@ -21,10 +20,6 @@ Building your own FRRouting RPM (use `dnf install` on new Fedora instead of `yum install`) - **CentOS 6:** Please check doc/Building_FRR_on_CentOS6.md for details on - how to install required version of autoconf, automake and bison. The - versions in the common Repo are too old. - 3. Checkout FRR under a **unpriviledged** user account git clone https://github.com/frrouting/frr.git frr diff --git a/redhat/daemons b/redhat/daemons index 8d12a1f5b8..c28414f0ea 100644 --- a/redhat/daemons +++ b/redhat/daemons @@ -35,7 +35,7 @@ # group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too. # watchfrr_enable=no -watchfrr_options=("-b_" "-r/etc/init.d/frr_restart_%s" "-s/etc/init.d/frr_start_%s" "-k/etc/init.d/frr_stop_%s") +watchfrr_options=("-b_" "-r/usr/lib/frr/frr_restart_%s" "-s/usr/lib/frr/frr_start_%s" "-k/usr/lib/frr/frr_stop_%s") # zebra=no bgpd=no diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index ea8a312364..4e05f7828c 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -333,6 +333,8 @@ install %{zeb_rh_src}/frr.init \ %else mkdir -p %{buildroot}/etc/rc.d/init.d install %{zeb_rh_src}/frr.init \ + %{buildroot}%{_sbindir}/frr +ln -s %{_sbindir}/frr \ %{buildroot}/etc/rc.d/init.d/frr %endif @@ -415,6 +417,10 @@ done /sbin/chkconfig --add frr %endif +# Fix bad path in previous config files +# Config files won't get replaced by default, so we do this ugly hack to fix it +%__sed -i 's|/etc/init.d/|%{_sbindir}/|g' %{_sysconfdir}/daemons 2> /dev/null || true + /sbin/install-info %{_infodir}/frr.info.gz %{_infodir}/dir # Create dummy files if they don't exist so basic functions can be used. @@ -463,7 +469,7 @@ if [ "$1" -ge 1 ]; then ## ## Systemd Version ## - %systemd_postun frr.service + %systemd_postun_with_restart frr.service %else ## ## init.d Version @@ -478,18 +484,14 @@ fi ## ## Systemd Version ## - if [ "$1" = "0" ]; then - for daemon in %all_daemons ; do - if [ x"${daemon}" != x"" ] ; then - %systemd_preun frr.service - fi - done + if [ $1 -eq 0 ] ; then + %systemd_preun frr.service fi %else ## ## init.d Version ## - if [ "$1" = "0" ]; then + if [ $1 -eq 0 ] ; then /etc/rc.d/init.d/frr stop >/dev/null 2>&1 /sbin/chkconfig --del frr fi @@ -557,10 +559,11 @@ rm -rf %{buildroot} %config(noreplace) /etc/frr/[!v]*.conf* %config(noreplace) %attr(750,%frr_user,%frr_user) /etc/frr/daemons %if "%{initsystem}" == "systemd" - %config %{_unitdir}/frr.service + %attr(644,root,root) %{_unitdir}/frr.service %{_sbindir}/frr %else - %config /etc/rc.d/init.d/frr + /etc/rc.d/init.d/frr + %{_sbindir}/frr %endif %config(noreplace) /etc/pam.d/frr %config(noreplace) %attr(640,root,root) /etc/logrotate.d/* @@ -596,7 +599,11 @@ rm -rf %{buildroot} %endif %changelog -* Mon Jun 5 2017 Martin Winter <mwinter@opensourcerouting.org> - %{version} +* Fri Oct 20 2017 Martin Winter <mwinter@opensourcerouting.org> - %{version} +- Fix script location for watchfrr restart functions in daemon config +- Fix postun script to restart frr during upgrade + +* Mon Jun 5 2017 Martin Winter <mwinter@opensourcerouting.org> - added NHRP and EIGRP daemon * Mon Apr 17 2017 Martin Winter <mwinter@opensourcerouting.org> diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 9282896c28..a997ca5f2e 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -58,8 +58,6 @@ const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"}, {RI_RIP_VERSION_NONE, "none"}, {0}}; -extern struct zebra_privs_t ripd_privs; - /* RIP enabled network vector. */ vector rip_enable_interface; diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index 28144a2435..3772f6223e 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -586,7 +586,7 @@ void rip_zclient_init(struct thread_master *master) { /* Set default value to the zebra client structure. */ zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_RIP, 0); + zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs); zclient->zebra_connected = rip_zebra_connected; zclient->interface_add = rip_interface_add; zclient->interface_delete = rip_interface_delete; diff --git a/ripd/ripd.c b/ripd/ripd.c index a4b56d9fbf..aece5d03cd 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -49,9 +49,6 @@ DEFINE_QOBJ_TYPE(rip) /* UDP receive buffer size */ #define RIP_UDP_RCV_BUF 41600 -/* privileges global */ -extern struct zebra_privs_t ripd_privs; - /* RIP Structure. */ struct rip *rip = NULL; diff --git a/ripd/ripd.h b/ripd/ripd.h index 895a48c3db..ae34ed3f48 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -427,6 +427,8 @@ extern struct rip_info *rip_ecmp_delete(struct rip_info *); /* There is only one rip strucutre. */ extern struct rip *rip; +extern struct zebra_privs_t ripd_privs; + /* Master thread strucutre. */ extern struct thread_master *master; diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index d450d5a7f9..d1057bf53e 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -47,8 +47,6 @@ #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP #endif -extern struct zebra_privs_t ripngd_privs; - /* Static utility function. */ static void ripng_enable_apply(struct interface *); static void ripng_passive_interface_apply(struct interface *); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index 7edaaa5dff..084d58ee53 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -414,7 +414,7 @@ void zebra_init(struct thread_master *master) { /* Allocate zebra structure. */ zclient = zclient_new(master); - zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0); + zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs); zclient->zebra_connected = ripng_zebra_connected; zclient->interface_up = ripng_interface_up; diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index df3af2a17f..daa2526a0c 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -50,8 +50,6 @@ enum { ripng_all_route, ripng_changed_route, }; -extern struct zebra_privs_t ripngd_privs; - /* Prototypes. */ void ripng_output_process(struct interface *, struct sockaddr_in6 *, int); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index 9a609cab8a..25a5b46c02 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -327,7 +327,7 @@ enum ripng_event { /* Extern variables. */ extern struct ripng *ripng; - +extern struct zebra_privs_t ripngd_privs; extern struct thread_master *master; /* Prototypes. */ diff --git a/tests/isisd/test_fuzz_isis_tlv.c b/tests/isisd/test_fuzz_isis_tlv.c index 1f5abba392..67a1593500 100644 --- a/tests/isisd/test_fuzz_isis_tlv.c +++ b/tests/isisd/test_fuzz_isis_tlv.c @@ -19,6 +19,8 @@ int isis_sock_init(struct isis_circuit *circuit) return 0; } +struct zebra_privs_t isisd_privs; + static bool atexit_registered; static void show_meminfo_at_exit(void) diff --git a/tests/isisd/test_isis_vertex_queue.c b/tests/isisd/test_isis_vertex_queue.c index 674482cd17..0e473d7a6b 100644 --- a/tests/isisd/test_isis_vertex_queue.c +++ b/tests/isisd/test_isis_vertex_queue.c @@ -9,6 +9,8 @@ int isis_sock_init(struct isis_circuit *circuit) return 0; } +struct zebra_privs_t isisd_privs; + static struct isis_vertex **vertices; static size_t vertex_count; diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 6a8e2ac594..7f9bc47315 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -799,7 +799,7 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp, * if the operator has explicitly enabled RA. The enable request can also * specify a RA interval (in seconds). */ -void zebra_interface_radv_set(struct zserv *client, int sock, u_short length, +void zebra_interface_radv_set(struct zserv *client, u_short length, struct zebra_vrf *zvrf, int enable) { struct stream *s; diff --git a/zebra/rtadv.h b/zebra/rtadv.h index dcaeb3ed28..9ec1bffa8d 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -103,7 +103,7 @@ typedef enum { extern void rtadv_init(struct zebra_ns *); extern void rtadv_terminate(struct zebra_ns *); extern void rtadv_cmd_init(void); -extern void zebra_interface_radv_set(struct zserv *client, int sock, +extern void zebra_interface_radv_set(struct zserv *client, u_short length, struct zebra_vrf *zvrf, int enable); diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 6d3a8de8c9..a5d256b7aa 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -92,7 +92,6 @@ typedef struct zfpm_stats_t_ { unsigned long updates_triggered; unsigned long redundant_triggers; - unsigned long non_fpm_table_triggers; unsigned long dests_del_after_update; @@ -312,31 +311,6 @@ static time_t zfpm_get_elapsed_time(time_t reference) } /* - * zfpm_is_table_for_fpm - * - * Returns TRUE if the the given table is to be communicated to the - * FPM. - */ -static inline int zfpm_is_table_for_fpm(struct route_table *table) -{ - rib_table_info_t *info; - - info = rib_table_info(table); - - /* - * We only send the unicast tables in the main instance to the FPM - * at this point. - */ - if (zvrf_id(info->zvrf) != 0) - return 0; - - if (info->safi != SAFI_UNICAST) - return 0; - - return 1; -} - -/* * zfpm_rnodes_iter_init */ static inline void zfpm_rnodes_iter_init(zfpm_rnodes_iter_t *iter) @@ -371,10 +345,7 @@ static inline struct route_node *zfpm_rnodes_iter_next(zfpm_rnodes_iter_t *iter) */ route_table_iter_cleanup(&iter->iter); - while ((table = rib_tables_iter_next(&iter->tables_iter))) { - if (zfpm_is_table_for_fpm(table)) - break; - } + table = rib_tables_iter_next(&iter->tables_iter); if (!table) return NULL; @@ -1278,15 +1249,6 @@ static int zfpm_trigger_update(struct route_node *rn, const char *reason) dest = rib_dest_from_rnode(rn); - /* - * Ignore the trigger if the dest is not in a table that we would - * send to the FPM. - */ - if (!zfpm_is_table_for_fpm(rib_dest_table(dest))) { - zfpm_g->stats.non_fpm_table_triggers++; - return 0; - } - if (CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM)) { zfpm_g->stats.redundant_triggers++; return 0; @@ -1401,7 +1363,6 @@ static void zfpm_show_stats(struct vty *vty) ZFPM_SHOW_STAT(route_adds); ZFPM_SHOW_STAT(route_dels); ZFPM_SHOW_STAT(updates_triggered); - ZFPM_SHOW_STAT(non_fpm_table_triggers); ZFPM_SHOW_STAT(redundant_triggers); ZFPM_SHOW_STAT(dests_del_after_update); ZFPM_SHOW_STAT(t_conn_down_starts); diff --git a/zebra/zebra_mroute.c b/zebra/zebra_mroute.c index 75d5d5d627..8fa00b83c9 100644 --- a/zebra/zebra_mroute.c +++ b/zebra/zebra_mroute.c @@ -32,7 +32,7 @@ #include "zebra/rt.h" #include "zebra/debug.h" -int zebra_ipmr_route_stats(struct zserv *client, int fd, u_short length, +int zebra_ipmr_route_stats(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { struct mcast_route_data mroute; diff --git a/zebra/zebra_mroute.h b/zebra/zebra_mroute.h index fda97e80d7..616c3a83ab 100644 --- a/zebra/zebra_mroute.h +++ b/zebra/zebra_mroute.h @@ -28,7 +28,7 @@ struct mcast_route_data { unsigned long long lastused; }; -int zebra_ipmr_route_stats(struct zserv *client, int sock, u_short length, +int zebra_ipmr_route_stats(struct zserv *client, u_short length, struct zebra_vrf *zvf); #endif diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 93b0723d8b..464a8cf875 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -661,7 +661,7 @@ int zebra_ptm_sock_read(struct thread *thread) } /* BFD peer/dst register/update */ -int zebra_ptm_bfd_dst_register(struct zserv *client, int sock, u_short length, +int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, int command, struct zebra_vrf *zvrf) { struct stream *s; @@ -819,7 +819,7 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, int sock, u_short length, } /* BFD peer/dst deregister */ -int zebra_ptm_bfd_dst_deregister(struct zserv *client, int sock, u_short length, +int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { struct stream *s; @@ -946,7 +946,7 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, int sock, u_short length, } /* BFD client register */ -int zebra_ptm_bfd_client_register(struct zserv *client, int sock, +int zebra_ptm_bfd_client_register(struct zserv *client, u_short length) { struct stream *s; @@ -961,6 +961,9 @@ int zebra_ptm_bfd_client_register(struct zserv *client, int sock, zlog_debug("bfd_client_register msg from client %s: length=%d", zebra_route_string(client->proto), length); + s = client->ibuf; + pid = stream_getl(s); + if (ptm_cb.ptm_sock == -1) { ptm_cb.t_timer = NULL; thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, @@ -977,9 +980,6 @@ int zebra_ptm_bfd_client_register(struct zserv *client, int sock, ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, tmp_buf); - s = client->ibuf; - - pid = stream_getl(s); sprintf(tmp_buf, "%d", pid); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 9f9269ab55..664221eff7 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -62,12 +62,12 @@ int zebra_ptm_connect(struct thread *t); void zebra_ptm_write(struct vty *vty); int zebra_ptm_get_enable_state(void); -int zebra_ptm_bfd_dst_register(struct zserv *client, int sock, u_short length, +int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, int command, struct zebra_vrf *zvrf); -int zebra_ptm_bfd_dst_deregister(struct zserv *client, int sock, u_short length, +int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, struct zebra_vrf *zvrf); void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); -int zebra_ptm_bfd_client_register(struct zserv *client, int sock, +int zebra_ptm_bfd_client_register(struct zserv *client, u_short length); void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index c0b5f9d10f..bd430423b3 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -3028,7 +3028,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp, /* * Handle message from client to delete a remote MACIP for a VNI. */ -int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, +int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { struct stream *s; @@ -3168,7 +3168,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length, * could be just the add of a MAC address or the add of a neighbor * (IP+MAC). */ -int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length, +int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { struct stream *s; @@ -3671,7 +3671,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, /* * Handle message from client to delete a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, +int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { struct stream *s; @@ -3750,7 +3750,7 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length, /* * Handle message from client to add a remote VTEP for a VNI. */ -int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length, +int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { struct stream *s; @@ -4280,8 +4280,8 @@ int zebra_vxlan_if_add(struct interface *ifp) * Handle message from client to enable/disable advertisement of g/w macip * routes */ -int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock, - u_short length, struct zebra_vrf *zvrf) +int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, + struct zebra_vrf *zvrf) { struct stream *s; int advertise; @@ -4388,7 +4388,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock, * when disabled, the entries should be deleted and remote VTEPs and MACs * uninstalled from the kernel. */ -int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, +int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, struct zebra_vrf *zvrf) { struct stream *s; diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index 8b43615bb3..290d19bcf3 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -96,9 +96,9 @@ extern int zebra_vxlan_local_neigh_add_update( extern int zebra_vxlan_local_neigh_del(struct interface *ifp, struct interface *link_if, struct ipaddr *ip); -extern int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, +extern int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, +extern int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, struct zebra_vrf *zvrf); extern int zebra_vxlan_local_mac_add_update(struct interface *ifp, struct interface *br_if, @@ -119,14 +119,14 @@ extern int zebra_vxlan_if_down(struct interface *ifp); extern int zebra_vxlan_if_add(struct interface *ifp); extern int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags); extern int zebra_vxlan_if_del(struct interface *ifp); -extern int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, +extern int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, +extern int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock, +extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, struct zebra_vrf *zvrf); -extern int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, +extern int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, struct zebra_vrf *zvrf); extern void zebra_vxlan_init_tables(struct zebra_vrf *zvrf); diff --git a/zebra/zserv.c b/zebra/zserv.c index cbc9f2bed9..6295de0c2e 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -40,6 +40,7 @@ #include "nexthop.h" #include "vrf.h" #include "libfrr.h" +#include "sockopt.h" #include "zebra/zserv.h" #include "zebra/zebra_ns.h" @@ -693,7 +694,7 @@ static int zsend_write_nexthop(struct stream *s, struct nexthop *nexthop) } /* Nexthop register */ -static int zserv_rnh_register(struct zserv *client, int sock, u_short length, +static int zserv_rnh_register(struct zserv *client, u_short length, rnh_type_t type, struct zebra_vrf *zvrf) { struct rnh *rnh; @@ -754,7 +755,7 @@ static int zserv_rnh_register(struct zserv *client, int sock, u_short length, } /* Nexthop register */ -static int zserv_rnh_unregister(struct zserv *client, int sock, u_short length, +static int zserv_rnh_unregister(struct zserv *client, u_short length, rnh_type_t type, struct zebra_vrf *zvrf) { struct rnh *rnh; @@ -798,7 +799,7 @@ static int zserv_rnh_unregister(struct zserv *client, int sock, u_short length, #define ZEBRA_MIN_FEC_LENGTH 5 /* FEC register */ -static int zserv_fec_register(struct zserv *client, int sock, u_short length) +static int zserv_fec_register(struct zserv *client, u_short length) { struct stream *s; struct zebra_vrf *zvrf; @@ -849,7 +850,7 @@ static int zserv_fec_register(struct zserv *client, int sock, u_short length) } /* FEC unregister */ -static int zserv_fec_unregister(struct zserv *client, int sock, u_short length) +static int zserv_fec_unregister(struct zserv *client, u_short length) { struct stream *s; struct zebra_vrf *zvrf; @@ -1763,7 +1764,7 @@ static int zread_vrf_unregister(struct zserv *client, u_short length, } static void zread_mpls_labels(int command, struct zserv *client, u_short length, - vrf_id_t vrf_id) + struct zebra_vrf *zvrf) { struct stream *s; enum lsp_types_t type; @@ -1773,11 +1774,6 @@ static void zread_mpls_labels(int command, struct zserv *client, u_short length, ifindex_t ifindex; mpls_label_t in_label, out_label; u_int8_t distance; - struct zebra_vrf *zvrf; - - zvrf = vrf_info_lookup(vrf_id); - if (!zvrf) - return; /* Get input stream. */ s = client->ibuf; @@ -1959,7 +1955,7 @@ static void zread_release_label_chunk(struct zserv *client) release_label_chunk(client->proto, client->instance, start, end); } static void zread_label_manager_request(int cmd, struct zserv *client, - vrf_id_t vrf_id) + struct zebra_vrf *zvrf) { /* to avoid sending other messages like ZERBA_INTERFACE_UP */ if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) @@ -1967,11 +1963,13 @@ static void zread_label_manager_request(int cmd, struct zserv *client, /* external label manager */ if (lm_is_external) - zread_relay_label_manager_request(cmd, client, vrf_id); + zread_relay_label_manager_request(cmd, client, + zvrf_id(zvrf)); /* this is a label manager */ else { if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) - zread_label_manager_connect(client, vrf_id); + zread_label_manager_connect(client, + zvrf_id(zvrf)); else { /* Sanity: don't allow 'unidentified' requests */ if (!client->proto) { @@ -1980,7 +1978,8 @@ static void zread_label_manager_request(int cmd, struct zserv *client, return; } if (cmd == ZEBRA_GET_LABEL_CHUNK) - zread_get_label_chunk(client, vrf_id); + zread_get_label_chunk(client, + zvrf_id(zvrf)); else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) zread_release_label_chunk(client); } @@ -1988,10 +1987,9 @@ static void zread_label_manager_request(int cmd, struct zserv *client, } static int zread_pseudowire(int command, struct zserv *client, u_short length, - vrf_id_t vrf_id) + struct zebra_vrf *zvrf) { struct stream *s; - struct zebra_vrf *zvrf; char ifname[IF_NAMESIZE]; ifindex_t ifindex; int type; @@ -2004,10 +2002,6 @@ static int zread_pseudowire(int command, struct zserv *client, u_short length, uint8_t protocol; struct zebra_pw *pw; - zvrf = vrf_info_lookup(vrf_id); - if (!zvrf) - return -1; - /* Get input stream. */ s = client->ibuf; @@ -2210,7 +2204,7 @@ static void zebra_client_create(int sock) zebra_vrf_update_all(client); } -static int zread_interface_set_master(struct zserv *client, int sock, +static int zread_interface_set_master(struct zserv *client, u_short length) { struct interface *master; @@ -2235,122 +2229,11 @@ static int zread_interface_set_master(struct zserv *client, int sock, return 1; } -/* Handler of zebra service request. */ -static int zebra_client_read(struct thread *thread) +static inline void zserv_handle_commands(struct zserv *client, + uint16_t command, + uint16_t length, + struct zebra_vrf *zvrf) { - int sock; - struct zserv *client; - size_t already; - uint16_t length, command; - uint8_t marker, version; - vrf_id_t vrf_id; - struct zebra_vrf *zvrf; - - /* Get thread data. Reset reading thread because I'm running. */ - sock = THREAD_FD(thread); - client = THREAD_ARG(thread); - client->t_read = NULL; - - if (client->t_suicide) { - zebra_client_close(client); - return -1; - } - - /* Read length and command (if we don't have it already). */ - if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) { - ssize_t nbyte; - if (((nbyte = stream_read_try(client->ibuf, sock, - ZEBRA_HEADER_SIZE - already)) - == 0) - || (nbyte == -1)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("connection closed socket [%d]", - sock); - zebra_client_close(client); - return -1; - } - if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) { - /* Try again later. */ - zebra_event(ZEBRA_READ, sock, client); - return 0; - } - already = ZEBRA_HEADER_SIZE; - } - - /* Reset to read from the beginning of the incoming packet. */ - stream_set_getp(client->ibuf, 0); - - /* Fetch header values */ - length = stream_getw(client->ibuf); - marker = stream_getc(client->ibuf); - version = stream_getc(client->ibuf); - vrf_id = stream_getw(client->ibuf); - command = stream_getw(client->ibuf); - - if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { - zlog_err( - "%s: socket %d version mismatch, marker %d, version %d", - __func__, sock, marker, version); - zebra_client_close(client); - return -1; - } - if (length < ZEBRA_HEADER_SIZE) { - zlog_warn( - "%s: socket %d message length %u is less than header size %d", - __func__, sock, length, ZEBRA_HEADER_SIZE); - zebra_client_close(client); - return -1; - } - if (length > STREAM_SIZE(client->ibuf)) { - zlog_warn( - "%s: socket %d message length %u exceeds buffer size %lu", - __func__, sock, length, - (u_long)STREAM_SIZE(client->ibuf)); - zebra_client_close(client); - return -1; - } - - /* Read rest of data. */ - if (already < length) { - ssize_t nbyte; - if (((nbyte = stream_read_try(client->ibuf, sock, - length - already)) - == 0) - || (nbyte == -1)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug( - "connection closed [%d] when reading zebra data", - sock); - zebra_client_close(client); - return -1; - } - if (nbyte != (ssize_t)(length - already)) { - /* Try again later. */ - zebra_event(ZEBRA_READ, sock, client); - return 0; - } - } - - length -= ZEBRA_HEADER_SIZE; - - /* Debug packet information. */ - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("zebra message comes from socket [%d]", sock); - - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug("zebra message received [%s] %d in VRF %u", - zserv_command_string(command), length, vrf_id); - - client->last_read_time = monotime(NULL); - client->last_read_cmd = command; - - zvrf = zebra_vrf_lookup_by_id(vrf_id); - if (!zvrf) { - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) - zlog_debug("zebra received unknown VRF[%u]", vrf_id); - goto zclient_read_out; - } - switch (command) { case ZEBRA_ROUTER_ID_ADD: zread_router_id_add(client, length, zvrf); @@ -2405,101 +2288,227 @@ static int zebra_client_read(struct thread *thread) zread_hello(client); break; case ZEBRA_NEXTHOP_REGISTER: - zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, + zserv_rnh_register(client, length, RNH_NEXTHOP_TYPE, zvrf); break; case ZEBRA_NEXTHOP_UNREGISTER: - zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, + zserv_rnh_unregister(client, length, RNH_NEXTHOP_TYPE, zvrf); break; case ZEBRA_IMPORT_ROUTE_REGISTER: - zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, + zserv_rnh_register(client, length, RNH_IMPORT_CHECK_TYPE, zvrf); break; case ZEBRA_IMPORT_ROUTE_UNREGISTER: - zserv_rnh_unregister(client, sock, length, + zserv_rnh_unregister(client, length, RNH_IMPORT_CHECK_TYPE, zvrf); break; case ZEBRA_BFD_DEST_UPDATE: case ZEBRA_BFD_DEST_REGISTER: - zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf); + zebra_ptm_bfd_dst_register(client, length, command, zvrf); break; case ZEBRA_BFD_DEST_DEREGISTER: - zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf); + zebra_ptm_bfd_dst_deregister(client, length, zvrf); break; case ZEBRA_VRF_UNREGISTER: zread_vrf_unregister(client, length, zvrf); break; case ZEBRA_BFD_CLIENT_REGISTER: - zebra_ptm_bfd_client_register(client, sock, length); + zebra_ptm_bfd_client_register(client, length); break; case ZEBRA_INTERFACE_ENABLE_RADV: #if defined(HAVE_RTADV) - zebra_interface_radv_set(client, sock, length, zvrf, 1); + zebra_interface_radv_set(client, length, zvrf, 1); #endif break; case ZEBRA_INTERFACE_DISABLE_RADV: #if defined(HAVE_RTADV) - zebra_interface_radv_set(client, sock, length, zvrf, 0); + zebra_interface_radv_set(client, length, zvrf, 0); #endif break; case ZEBRA_MPLS_LABELS_ADD: case ZEBRA_MPLS_LABELS_DELETE: - zread_mpls_labels(command, client, length, vrf_id); + zread_mpls_labels(command, client, length, zvrf); break; case ZEBRA_IPMR_ROUTE_STATS: - zebra_ipmr_route_stats(client, sock, length, zvrf); + zebra_ipmr_route_stats(client, length, zvrf); break; case ZEBRA_LABEL_MANAGER_CONNECT: case ZEBRA_GET_LABEL_CHUNK: case ZEBRA_RELEASE_LABEL_CHUNK: - zread_label_manager_request(command, client, vrf_id); + zread_label_manager_request(command, client, zvrf); break; case ZEBRA_FEC_REGISTER: - zserv_fec_register(client, sock, length); + zserv_fec_register(client, length); break; case ZEBRA_FEC_UNREGISTER: - zserv_fec_unregister(client, sock, length); + zserv_fec_unregister(client, length); break; case ZEBRA_ADVERTISE_DEFAULT_GW: - zebra_vxlan_advertise_gw_macip(client, sock, length, zvrf); + zebra_vxlan_advertise_gw_macip(client, length, zvrf); break; case ZEBRA_ADVERTISE_ALL_VNI: - zebra_vxlan_advertise_all_vni(client, sock, length, zvrf); + zebra_vxlan_advertise_all_vni(client, length, zvrf); break; case ZEBRA_REMOTE_VTEP_ADD: - zebra_vxlan_remote_vtep_add(client, sock, length, zvrf); + zebra_vxlan_remote_vtep_add(client, length, zvrf); break; case ZEBRA_REMOTE_VTEP_DEL: - zebra_vxlan_remote_vtep_del(client, sock, length, zvrf); + zebra_vxlan_remote_vtep_del(client, length, zvrf); break; case ZEBRA_REMOTE_MACIP_ADD: - zebra_vxlan_remote_macip_add(client, sock, length, zvrf); + zebra_vxlan_remote_macip_add(client, length, zvrf); break; case ZEBRA_REMOTE_MACIP_DEL: - zebra_vxlan_remote_macip_del(client, sock, length, zvrf); + zebra_vxlan_remote_macip_del(client, length, zvrf); break; case ZEBRA_INTERFACE_SET_MASTER: - zread_interface_set_master(client, sock, length); + zread_interface_set_master(client, length); break; case ZEBRA_PW_ADD: case ZEBRA_PW_DELETE: case ZEBRA_PW_SET: case ZEBRA_PW_UNSET: - zread_pseudowire(command, client, length, vrf_id); + zread_pseudowire(command, client, length, zvrf); break; default: zlog_info("Zebra received unknown command %d", command); break; } +} + +/* Handler of zebra service request. */ +static int zebra_client_read(struct thread *thread) +{ + int sock; + struct zserv *client; + size_t already; + uint16_t length, command; + uint8_t marker, version; + vrf_id_t vrf_id; + struct zebra_vrf *zvrf; + int packets = 10; + + /* Get thread data. Reset reading thread because I'm running. */ + sock = THREAD_FD(thread); + client = THREAD_ARG(thread); + client->t_read = NULL; if (client->t_suicide) { - /* No need to wait for thread callback, just kill immediately. - */ zebra_client_close(client); return -1; } + while (packets) { + /* Read length and command (if we don't have it already). */ + if ((already = stream_get_endp(client->ibuf)) + < ZEBRA_HEADER_SIZE) { + ssize_t nbyte; + if (((nbyte = + stream_read_try(client->ibuf, sock, + ZEBRA_HEADER_SIZE - already)) + == 0) + || (nbyte == -1)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("connection closed socket [%d]", + sock); + zebra_client_close(client); + return -1; + } + if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE - already)) { + /* Try again later. */ + zebra_event(ZEBRA_READ, sock, client); + return 0; + } + already = ZEBRA_HEADER_SIZE; + } + + /* Reset to read from the beginning of the incoming packet. */ + stream_set_getp(client->ibuf, 0); + + /* Fetch header values */ + length = stream_getw(client->ibuf); + marker = stream_getc(client->ibuf); + version = stream_getc(client->ibuf); + vrf_id = stream_getw(client->ibuf); + command = stream_getw(client->ibuf); + + if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { + zlog_err( + "%s: socket %d version mismatch, marker %d, version %d", + __func__, sock, marker, version); + zebra_client_close(client); + return -1; + } + if (length < ZEBRA_HEADER_SIZE) { + zlog_warn( + "%s: socket %d message length %u is less than header size %d", + __func__, sock, length, ZEBRA_HEADER_SIZE); + zebra_client_close(client); + return -1; + } + if (length > STREAM_SIZE(client->ibuf)) { + zlog_warn( + "%s: socket %d message length %u exceeds buffer size %lu", + __func__, sock, length, + (u_long)STREAM_SIZE(client->ibuf)); + zebra_client_close(client); + return -1; + } + + /* Read rest of data. */ + if (already < length) { + ssize_t nbyte; + if (((nbyte = stream_read_try(client->ibuf, sock, + length - already)) + == 0) + || (nbyte == -1)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "connection closed [%d] when reading zebra data", + sock); + zebra_client_close(client); + return -1; + } + if (nbyte != (ssize_t)(length - already)) { + /* Try again later. */ + zebra_event(ZEBRA_READ, sock, client); + return 0; + } + } + + length -= ZEBRA_HEADER_SIZE; + + /* Debug packet information. */ + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("zebra message comes from socket [%d]", sock); + + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("zebra message received [%s] %d in VRF %u", + zserv_command_string(command), length, vrf_id); + + client->last_read_time = monotime(NULL); + client->last_read_cmd = command; + + zvrf = zebra_vrf_lookup_by_id(vrf_id); + if (!zvrf) { + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + zlog_debug("zebra received unknown VRF[%u]", vrf_id); + goto zclient_read_out; + } + + zserv_handle_commands(client, command, length, zvrf); + + if (client->t_suicide) { + /* No need to wait for thread callback, just kill immediately. + */ + zebra_client_close(client); + return -1; + } + packets -= 1; + stream_reset(client->ibuf); + } + zclient_read_out: stream_reset(client->ibuf); zebra_event(ZEBRA_READ, sock, client); @@ -2573,6 +2582,11 @@ void zebra_zserv_socket_init(char *path) unlink(suna->sun_path); } + zserv_privs.change(ZPRIVS_RAISE); + setsockopt_so_recvbuf(sock, 1048576); + setsockopt_so_sendbuf(sock, 1048576); + zserv_privs.change(ZPRIVS_LOWER); + if (sa.ss_family != AF_UNIX && zserv_privs.change(ZPRIVS_RAISE)) zlog_err("Can't raise privileges"); |
