From ee22bbae78d0a17c0f34da106f77ba2fd80e6b0d Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Fri, 12 May 2017 12:05:46 -0700 Subject: [PATCH 01/34] pimd: Fix to Tx S,G Join when SGRpt->Join state -Upon Rx (*,G) Join w/o SGRpt at RP, trigger (S,G) Join towards FHR, unset SGRpt flag from channel, add (*,G) oif to (S,G) entry. -Add I am not RP check to triger SGRpt on *,G path otherwise, send S,G Prune on SPT path from RP to FHR upon receving *,G Prune. -Upon Rx SGRpt receive, remove OIF(downstream where Prune received) from specific S,G. Testing Done: pim-smoke Ran 95 tests in 11790.552s FAILED (SKIP=10, failures=4) Signed-off-by: Chirag Shah --- pimd/pim_ifchannel.c | 23 ++++++----------------- pimd/pim_ifchannel.h | 2 +- pimd/pim_join.c | 39 +++++++++++++++++++++++++++++++-------- pimd/pim_rpf.c | 13 +++++++------ pimd/pim_upstream.c | 5 +++-- 5 files changed, 48 insertions(+), 34 deletions(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index d46cc70b06..6f5e8f1493 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -1287,7 +1287,7 @@ pim_ifchannel_scan_forward_start (struct interface *new_ifp) * we get End of Message */ void -pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join) +pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone) { struct pim_ifchannel *child; struct listnode *ch_node; @@ -1302,10 +1302,11 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child)) { /* Only *,G Join received and no (SG-RPT) prune. + eom = 1, only (W,G) join_alone is true, WC and RPT are set. Scan all S,G associated to G and if any SG-RPT remove the SG-RPT flag. */ - if (join && (source_flags & PIM_RPT_BIT_MASK) && + if (eom && starg_alone && (source_flags & PIM_RPT_BIT_MASK) && (source_flags & PIM_WILDCARD_BIT_MASK)) { if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) @@ -1316,25 +1317,13 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t if (up) { if (PIM_DEBUG_TRACE) - zlog_debug ("%s: clearing SGRpt flag, add inherit oif to up %s ", __PRETTY_FUNCTION__, up->sg_str); + zlog_debug ("%s: SGRpt flag is cleared, add inherit oif to up %s", + __PRETTY_FUNCTION__, up->sg_str); pim_channel_add_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); + pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, child, PIM_IFJOIN_JOIN); } } } - /* Received SG-RPT Prune delete oif from S,G */ - else if (join == 0 && (source_flags & PIM_RPT_BIT_MASK) && - !(source_flags & PIM_WILDCARD_BIT_MASK)) - { - struct pim_upstream *up = child->upstream; - - PIM_IF_FLAG_SET_S_G_RPT(child->flags); - if (up) - { - if (PIM_DEBUG_TRACE) - zlog_debug ("%s: SGRpt Set, del inherit oif from up %s", __PRETTY_FUNCTION__, up->sg_str); - pim_channel_del_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); - } - } if (!PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) continue; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 3ffb9190fb..4c804cc720 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -151,7 +151,7 @@ void pim_ifchannel_update_my_assert_metric(struct pim_ifchannel *ch); void pim_ifchannel_update_assert_tracking_desired(struct pim_ifchannel *ch); void pim_ifchannel_scan_forward_start (struct interface *new_ifp); -void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join); +void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t source_flags, uint8_t join, uint8_t starg_alone); int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2); diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 828781a467..2da0b99353 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -215,7 +215,8 @@ int pim_joinprune_recv(struct interface *ifp, uint16_t msg_num_joined_sources; uint16_t msg_num_pruned_sources; int source; - struct pim_ifchannel *ch = NULL; + struct pim_ifchannel *starg_ch = NULL, *sg_ch = NULL; + uint8_t starg_alone = 0; memset (&sg, 0, sizeof (struct prefix_sg)); addr_offset = pim_parse_addr_group (&sg, @@ -274,9 +275,10 @@ int pim_joinprune_recv(struct interface *ifp, if (sg.src.s_addr == INADDR_ANY) { - ch = pim_ifchannel_find (ifp, &sg); - if (ch) - pim_ifchannel_set_star_g_join_state (ch, 0, msg_source_flags, 1); + starg_alone = 1; + starg_ch = pim_ifchannel_find (ifp, &sg); + if (starg_ch) + pim_ifchannel_set_star_g_join_state (starg_ch, 0, msg_source_flags, 1, starg_alone); } } @@ -289,16 +291,33 @@ int pim_joinprune_recv(struct interface *ifp, return -8; } - buf += addr_offset; + sg_ch = pim_ifchannel_find (ifp, &sg); + buf += addr_offset; + starg_alone = 0; recv_prune(ifp, neigh, msg_holdtime, msg_upstream_addr.u.prefix4, &sg, msg_source_flags); + + /* Received SG-RPT Prune delete oif from specific S,G */ + if (starg_ch && sg_ch && (msg_source_flags & PIM_RPT_BIT_MASK) + && !(msg_source_flags & PIM_WILDCARD_BIT_MASK)) + { + struct pim_upstream *up = sg_ch->upstream; + PIM_IF_FLAG_SET_S_G_RPT(sg_ch->flags); + if (up) + { + if (PIM_DEBUG_TRACE) + zlog_debug ("%s: SGRpt flag is set, del inherit oif from up %s", + __PRETTY_FUNCTION__, up->sg_str); + pim_channel_del_oif (up->channel_oil, starg_ch->interface, PIM_OIF_FLAG_PROTO_STAR); + } + } } - if (ch) - pim_ifchannel_set_star_g_join_state (ch, 1, msg_source_flags, 0); - ch = NULL; + if (starg_ch) + pim_ifchannel_set_star_g_join_state (starg_ch, 1, msg_source_flags, 0, starg_alone); + starg_ch = NULL; } /* scan groups */ return 0; @@ -502,6 +521,10 @@ int pim_joinprune_send(struct pim_rpf *rpf, packet_size += group_size; pim_msg_build_jp_groups (grp, group, group_size); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: interface %s num_joins %u num_prunes %u", __PRETTY_FUNCTION__, + rpf->source_nexthop.interface->name, ntohs(grp->joins), ntohs (grp->prunes)); + grp = (struct pim_jp_groups *)curr_ptr; if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255) { diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index f46ebfb979..d16106dec8 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -244,17 +244,18 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, { return PIM_RPF_FAILURE; } - } + } rpf->rpf_addr.family = AF_INET; rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up); - if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) { - /* RPF'(S,G) not found */ - zlog_debug("%s %s: RPF'%s not found: won't send join upstream", + if (pim_rpf_addr_is_inaddr_any(rpf) && PIM_DEBUG_ZEBRA) + { + /* RPF'(S,G) not found */ + zlog_debug("%s %s: RPF'%s not found: won't send join upstream", __FILE__, __PRETTY_FUNCTION__, up->sg_str); - /* warning only */ - } + /* warning only */ + } /* detect change in pim_nexthop */ if (nexthop_mismatch(&rpf->source_nexthop, &saved.source_nexthop)) { diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 6fadfc2f29..af9c3913a5 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -582,8 +582,9 @@ pim_upstream_switch(struct pim_upstream *up, if (old_state == PIM_UPSTREAM_JOINED) pim_msdp_up_join_state_changed(up); - /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT */ - if (pim_upstream_is_sg_rpt(up) && up->parent) + /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards RP. + If I am RP for G then send S,G prune to its IIF. */ + if (pim_upstream_is_sg_rpt(up) && up->parent && !I_am_RP(up->sg.grp)) { if (PIM_DEBUG_PIM_TRACE_DETAIL) zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__, From 9e8df9882c7c3fcc80aba2923cafd8d3188d83ad Mon Sep 17 00:00:00 2001 From: Jafar Al-Gharaibeh Date: Tue, 23 May 2017 13:23:04 -0500 Subject: [PATCH 02/34] vtysh: fix a compile error when user/group are disabled If FRR is configured explicilty with --disable-user and --disable-group, FRR_USER and FRR_GROUP will not be defined and can be safely skipped in vtysh. Signed-off-by: Jafar Al-Gharaibeh --- vtysh/vtysh.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 24ac9675e8..17b95707d6 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2488,6 +2488,7 @@ vtysh_write_config_integrated(void) err++; } +#ifdef FRR_USER pwentry = getpwnam (FRR_USER); if (pwentry) uid = pwentry->pw_uid; @@ -2496,7 +2497,8 @@ vtysh_write_config_integrated(void) printf ("%% Warning: could not look up user \"%s\"\n", FRR_USER); err++; } - +#endif +#ifdef FRR_GROUP grentry = getgrnam (FRR_GROUP); if (grentry) gid = grentry->gr_gid; @@ -2505,6 +2507,7 @@ vtysh_write_config_integrated(void) printf ("%% Warning: could not look up group \"%s\"\n", FRR_GROUP); err++; } +#endif if (!fstat (fd, &st)) { From 3c5211b4c9c1fef0ba0b540f2504d4d09488012e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 25 May 2017 13:53:50 -0400 Subject: [PATCH 03/34] vtysh: Add back some missing bgp commands Signed-off-by: Donald Sharp --- vtysh/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am index a8dbb8d71d..9a5008f9d7 100644 --- a/vtysh/Makefile.am +++ b/vtysh/Makefile.am @@ -50,6 +50,7 @@ vtysh_scan += $(top_srcdir)/bgpd/bgp_dump.c vtysh_scan += $(top_srcdir)/bgpd/bgp_evpn_vty.c vtysh_scan += $(top_srcdir)/bgpd/bgp_filter.c vtysh_scan += $(top_srcdir)/bgpd/bgp_mplsvpn.c +vtysh_scan += $(top_srcdir)/bgpd/bgp_nexthop.c vtysh_scan += $(top_srcdir)/bgpd/bgp_route.c vtysh_scan += $(top_srcdir)/bgpd/bgp_routemap.c vtysh_scan += $(top_srcdir)/bgpd/bgp_vty.c From 95db01eb22d4afe43a7f37243077f24b0b90ae9d Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 31 May 2017 23:21:40 +0000 Subject: [PATCH 04/34] lib: use heap for pollfds a bunch of pollfds can cause a stack overflow when using a stack allocated buffer...silly me... Signed-off-by: Quentin Young --- lib/thread.c | 13 +++++++------ lib/thread.h | 3 +++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 848e39e1ae..2f15659a18 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -393,6 +393,8 @@ thread_master_create (void) rv->handler.pfdcount = 0; rv->handler.pfds = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct pollfd) * rv->handler.pfdsize); + rv->handler.copy = XCALLOC (MTYPE_THREAD_MASTER, + sizeof (struct pollfd) * rv->handler.pfdsize); return rv; } @@ -544,6 +546,7 @@ thread_master_free (struct thread_master *m) close (m->io_pipe[1]); XFREE (MTYPE_THREAD_MASTER, m->handler.pfds); + XFREE (MTYPE_THREAD_MASTER, m->handler.copy); XFREE (MTYPE_THREAD_MASTER, m); pthread_mutex_lock (&cpu_record_mtx); @@ -1231,17 +1234,15 @@ thread_fetch (struct thread_master *m, struct thread *fetch) timer_wait = &timer_val; } - /* copy pollfds so we can unlock during blocking calls to poll() */ - struct pollfd pfds[m->handler.pfdsize]; unsigned int count = m->handler.pfdcount + m->handler.pfdcountsnmp; - memcpy (pfds, m->handler.pfds, count * sizeof (struct pollfd)); + memcpy (m->handler.copy, m->handler.pfds, count * sizeof (struct pollfd)); pthread_mutex_unlock (&m->mtx); { - num = fd_poll (m, pfds, m->handler.pfdsize, count, timer_wait); + num = fd_poll (m, m->handler.copy, m->handler.pfdsize, count, timer_wait); } pthread_mutex_lock (&m->mtx); - + /* Signals should get quick treatment */ if (num < 0) { @@ -1263,7 +1264,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) /* Got IO, process it */ if (num > 0) - thread_process_io (m, pfds, num, count); + thread_process_io (m, m->handler.copy, num, count); #if 0 /* If any threads were made ready above (I/O or foreground timer), diff --git a/lib/thread.h b/lib/thread.h index 753aa41ffd..608fb8b8c0 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -53,7 +53,10 @@ struct fd_handler nfds_t pfdcountsnmp; /* number of pfd that fit in the allocated space of pfds */ nfds_t pfdsize; + /* file descriptors to monitor for i/o */ struct pollfd *pfds; + /* chunk used for temp copy of pollfds */ + struct pollfd *copy; }; /* Master of the theads. */ From 509fac8d8564fcb3d0bec3be9567312f6d83e889 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Thu, 1 Jun 2017 19:23:00 +0200 Subject: [PATCH 05/34] release: frr-3.0-rc0 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d9bed28c95..e6f680d85a 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ(2.60) -AC_INIT(frr, 3.0, [https://github.com/frrouting/frr/issues]) +AC_INIT(frr, 3.0-rc0, [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" PACKAGE_FULLNAME="FRRouting" AC_SUBST(PACKAGE_FULLNAME) From f1c2f411430b996af6a3373a173b249af888c59c Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 31 May 2017 19:00:39 +0000 Subject: [PATCH 06/34] ospfd: fix virtual-link timers commands Use {} semantics, correct docstrings, switchup parsing. Signed-off-by: Quentin Young --- ospfd/ospf_vty.c | 67 ++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index caf1b0c668..c6465f1934 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -989,15 +989,15 @@ ospf_vl_set (struct ospf *ospf, struct ospf_vl_config_data *vl_config) "Use null authentication\n" \ "Use message-digest authentication\n" -#define VLINK_HELPSTR_TIME_PARAM_NOSECS \ - "Time between HELLO packets\n" \ - "Time between retransmitting lost link state advertisements\n" \ - "Link state transmit delay\n" \ - "Interval time after which a neighbor is declared down\n" - #define VLINK_HELPSTR_TIME_PARAM \ - VLINK_HELPSTR_TIME_PARAM_NOSECS \ - "Seconds\n" + "Time between HELLO packets\n" \ + "Seconds\n" \ + "Time between retransmitting lost link state advertisements\n" \ + "Seconds\n" \ + "Link state transmit delay\n" \ + "Seconds\n" \ + "Interval time after which a neighbor is declared down\n" \ + "Seconds\n" \ #define VLINK_HELPSTR_AUTH_SIMPLE \ "Authentication password (key)\n" \ @@ -1132,16 +1132,8 @@ DEFUN (ospf_area_vlink, DEFUN (ospf_area_vlink_intervals, ospf_area_vlink_intervals_cmd, - "area virtual-link A.B.C.D" - " (1-65535)" - "[ (1-65535)" - "[ (1-65535)" - "[ (1-65535)" - "]]]", + "area virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}", VLINK_HELPSTR_IPADDR - VLINK_HELPSTR_TIME_PARAM - VLINK_HELPSTR_TIME_PARAM - VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) { VTY_DECLVAR_CONTEXT(ospf, ospf); @@ -1166,17 +1158,17 @@ DEFUN (ospf_area_vlink_intervals, vty_out (vty, "Please specify valid Router ID as a.b.c.d%s", VTY_NEWLINE); return CMD_WARNING; } - for (unsigned int i = 0; i < 4; i++) + + for (int idx = 4; idx < argc; idx++) { - int idx = 0; - if (argv_find (argv, argc, "hello-interval", &idx)) - vl_config.hello_interval = strtol(argv[idx+1]->arg, NULL, 10); - else if (argv_find (argv, argc, "retransmit-interval", &idx)) - vl_config.retransmit_interval = strtol(argv[idx+1]->arg, NULL, 10); - else if (argv_find (argv, argc, "transmit-delay", &idx)) - vl_config.transmit_delay = strtol(argv[idx+1]->arg, NULL, 10); - else if (argv_find (argv, argc, "dead-interval", &idx)) - vl_config.dead_interval = strtol(argv[idx+1]->arg, NULL, 10); + if (strmatch (argv[idx]->text, "hello-interval")) + vl_config.hello_interval = strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch (argv[idx]->text, "retransmit-interval")) + vl_config.retransmit_interval = strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch (argv[idx]->text, "transmit-delay")) + vl_config.transmit_delay = strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch (argv[idx]->text, "dead-interval")) + vl_config.dead_interval = strtol(argv[++idx]->arg, NULL, 10); } /* Action configuration */ @@ -1295,17 +1287,9 @@ DEFUN (no_ospf_area_vlink, DEFUN (no_ospf_area_vlink_intervals, no_ospf_area_vlink_intervals_cmd, - "no area virtual-link A.B.C.D" - " (1-65535)" - "[ (1-65535)" - "[ (1-65535)" - "[ (1-65535)" - "]]]", + "no area virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}", NO_STR VLINK_HELPSTR_IPADDR - VLINK_HELPSTR_TIME_PARAM - VLINK_HELPSTR_TIME_PARAM - VLINK_HELPSTR_TIME_PARAM VLINK_HELPSTR_TIME_PARAM) { VTY_DECLVAR_CONTEXT(ospf, ospf); @@ -1331,16 +1315,15 @@ DEFUN (no_ospf_area_vlink_intervals, return CMD_WARNING; } - for (unsigned int i = 0; i < 4; i++) + for (int idx = 5; idx < argc; idx++) { - int idx = 0; - if (argv_find (argv, argc, "hello-interval", &idx)) + if (strmatch (argv[idx]->text, "hello-interval")) vl_config.hello_interval = OSPF_HELLO_INTERVAL_DEFAULT; - else if (argv_find (argv, argc, "retransmit-interval", &idx)) + else if (strmatch (argv[idx]->text, "retransmit-interval")) vl_config.retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; - else if (argv_find (argv, argc, "transmit-delay", &idx)) + else if (strmatch (argv[idx]->text, "transmit-delay")) vl_config.transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; - else if (argv_find (argv, argc, "dead-interval", &idx)) + else if (strmatch (argv[idx]->text, "dead-interval")) vl_config.dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; } From 0c2206de310506f9d420e4c99fe2fcab50973fd1 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 31 May 2017 19:04:53 +0000 Subject: [PATCH 07/34] ospfd: shufflin move virtual-link command down to be next to its no form Signed-off-by: Quentin Young --- ospfd/ospf_vty.c | 90 ++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index c6465f1934..49840a34b4 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -1130,51 +1130,6 @@ DEFUN (ospf_area_vlink, } -DEFUN (ospf_area_vlink_intervals, - ospf_area_vlink_intervals_cmd, - "area virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}", - VLINK_HELPSTR_IPADDR - VLINK_HELPSTR_TIME_PARAM) -{ - VTY_DECLVAR_CONTEXT(ospf, ospf); - struct ospf_vl_config_data vl_config; - int ret = 0; - - ospf_vl_config_data_init(&vl_config, vty); - - char *area_id = argv[1]->arg; - char *router_id = argv[3]->arg; - - ret = str2area_id (area_id, &vl_config.area_id, &vl_config.area_id_fmt); - if (ret < 0) - { - vty_out (vty, "OSPF area ID is invalid%s", VTY_NEWLINE); - return CMD_WARNING; - } - - ret = inet_aton (router_id, &vl_config.vl_peer); - if (! ret) - { - vty_out (vty, "Please specify valid Router ID as a.b.c.d%s", VTY_NEWLINE); - return CMD_WARNING; - } - - for (int idx = 4; idx < argc; idx++) - { - if (strmatch (argv[idx]->text, "hello-interval")) - vl_config.hello_interval = strtol(argv[++idx]->arg, NULL, 10); - else if (strmatch (argv[idx]->text, "retransmit-interval")) - vl_config.retransmit_interval = strtol(argv[++idx]->arg, NULL, 10); - else if (strmatch (argv[idx]->text, "transmit-delay")) - vl_config.transmit_delay = strtol(argv[++idx]->arg, NULL, 10); - else if (strmatch (argv[idx]->text, "dead-interval")) - vl_config.dead_interval = strtol(argv[++idx]->arg, NULL, 10); - } - - /* Action configuration */ - return ospf_vl_set (ospf, &vl_config); -} - DEFUN (no_ospf_area_vlink, no_ospf_area_vlink_cmd, "no area virtual-link A.B.C.D [authentication] [] []", @@ -1285,6 +1240,51 @@ DEFUN (no_ospf_area_vlink, return ospf_vl_set (ospf, &vl_config); } +DEFUN (ospf_area_vlink_intervals, + ospf_area_vlink_intervals_cmd, + "area virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}", + VLINK_HELPSTR_IPADDR + VLINK_HELPSTR_TIME_PARAM) +{ + VTY_DECLVAR_CONTEXT(ospf, ospf); + struct ospf_vl_config_data vl_config; + int ret = 0; + + ospf_vl_config_data_init(&vl_config, vty); + + char *area_id = argv[1]->arg; + char *router_id = argv[3]->arg; + + ret = str2area_id (area_id, &vl_config.area_id, &vl_config.area_id_fmt); + if (ret < 0) + { + vty_out (vty, "OSPF area ID is invalid%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ret = inet_aton (router_id, &vl_config.vl_peer); + if (! ret) + { + vty_out (vty, "Please specify valid Router ID as a.b.c.d%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (int idx = 4; idx < argc; idx++) + { + if (strmatch (argv[idx]->text, "hello-interval")) + vl_config.hello_interval = strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch (argv[idx]->text, "retransmit-interval")) + vl_config.retransmit_interval = strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch (argv[idx]->text, "transmit-delay")) + vl_config.transmit_delay = strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch (argv[idx]->text, "dead-interval")) + vl_config.dead_interval = strtol(argv[++idx]->arg, NULL, 10); + } + + /* Action configuration */ + return ospf_vl_set (ospf, &vl_config); +} + DEFUN (no_ospf_area_vlink_intervals, no_ospf_area_vlink_intervals_cmd, "no area virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}", From 7d6e13e13838ca05573ac28e1cc4ace4585ed6e2 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 2 Jun 2017 19:10:03 +0000 Subject: [PATCH 08/34] ospfd: fix 'show ip ospf interface json' json obj not recreated for each interface Signed-off-by: Quentin Young --- ospfd/ospf_vty.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 49840a34b4..0eb3aa6a8a 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3536,7 +3536,6 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, if (use_json) { json = json_object_new_object(); - json_interface_sub = json_object_new_object(); } if (ospf->instance) @@ -3555,7 +3554,11 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, { if (ospf_oi_count(ifp)) { + if (use_json) + json_interface_sub = json_object_new_object(); + show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json); + if (use_json) json_object_object_add (json, ifp->name, json_interface_sub); } @@ -3573,7 +3576,11 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, } else { + if (use_json) + json_interface_sub = json_object_new_object(); + show_ip_ospf_interface_sub (vty, ospf, ifp, json_interface_sub, use_json); + if (use_json) json_object_object_add(json, ifp->name, json_interface_sub); } From ce2570bc0a1810a6dd1eaea683d4a8a73c00a53c Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 2 Jun 2017 21:48:01 +0000 Subject: [PATCH 09/34] bgpd: fix large-community-list commands Signed-off-by: Quentin Young --- bgpd/bgp_vty.c | 1 + 1 file changed, 1 insertion(+) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 66689c8367..7e2912440a 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -11249,6 +11249,7 @@ lcommunity_list_set_vty (struct vty *vty, int argc, struct cmd_token **argv, return CMD_WARNING; } + idx = 0; argv_find (argv, argc, "AA:BB:CC", &idx); argv_find (argv, argc, "LINE", &idx); /* Concat community string argument. */ From cb63fd542ac770fa8cfd572db8d1e4afc8498e35 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 2 Jun 2017 21:20:33 +0000 Subject: [PATCH 10/34] ospf6d: fix filter-list commands incorrect indexes resulted in use of area id as the name of the prefix list Signed-off-by: Quentin Young --- ospf6d/ospf6_area.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index fd5e84d88c..a010ff322a 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -610,21 +610,23 @@ DEFUN (area_filter_list, "Filter networks sent to this area\n" "Filter networks sent from this area\n") { - int idx_ipv4 = 1; - int idx_word = 4; + char *inout = argv[argc - 1]->text; + char *areaid = argv[1]->arg; + char *plistname = argv[4]->arg; + struct ospf6_area *area; struct prefix_list *plist; - OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, area); + OSPF6_CMD_AREA_GET (areaid, area); - plist = prefix_list_lookup (AFI_IP6, argv[idx_ipv4]->arg); - if (strncmp (argv[idx_word]->arg, "in", 2) == 0) + plist = prefix_list_lookup (AFI_IP6, plistname); + if (strmatch (inout, "in")) { PREFIX_LIST_IN (area) = plist; if (PREFIX_NAME_IN (area)) free (PREFIX_NAME_IN (area)); - PREFIX_NAME_IN (area) = strdup (argv[idx_ipv4]->arg); + PREFIX_NAME_IN (area) = strdup (plistname); ospf6_abr_reimport (area); } else @@ -633,7 +635,7 @@ DEFUN (area_filter_list, if (PREFIX_NAME_OUT (area)) free (PREFIX_NAME_OUT (area)); - PREFIX_NAME_OUT (area) = strdup (argv[idx_ipv4]->arg); + PREFIX_NAME_OUT (area) = strdup (plistname); ospf6_abr_enable_area (area); } @@ -652,16 +654,18 @@ DEFUN (no_area_filter_list, "Filter networks sent to this area\n" "Filter networks sent from this area\n") { - int idx_ipv4 = 2; - int idx_word = 5; + char *inout = argv[argc - 1]->text; + char *areaid = argv[2]->arg; + char *plistname = argv[5]->arg; + struct ospf6_area *area; - OSPF6_CMD_AREA_GET (argv[idx_ipv4]->arg, area); + OSPF6_CMD_AREA_GET (areaid, area); - if (strncmp (argv[idx_word]->arg, "in", 2) == 0) + if (strmatch (inout, "in")) { if (PREFIX_NAME_IN (area)) - if (strcmp (PREFIX_NAME_IN (area), argv[idx_ipv4]->arg) != 0) + if (!strmatch (PREFIX_NAME_IN (area), plistname)) return CMD_SUCCESS; PREFIX_LIST_IN (area) = NULL; @@ -674,7 +678,7 @@ DEFUN (no_area_filter_list, else { if (PREFIX_NAME_OUT (area)) - if (strcmp (PREFIX_NAME_OUT (area), argv[idx_ipv4]->arg) != 0) + if (!strmatch (PREFIX_NAME_OUT (area), plistname)) return CMD_SUCCESS; PREFIX_LIST_OUT (area) = NULL; From 406f99f81d8d77bc5b2905afec2c4ed53739b306 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 2 Jun 2017 20:53:37 +0000 Subject: [PATCH 11/34] bgpd: fix addpath buffer overrun Signed-off-by: Quentin Young --- bgpd/bgp_debug.c | 11 +++++++---- bgpd/bgp_updgrp_packet.c | 35 +++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 232f53c778..fb350d51a1 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -40,8 +40,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_mplsvpn.h" -#define BGP_ADDPATH_STR 20 - unsigned long conf_bgp_debug_as4; unsigned long conf_bgp_debug_neighbor_events; unsigned long conf_bgp_debug_events; @@ -2132,7 +2130,12 @@ bgp_debug_rdpfxpath2str (struct prefix_rd *prd, union prefixconstptr pu, { char rd_buf[RD_ADDRSTRLEN]; char pfx_buf[PREFIX_STRLEN]; - char pathid_buf[BGP_ADDPATH_STR]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (in case of idiocy) + 1 + * null terminator + 1 + * ============================ 29 */ + char pathid_buf[30]; if (size < BGP_PRD_PATH_STRLEN) return NULL; @@ -2140,7 +2143,7 @@ bgp_debug_rdpfxpath2str (struct prefix_rd *prd, union prefixconstptr pu, /* Note: Path-id is created by default, but only included in update sometimes. */ pathid_buf[0] = '\0'; if (addpath_valid) - sprintf(pathid_buf, " with addpath ID %d", addpath_id); + snprintf(pathid_buf, sizeof(pathid_buf), " with addpath ID %u", addpath_id); if (prd) snprintf (str, size, "RD %s %s%s", diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 5872ca6f3f..588f8a66fa 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -650,17 +650,6 @@ subgroup_packets_to_build (struct update_subgroup *subgrp) return 0; } -static void -bgp_info_addpath_tx_str (int addpath_encode, u_int32_t addpath_tx_id, - char *buf) -{ - buf[0] = '\0'; - if (addpath_encode) - sprintf(buf, " with addpath ID %d", addpath_tx_id); - else - buf[0] = '\0'; -} - /* Make BGP update packet. */ struct bpacket * subgroup_update_packet (struct update_subgroup *subgrp) @@ -1051,11 +1040,21 @@ subgroup_default_update_packet (struct update_subgroup *subgrp, { char attrstr[BUFSIZ]; char buf[PREFIX_STRLEN]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (in case of idiocy) + 1 + * null terminator + 1 + * ============================ 29 */ char tx_id_buf[30]; + attrstr[0] = '\0'; bgp_dump_attr (peer, attr, attrstr, BUFSIZ); - bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf); + + if (addpath_encode) + snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u", + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s", (SUBGRP_UPDGRP (subgrp))->id, subgrp->id, prefix2str (&p, buf, sizeof (buf)), @@ -1125,9 +1124,17 @@ subgroup_default_withdraw_packet (struct update_subgroup *subgrp) if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) { char buf[PREFIX_STRLEN]; - char tx_id_buf[INET6_BUFSIZ]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (in case of idiocy) + 1 + * null terminator + 1 + * ============================ 29 */ + char tx_id_buf[30]; + + if (addpath_encode) + snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u", + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf); zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s -- unreachable", (SUBGRP_UPDGRP (subgrp))->id, subgrp->id, prefix2str (&p, buf, sizeof (buf)), tx_id_buf); From 33a57d94fadfce9951fbcf74f7f7a4e85492b00a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 30 May 2017 08:30:57 -0300 Subject: [PATCH 12/34] bgpd: fix segfault with some show commands The following commands were causing bgpd to crash when vpnv4/vpnv6 static routes are configured: bgpd aborted: vtysh -c "show ip bgp view all ipv4 vpn json" bgpd aborted: vtysh -c "show ip bgp view all ipv4 vpn" bgpd aborted: vtysh -c "show ip bgp view all ipv6 vpn json" bgpd aborted: vtysh -c "show ip bgp view all ipv6 vpn" bgpd aborted: vtysh -c "show ip bgp vrf all ipv4 vpn json" bgpd aborted: vtysh -c "show ip bgp vrf all ipv4 vpn" bgpd aborted: vtysh -c "show ip bgp vrf all ipv6 vpn json" bgpd aborted: vtysh -c "show ip bgp vrf all ipv6 vpn" bgpd aborted: vtysh -c "show bgp view all ipv4 vpn json" bgpd aborted: vtysh -c "show bgp view all ipv4 vpn" bgpd aborted: vtysh -c "show bgp view all ipv6 vpn json" bgpd aborted: vtysh -c "show bgp view all ipv6 vpn" bgpd aborted: vtysh -c "show bgp vrf all ipv4 vpn json" bgpd aborted: vtysh -c "show bgp vrf all ipv4 vpn" bgpd aborted: vtysh -c "show bgp vrf all ipv6 vpn json" bgpd aborted: vtysh -c "show bgp vrf all ipv6 vpn" Problem found with the CLI fuzzer. Signed-off-by: Renato Westphal --- bgpd/bgp_route.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 38e696d11b..9b85ad3d96 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7852,7 +7852,6 @@ bgp_show_all_instances_routes_vty (struct vty *vty, afi_t afi, safi_t safi, { struct listnode *node, *nnode; struct bgp *bgp; - struct bgp_table *table; int is_first = 1; if (use_json) @@ -7878,9 +7877,7 @@ bgp_show_all_instances_routes_vty (struct vty *vty, afi_t afi, safi_t safi, ? "Default" : bgp->name, VTY_NEWLINE); } - table = bgp->rib[afi][safi]; - bgp_show_table (vty, bgp, table, - bgp_show_type_normal, NULL, use_json); + bgp_show (vty, bgp, afi, safi, bgp_show_type_normal, NULL, use_json); } From 31c6fa450a4ce10348b8a4633ba287b22b7eba00 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Sun, 4 Jun 2017 21:01:52 +0000 Subject: [PATCH 13/34] zebra: remove extraneous help string caused tag to display null0 helpstr Signed-off-by: Quentin Young --- zebra/zebra_vty.c | 1 - 1 file changed, 1 deletion(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 6c3dfe0e06..6f1c81eda1 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2172,7 +2172,6 @@ DEFUN (ipv6_route, "IPv6 gateway address\n" "IPv6 gateway interface name\n" "Null interface\n" - "Null interface\n" "Set tag for this route\n" "Tag value\n" "Distance value for this prefix\n" From a9609069a5cf67f20b28d93dfdf2d5d05299a0c7 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Mon, 5 Jun 2017 13:13:57 +0000 Subject: [PATCH 14/34] bgpd: fix ipv6 network statement label-index node Problem reported with the inability to define "network x:x:x::/64 label-index" to the config. Found that the install_element was pointing to the wrong node. Ticket: CM-16615 Signed-off-by: Don Slice --- bgpd/bgp_route.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index b3e1f8b27e..a345cb6526 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -10988,10 +10988,10 @@ bgp_route_init (void) install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd); install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd); install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd); - install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_route_map_cmd); - install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_route_map_cmd); + install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_label_index_cmd); + install_element (BGP_IPV6L_NODE, &no_ipv6_bgp_network_label_index_cmd); + install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_label_index_route_map_cmd); + install_element (BGP_IPV6L_NODE, &no_ipv6_bgp_network_label_index_route_map_cmd); install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); From 0b4d8f1e38ea1dbade4d2f714775608b379e992e Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 18 Apr 2017 12:04:44 -0300 Subject: [PATCH 15/34] ldpd: split log.c into two files This is basically to keep in sync with OpenBSD's ldpd(8) where the same change was done. Signed-off-by: Renato Westphal --- ldpd/Makefile.am | 2 +- ldpd/lde.c | 1 + ldpd/ldpd.c | 1 + ldpd/ldpd.h | 30 +++ ldpd/ldpe.c | 1 + ldpd/log.c | 477 +--------------------------------------------- ldpd/log.h | 66 +++---- ldpd/logmsg.c | 487 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 549 insertions(+), 516 deletions(-) create mode 100644 ldpd/logmsg.c diff --git a/ldpd/Makefile.am b/ldpd/Makefile.am index 19f819ae36..b760b44573 100644 --- a/ldpd/Makefile.am +++ b/ldpd/Makefile.am @@ -16,7 +16,7 @@ EXTRA_DIST += ldp_vty.xml libldp_a_SOURCES = \ accept.c address.c adjacency.c control.c hello.c init.c interface.c \ keepalive.c l2vpn.c labelmapping.c lde.c lde_lib.c ldpd.c \ - ldpe.c log.c neighbor.c notification.c packet.c pfkey.c \ + ldpe.c log.c logmsg.c neighbor.c notification.c packet.c pfkey.c \ socket.c util.c ldp_vty_cmds.c ldp_vty_conf.c ldp_vty_exec.c \ ldp_debug.c ldp_zebra.c diff --git a/ldpd/lde.c b/ldpd/lde.c index 36998e7cf8..c4a610b6d3 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -163,6 +163,7 @@ lde(const char *user, const char *group, u_short instance) setproctitle("label decision engine"); #endif ldpd_process = PROC_LDE_ENGINE; + log_procname = log_procnames[PROC_LDE_ENGINE]; /* drop privileges */ if (user) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index def3d2e2f3..8da830ccef 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -208,6 +208,7 @@ main(int argc, char *argv[]) const char *instance_char = NULL; ldpd_process = PROC_MAIN; + log_procname = log_procnames[ldpd_process]; saved_argv0 = argv[0]; if (saved_argv0 == NULL) diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 10742cf0dc..759f1d0da5 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -439,6 +439,12 @@ enum ldpd_process { PROC_LDE_ENGINE } ldpd_process; +static const char * const log_procnames[] = { + "parent", + "ldpe", + "lde" +}; + enum socket_type { LDP_SOCKET_DISC, LDP_SOCKET_EDISC, @@ -762,6 +768,30 @@ int sock_set_ipv6_mcast_hops(int, int); int sock_set_ipv6_mcast(struct iface *); int sock_set_ipv6_mcast_loop(int); +/* logmsg.h */ +struct in6_addr; +union ldpd_addr; +struct hello_source; +struct fec; + +const char *log_sockaddr(void *); +const char *log_in6addr(const struct in6_addr *); +const char *log_in6addr_scope(const struct in6_addr *, unsigned int); +const char *log_addr(int, const union ldpd_addr *); +char *log_label(uint32_t); +const char *log_time(time_t); +char *log_hello_src(const struct hello_source *); +const char *log_map(const struct map *); +const char *log_fec(const struct fec *); +const char *af_name(int); +const char *socket_name(int); +const char *nbr_state_name(int); +const char *if_state_name(int); +const char *if_type_name(enum iface_type); +const char *msg_name(uint16_t); +const char *status_code_name(uint32_t); +const char *pw_type_name(uint16_t); + /* quagga */ extern struct thread_master *master; extern char ctl_sock_path[MAXPATHLEN]; diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 1bec3d2a95..e82416276b 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -113,6 +113,7 @@ ldpe(const char *user, const char *group, const char *ctl_path) setproctitle("ldp engine"); #endif ldpd_process = PROC_LDP_ENGINE; + log_procname = log_procnames[ldpd_process]; LIST_INIT(&global.addr_list); RB_INIT(&global.adj_tree); diff --git a/ldpd/log.c b/ldpd/log.c index 407668bb03..408aaeb699 100644 --- a/ldpd/log.c +++ b/ldpd/log.c @@ -25,15 +25,8 @@ #include #include -#include "mpls.h" -static const char * const procnames[] = { - "parent", - "ldpe", - "lde" -}; - -void vlog(int, const char *, va_list); +const char *log_procname; void logit(int pri, const char *fmt, ...) @@ -133,15 +126,15 @@ void fatal(const char *emsg) { if (emsg == NULL) - logit(LOG_CRIT, "fatal in %s: %s", procnames[ldpd_process], + logit(LOG_CRIT, "fatal in %s: %s", log_procname, strerror(errno)); else if (errno) logit(LOG_CRIT, "fatal in %s: %s: %s", - procnames[ldpd_process], emsg, strerror(errno)); + log_procname, emsg, strerror(errno)); else logit(LOG_CRIT, "fatal in %s: %s", - procnames[ldpd_process], emsg); + log_procname, emsg); exit(1); } @@ -152,465 +145,3 @@ fatalx(const char *emsg) errno = 0; fatal(emsg); } - -#define NUM_LOGS 4 -const char * -log_sockaddr(void *vp) -{ - static char buf[NUM_LOGS][NI_MAXHOST]; - static int round = 0; - struct sockaddr *sa = vp; - - round = (round + 1) % NUM_LOGS; - - if (getnameinfo(sa, sockaddr_len(sa), buf[round], NI_MAXHOST, NULL, 0, - NI_NUMERICHOST)) - return ("(unknown)"); - else - return (buf[round]); -} - -const char * -log_in6addr(const struct in6_addr *addr) -{ - struct sockaddr_in6 sa_in6; - - memset(&sa_in6, 0, sizeof(sa_in6)); -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sa_in6.sin6_len = sizeof(sa_in6); -#endif - sa_in6.sin6_family = AF_INET6; - sa_in6.sin6_addr = *addr; - - recoverscope(&sa_in6); - - return (log_sockaddr(&sa_in6)); -} - -const char * -log_in6addr_scope(const struct in6_addr *addr, unsigned int ifindex) -{ - struct sockaddr_in6 sa_in6; - - memset(&sa_in6, 0, sizeof(sa_in6)); -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sa_in6.sin6_len = sizeof(sa_in6); -#endif - sa_in6.sin6_family = AF_INET6; - sa_in6.sin6_addr = *addr; - - addscope(&sa_in6, ifindex); - - return (log_sockaddr(&sa_in6)); -} - -const char * -log_addr(int af, const union ldpd_addr *addr) -{ - static char buf[NUM_LOGS][INET6_ADDRSTRLEN]; - static int round = 0; - - switch (af) { - case AF_INET: - round = (round + 1) % NUM_LOGS; - if (inet_ntop(AF_INET, &addr->v4, buf[round], - sizeof(buf[round])) == NULL) - return ("???"); - return (buf[round]); - case AF_INET6: - return (log_in6addr(&addr->v6)); - default: - break; - } - - return ("???"); -} - -#define TF_BUFS 4 -#define TF_LEN 32 - -char * -log_label(uint32_t label) -{ - char *buf; - static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ - static int idx = 0; - - buf = tfbuf[idx++]; - if (idx == TF_BUFS) - idx = 0; - - switch (label) { - case NO_LABEL: - snprintf(buf, TF_LEN, "-"); - break; - case MPLS_LABEL_IMPLNULL: - snprintf(buf, TF_LEN, "imp-null"); - break; - case MPLS_LABEL_IPV4NULL: - case MPLS_LABEL_IPV6NULL: - snprintf(buf, TF_LEN, "exp-null"); - break; - default: - snprintf(buf, TF_LEN, "%u", label); - break; - } - - return (buf); -} - -const char * -log_time(time_t t) -{ - char *buf; - static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ - static int idx = 0; - unsigned int sec, min, hrs, day, week; - - buf = tfbuf[idx++]; - if (idx == TF_BUFS) - idx = 0; - - week = t; - - sec = week % 60; - week /= 60; - min = week % 60; - week /= 60; - hrs = week % 24; - week /= 24; - day = week % 7; - week /= 7; - - if (week > 0) - snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); - else if (day > 0) - snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); - else - snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); - - return (buf); -} - -char * -log_hello_src(const struct hello_source *src) -{ - static char buf[64]; - - switch (src->type) { - case HELLO_LINK: - snprintf(buf, sizeof(buf), "iface %s", - src->link.ia->iface->name); - break; - case HELLO_TARGETED: - snprintf(buf, sizeof(buf), "source %s", - log_addr(src->target->af, &src->target->addr)); - break; - } - - return (buf); -} - -const char * -log_map(const struct map *map) -{ - static char buf[128]; - - switch (map->type) { - case MAP_TYPE_WILDCARD: - if (snprintf(buf, sizeof(buf), "wildcard") < 0) - return ("???"); - break; - case MAP_TYPE_PREFIX: - if (snprintf(buf, sizeof(buf), "%s/%u", - log_addr(map->fec.prefix.af, &map->fec.prefix.prefix), - map->fec.prefix.prefixlen) == -1) - return ("???"); - break; - case MAP_TYPE_PWID: - if (snprintf(buf, sizeof(buf), "pw-id %u group-id %u (%s)", - map->fec.pwid.pwid, map->fec.pwid.group_id, - pw_type_name(map->fec.pwid.type)) == -1) - return ("???"); - break; - case MAP_TYPE_TYPED_WCARD: - if (snprintf(buf, sizeof(buf), "typed wildcard") < 0) - return ("???"); - switch (map->fec.twcard.type) { - case MAP_TYPE_PREFIX: - if (snprintf(buf + strlen(buf), sizeof(buf) - - strlen(buf), " (prefix, address-family %s)", - af_name(map->fec.twcard.u.prefix_af)) < 0) - return ("???"); - break; - case MAP_TYPE_PWID: - if (snprintf(buf + strlen(buf), sizeof(buf) - - strlen(buf), " (pwid, type %s)", - pw_type_name(map->fec.twcard.u.pw_type)) < 0) - return ("???"); - break; - default: - if (snprintf(buf + strlen(buf), sizeof(buf) - - strlen(buf), " (unknown type)") < 0) - return ("???"); - break; - } - break; - default: - return ("???"); - } - - return (buf); -} - -const char * -log_fec(const struct fec *fec) -{ - static char buf[64]; - union ldpd_addr addr; - - switch (fec->type) { - case FEC_TYPE_IPV4: - addr.v4 = fec->u.ipv4.prefix; - if (snprintf(buf, sizeof(buf), "ipv4 %s/%u", - log_addr(AF_INET, &addr), fec->u.ipv4.prefixlen) == -1) - return ("???"); - break; - case FEC_TYPE_IPV6: - addr.v6 = fec->u.ipv6.prefix; - if (snprintf(buf, sizeof(buf), "ipv6 %s/%u", - log_addr(AF_INET6, &addr), fec->u.ipv6.prefixlen) == -1) - return ("???"); - break; - case FEC_TYPE_PWID: - if (snprintf(buf, sizeof(buf), - "pwid %u (%s) - %s", - fec->u.pwid.pwid, pw_type_name(fec->u.pwid.type), - inet_ntoa(fec->u.pwid.lsr_id)) == -1) - return ("???"); - break; - default: - return ("???"); - } - - return (buf); -} - -/* names */ -const char * -af_name(int af) -{ - switch (af) { - case AF_INET: - return ("ipv4"); - case AF_INET6: - return ("ipv6"); -#ifdef AF_MPLS - case AF_MPLS: - return ("mpls"); -#endif - default: - return ("UNKNOWN"); - } -} - -const char * -socket_name(int type) -{ - switch (type) { - case LDP_SOCKET_DISC: - return ("discovery"); - case LDP_SOCKET_EDISC: - return ("extended discovery"); - case LDP_SOCKET_SESSION: - return ("session"); - default: - return ("UNKNOWN"); - } -} - -const char * -nbr_state_name(int state) -{ - switch (state) { - case NBR_STA_PRESENT: - return ("PRESENT"); - case NBR_STA_INITIAL: - return ("INITIALIZED"); - case NBR_STA_OPENREC: - return ("OPENREC"); - case NBR_STA_OPENSENT: - return ("OPENSENT"); - case NBR_STA_OPER: - return ("OPERATIONAL"); - default: - return ("UNKNOWN"); - } -} - -const char * -if_state_name(int state) -{ - switch (state) { - case IF_STA_DOWN: - return ("DOWN"); - case IF_STA_ACTIVE: - return ("ACTIVE"); - default: - return ("UNKNOWN"); - } -} - -const char * -if_type_name(enum iface_type type) -{ - switch (type) { - case IF_TYPE_POINTOPOINT: - return ("POINTOPOINT"); - case IF_TYPE_BROADCAST: - return ("BROADCAST"); - } - /* NOTREACHED */ - return ("UNKNOWN"); -} - -const char * -msg_name(uint16_t msg) -{ - static char buf[16]; - - switch (msg) { - case MSG_TYPE_NOTIFICATION: - return ("notification"); - case MSG_TYPE_HELLO: - return ("hello"); - case MSG_TYPE_INIT: - return ("initialization"); - case MSG_TYPE_KEEPALIVE: - return ("keepalive"); - case MSG_TYPE_CAPABILITY: - return ("capability"); - case MSG_TYPE_ADDR: - return ("address"); - case MSG_TYPE_ADDRWITHDRAW: - return ("address withdraw"); - case MSG_TYPE_LABELMAPPING: - return ("label mapping"); - case MSG_TYPE_LABELREQUEST: - return ("label request"); - case MSG_TYPE_LABELWITHDRAW: - return ("label withdraw"); - case MSG_TYPE_LABELRELEASE: - return ("label release"); - case MSG_TYPE_LABELABORTREQ: - default: - snprintf(buf, sizeof(buf), "[%08x]", msg); - return (buf); - } -} - -const char * -status_code_name(uint32_t status) -{ - static char buf[16]; - - switch (status) { - case S_SUCCESS: - return ("Success"); - case S_BAD_LDP_ID: - return ("Bad LDP Identifier"); - case S_BAD_PROTO_VER: - return ("Bad Protocol Version"); - case S_BAD_PDU_LEN: - return ("Bad PDU Length"); - case S_UNKNOWN_MSG: - return ("Unknown Message Type"); - case S_BAD_MSG_LEN: - return ("Bad Message Length"); - case S_UNKNOWN_TLV: - return ("Unknown TLV"); - case S_BAD_TLV_LEN: - return ("Bad TLV Length"); - case S_BAD_TLV_VAL: - return ("Malformed TLV Value"); - case S_HOLDTIME_EXP: - return ("Hold Timer Expired"); - case S_SHUTDOWN: - return ("Shutdown"); - case S_LOOP_DETECTED: - return ("Loop Detected"); - case S_UNKNOWN_FEC: - return ("Unknown FEC"); - case S_NO_ROUTE: - return ("No Route"); - case S_NO_LABEL_RES: - return ("No Label Resources"); - case S_AVAILABLE: - return ("Label Resources Available"); - case S_NO_HELLO: - return ("Session Rejected, No Hello"); - case S_PARM_ADV_MODE: - return ("Rejected Advertisement Mode Parameter"); - case S_MAX_PDU_LEN: - return ("Rejected Max PDU Length Parameter"); - case S_PARM_L_RANGE: - return ("Rejected Label Range Parameter"); - case S_KEEPALIVE_TMR: - return ("KeepAlive Timer Expired"); - case S_LAB_REQ_ABRT: - return ("Label Request Aborted"); - case S_MISS_MSG: - return ("Missing Message Parameters"); - case S_UNSUP_ADDR: - return ("Unsupported Address Family"); - case S_KEEPALIVE_BAD: - return ("Bad KeepAlive Time"); - case S_INTERN_ERR: - return ("Internal Error"); - case S_ILLEGAL_CBIT: - return ("Illegal C-Bit"); - case S_WRONG_CBIT: - return ("Wrong C-Bit"); - case S_INCPT_BITRATE: - return ("Incompatible bit-rate"); - case S_CEP_MISCONF: - return ("CEP-TDM mis-configuration"); - case S_PW_STATUS: - return ("PW Status"); - case S_UNASSIGN_TAI: - return ("Unassigned/Unrecognized TAI"); - case S_MISCONF_ERR: - return ("Generic Misconfiguration Error"); - case S_WITHDRAW_MTHD: - return ("Label Withdraw PW Status Method"); - case S_UNSSUPORTDCAP: - return ("Unsupported Capability"); - case S_ENDOFLIB: - return ("End-of-LIB"); - case S_TRANS_MISMTCH: - return ("Transport Connection Mismatch"); - case S_DS_NONCMPLNCE: - return ("Dual-Stack Noncompliance"); - default: - snprintf(buf, sizeof(buf), "[%08x]", status); - return (buf); - } -} - -const char * -pw_type_name(uint16_t pw_type) -{ - static char buf[64]; - - switch (pw_type) { - case PW_TYPE_ETHERNET_TAGGED: - return ("Eth Tagged"); - case PW_TYPE_ETHERNET: - return ("Ethernet"); - case PW_TYPE_WILDCARD: - return ("Wildcard"); - default: - snprintf(buf, sizeof(buf), "[%0x]", pw_type); - return (buf); - } -} diff --git a/ldpd/log.h b/ldpd/log.h index 4d6da43cac..8c236ff5fe 100644 --- a/ldpd/log.h +++ b/ldpd/log.h @@ -16,50 +16,32 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef _LOG_H_ -#define _LOG_H_ +#ifndef LOG_H +#define LOG_H #include -struct in6_addr; -union ldpd_addr; -struct hello_source; -struct fec; +extern const char *log_procname; -void logit(int, const char *, ...) - __attribute__((__format__ (printf, 2, 3))); -void log_warn(const char *, ...) - __attribute__((__format__ (printf, 1, 2))); -void log_warnx(const char *, ...) - __attribute__((__format__ (printf, 1, 2))); -void log_info(const char *, ...) - __attribute__((__format__ (printf, 1, 2))); -void log_notice(const char *, ...) - __attribute__((__format__ (printf, 1, 2))); -void log_debug(const char *, ...) - __attribute__((__format__ (printf, 1, 2))); -void fatal(const char *) - __attribute__ ((noreturn)) - __attribute__((__format__ (printf, 1, 0))); -void fatalx(const char *) - __attribute__ ((noreturn)) - __attribute__((__format__ (printf, 1, 0))); -const char *log_sockaddr(void *); -const char *log_in6addr(const struct in6_addr *); -const char *log_in6addr_scope(const struct in6_addr *, unsigned int); -const char *log_addr(int, const union ldpd_addr *); -char *log_label(uint32_t); -const char *log_time(time_t); -char *log_hello_src(const struct hello_source *); -const char *log_map(const struct map *); -const char *log_fec(const struct fec *); -const char *af_name(int); -const char *socket_name(int); -const char *nbr_state_name(int); -const char *if_state_name(int); -const char *if_type_name(enum iface_type); -const char *msg_name(uint16_t); -const char *status_code_name(uint32_t); -const char *pw_type_name(uint16_t); +void logit(int, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void vlog(int, const char *, va_list) + __attribute__((__format__ (printf, 2, 0))); +void log_warn(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_warnx(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_info(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_notice(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_debug(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void fatal(const char *) + __attribute__ ((noreturn)) + __attribute__((__format__ (printf, 1, 0))); +void fatalx(const char *) + __attribute__ ((noreturn)) + __attribute__((__format__ (printf, 1, 0))); -#endif /* _LOG_H_ */ +#endif /* LOG_H */ diff --git a/ldpd/logmsg.c b/ldpd/logmsg.c new file mode 100644 index 0000000000..c819b33b43 --- /dev/null +++ b/ldpd/logmsg.c @@ -0,0 +1,487 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer + * + * 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. + */ + +#include + +#include "mpls.h" + +#include "ldpd.h" +#include "ldpe.h" +#include "lde.h" + +#define NUM_LOGS 4 +const char * +log_sockaddr(void *vp) +{ + static char buf[NUM_LOGS][NI_MAXHOST]; + static int round = 0; + struct sockaddr *sa = vp; + + round = (round + 1) % NUM_LOGS; + + if (getnameinfo(sa, sockaddr_len(sa), buf[round], NI_MAXHOST, NULL, 0, + NI_NUMERICHOST)) + return ("(unknown)"); + else + return (buf[round]); +} + +const char * +log_in6addr(const struct in6_addr *addr) +{ + struct sockaddr_in6 sa_in6; + + memset(&sa_in6, 0, sizeof(sa_in6)); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + sa_in6.sin6_len = sizeof(sa_in6); +#endif + sa_in6.sin6_family = AF_INET6; + sa_in6.sin6_addr = *addr; + + recoverscope(&sa_in6); + + return (log_sockaddr(&sa_in6)); +} + +const char * +log_in6addr_scope(const struct in6_addr *addr, unsigned int ifindex) +{ + struct sockaddr_in6 sa_in6; + + memset(&sa_in6, 0, sizeof(sa_in6)); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + sa_in6.sin6_len = sizeof(sa_in6); +#endif + sa_in6.sin6_family = AF_INET6; + sa_in6.sin6_addr = *addr; + + addscope(&sa_in6, ifindex); + + return (log_sockaddr(&sa_in6)); +} + +const char * +log_addr(int af, const union ldpd_addr *addr) +{ + static char buf[NUM_LOGS][INET6_ADDRSTRLEN]; + static int round = 0; + + switch (af) { + case AF_INET: + round = (round + 1) % NUM_LOGS; + if (inet_ntop(AF_INET, &addr->v4, buf[round], + sizeof(buf[round])) == NULL) + return ("???"); + return (buf[round]); + case AF_INET6: + return (log_in6addr(&addr->v6)); + default: + break; + } + + return ("???"); +} + +#define TF_BUFS 4 +#define TF_LEN 32 + +char * +log_label(uint32_t label) +{ + char *buf; + static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ + static int idx = 0; + + buf = tfbuf[idx++]; + if (idx == TF_BUFS) + idx = 0; + + switch (label) { + case NO_LABEL: + snprintf(buf, TF_LEN, "-"); + break; + case MPLS_LABEL_IMPLNULL: + snprintf(buf, TF_LEN, "imp-null"); + break; + case MPLS_LABEL_IPV4NULL: + case MPLS_LABEL_IPV6NULL: + snprintf(buf, TF_LEN, "exp-null"); + break; + default: + snprintf(buf, TF_LEN, "%u", label); + break; + } + + return (buf); +} + +const char * +log_time(time_t t) +{ + char *buf; + static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ + static int idx = 0; + unsigned int sec, min, hrs, day, week; + + buf = tfbuf[idx++]; + if (idx == TF_BUFS) + idx = 0; + + week = t; + + sec = week % 60; + week /= 60; + min = week % 60; + week /= 60; + hrs = week % 24; + week /= 24; + day = week % 7; + week /= 7; + + if (week > 0) + snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); + else if (day > 0) + snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); + else + snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); + + return (buf); +} + +char * +log_hello_src(const struct hello_source *src) +{ + static char buf[64]; + + switch (src->type) { + case HELLO_LINK: + snprintf(buf, sizeof(buf), "iface %s", + src->link.ia->iface->name); + break; + case HELLO_TARGETED: + snprintf(buf, sizeof(buf), "source %s", + log_addr(src->target->af, &src->target->addr)); + break; + } + + return (buf); +} + +const char * +log_map(const struct map *map) +{ + static char buf[128]; + + switch (map->type) { + case MAP_TYPE_WILDCARD: + if (snprintf(buf, sizeof(buf), "wildcard") < 0) + return ("???"); + break; + case MAP_TYPE_PREFIX: + if (snprintf(buf, sizeof(buf), "%s/%u", + log_addr(map->fec.prefix.af, &map->fec.prefix.prefix), + map->fec.prefix.prefixlen) == -1) + return ("???"); + break; + case MAP_TYPE_PWID: + if (snprintf(buf, sizeof(buf), "pw-id %u group-id %u (%s)", + map->fec.pwid.pwid, map->fec.pwid.group_id, + pw_type_name(map->fec.pwid.type)) == -1) + return ("???"); + break; + case MAP_TYPE_TYPED_WCARD: + if (snprintf(buf, sizeof(buf), "typed wildcard") < 0) + return ("???"); + switch (map->fec.twcard.type) { + case MAP_TYPE_PREFIX: + if (snprintf(buf + strlen(buf), sizeof(buf) - + strlen(buf), " (prefix, address-family %s)", + af_name(map->fec.twcard.u.prefix_af)) < 0) + return ("???"); + break; + case MAP_TYPE_PWID: + if (snprintf(buf + strlen(buf), sizeof(buf) - + strlen(buf), " (pwid, type %s)", + pw_type_name(map->fec.twcard.u.pw_type)) < 0) + return ("???"); + break; + default: + if (snprintf(buf + strlen(buf), sizeof(buf) - + strlen(buf), " (unknown type)") < 0) + return ("???"); + break; + } + break; + default: + return ("???"); + } + + return (buf); +} + +const char * +log_fec(const struct fec *fec) +{ + static char buf[64]; + union ldpd_addr addr; + + switch (fec->type) { + case FEC_TYPE_IPV4: + addr.v4 = fec->u.ipv4.prefix; + if (snprintf(buf, sizeof(buf), "ipv4 %s/%u", + log_addr(AF_INET, &addr), fec->u.ipv4.prefixlen) == -1) + return ("???"); + break; + case FEC_TYPE_IPV6: + addr.v6 = fec->u.ipv6.prefix; + if (snprintf(buf, sizeof(buf), "ipv6 %s/%u", + log_addr(AF_INET6, &addr), fec->u.ipv6.prefixlen) == -1) + return ("???"); + break; + case FEC_TYPE_PWID: + if (snprintf(buf, sizeof(buf), + "pwid %u (%s) - %s", + fec->u.pwid.pwid, pw_type_name(fec->u.pwid.type), + inet_ntoa(fec->u.pwid.lsr_id)) == -1) + return ("???"); + break; + default: + return ("???"); + } + + return (buf); +} + +/* names */ +const char * +af_name(int af) +{ + switch (af) { + case AF_INET: + return ("ipv4"); + case AF_INET6: + return ("ipv6"); +#ifdef AF_MPLS + case AF_MPLS: + return ("mpls"); +#endif + default: + return ("UNKNOWN"); + } +} + +const char * +socket_name(int type) +{ + switch (type) { + case LDP_SOCKET_DISC: + return ("discovery"); + case LDP_SOCKET_EDISC: + return ("extended discovery"); + case LDP_SOCKET_SESSION: + return ("session"); + default: + return ("UNKNOWN"); + } +} + +const char * +nbr_state_name(int state) +{ + switch (state) { + case NBR_STA_PRESENT: + return ("PRESENT"); + case NBR_STA_INITIAL: + return ("INITIALIZED"); + case NBR_STA_OPENREC: + return ("OPENREC"); + case NBR_STA_OPENSENT: + return ("OPENSENT"); + case NBR_STA_OPER: + return ("OPERATIONAL"); + default: + return ("UNKNOWN"); + } +} + +const char * +if_state_name(int state) +{ + switch (state) { + case IF_STA_DOWN: + return ("DOWN"); + case IF_STA_ACTIVE: + return ("ACTIVE"); + default: + return ("UNKNOWN"); + } +} + +const char * +if_type_name(enum iface_type type) +{ + switch (type) { + case IF_TYPE_POINTOPOINT: + return ("POINTOPOINT"); + case IF_TYPE_BROADCAST: + return ("BROADCAST"); + } + /* NOTREACHED */ + return ("UNKNOWN"); +} + +const char * +msg_name(uint16_t msg) +{ + static char buf[16]; + + switch (msg) { + case MSG_TYPE_NOTIFICATION: + return ("notification"); + case MSG_TYPE_HELLO: + return ("hello"); + case MSG_TYPE_INIT: + return ("initialization"); + case MSG_TYPE_KEEPALIVE: + return ("keepalive"); + case MSG_TYPE_CAPABILITY: + return ("capability"); + case MSG_TYPE_ADDR: + return ("address"); + case MSG_TYPE_ADDRWITHDRAW: + return ("address withdraw"); + case MSG_TYPE_LABELMAPPING: + return ("label mapping"); + case MSG_TYPE_LABELREQUEST: + return ("label request"); + case MSG_TYPE_LABELWITHDRAW: + return ("label withdraw"); + case MSG_TYPE_LABELRELEASE: + return ("label release"); + case MSG_TYPE_LABELABORTREQ: + default: + snprintf(buf, sizeof(buf), "[%08x]", msg); + return (buf); + } +} + +const char * +status_code_name(uint32_t status) +{ + static char buf[16]; + + switch (status) { + case S_SUCCESS: + return ("Success"); + case S_BAD_LDP_ID: + return ("Bad LDP Identifier"); + case S_BAD_PROTO_VER: + return ("Bad Protocol Version"); + case S_BAD_PDU_LEN: + return ("Bad PDU Length"); + case S_UNKNOWN_MSG: + return ("Unknown Message Type"); + case S_BAD_MSG_LEN: + return ("Bad Message Length"); + case S_UNKNOWN_TLV: + return ("Unknown TLV"); + case S_BAD_TLV_LEN: + return ("Bad TLV Length"); + case S_BAD_TLV_VAL: + return ("Malformed TLV Value"); + case S_HOLDTIME_EXP: + return ("Hold Timer Expired"); + case S_SHUTDOWN: + return ("Shutdown"); + case S_LOOP_DETECTED: + return ("Loop Detected"); + case S_UNKNOWN_FEC: + return ("Unknown FEC"); + case S_NO_ROUTE: + return ("No Route"); + case S_NO_LABEL_RES: + return ("No Label Resources"); + case S_AVAILABLE: + return ("Label Resources Available"); + case S_NO_HELLO: + return ("Session Rejected, No Hello"); + case S_PARM_ADV_MODE: + return ("Rejected Advertisement Mode Parameter"); + case S_MAX_PDU_LEN: + return ("Rejected Max PDU Length Parameter"); + case S_PARM_L_RANGE: + return ("Rejected Label Range Parameter"); + case S_KEEPALIVE_TMR: + return ("KeepAlive Timer Expired"); + case S_LAB_REQ_ABRT: + return ("Label Request Aborted"); + case S_MISS_MSG: + return ("Missing Message Parameters"); + case S_UNSUP_ADDR: + return ("Unsupported Address Family"); + case S_KEEPALIVE_BAD: + return ("Bad KeepAlive Time"); + case S_INTERN_ERR: + return ("Internal Error"); + case S_ILLEGAL_CBIT: + return ("Illegal C-Bit"); + case S_WRONG_CBIT: + return ("Wrong C-Bit"); + case S_INCPT_BITRATE: + return ("Incompatible bit-rate"); + case S_CEP_MISCONF: + return ("CEP-TDM mis-configuration"); + case S_PW_STATUS: + return ("PW Status"); + case S_UNASSIGN_TAI: + return ("Unassigned/Unrecognized TAI"); + case S_MISCONF_ERR: + return ("Generic Misconfiguration Error"); + case S_WITHDRAW_MTHD: + return ("Label Withdraw PW Status Method"); + case S_UNSSUPORTDCAP: + return ("Unsupported Capability"); + case S_ENDOFLIB: + return ("End-of-LIB"); + case S_TRANS_MISMTCH: + return ("Transport Connection Mismatch"); + case S_DS_NONCMPLNCE: + return ("Dual-Stack Noncompliance"); + default: + snprintf(buf, sizeof(buf), "[%08x]", status); + return (buf); + } +} + +const char * +pw_type_name(uint16_t pw_type) +{ + static char buf[64]; + + switch (pw_type) { + case PW_TYPE_ETHERNET_TAGGED: + return ("Eth Tagged"); + case PW_TYPE_ETHERNET: + return ("Ethernet"); + case PW_TYPE_WILDCARD: + return ("Wildcard"); + default: + snprintf(buf, sizeof(buf), "[%0x]", pw_type); + return (buf); + } +} From 9785dbcbca1a09806217e20b033a71789a89623b Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 18 Apr 2017 12:14:15 -0300 Subject: [PATCH 16/34] ldpd: fix log level of log_warn() and log_warnx() The log_warn() and log_warnx() functions indicate non-critical warnings and errors, so use LOG_ERR instead of LOG_CRIT. Keep using LOG_CRIT only in fatal() and fatalx() since these functions indicate critical errors (when the program needs to exit). Signed-off-by: Renato Westphal --- ldpd/log.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ldpd/log.c b/ldpd/log.c index 408aaeb699..fc8c995ba3 100644 --- a/ldpd/log.c +++ b/ldpd/log.c @@ -66,16 +66,16 @@ log_warn(const char *emsg, ...) /* best effort to even work in out of memory situations */ if (emsg == NULL) - logit(LOG_CRIT, "%s", strerror(errno)); + logit(LOG_ERR, "%s", strerror(errno)); else { va_start(ap, emsg); if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) { /* we tried it... */ - vlog(LOG_CRIT, emsg, ap); - logit(LOG_CRIT, "%s", strerror(errno)); + vlog(LOG_ERR, emsg, ap); + logit(LOG_ERR, "%s", strerror(errno)); } else { - vlog(LOG_CRIT, nfmt, ap); + vlog(LOG_ERR, nfmt, ap); free(nfmt); } va_end(ap); @@ -88,7 +88,7 @@ log_warnx(const char *emsg, ...) va_list ap; va_start(ap, emsg); - vlog(LOG_CRIT, emsg, ap); + vlog(LOG_ERR, emsg, ap); va_end(ap); } From e0d7c8996d6fe3bc39a1b9fd0310f17ff272ec1a Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 18 Apr 2017 12:17:30 -0300 Subject: [PATCH 17/34] ldpd: call openzlog() in the child processes as well Signed-off-by: Renato Westphal --- ldpd/ldpd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 8da830ccef..5fbdf52ec2 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -282,14 +282,14 @@ main(int argc, char *argv[]) exit(1); } + openzlog(ldpd_di.progname, "LDP", 0, + LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); + if (lflag) lde(user, group, instance); else if (eflag) ldpe(user, group, ctl_sock_path); - openzlog(ldpd_di.progname, "LDP", 0, - LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1) fatal("socketpair"); if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, From e75f810c2f6d3322e981c3e50f7d87f181005461 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Tue, 18 Apr 2017 22:03:35 -0300 Subject: [PATCH 18/34] ldpd: simplify initialization of the child processes In order to have separate ASLR/cookies per process, ldpd calls exec() in the child processes after fork() (this is also known as the fork+exec model). This is an important security feature but it makes the initialization of the child processes a bit more complicated as they're not a copy of the parent anymore, so all parameters given via command line are lost. To solve this problem, we were creating an argv array by hand with all necessary parameters and providing it to the exec() syscall. This works but it's a very ugly solution. This patch introduces a different approach to solve the problem: send an IMSG_INIT message to the child processes with all parameters they need in order to initialize properly. This makes adding additional initialization parameters much more convenient and less error prone. Signed-off-by: Renato Westphal Conflicts: ldpd/ldpd.c ldpd/ldpd.h --- ldpd/control.c | 18 +++++------ ldpd/control.h | 4 +-- ldpd/lde.c | 60 ++++++++++++++++++++-------------- ldpd/lde.h | 3 +- ldpd/ldpd.c | 65 ++++++++++--------------------------- ldpd/ldpd.h | 13 ++++++-- ldpd/ldpe.c | 88 ++++++++++++++++++++++++++++---------------------- ldpd/ldpe.h | 3 +- 8 files changed, 127 insertions(+), 127 deletions(-) diff --git a/ldpd/control.c b/ldpd/control.c index 5c530e1b70..d40e0342c1 100644 --- a/ldpd/control.c +++ b/ldpd/control.c @@ -37,7 +37,7 @@ struct ctl_conns ctl_conns; static int control_fd; int -control_init(void) +control_init(char *path) { struct sockaddr_un s_un; int fd; @@ -51,28 +51,28 @@ control_init(void) memset(&s_un, 0, sizeof(s_un)); s_un.sun_family = AF_UNIX; - strlcpy(s_un.sun_path, ctl_sock_path, sizeof(s_un.sun_path)); + strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)); - if (unlink(ctl_sock_path) == -1) + if (unlink(path) == -1) if (errno != ENOENT) { - log_warn("%s: unlink %s", __func__, ctl_sock_path); + log_warn("%s: unlink %s", __func__, path); close(fd); return (-1); } old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); if (bind(fd, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) { - log_warn("%s: bind: %s", __func__, ctl_sock_path); + log_warn("%s: bind: %s", __func__, path); close(fd); umask(old_umask); return (-1); } umask(old_umask); - if (chmod(ctl_sock_path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) { + if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) { log_warn("%s: chmod", __func__); close(fd); - (void)unlink(ctl_sock_path); + (void)unlink(path); return (-1); } @@ -93,11 +93,11 @@ control_listen(void) } void -control_cleanup(void) +control_cleanup(char *path) { accept_del(control_fd); close(control_fd); - unlink(ctl_sock_path); + unlink(path); } /* ARGSUSED */ diff --git a/ldpd/control.h b/ldpd/control.h index 32c49fdf87..0e66a1636a 100644 --- a/ldpd/control.h +++ b/ldpd/control.h @@ -29,9 +29,9 @@ TAILQ_HEAD(ctl_conns, ctl_conn); extern struct ctl_conns ctl_conns; -int control_init(void); +int control_init(char *); int control_listen(void); -void control_cleanup(void); +void control_cleanup(char *); int control_imsg_relay(struct imsg *); #endif /* _CONTROL_H_ */ diff --git a/ldpd/lde.c b/ldpd/lde.c index c4a610b6d3..ed8274bec7 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -152,12 +152,9 @@ zclient_sync_init(u_short instance) /* label decision engine */ void -lde(const char *user, const char *group, u_short instance) +lde(void) { struct thread thread; - struct timeval now; - - ldeconf = config_new_empty(); #ifdef HAVE_SETPROCTITLE setproctitle("label decision engine"); @@ -165,18 +162,6 @@ lde(const char *user, const char *group, u_short instance) ldpd_process = PROC_LDE_ENGINE; log_procname = log_procnames[PROC_LDE_ENGINE]; - /* drop privileges */ - if (user) - lde_privs.user = user; - if (group) - lde_privs.group = group; - zprivs_init(&lde_privs); - -#ifdef HAVE_PLEDGE - if (pledge("stdio recvfd unix", NULL) == -1) - fatal("pledge"); -#endif - master = thread_master_create(); /* setup signal handler */ @@ -195,21 +180,38 @@ lde(const char *user, const char *group, u_short instance) fatal(NULL); imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC); - /* start the LIB garbage collector */ - lde_gc_start_timer(); - - gettimeofday(&now, NULL); - global.uptime = now.tv_sec; - - /* Init synchronous zclient and label list */ - zclient_sync_init(instance); - lde_label_list_init(); + /* create base configuration */ + ldeconf = config_new_empty(); /* Fetch next active thread. */ while (thread_fetch(master, &thread)) thread_call(&thread); } +void +lde_init(struct ldpd_init *init) +{ + /* drop privileges */ + if (init->user) + lde_privs.user = init->user; + if (init->group) + lde_privs.group = init->group; + zprivs_init(&lde_privs); + +#ifdef HAVE_PLEDGE + if (pledge("stdio recvfd unix", NULL) == -1) + fatal("pledge"); +#endif + + /* start the LIB garbage collector */ + lde_gc_start_timer(); + + /* Init synchronous zclient and label list */ + zclient_serv_path_set(init->zclient_serv_path); + zclient_sync_init(init->instance); + lde_label_list_init(); +} + static void lde_shutdown(void) { @@ -553,6 +555,14 @@ lde_dispatch_parent(struct thread *thread) iev_ldpe->handler_write = ldp_write_handler; iev_ldpe->ev_write = NULL; break; + case IMSG_INIT: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct ldpd_init)) + fatalx("INIT imsg with wrong len"); + + memcpy(&init, imsg.data, sizeof(init)); + lde_init(&init); + break; case IMSG_RECONF_CONF: if ((nconf = malloc(sizeof(struct ldpd_conf))) == NULL) diff --git a/ldpd/lde.h b/ldpd/lde.h index 57791cd1b0..3349d4ca00 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -139,7 +139,8 @@ extern struct nbr_tree lde_nbrs; extern struct thread *gc_timer; /* lde.c */ -void lde(const char *, const char *, u_short instance); +void lde(void); +void lde_init(struct ldpd_init *); int lde_imsg_compose_parent(int, pid_t, void *, uint16_t); int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t); int lde_acl_check(char *, int, union ldpd_addr *, uint8_t); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 5fbdf52ec2..bdf7097323 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -44,8 +44,7 @@ #include "libfrr.h" static void ldpd_shutdown(void); -static pid_t start_child(enum ldpd_process, char *, int, int, - const char *, const char *, const char *, const char *); +static pid_t start_child(enum ldpd_process, char *, int, int); static int main_dispatch_ldpe(struct thread *); static int main_dispatch_lde(struct thread *); static int main_imsg_send_ipc_sockets(struct imsgbuf *, @@ -77,6 +76,7 @@ DEFINE_QOBJ_TYPE(l2vpn) DEFINE_QOBJ_TYPE(ldpd_conf) struct ldpd_global global; +struct ldpd_init init; struct ldpd_conf *ldpd_conf, *vty_conf; static struct imsgev *iev_ldpe, *iev_ldpe_sync; @@ -200,12 +200,7 @@ main(int argc, char *argv[]) int lflag = 0, eflag = 0; int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2]; int pipe_parent2lde[2], pipe_parent2lde_sync[2]; - char *ctl_sock_custom_path = NULL; char *ctl_sock_name; - const char *user = NULL; - const char *group = NULL; - u_short instance = 0; - const char *instance_char = NULL; ldpd_process = PROC_MAIN; log_procname = log_procnames[ldpd_process]; @@ -242,17 +237,14 @@ main(int argc, char *argv[]) * sensible config */ ctl_sock_name = (char *)LDPD_SOCKET; - ctl_sock_custom_path = optarg; - strlcpy(ctl_sock_path, ctl_sock_custom_path, - sizeof(ctl_sock_path)); + strlcpy(ctl_sock_path, optarg, sizeof(ctl_sock_path)); strlcat(ctl_sock_path, "/", sizeof(ctl_sock_path)); strlcat(ctl_sock_path, ctl_sock_name, sizeof(ctl_sock_path)); break; case 'n': - instance = atoi(optarg); - instance_char = optarg; - if (instance < 1) + init.instance = atoi(optarg); + if (init.instance < 1) exit(0); break; case 'L': @@ -267,8 +259,11 @@ main(int argc, char *argv[]) } } - user = ldpd_privs.user; - group = ldpd_privs.group; + strlcpy(init.user, ldpd_privs.user, sizeof(init.user)); + strlcpy(init.group, ldpd_privs.group, sizeof(init.group)); + strlcpy(init.ctl_sock_path, ctl_sock_path, sizeof(init.ctl_sock_path)); + strlcpy(init.zclient_serv_path, zclient_serv_path_get(), + sizeof(init.zclient_serv_path)); argc -= optind; argv += optind; @@ -286,9 +281,9 @@ main(int argc, char *argv[]) LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); if (lflag) - lde(user, group, instance); + lde(); else if (eflag) - ldpe(user, group, ctl_sock_path); + ldpe(); if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1) fatal("socketpair"); @@ -317,11 +312,9 @@ main(int argc, char *argv[]) /* start children */ lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0, - pipe_parent2lde[1], pipe_parent2lde_sync[1], - user, group, ctl_sock_custom_path, instance_char); + pipe_parent2lde[1], pipe_parent2lde_sync[1]); ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0, - pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1], - user, group, ctl_sock_custom_path, instance_char); + pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1]); /* drop privileges */ zprivs_init(&ldpd_privs); @@ -389,6 +382,7 @@ main(int argc, char *argv[]) if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf)) fatal("could not establish imsg links"); + main_imsg_compose_both(IMSG_INIT, &init, sizeof(init)); main_imsg_compose_both(IMSG_DEBUG_UPDATE, &ldp_debug, sizeof(ldp_debug)); main_imsg_send_config(ldpd_conf); @@ -453,11 +447,9 @@ ldpd_shutdown(void) } static pid_t -start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync, - const char *user, const char *group, const char *ctl_sock_custom_path, - const char *instance) +start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync) { - char *argv[13]; + char *argv[3]; int argc = 0; pid_t pid; @@ -488,29 +480,6 @@ start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync, argv[argc++] = (char *)"-E"; break; } - if (user) { - argv[argc++] = (char *)"-u"; - argv[argc++] = (char *)user; - } - if (group) { - argv[argc++] = (char *)"-g"; - argv[argc++] = (char *)group; - } - if (ctl_sock_custom_path) { - argv[argc++] = (char *)"--ctl_socket"; - argv[argc++] = (char *)ctl_sock_custom_path; - } - /* zclient serv path */ -#ifdef HAVE_TCP_ZEBRA -#else - argv[argc++] = (char *)"-z"; - argv[argc++] = (char *)zclient_serv_path_get(); -#endif - /* instance */ - if (instance) { - argv[argc++] = (char *)"-n"; - argv[argc++] = (char *)instance; - } argv[argc++] = NULL; execvp(argv0, argv); diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 759f1d0da5..97239ed08e 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -147,7 +147,16 @@ enum imsg_type { IMSG_LOG, IMSG_ACL_CHECK, IMSG_GET_LABEL_CHUNK, - IMSG_RELEASE_LABEL_CHUNK + IMSG_RELEASE_LABEL_CHUNK, + IMSG_INIT +}; + +struct ldpd_init { + char user[256]; + char group[256]; + char ctl_sock_path[MAXPATHLEN]; + char zclient_serv_path[MAXPATHLEN]; + u_short instance; }; union ldpd_addr { @@ -510,7 +519,6 @@ struct ldpd_af_global { struct ldpd_global { int cmd_opts; int sighup; - time_t uptime; struct in_addr rtr_id; struct ldpd_af_global ipv4; struct ldpd_af_global ipv6; @@ -655,6 +663,7 @@ struct ctl_pw { extern struct ldpd_conf *ldpd_conf, *vty_conf; extern struct ldpd_global global; +extern struct ldpd_init init; /* parse.y */ struct ldpd_conf *parse_config(char *); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index e82416276b..1248d4f86e 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -103,47 +103,17 @@ static struct quagga_signal_t ldpe_signals[] = /* label distribution protocol engine */ void -ldpe(const char *user, const char *group, const char *ctl_path) +ldpe(void) { struct thread thread; - leconf = config_new_empty(); - #ifdef HAVE_SETPROCTITLE setproctitle("ldp engine"); #endif ldpd_process = PROC_LDP_ENGINE; log_procname = log_procnames[ldpd_process]; - LIST_INIT(&global.addr_list); - RB_INIT(&global.adj_tree); - TAILQ_INIT(&global.pending_conns); - if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1) - fatal("inet_pton"); - if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1) - fatal("inet_pton"); -#ifdef __OpenBSD__ - global.pfkeysock = pfkey_init(); -#endif - - /* drop privileges */ - if (user) - ldpe_privs.user = user; - if (group) - ldpe_privs.group = group; - zprivs_init(&ldpe_privs); - - strlcpy(ctl_sock_path, ctl_path, sizeof(ctl_sock_path)); - if (control_init() == -1) - fatalx("control socket setup failed"); - -#ifdef HAVE_PLEDGE - if (pledge("stdio cpath inet mcast recvfd", NULL) == -1) - fatal("pledge"); -#endif - master = thread_master_create(); - accept_init(); /* setup signal handler */ signal_init(master, array_size(ldpe_signals), ldpe_signals); @@ -161,7 +131,45 @@ ldpe(const char *user, const char *group, const char *ctl_path) fatal(NULL); imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC); + /* create base configuration */ + leconf = config_new_empty(); + + /* Fetch next active thread. */ + while (thread_fetch(master, &thread)) + thread_call(&thread); +} + +void +ldpe_init(struct ldpd_init *init) +{ + /* drop privileges */ + if (init->user) + ldpe_privs.user = init->user; + if (init->group) + ldpe_privs.group = init->group; + zprivs_init(&ldpe_privs); + + /* listen on ldpd control socket */ + strlcpy(ctl_sock_path, init->ctl_sock_path, sizeof(ctl_sock_path)); + if (control_init(ctl_sock_path) == -1) + fatalx("control socket setup failed"); + TAILQ_INIT(&ctl_conns); + control_listen(); + +#ifdef HAVE_PLEDGE + if (pledge("stdio cpath inet mcast recvfd", NULL) == -1) + fatal("pledge"); +#endif + + LIST_INIT(&global.addr_list); + RB_INIT(&global.adj_tree); + TAILQ_INIT(&global.pending_conns); + if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1) + fatal("inet_pton"); + if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1) + fatal("inet_pton"); #ifdef __OpenBSD__ + global.pfkeysock = pfkey_init(); if (sysdep.no_pfkey == 0) pfkey_ev = thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock); @@ -175,16 +183,10 @@ ldpe(const char *user, const char *group, const char *ctl_path) global.ipv6.ldp_edisc_socket = -1; global.ipv6.ldp_session_socket = -1; - /* listen on ldpd control socket */ - TAILQ_INIT(&ctl_conns); - control_listen(); - if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL) fatal(__func__); - /* Fetch next active thread. */ - while (thread_fetch(master, &thread)) - thread_call(&thread); + accept_init(); } static void @@ -203,7 +205,7 @@ ldpe_shutdown(void) msgbuf_clear(&iev_main_sync->ibuf.w); close(iev_main_sync->ibuf.fd); - control_cleanup(); + control_cleanup(ctl_sock_path); config_clear(leconf); #ifdef __OpenBSD__ @@ -352,6 +354,14 @@ ldpe_dispatch_main(struct thread *thread) iev_lde->handler_write = ldp_write_handler; iev_lde->ev_write = NULL; break; + case IMSG_INIT: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct ldpd_init)) + fatalx("INIT imsg with wrong len"); + + memcpy(&init, imsg.data, sizeof(init)); + ldpe_init(&init); + break; case IMSG_CLOSE_SOCKETS: af = imsg.hdr.peerid; diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index a3f41a8b9f..2c1ba46c6b 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -195,7 +195,8 @@ int tlv_decode_fec_elm(struct nbr *, struct ldp_msg *, char *, uint16_t, struct map *); /* ldpe.c */ -void ldpe(const char *, const char *, const char *); +void ldpe(void); +void ldpe_init(struct ldpd_init *); int ldpe_imsg_compose_parent(int, pid_t, void *, uint16_t); int ldpe_imsg_compose_lde(int, uint32_t, pid_t, void *, From b3121cd7d14f28cad53d39d9fbf09b036d3e95c9 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 19 Apr 2017 15:15:56 -0300 Subject: [PATCH 19/34] ldpd: fix segfault after failed initialization When ldpd fails to start for some reason, like failing to create a pid file, the child processes call their shutdown functions without being completely initialized. This patch adds some protections to prevent a segmentation fault on such circumstances. Signed-off-by: Renato Westphal --- ldpd/lde.c | 9 ++++++--- ldpd/ldpe.c | 11 +++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ldpd/lde.c b/ldpd/lde.c index ed8274bec7..3dfcd8f885 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -216,8 +216,10 @@ static void lde_shutdown(void) { /* close pipes */ - msgbuf_clear(&iev_ldpe->ibuf.w); - close(iev_ldpe->ibuf.fd); + if (iev_ldpe) { + msgbuf_clear(&iev_ldpe->ibuf.w); + close(iev_ldpe->ibuf.fd); + } msgbuf_clear(&iev_main->ibuf.w); close(iev_main->ibuf.fd); msgbuf_clear(&iev_main_sync->ibuf.w); @@ -229,7 +231,8 @@ lde_shutdown(void) config_clear(ldeconf); - free(iev_ldpe); + if (iev_ldpe) + free(iev_ldpe); free(iev_main); free(iev_main_sync); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 1248d4f86e..bd0f9dbd6f 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -196,9 +196,11 @@ ldpe_shutdown(void) struct adj *adj; /* close pipes */ - msgbuf_write(&iev_lde->ibuf.w); - msgbuf_clear(&iev_lde->ibuf.w); - close(iev_lde->ibuf.fd); + if (iev_lde) { + msgbuf_write(&iev_lde->ibuf.w); + msgbuf_clear(&iev_lde->ibuf.w); + close(iev_lde->ibuf.fd); + } msgbuf_write(&iev_main->ibuf.w); msgbuf_clear(&iev_main->ibuf.w); close(iev_main->ibuf.fd); @@ -226,7 +228,8 @@ ldpe_shutdown(void) adj_del(adj, S_SHUTDOWN); /* clean up */ - free(iev_lde); + if (iev_lde) + free(iev_lde); free(iev_main); free(iev_main_sync); free(pkt_ptr); From 30f35e856608b29c7e4f091c7a22f4a3b4019258 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 19 Apr 2017 15:28:43 -0300 Subject: [PATCH 20/34] ldpd: remove unnecessary checks if a signal was caught Signed-off-by: Renato Westphal --- ldpd/lde.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ldpd/lde.c b/ldpd/lde.c index 3dfcd8f885..426af8dbe8 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -119,13 +119,6 @@ static struct quagga_signal_t lde_signals[] = }, }; -static void -lde_sleep (void) -{ - sleep(1); - if (lde_signals[0].caught || lde_signals[1].caught) - lde_shutdown(); -} struct zclient *zclient_sync = NULL; static void zclient_sync_init(u_short instance) @@ -138,7 +131,7 @@ zclient_sync_init(u_short instance) zclient_sync->instance = instance; while (zclient_socket_connect (zclient_sync) < 0) { fprintf(stderr, "Error connecting synchronous zclient!\n"); - lde_sleep(); + sleep(1); } /* make socket non-blocking */ sock_set_nonblock(zclient_sync->sock); @@ -146,7 +139,7 @@ zclient_sync_init(u_short instance) /* Connect to label manager */ while (lm_label_manager_connect (zclient_sync) != 0) { fprintf(stderr, "Error connecting to label manager!\n"); - lde_sleep(); + sleep(1); } } @@ -1628,7 +1621,7 @@ lde_label_list_init(void) /* get first chunk */ while (lde_get_label_chunk () != 0) { fprintf(stderr, "Error getting first label chunk!\n"); - lde_sleep(); + sleep(1); } } From d8292558bde9802b8267deff44dabb87b12b885f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 19 Apr 2017 16:59:50 -0300 Subject: [PATCH 21/34] ldpd: use synchronous channels for sending log messages This is necessary to guarantee that all log messages sent from the child processes are received in the parent process right away. Without this patch, when a child process calls fatal() or fatalx(), the log messages don't make it to the parent because the child doesn't have a chance to flush its buffers before exiting. Signed-off-by: Renato Westphal --- ldpd/lde.c | 13 ++++++++++--- ldpd/lde.h | 1 + ldpd/ldpe.c | 7 +++++++ ldpd/ldpe.h | 1 + ldpd/log.c | 6 ++++-- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/ldpd/lde.c b/ldpd/lde.c index 426af8dbe8..1c7458ce73 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -130,7 +130,7 @@ zclient_sync_init(u_short instance) zclient_sync->redist_default = ZEBRA_ROUTE_LDP; zclient_sync->instance = instance; while (zclient_socket_connect (zclient_sync) < 0) { - fprintf(stderr, "Error connecting synchronous zclient!\n"); + log_warnx("Error connecting synchronous zclient!"); sleep(1); } /* make socket non-blocking */ @@ -138,7 +138,7 @@ zclient_sync_init(u_short instance) /* Connect to label manager */ while (lm_label_manager_connect (zclient_sync) != 0) { - fprintf(stderr, "Error connecting to label manager!\n"); + log_warnx("Error connecting to label manager!"); sleep(1); } } @@ -240,6 +240,13 @@ lde_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen) return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); } +void +lde_imsg_compose_parent_sync(int type, pid_t pid, void *data, uint16_t datalen) +{ + imsg_compose_event(iev_main_sync, type, 0, pid, -1, data, datalen); + imsg_flush(&iev_main_sync->ibuf); +} + int lde_imsg_compose_ldpe(int type, uint32_t peerid, pid_t pid, void *data, uint16_t datalen) @@ -1620,7 +1627,7 @@ lde_label_list_init(void) /* get first chunk */ while (lde_get_label_chunk () != 0) { - fprintf(stderr, "Error getting first label chunk!\n"); + log_warnx("Error getting first label chunk!"); sleep(1); } } diff --git a/ldpd/lde.h b/ldpd/lde.h index 3349d4ca00..c1d66f9fff 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -142,6 +142,7 @@ extern struct thread *gc_timer; void lde(void); void lde_init(struct ldpd_init *); int lde_imsg_compose_parent(int, pid_t, void *, uint16_t); +void lde_imsg_compose_parent_sync(int, pid_t, void *, uint16_t); int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t); int lde_acl_check(char *, int, union ldpd_addr *, uint8_t); uint32_t lde_update_label(struct fec_node *); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index bd0f9dbd6f..20cc9f7444 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -245,6 +245,13 @@ ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen) return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); } +void +ldpe_imsg_compose_parent_sync(int type, pid_t pid, void *data, uint16_t datalen) +{ + imsg_compose_event(iev_main_sync, type, 0, pid, -1, data, datalen); + imsg_flush(&iev_main_sync->ibuf); +} + int ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data, uint16_t datalen) diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index 2c1ba46c6b..d34ca4dc24 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -199,6 +199,7 @@ void ldpe(void); void ldpe_init(struct ldpd_init *); int ldpe_imsg_compose_parent(int, pid_t, void *, uint16_t); +void ldpe_imsg_compose_parent_sync(int, pid_t, void *, uint16_t); int ldpe_imsg_compose_lde(int, uint32_t, pid_t, void *, uint16_t); int ldpe_acl_check(char *, int, union ldpd_addr *, uint8_t); diff --git a/ldpd/log.c b/ldpd/log.c index fc8c995ba3..b138e5754a 100644 --- a/ldpd/log.c +++ b/ldpd/log.c @@ -46,11 +46,13 @@ vlog(int pri, const char *fmt, va_list ap) switch (ldpd_process) { case PROC_LDE_ENGINE: vsnprintf(buf, sizeof(buf), fmt, ap); - lde_imsg_compose_parent(IMSG_LOG, pri, buf, strlen(buf) + 1); + lde_imsg_compose_parent_sync(IMSG_LOG, pri, buf, + strlen(buf) + 1); break; case PROC_LDP_ENGINE: vsnprintf(buf, sizeof(buf), fmt, ap); - ldpe_imsg_compose_parent(IMSG_LOG, pri, buf, strlen(buf) + 1); + ldpe_imsg_compose_parent_sync(IMSG_LOG, pri, buf, + strlen(buf) + 1); break; case PROC_MAIN: vzlog(pri, fmt, ap); From 3dcdcbb478d760208e7d82241bbdc359e9479475 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 19 Apr 2017 17:12:35 -0300 Subject: [PATCH 22/34] ldpd: minor changes in the output of some show commands Signed-off-by: Renato Westphal --- ldpd/ldp_vty_exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c index a149b7fe35..ffd20abb4a 100644 --- a/ldpd/ldp_vty_exec.c +++ b/ldpd/ldp_vty_exec.c @@ -517,8 +517,7 @@ show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_params *params) nbr_state_name(nbr->nbr_state), addr); if (strlen(addr) > 15) vty_out(vty, "%s%48s", VTY_NEWLINE, " "); - vty_out(vty, " %8s%s", nbr->uptime == 0 ? "-" : - log_time(nbr->uptime), VTY_NEWLINE); + vty_out(vty, " %8s%s", log_time(nbr->uptime), VTY_NEWLINE); break; case IMSG_CTL_END: return (1); @@ -909,6 +908,7 @@ show_nbr_capabilities_msg(struct vty *vty, struct imsg *imsg, struct show_params vty_out(vty, "Peer LDP Identifier: %s:0%s", inet_ntoa(nbr->id), VTY_NEWLINE); show_nbr_capabilities(vty, nbr); + vty_out(vty, "%s", VTY_NEWLINE); break; case IMSG_CTL_END: vty_out(vty, "%s", VTY_NEWLINE); From 9b2868bc019b15a878b3b08d165194b8c00b0e63 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 19 Apr 2017 19:31:19 -0300 Subject: [PATCH 23/34] ldpd: accept notifications during the session establishment process If we don't do this, we'll never trigger the backoff exponential timer since it's impossible to distinguish between Initialization NAK's and general errors. Also: * Implement some missing bits from RFC 5036; * remove superfluous log message in session_shutdown() (send_notification() logs that we're sending a fatal notification). Regression introduced by commit 8819fc3. Fixes the following ANVL LDP regressions: 6.19 and 6.21. Signed-off-by: Renato Westphal --- ldpd/notification.c | 10 ++++++++++ ldpd/packet.c | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ldpd/notification.c b/ldpd/notification.c index f10faa4a54..4a5f3c8fa4 100644 --- a/ldpd/notification.c +++ b/ldpd/notification.c @@ -237,6 +237,16 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len) if (nbr->state == NBR_STA_OPENSENT) nbr_start_idtimer(nbr); + /* + * RFC 5036 - Section 3.5.1.1: + * "When an LSR receives a Shutdown message during session + * initialization, it SHOULD transmit a Shutdown message and + * then close the transport connection". + */ + if (nbr->state != NBR_STA_OPER && nm.status_code == S_SHUTDOWN) + send_notification(nbr->tcp, S_SHUTDOWN, + msg.id, msg.type); + nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); return (-1); } diff --git a/ldpd/packet.c b/ldpd/packet.c index 46893b992b..75e1a9a027 100644 --- a/ldpd/packet.c +++ b/ldpd/packet.c @@ -519,6 +519,8 @@ session_read(struct thread *thread) return (0); } break; + case MSG_TYPE_NOTIFICATION: + break; default: if (nbr->state != NBR_STA_OPER) { session_shutdown(nbr, S_SHUTDOWN, @@ -661,8 +663,6 @@ session_shutdown(struct nbr *nbr, uint32_t status, uint32_t msg_id, case NBR_STA_OPENREC: case NBR_STA_OPENSENT: case NBR_STA_OPER: - log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); - send_notification(nbr->tcp, status, msg_id, msg_type); nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); From a8e8b867974cfbc37aeabe34b067f10448690bd2 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 21 Apr 2017 15:41:14 -0300 Subject: [PATCH 24/34] ldpd: be more conservative with labels On unstable networks, routes can be lost and relearned very often. If we deallocate the input label every time a route is lost and allocate a new one when the route is relearned, a lot of changes are made in vain. This patch introduces a logic in which labels are preserved for at least five minutes before being deallocated by the LIB garbage collector. This is consistent with what other implementations do. Signed-off-by: Renato Westphal --- ldpd/lde_lib.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index db2682a173..b074bf3498 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -383,20 +383,23 @@ lde_kernel_update(struct fec *fec) if (LIST_EMPTY(&fn->nexthops)) { RB_FOREACH(ln, nbr_tree, &lde_nbrs) lde_send_labelwithdraw(ln, fn, NULL, NULL); - fn->local_label = NO_LABEL; fn->data = NULL; + + /* + * Do not deallocate the local label now, do that only in the + * LIB garbage collector. This will prevent ldpd from changing + * the input label of some prefixes too often when running on + * an unstable network. Also, restart the garbage collector + * timer so that labels are deallocated only when the network + * is stabilized. + */ + lde_gc_start_timer(); } else { - uint32_t previous_label; - - previous_label = fn->local_label; fn->local_label = lde_update_label(fn); - - if (fn->local_label != NO_LABEL && - fn->local_label != previous_label) { + if (fn->local_label != NO_LABEL && RB_EMPTY(&fn->upstream)) /* FEC.1: perform lsr label distribution procedure */ RB_FOREACH(ln, nbr_tree, &lde_nbrs) lde_send_labelmapping(ln, fn, 1); - } } LIST_FOREACH(fnh, &fn->nexthops, entry) { From 79f62ef746f4cc6e1f9c233a4f1afab86d928d46 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 21 Apr 2017 19:39:11 -0300 Subject: [PATCH 25/34] ldpd: improve ldp_zebra_read_route() Log deleted routes and simplify the code a bit. Signed-off-by: Renato Westphal --- ldpd/ldp_zebra.c | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index fde6e56c64..3320238a05 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -360,6 +360,7 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, struct kroute kr; int nhnum = 0, nhlen; size_t nhmark; + int add = 0; memset(&kr, 0, sizeof(kr)); s = zclient->ibuf; @@ -426,21 +427,14 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, if (CHECK_FLAG(message_flags, ZAPI_MESSAGE_NEXTHOP)) stream_set_getp(s, nhmark); - if (nhnum == 0) { - switch (command) { - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - return (0); - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - case ZEBRA_REDISTRIBUTE_IPV6_DEL: - debug_zebra_in("route delete %s/%d (%s)", - log_addr(kr.af, &kr.prefix), kr.prefixlen, - zebra_route_string(type)); - break; - default: - fatalx("ldp_zebra_read_route: unknown command"); - } - } + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD || + command == ZEBRA_REDISTRIBUTE_IPV6_ADD) + add = 1; + + if (nhnum == 0) + debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete", + log_addr(kr.af, &kr.prefix), kr.prefixlen, + zebra_route_string(type)); /* loop through all the nexthops */ for (; nhnum > 0; nhnum--) { @@ -457,19 +451,14 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, stream_getc(s); /* ifindex_num, unused. */ kr.ifindex = stream_getl(s); - switch (command) { - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - case ZEBRA_REDISTRIBUTE_IPV6_ADD: - debug_zebra_in("route add %s/%d nexthop %s " - "ifindex %u (%s)", log_addr(kr.af, &kr.prefix), - kr.prefixlen, log_addr(kr.af, &kr.nexthop), - kr.ifindex, zebra_route_string(type)); + debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)", + (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), + kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex, + zebra_route_string(type)); + + if (add) main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr, sizeof(kr)); - break; - default: - break; - } } main_imsg_compose_lde(IMSG_NETWORK_UPDATE, 0, &kr, sizeof(kr)); From abb160061189c9e4a1a8ab28aea4acbd64c32066 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 21 Apr 2017 22:10:42 -0300 Subject: [PATCH 26/34] ldpd: schedule the sending of label messages when necessary Once we send a Label Withdraw, we can't send a Label Mapping for the same FEC until we receive a Label Release from the peer. This is due to some limitations in the LDP algorithms described in Appendix A. ("LDP Label Distribution Procedures") of RFC 5036. To workaround this issue, make it possible to schedule the sending of a Label Mapping as soon as a Label Release is received for the same FEC. The easiest way to test this patch is by typing the "label local advertise explicit-null" command. ldpd will withdraw all null labels using a Wildcard FEC and then send new Label Mappings as soon the corresponding Label Releases are received. Signed-off-by: Renato Westphal --- ldpd/lde.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- ldpd/lde.h | 3 +++ ldpd/lde_lib.c | 36 ++++++++++++++++++++++++++---------- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/ldpd/lde.c b/ldpd/lde.c index 1c7458ce73..e5d1402832 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -917,10 +917,23 @@ lde_map2fec(struct map *map, struct in_addr lsr_id, struct fec *fec) void lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single) { - struct lde_req *lre; - struct lde_map *me; - struct map map; - struct l2vpn_pw *pw; + struct lde_wdraw *lw; + struct lde_map *me; + struct lde_req *lre; + struct map map; + struct l2vpn_pw *pw; + + /* + * We shouldn't send a new label mapping if we have a pending + * label release to receive. In this case, schedule to send a + * label mapping as soon as a label release is received. + */ + lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec); + if (lw) { + if (!fec_find(&ln->sent_map_pending, &fn->fec)) + lde_map_pending_add(ln, fn); + return; + } /* * This function skips SL.1 - 3 and SL.9 - 14 because the label @@ -1226,6 +1239,7 @@ lde_nbr_new(uint32_t peerid, struct lde_nbr *new) ln->peerid = peerid; fec_init(&ln->recv_map); fec_init(&ln->sent_map); + fec_init(&ln->sent_map_pending); fec_init(&ln->recv_req); fec_init(&ln->sent_req); fec_init(&ln->sent_wdraw); @@ -1281,6 +1295,7 @@ lde_nbr_del(struct lde_nbr *ln) fec_clear(&ln->recv_map, lde_map_free); fec_clear(&ln->sent_map, lde_map_free); + fec_clear(&ln->sent_map_pending, free); fec_clear(&ln->recv_req, free); fec_clear(&ln->sent_req, free); fec_clear(&ln->sent_wdraw, free); @@ -1431,6 +1446,30 @@ lde_map_free(void *ptr) free(map); } +struct fec * +lde_map_pending_add(struct lde_nbr *ln, struct fec_node *fn) +{ + struct fec *map; + + map = calloc(1, sizeof(*map)); + if (map == NULL) + fatal(__func__); + + *map = fn->fec; + if (fec_insert(&ln->sent_map_pending, map)) + log_warnx("failed to add %s to sent map (pending)", + log_fec(map)); + + return (map); +} + +void +lde_map_pending_del(struct lde_nbr *ln, struct fec *map) +{ + fec_remove(&ln->sent_map_pending, map); + free(map); +} + struct lde_req * lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent) { diff --git a/ldpd/lde.h b/ldpd/lde.h index c1d66f9fff..1cce483832 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -95,6 +95,7 @@ struct lde_nbr { struct fec_tree sent_req; struct fec_tree recv_map; struct fec_tree sent_map; + struct fec_tree sent_map_pending; struct fec_tree sent_wdraw; TAILQ_HEAD(, lde_addr) addr_list; }; @@ -171,6 +172,8 @@ struct lde_nbr *lde_nbr_find_by_lsrid(struct in_addr); struct lde_nbr *lde_nbr_find_by_addr(int, union ldpd_addr *); struct lde_map *lde_map_add(struct lde_nbr *, struct fec_node *, int); void lde_map_del(struct lde_nbr *, struct lde_map *, int); +struct fec *lde_map_pending_add(struct lde_nbr *, struct fec_node *); +void lde_map_pending_del(struct lde_nbr *, struct fec *); struct lde_req *lde_req_add(struct lde_nbr *, struct fec *, int); void lde_req_del(struct lde_nbr *, struct lde_req *, int); struct lde_wdraw *lde_wdraw_add(struct lde_nbr *, struct fec_node *); diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index b074bf3498..37a670bc8c 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -662,6 +662,7 @@ lde_check_release(struct map *map, struct lde_nbr *ln) struct fec_node *fn; struct lde_wdraw *lw; struct lde_map *me; + struct fec *pending_map; /* wildcard label release */ if (map->type == MAP_TYPE_WILDCARD || @@ -677,17 +678,24 @@ lde_check_release(struct map *map, struct lde_nbr *ln) if (fn == NULL) return; + /* LRl.6: check sent map list and remove it if available */ + me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec); + if (me && (map->label == NO_LABEL || map->label == me->map.label)) + lde_map_del(ln, me, 1); + /* LRl.3: first check if we have a pending withdraw running */ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec); if (lw && (map->label == NO_LABEL || map->label == lw->label)) { /* LRl.4: delete record of outstanding label withdraw */ lde_wdraw_del(ln, lw); - } - /* LRl.6: check sent map list and remove it if available */ - me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec); - if (me && (map->label == NO_LABEL || map->label == me->map.label)) - lde_map_del(ln, me, 1); + /* send pending label mapping if any */ + pending_map = fec_find(&ln->sent_map_pending, &fn->fec); + if (pending_map) { + lde_send_labelmapping(ln, fn, 1); + lde_map_pending_del(ln, pending_map); + } + } /* * LRl.11 - 13 are unnecessary since we remove the label from @@ -702,6 +710,7 @@ lde_check_release_wcard(struct map *map, struct lde_nbr *ln) struct fec_node *fn; struct lde_wdraw *lw; struct lde_map *me; + struct fec *pending_map; RB_FOREACH(f, fec_tree, &ft) { fn = (struct fec_node *)f; @@ -711,17 +720,24 @@ lde_check_release_wcard(struct map *map, struct lde_nbr *ln) if (lde_wildcard_apply(map, &fn->fec, me) == 0) continue; + /* LRl.6: check sent map list and remove it if available */ + if (me && + (map->label == NO_LABEL || map->label == me->map.label)) + lde_map_del(ln, me, 1); + /* LRl.3: first check if we have a pending withdraw running */ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec); if (lw && (map->label == NO_LABEL || map->label == lw->label)) { /* LRl.4: delete record of outstanding lbl withdraw */ lde_wdraw_del(ln, lw); - } - /* LRl.6: check sent map list and remove it if available */ - if (me && - (map->label == NO_LABEL || map->label == me->map.label)) - lde_map_del(ln, me, 1); + /* send pending label mapping if any */ + pending_map = fec_find(&ln->sent_map_pending, &fn->fec); + if (pending_map) { + lde_send_labelmapping(ln, fn, 1); + lde_map_pending_del(ln, pending_map); + } + } /* * LRl.11 - 13 are unnecessary since we remove the label from From cb7426d40354d69a2705ee01240aef8a211cf3db Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 22 Apr 2017 10:55:27 -0300 Subject: [PATCH 27/34] ldpd: allow targeted neighbors over any interface It's doesn't make sense to enforce that a targeted-hello is received on an LDP-enabled interface. It should be possible, for example, to use LDP only to signal pseudowires and other another protocol (e.g. RSVP-TE) to create end-to-end LSPs. Signed-off-by: Renato Westphal --- ldpd/packet.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ldpd/packet.c b/ldpd/packet.c index 75e1a9a027..df6bd8e57a 100644 --- a/ldpd/packet.c +++ b/ldpd/packet.c @@ -27,7 +27,7 @@ #include "sockopt.h" static struct iface *disc_find_iface(unsigned int, int, - union ldpd_addr *, int); + union ldpd_addr *); static int session_read(struct thread *); static int session_write(struct thread *); static ssize_t session_get_pdu(struct ibuf_read *, char **); @@ -134,7 +134,7 @@ disc_recv_packet(struct thread *thread) int af; union ldpd_addr src; unsigned int ifindex = 0; - struct iface *iface; + struct iface *iface = NULL; uint16_t len; struct ldp_hdr ldp_hdr; uint16_t pdu_len; @@ -212,9 +212,11 @@ disc_recv_packet(struct thread *thread) ifindex = getsockopt_ifindex(af, &m); /* find a matching interface */ - iface = disc_find_iface(ifindex, af, &src, multicast); - if (iface == NULL) - return (0); + if (multicast) { + iface = disc_find_iface(ifindex, af, &src); + if (iface == NULL) + return (0); + } /* check packet size */ len = (uint16_t)r; @@ -280,8 +282,7 @@ disc_recv_packet(struct thread *thread) } static struct iface * -disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src, - int multicast) +disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src) { struct iface *iface; struct iface_af *ia; @@ -299,7 +300,7 @@ disc_find_iface(unsigned int ifindex, int af, union ldpd_addr *src, * "Link-local IPv6 address MUST be used as the source IP address in * IPv6 LDP Link Hellos". */ - if (multicast && af == AF_INET6 && !IN6_IS_ADDR_LINKLOCAL(&src->v6)) + if (af == AF_INET6 && !IN6_IS_ADDR_LINKLOCAL(&src->v6)) return (NULL); return (iface); From 602c726ef2a37597d9cba1f0adafc9bc4fc7e3db Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 22 Apr 2017 12:03:14 -0300 Subject: [PATCH 28/34] ldpd: fix bug when changing the transport address When the transport address is changed, all interfaces and targeted neighbors are temporary disabled in the ldpe process until new sockets bound to the new transport address are received from the parent. This patch fixes a problem in which adjacencies weren't being removed after the associated targeted neighbors were disabled. This was causing ldpd not to set some MD5 sockoptions for new neighbors are thus preventing MD5-protected sessions to come up after a change in the transport-address. Signed-off-by: Renato Westphal --- ldpd/adjacency.c | 31 ++++++++++++++++++++++--------- ldpd/interface.c | 9 +++++---- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/ldpd/adjacency.c b/ldpd/adjacency.c index 8659202ee4..3ec57f1589 100644 --- a/ldpd/adjacency.c +++ b/ldpd/adjacency.c @@ -29,6 +29,8 @@ static __inline int adj_compare(struct adj *, struct adj *); static int adj_itimer(struct thread *); static __inline int tnbr_compare(struct tnbr *, struct tnbr *); static void tnbr_del(struct ldpd_conf *, struct tnbr *); +static void tnbr_start(struct tnbr *); +static void tnbr_stop(struct tnbr *); static int tnbr_hello_timer(struct thread *); static void tnbr_start_hello_timer(struct tnbr *); static void tnbr_stop_hello_timer(struct tnbr *); @@ -245,9 +247,7 @@ tnbr_new(int af, union ldpd_addr *addr) static void tnbr_del(struct ldpd_conf *xconf, struct tnbr *tnbr) { - tnbr_stop_hello_timer(tnbr); - if (tnbr->adj) - adj_del(tnbr->adj, S_SHUTDOWN); + tnbr_stop(tnbr); RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr); free(tnbr); } @@ -273,6 +273,23 @@ tnbr_check(struct ldpd_conf *xconf, struct tnbr *tnbr) return (tnbr); } +static void +tnbr_start(struct tnbr *tnbr) +{ + send_hello(HELLO_TARGETED, NULL, tnbr); + tnbr_start_hello_timer(tnbr); + tnbr->state = TNBR_STA_ACTIVE; +} + +static void +tnbr_stop(struct tnbr *tnbr) +{ + tnbr_stop_hello_timer(tnbr); + if (tnbr->adj) + adj_del(tnbr->adj, S_SHUTDOWN); + tnbr->state = TNBR_STA_DOWN; +} + void tnbr_update(struct tnbr *tnbr) { @@ -292,16 +309,12 @@ tnbr_update(struct tnbr *tnbr) if (!socket_ok || !rtr_id_ok) return; - tnbr->state = TNBR_STA_ACTIVE; - send_hello(HELLO_TARGETED, NULL, tnbr); - - tnbr_start_hello_timer(tnbr); + tnbr_start(tnbr); } else if (tnbr->state == TNBR_STA_ACTIVE) { if (socket_ok && rtr_id_ok) return; - tnbr->state = TNBR_STA_DOWN; - tnbr_stop_hello_timer(tnbr); + tnbr_stop(tnbr); } } diff --git a/ldpd/interface.c b/ldpd/interface.c index 7be8be755e..440bb2dca0 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -287,8 +287,9 @@ if_start(struct iface *iface, int af) } send_hello(HELLO_LINK, ia, NULL); - if_start_hello_timer(ia); + ia->state = IF_STA_ACTIVE; + return (0); } @@ -318,9 +319,11 @@ if_reset(struct iface *iface, int af) if_leave_ipv6_group(iface, &global.mcast_addr_v6); break; default: - fatalx("if_start: unknown af"); + fatalx("if_reset: unknown af"); } + ia->state = IF_STA_DOWN; + return (0); } @@ -367,14 +370,12 @@ if_update_af(struct iface_af *ia) !socket_ok || !rtr_id_ok) return; - ia->state = IF_STA_ACTIVE; if_start(ia->iface, ia->af); } else if (ia->state == IF_STA_ACTIVE) { if (ia->enabled && ia->iface->operative && addr_ok && socket_ok && rtr_id_ok) return; - ia->state = IF_STA_DOWN; if_reset(ia->iface, ia->af); } } From 6bbf78cf5278c2b011bcb4f22fd92dbefd113e0e Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 27 Apr 2017 08:56:15 -0300 Subject: [PATCH 29/34] ldpd: fix issues detected by Coverity Scan Signed-off-by: Renato Westphal --- ldpd/lde.c | 10 ++-------- ldpd/ldpe.c | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/ldpd/lde.c b/ldpd/lde.c index e5d1402832..0cfc02d5ba 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -80,10 +80,6 @@ static zebra_capabilities_t _caps_p [] = static struct zebra_privs_t lde_privs = { -#if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, -#endif #if defined(VTY_GROUP) .vty_group = VTY_GROUP, #endif @@ -185,10 +181,8 @@ void lde_init(struct ldpd_init *init) { /* drop privileges */ - if (init->user) - lde_privs.user = init->user; - if (init->group) - lde_privs.group = init->group; + lde_privs.user = init->user; + lde_privs.group = init->group; zprivs_init(&lde_privs); #ifdef HAVE_PLEDGE diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 20cc9f7444..017eec2502 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -66,10 +66,6 @@ static zebra_capabilities_t _caps_p [] = struct zebra_privs_t ldpe_privs = { -#if defined(FRR_USER) && defined(FRR_GROUP) - .user = FRR_USER, - .group = FRR_GROUP, -#endif #if defined(VTY_GROUP) .vty_group = VTY_GROUP, #endif @@ -143,10 +139,8 @@ void ldpe_init(struct ldpd_init *init) { /* drop privileges */ - if (init->user) - ldpe_privs.user = init->user; - if (init->group) - ldpe_privs.group = init->group; + ldpe_privs.user = init->user; + ldpe_privs.group = init->group; zprivs_init(&ldpe_privs); /* listen on ldpd control socket */ From c18ac4c29a829edd98591931ba4ed827b3569095 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 2 Jun 2017 11:14:54 -0300 Subject: [PATCH 30/34] ldpd: fix bug in pseudowire control-word negotiation Bingen discovered a bug in the pseudowire control-word negotiation that might happen when the "control-word exclude" command is used. Under some very specific conditions, ldpd might ignore a PWID label mapping when it shouldn't. This patch removes a wrong optimization that was preventing ldpd to call l2vpn_pw_reset() every time we change the configuration of a pseudowire. Signed-off-by: Renato Westphal --- ldpd/ldpd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index bdf7097323..f9e44012ef 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1679,8 +1679,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) session_shutdown(nbr, S_SHUTDOWN, 0, 0); } } - if (ldpd_process == PROC_LDE_ENGINE && - !reset_nbr && reinstall_pwfec) + if (ldpd_process == PROC_LDE_ENGINE && reinstall_pwfec) l2vpn_pw_exit(pw); pw->lsr_id = xp->lsr_id; pw->af = xp->af; @@ -1702,8 +1701,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) pw->flags &= ~F_PW_STATIC_NBR_ADDR; if (ldpd_process == PROC_LDP_ENGINE && reinstall_tnbr) ldpe_l2vpn_pw_init(pw); - if (ldpd_process == PROC_LDE_ENGINE && - !reset_nbr && reinstall_pwfec) { + if (ldpd_process == PROC_LDE_ENGINE && reinstall_pwfec) { l2vpn->pw_type = xl->pw_type; l2vpn->mtu = xl->mtu; l2vpn_pw_init(pw); From d23670ca0348f990fdd801bf15904ecf2df569ff Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Mon, 5 Jun 2017 14:19:15 -0700 Subject: [PATCH 31/34] redhat: Remove accidental leftover HEAD tag from merge Signed-off-by: Martin Winter --- redhat/frr.spec.in | 1 - 1 file changed, 1 deletion(-) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index d7cb517ea8..57deeae2ab 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -10,7 +10,6 @@ #################### FRRouting (FRR) configure options ##################### # with-feature options -<<<<<<< HEAD %{!?with_tcp_zebra: %global with_tcp_zebra 0 } %{!?with_pam: %global with_pam 0 } %{!?with_ospfclient: %global with_ospfclient 1 } From 5a76db684adfedef5ae0926686a1d85fe7fff1ac Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Mon, 5 Jun 2017 16:59:20 -0700 Subject: [PATCH 32/34] redhat: Cleanup more merge fixes and add nhrpd/eigrpd to red hat package Signed-off-by: Martin Winter --- redhat/README.rpm_build.md | 2 + redhat/daemons | 4 ++ redhat/frr.init | 2 +- redhat/frr.logrotate | 17 ++++++++ redhat/frr.spec.in | 85 ++++++++++++++++++++++++-------------- 5 files changed, 77 insertions(+), 33 deletions(-) diff --git a/redhat/README.rpm_build.md b/redhat/README.rpm_build.md index d2b0814364..dd01babf50 100644 --- a/redhat/README.rpm_build.md +++ b/redhat/README.rpm_build.md @@ -59,6 +59,8 @@ Building your own FRRouting RPM %{!?with_irdp: %global with_irdp 1 } %{!?with_rtadv: %global with_rtadv 1 } %{!?with_ldpd: %global with_ldpd 1 } + %{!?with_nhrpd: %global with_nhrpd 1 } + %{!?with_eigrp: %global with_eigrpd 1 } %{!?with_shared: %global with_shared 1 } %{!?with_multipath: %global with_multipath 256 } %{!?frr_user: %global frr_user frr } diff --git a/redhat/daemons b/redhat/daemons index ce0f7747a2..e08302cb5c 100644 --- a/redhat/daemons +++ b/redhat/daemons @@ -45,6 +45,8 @@ ripd=no ripngd=no isisd=no ldpd=no +nhrpd=no +eigrpd=no # # Command line options for the daemons # @@ -56,4 +58,6 @@ ripd_options=("-A 127.0.0.1") ripngd_options=("-A ::1") isisd_options=("-A 127.0.0.1") ldpd_options=("-A 127.0.0.1") +nhrpd_options=("-A 127.0.0.1") +eigrpd_options=("-A 127.0.0.1") diff --git a/redhat/frr.init b/redhat/frr.init index 96c0a833af..0a922aab58 100755 --- a/redhat/frr.init +++ b/redhat/frr.init @@ -33,7 +33,7 @@ V_PATH=/var/run/frr # Local Daemon selection may be done by using /etc/frr/daemons. # See /usr/share/doc/frr/README.Debian.gz for further information. # Keep zebra first and do not list watchfrr! -DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd ldpd" +DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd pimd ldpd nhrpd eigrpd" MAX_INSTANCES=5 RELOAD_SCRIPT=/usr/lib/frr/frr-reload.py diff --git a/redhat/frr.logrotate b/redhat/frr.logrotate index 2db3af63dd..f43a86efe7 100644 --- a/redhat/frr.logrotate +++ b/redhat/frr.logrotate @@ -61,3 +61,20 @@ /bin/kill -USR1 `cat /var/run/frr/ldpd.pid 2> /dev/null` 2> /dev/null || true endscript } + +/var/log/frr/nhrpd.log { + notifempty + missingok + postrotate + /bin/kill -USR1 `cat /var/run/frr/nhrpd.pid 2> /dev/null` 2> /dev/null || true + endscript +} + +/var/log/frr/eigrpd.log { + notifempty + missingok + postrotate + /bin/kill -USR1 `cat /var/run/frr/eigrpd.pid 2> /dev/null` 2> /dev/null || true + endscript +} + diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 57deeae2ab..fea80d7f72 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -10,32 +10,31 @@ #################### FRRouting (FRR) configure options ##################### # with-feature options -%{!?with_tcp_zebra: %global with_tcp_zebra 0 } -%{!?with_pam: %global with_pam 0 } -%{!?with_ospfclient: %global with_ospfclient 1 } -%{!?with_ospfapi: %global with_ospfapi 1 } -%{!?with_irdp: %global with_irdp 1 } -%{!?with_rtadv: %global with_rtadv 1 } -%{!?with_mpls: %global with_mpls 1 } -%{!?with_ldpd: %global with_ldpd 1 } -%{!?with_nhrpd: %global with_nhrpd 1 } -%{!?with_shared: %global with_shared 1 } -%{!?with_multipath: %global with_multipath 256 } -%{!?frr_user: %global frr_user frr } -%{!?vty_group: %global vty_group frrvty } -%{!?with_fpm: %global with_fpm 0 } -%{!?with_watchfrr: %global with_watchfrr 1 } -%{!?with_bgp_vnc: %global with_bgp_vnc 0 } -%{!?with_pimd: %global with_pimd 1 } +%{!?with_tcp_zebra: %global with_tcp_zebra 0 } +%{!?with_pam: %global with_pam 0 } +%{!?with_ospfclient: %global with_ospfclient 1 } +%{!?with_ospfapi: %global with_ospfapi 1 } +%{!?with_irdp: %global with_irdp 1 } +%{!?with_rtadv: %global with_rtadv 1 } +%{!?with_ldpd: %global with_ldpd 1 } +%{!?with_nhrpd: %global with_nhrpd 1 } +%{!?with_eigrpd: %global with_eigrpd 1 } +%{!?with_shared: %global with_shared 1 } +%{!?with_multipath: %global with_multipath 256 } +%{!?frr_user: %global frr_user frr } +%{!?vty_group: %global vty_group frrvty } +%{!?with_fpm: %global with_fpm 0 } +%{!?with_watchfrr: %global with_watchfrr 1 } +%{!?with_bgp_vnc: %global with_bgp_vnc 0 } +%{!?with_pimd: %global with_pimd 1 } # path defines -%define _sysconfdir /etc/frr -%define _sbindir /usr/lib/frr -%define zeb_src %{_builddir}/%{name}-%{frrversion} -%define zeb_rh_src %{zeb_src}/redhat -%define zeb_docs %{zeb_src}/doc -%define frr_tools %{zeb_src}/tools -%define frr_tools_etc %{frr_tools}/etc +%define _sysconfdir /etc/frr +%define _sbindir /usr/lib/frr +%define zeb_src %{_builddir}/%{name}-%{frrversion} +%define zeb_rh_src %{zeb_src}/redhat +%define zeb_docs %{zeb_src}/doc +%define frr_tools %{zeb_src}/tools # defines for configure %define _localstatedir /var/run/frr @@ -83,7 +82,7 @@ %{!?frr_gid: %global frr_gid 92 } %{!?vty_gid: %global vty_gid 85 } -%define daemon_list zebra ripd ospfd bgpd isisd pimd ripngd ospf6d +%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospf6d %if %{with_ldpd} %define daemon_ldpd ldpd @@ -103,13 +102,19 @@ %define daemon_nhrpd "" %endif +%if %{with_eigrpd} +%define daemon_eigrpd eigrpd +%else +%define daemon_eigrpd "" +%endif + %if %{with_watchfrr} %define daemon_watchfrr watchfrr %else %define daemon_watchfrr "" %endif -%define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_nhrpd} %{daemon_watchfrr} +%define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_pimd} %{daemon_nhrpd} %{daemon_eigrpd} %{daemon_watchfrr} # allow build dir to be kept %{!?keep_build: %global keep_build 0 } @@ -155,7 +160,7 @@ protocol. It takes multi-server and multi-thread approach to resolve the current complexity of the Internet. FRRouting supports BGP4, OSPFv2, OSPFv3, ISIS, RIP, RIPng, PIM, LDP -and NHRP. +NHRP and EIGRP. FRRouting is a fork of Quagga. @@ -251,6 +256,11 @@ developing OSPF-API and frr applications. %else --disable-nhrpd \ %endif +%if %{with_eigrpd} + --enable-eigrpd \ +%else + --disable-eigrpd \ +%endif %if %{with_pam} --with-libpam \ %endif @@ -317,9 +327,7 @@ install %{zeb_rh_src}/frr.init \ %{buildroot}/etc/rc.d/init.d/frr %endif -install %{frr_tools_dir}/frr/daemons.conf %{buildroot}/etc/frr -install %{frr_tools_dir}/frr/daemons %{buildroot}/etc/frr -install -m644 %{frr_tools_dir}/default/frr %{buildroot}/etc/default +install %{zeb_rh_src}/daemons %{buildroot}/etc/frr install -m644 %{zeb_rh_src}/frr.pam \ %{buildroot}/etc/pam.d/frr install -m644 %{zeb_rh_src}/frr.logrotate \ @@ -374,6 +382,9 @@ zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty" zebra_spec_add_service ospfapi 2607/tcp "OSPF-API" %endif zebra_spec_add_service isisd 2608/tcp "ISISd vty" +%if %{with_eigrpd} +zebra_spec_add_service eigrpd 2609/tcp "EIGRPd vty" +%endif %if %{with_nhrpd} zebra_spec_add_service nhrpd 2610/tcp "NHRPd vty" %endif @@ -515,8 +526,11 @@ rm -rf %{buildroot} %if %{with_ldpd} %{_sbindir}/ldpd %endif +%if %{with_eigrpd} + %{_sbindir}/eigrpd +%endif %if %{with_nhrpd} -%{_sbindir}/nhrpd + %{_sbindir}/nhrpd %endif %if %{with_shared} %{_libdir}/lib*.so @@ -560,9 +574,16 @@ rm -rf %{buildroot} %dir %attr(755,root,root) %{_includedir}/%{name}/ospfapi %{_includedir}/%name/ospfapi/*.h %endif +%if %{with_eigrpd} +%dir %attr(755,root,root) %{_includedir}/%{name}/eigrpd +%{_includedir}/%name/eigrpd/*.h +%endif %changelog -* Mon Apr 17 2017 Martin Winter - %{version} +* Mon Jun 5 2017 Martin Winter - %{version} +- added NHRP and EIGRP daemon + +* Mon Apr 17 2017 Martin Winter - new subpackage frr-pythontools with python 2.7 restart script - remove PIMd from CentOS/RedHat 6 RPM packages (won't work - too old) - converted to single frr init script (not per daemon) based on debian init script From 82fc5591f440ee9810ce2c5d90d41a9f419062c8 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Mon, 5 Jun 2017 20:18:48 +0000 Subject: [PATCH 33/34] lib: allow infinite sleep in poll() If fd_poll() is called with no file descriptors, an incorrect check in the function prelude causes it to return instantly; for a thread that wishes to poll but has no file descriptors, this results in busy waiting. Desired behavior is to block. Signed-off-by: Quentin Young --- lib/thread.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 848e39e1ae..2280b96316 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -647,9 +647,6 @@ static int fd_poll (struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, nfds_t count, struct timeval *timer_wait) { - if (count == 0) - return 0; - /* If timer_wait is null here, that means poll() should block indefinitely, * unless the thread_master has overriden it by setting ->selectpoll_timeout. * If the value is positive, it specifies the maximum number of milliseconds From c7fb183833c81f9f6199272585882a635816c666 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Fri, 2 Jun 2017 20:53:37 +0000 Subject: [PATCH 34/34] bgpd: fix addpath buffer overrun Signed-off-by: Quentin Young [DL: removed compile_commands.json] --- bgpd/bgp_debug.c | 11 +++++++---- bgpd/bgp_updgrp_packet.c | 35 +++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index f4722e62dc..a39ec90cc6 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -40,8 +40,6 @@ #include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_mplsvpn.h" -#define BGP_ADDPATH_STR 20 - unsigned long conf_bgp_debug_as4; unsigned long conf_bgp_debug_neighbor_events; unsigned long conf_bgp_debug_events; @@ -2139,7 +2137,12 @@ bgp_debug_rdpfxpath2str (struct prefix_rd *prd, union prefixconstptr pu, { char rd_buf[RD_ADDRSTRLEN]; char pfx_buf[PREFIX_STRLEN]; - char pathid_buf[BGP_ADDPATH_STR]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (just in case) + 1 + * null terminator + 1 + * ============================ 29 */ + char pathid_buf[30]; if (size < BGP_PRD_PATH_STRLEN) return NULL; @@ -2147,7 +2150,7 @@ bgp_debug_rdpfxpath2str (struct prefix_rd *prd, union prefixconstptr pu, /* Note: Path-id is created by default, but only included in update sometimes. */ pathid_buf[0] = '\0'; if (addpath_valid) - sprintf(pathid_buf, " with addpath ID %d", addpath_id); + snprintf(pathid_buf, sizeof(pathid_buf), " with addpath ID %u", addpath_id); if (prd) snprintf (str, size, "RD %s %s%s", diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 7a45cddca9..567e1e927e 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -651,17 +651,6 @@ subgroup_packets_to_build (struct update_subgroup *subgrp) return 0; } -static void -bgp_info_addpath_tx_str (int addpath_encode, u_int32_t addpath_tx_id, - char *buf) -{ - buf[0] = '\0'; - if (addpath_encode) - sprintf(buf, " with addpath ID %d", addpath_tx_id); - else - buf[0] = '\0'; -} - /* Make BGP update packet. */ struct bpacket * subgroup_update_packet (struct update_subgroup *subgrp) @@ -1079,11 +1068,21 @@ subgroup_default_update_packet (struct update_subgroup *subgrp, { char attrstr[BUFSIZ]; char buf[PREFIX_STRLEN]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (just in case) + 1 + * null terminator + 1 + * ============================ 29 */ char tx_id_buf[30]; + attrstr[0] = '\0'; bgp_dump_attr (attr, attrstr, BUFSIZ); - bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf); + + if (addpath_encode) + snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u", + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s", (SUBGRP_UPDGRP (subgrp))->id, subgrp->id, prefix2str (&p, buf, sizeof (buf)), @@ -1153,9 +1152,17 @@ subgroup_default_withdraw_packet (struct update_subgroup *subgrp) if (bgp_debug_update(NULL, &p, subgrp->update_group, 0)) { char buf[PREFIX_STRLEN]; - char tx_id_buf[INET6_BUFSIZ]; + /* ' with addpath ID ' 17 + * max strlen of uint32 + 10 + * +/- (just in case) + 1 + * null terminator + 1 + * ============================ 29 */ + char tx_id_buf[30]; + + if (addpath_encode) + snprintf(tx_id_buf, sizeof (tx_id_buf), " with addpath ID %u", + BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); - bgp_info_addpath_tx_str (addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE, tx_id_buf); zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s -- unreachable", (SUBGRP_UPDGRP (subgrp))->id, subgrp->id, prefix2str (&p, buf, sizeof (buf)), tx_id_buf);