diff --git a/NEWS b/NEWS index 57cc99f076..8f9dd7a11f 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,35 @@ Note: this file lists major user-visible changes only. +* Changes in Quagga 0.99.24 + +User-visible changes: +- [pimd] New daemon: pimd provides IPv4 PIM-SSM multicast routing. +- [bgpd] New feature: "next-hop-self all" to override nexthop on iBGP route + reflector setups. +- [bgpd] route-maps have a new action "set ipv6 next-hop peer-address" +- [bgpd] route-maps have a new action "set as-path prepend last-as" +- [bgpd] Update validity checking (particularly MP-BGP / IPv6 routes) was + touched up significantly. Please report possible bugs. +- [ripd] New feature: RIP for IPv4 now supports equal-cost multipath (ECMP) +- [zebra] Multicast RIB support has been extended. It still is IPv4 only. +- [zebra] "no link-detect" is now printed in configurations since it won't + be the default anymore soon. To retain current behaviour, re-save your + configuration after updating to 0.99.24. + +Distributor-visible changes: +- --enable-pimd is added to enable pimd. It is considered experimental, though + unless the distribution target is embedded systems with little flash, there + is no reason to not include it in packages. +- --disable-ipv6 no longer exists as an option. It's 2015, your C library + really needs to have IPv6 support by now. +- --disable-netlink no longer exists as an option. It didn't work anyway. +- --disable-solaris no longer exists as an option. It only controlled some + init scripts. +- --enable-isisd is now the default. +- mrlg.cgi is no longer included (it was severely outdated). It can be found + independently at http://mrlg.op-sec.us/ +- build on Linux with the musl C library should now work + * Changes in Quagga 0.99.23 Known issues: diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 162c2adcdd..a7feb5cc1a 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index 73b2619c26..de27513a42 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -222,7 +222,7 @@ bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai) XFREE (MTYPE_BGP_ADJ_IN, bai); } -void +int bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer, u_int32_t addpath_id) { @@ -230,6 +230,10 @@ bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer, struct bgp_adj_in *adj_next; adj = rn->adj_in; + + if (!adj) + return 0; + while (adj) { adj_next = adj->next; @@ -242,6 +246,8 @@ bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer, adj = adj_next; } + + return 1; } void diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index ae6e6bd147..86c959478d 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -172,7 +172,7 @@ struct bgp_synchronize /* Prototypes. */ extern int bgp_adj_out_lookup (struct peer *, struct bgp_node *, u_int32_t); extern void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *, u_int32_t); -extern void bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t); +extern int bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t); extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *); extern void bgp_sync_init (struct peer *); diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index b5c8dccf87..4161d149fa 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -2144,7 +2144,7 @@ aspath_show_all_iterator (struct hash_backet *backet, struct vty *vty) as = (struct aspath *) backet->data; - vty_out (vty, "[%p:%u] (%ld) ", backet, backet->key, as->refcnt); + vty_out (vty, "[%p:%u] (%ld) ", (void *)backet, backet->key, as->refcnt); vty_out (vty, "%s%s", as->str, VTY_NEWLINE); } diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 844bc0fd91..ad8c7641e4 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1601,10 +1601,27 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args, break; #ifdef HAVE_IPV6 case BGP_ATTR_NHLEN_IPV6_GLOBAL: + case BGP_ATTR_NHLEN_VPNV6_GLOBAL: + if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) + { + stream_getl (s); /* RD high */ + stream_getl (s); /* RD low */ + } stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN); break; case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: + case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL: + if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) + { + stream_getl (s); /* RD high */ + stream_getl (s); /* RD low */ + } stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN); + if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) + { + stream_getl (s); /* RD high */ + stream_getl (s); /* RD low */ + } stream_get (&attre->mp_nexthop_local, s, IPV6_MAX_BYTELEN); if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local)) { diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index d71cb68052..da9bfec497 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -49,9 +49,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA /* Valid lengths for mp_nexthop_len */ #define BGP_ATTR_NHLEN_IPV4 IPV4_MAX_BYTELEN -#define BGP_ATTR_NHLEN_VPNV4 12 +#define BGP_ATTR_NHLEN_VPNV4 8+IPV4_MAX_BYTELEN #define BGP_ATTR_NHLEN_IPV6_GLOBAL IPV6_MAX_BYTELEN #define BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL (IPV6_MAX_BYTELEN * 2) +#define BGP_ATTR_NHLEN_VPNV6_GLOBAL 8+IPV6_MAX_BYTELEN +#define BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL ((8+IPV6_MAX_BYTELEN) * 2) /* Additional/uncommon BGP attributes. * lazily allocated as and when a struct attr diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index c1ab04407b..2e2dc42ad1 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -530,15 +530,15 @@ bgp_config_write_damp (struct vty *vty) && bgp_damp_cfg.reuse_limit == DEFAULT_REUSE && bgp_damp_cfg.suppress_value == DEFAULT_SUPPRESS && bgp_damp_cfg.max_suppress_time == bgp_damp_cfg.half_life*4) - vty_out (vty, " bgp dampening %ld%s", - bgp_damp_cfg.half_life/60, + vty_out (vty, " bgp dampening %lld%s", + bgp_damp_cfg.half_life/60LL, VTY_NEWLINE); else - vty_out (vty, " bgp dampening %ld %d %d %ld%s", - bgp_damp_cfg.half_life/60, + vty_out (vty, " bgp dampening %lld %d %d %lld%s", + bgp_damp_cfg.half_life/60LL, bgp_damp_cfg.reuse_limit, bgp_damp_cfg.suppress_value, - bgp_damp_cfg.max_suppress_time/60, + bgp_damp_cfg.max_suppress_time/60LL, VTY_NEWLINE); } diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index b60cbd0854..dc0137fd19 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -714,7 +714,7 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format) eas.val = (*pnt++ << 8); eas.val |= (*pnt++); - len = sprintf( str_buf + str_pnt, "%s%u:%d", prefix, + len = sprintf( str_buf + str_pnt, "%s%u:%u", prefix, eas.as, eas.val ); str_pnt += len; first = 0; @@ -729,7 +729,7 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format) eas.val |= (*pnt++ << 8); eas.val |= (*pnt++); - len = sprintf (str_buf + str_pnt, "%s%u:%d", prefix, + len = sprintf (str_buf + str_pnt, "%s%u:%u", prefix, eas.as, eas.val); str_pnt += len; first = 0; @@ -741,7 +741,7 @@ ecommunity_ecom2str (struct ecommunity *ecom, int format) eip.val = (*pnt++ << 8); eip.val |= (*pnt++); - len = sprintf (str_buf + str_pnt, "%s%s:%d", prefix, + len = sprintf (str_buf + str_pnt, "%s%s:%u", prefix, inet_ntoa (eip.ip), eip.val); str_pnt += len; first = 0; diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 2373bff104..9da21fdffd 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -940,7 +940,7 @@ bgp_fsm_change_status (struct peer *peer, int status) * the state change that happens below, so peer will be in Clearing * (or Deleted). */ - if (!peer->clear_node_queue->thread) + if (!work_queue_is_scheduled (peer->clear_node_queue)) BGP_EVENT_ADD (peer, Clearing_Completed); } diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 7fa80cc9c9..f873aba493 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -490,7 +490,7 @@ main (int argc, char **argv) /* Initializations. */ - srand (time (NULL)); + srandom (time (NULL)); signal_init (bm->master, array_size(bgp_signals), bgp_signals); zprivs_init (&bgpd_privs); cmd_init (1); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 2510e2e040..9f27c9addb 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -55,6 +55,7 @@ decode_label (u_char *pnt) return l; } +/* type == RD_TYPE_AS */ static void decode_rd_as (u_char *pnt, struct rd_as *rd_as) { @@ -67,6 +68,20 @@ decode_rd_as (u_char *pnt, struct rd_as *rd_as) rd_as->val |= (u_int32_t) *pnt; } +/* type == RD_TYPE_AS4 */ +static void +decode_rd_as4 (u_char *pnt, struct rd_as *rd_as) +{ + rd_as->as = (u_int32_t) *pnt++ << 24; + rd_as->as |= (u_int32_t) *pnt++ << 16; + rd_as->as |= (u_int32_t) *pnt++ << 8; + rd_as->as |= (u_int32_t) *pnt++; + + rd_as->val = ((u_int16_t) *pnt++ << 8); + rd_as->val |= (u_int16_t) *pnt; +} + +/* type == RD_TYPE_IP */ static void decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip) { @@ -78,13 +93,13 @@ decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip) } int -bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, - struct bgp_nlri *packet) +bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, + struct bgp_nlri *packet) { u_char *pnt; u_char *lim; struct prefix p; - int psize; + int psize = 0; int prefixlen; u_int16_t type; struct rd_as rd_as; @@ -136,9 +151,6 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, return -1; } - /* XXX: Not doing anything with the label */ - decode_label (pnt); - /* Fetch prefix length. */ prefixlen = *pnt++; p.family = afi2family (packet->afi); @@ -180,35 +192,37 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, /* Decode RD type. */ type = decode_rd_type (pnt + 3); - /* Decode RD value. */ - if (type == RD_TYPE_AS) - decode_rd_as (pnt + 5, &rd_as); - else if (type == RD_TYPE_IP) - decode_rd_ip (pnt + 5, &rd_ip); - else - { - zlog_err ("Invalid RD type %d", type); - return -1; - } + switch (type) + { + case RD_TYPE_AS: + decode_rd_as (pnt + 5, &rd_as); + break; + + case RD_TYPE_AS4: + decode_rd_as4 (pnt + 5, &rd_as); + break; + + case RD_TYPE_IP: + decode_rd_ip (pnt + 5, &rd_ip); + break; + + case RD_TYPE_EOI: + break; + + default: + zlog_err ("Invalid RD type %d", type); + return -1; + } p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8; memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, psize - VPN_PREFIXLEN_MIN_BYTES); -#if 0 - if (type == RD_TYPE_AS) - zlog_info ("prefix %ld:%ld:%ld:%s/%d", label, rd_as.as, rd_as.val, - inet_ntoa (p.u.prefix4), p.prefixlen); - else if (type == RD_TYPE_IP) - zlog_info ("prefix %ld:%s:%ld:%s/%d", label, inet_ntoa (rd_ip.ip), - rd_ip.val, inet_ntoa (p.u.prefix4), p.prefixlen); -#endif /* 0 */ - if (attr) - bgp_update (peer, &p, addpath_id, attr, AFI_IP, SAFI_MPLS_VPN, + bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0); else - bgp_withdraw (peer, &p, addpath_id, attr, AFI_IP, SAFI_MPLS_VPN, + bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt); } /* Packet length consistency check. */ @@ -322,12 +336,25 @@ prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size) snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val); return buf; } + else if (type == RD_TYPE_AS4) + { + decode_rd_as4 (pnt + 2, &rd_as); + snprintf (buf, size, "%u:%d", rd_as.as, rd_as.val); + return buf; + } else if (type == RD_TYPE_IP) { decode_rd_ip (pnt + 2, &rd_ip); snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); return buf; } + else if (type == RD_TYPE_EOI) + { + snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x", + pnt[1], /* LHI */ + pnt[2], pnt[3], pnt[4], pnt[5], pnt[6], pnt[7]); /* MAC */ + return buf; + } return NULL; } @@ -343,7 +370,22 @@ DEFUN (vpnv4_network, "BGP tag\n" "tag value\n") { - return bgp_static_set_vpnv4 (vty, argv[0], argv[1], argv[2]); + return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2], NULL); +} + +DEFUN (vpnv4_network_route_map, + vpnv4_network_route_map_cmd, + "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD route-map WORD", + "Specify a network to announce via BGP\n" + "IP prefix /, e.g., 35.0.0.0/8\n" + "Specify Route Distinguisher\n" + "VPN Route Distinguisher\n" + "BGP tag\n" + "tag value\n" + "route map\n" + "route map name\n") +{ + return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2], argv[3]); } /* For testing purpose, static route of MPLS-VPN. */ @@ -358,7 +400,7 @@ DEFUN (no_vpnv4_network, "BGP tag\n" "tag value\n") { - return bgp_static_unset_vpnv4 (vty, argv[0], argv[1], argv[2]); + return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2]); } static int @@ -460,13 +502,15 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, u /* Decode RD value. */ if (type == RD_TYPE_AS) decode_rd_as (pnt + 2, &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4 (pnt + 2, &rd_as); else if (type == RD_TYPE_IP) decode_rd_ip (pnt + 2, &rd_ip); if (use_json) { char buffer[BUFSIZ]; - if (type == RD_TYPE_AS) + if (type == RD_TYPE_AS || type == RD_TYPE_AS4) sprintf (buffer, "%u:%d", rd_as.as, rd_as.val); else if (type == RD_TYPE_IP) sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); @@ -476,7 +520,7 @@ show_adj_route_vpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd, u { vty_out (vty, "Route Distinguisher: "); - if (type == RD_TYPE_AS) + if (type == RD_TYPE_AS || type == RD_TYPE_AS4) vty_out (vty, "%u:%d", rd_as.as, rd_as.val); else if (type == RD_TYPE_IP) vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); @@ -528,6 +572,7 @@ static int bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type, void *output_arg, int tags, u_char use_json) { + afi_t afi = AFI_IP; struct bgp *bgp; struct bgp_table *table; struct bgp_node *rn; @@ -572,7 +617,13 @@ bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type ty json_object_string_add(json_ocode, "incomplete", "?"); } - for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) + if ((afi != AFI_IP) && (afi != AFI_IP6)) + { + vty_out (vty, "Afi %d not supported%s", afi, VTY_NEWLINE); + return CMD_WARNING; + } + + for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) { if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) continue; @@ -641,13 +692,15 @@ bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type ty /* Decode RD value. */ if (type == RD_TYPE_AS) decode_rd_as (pnt + 2, &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4 (pnt + 2, &rd_as); else if (type == RD_TYPE_IP) decode_rd_ip (pnt + 2, &rd_ip); if (use_json) { char buffer[BUFSIZ]; - if (type == RD_TYPE_AS) + if (type == RD_TYPE_AS || type == RD_TYPE_AS4) sprintf (buffer, "%u:%d", rd_as.as, rd_as.val); else if (type == RD_TYPE_IP) sprintf (buffer, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); @@ -657,7 +710,7 @@ bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type ty { vty_out (vty, "Route Distinguisher: "); - if (type == RD_TYPE_AS) + if (type == RD_TYPE_AS || type == RD_TYPE_AS4) vty_out (vty, "%u:%d", rd_as.as, rd_as.val); else if (type == RD_TYPE_IP) vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); @@ -1023,6 +1076,7 @@ void bgp_mplsvpn_init (void) { install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd); + install_element (BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd); install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd); diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index b221c3bdda..4e9b317b71 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -23,6 +23,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define RD_TYPE_AS 0 #define RD_TYPE_IP 1 +#define RD_TYPE_AS4 2 +#define RD_TYPE_EOI 0xff00 #define RD_ADDRSTRLEN 28 @@ -41,7 +43,7 @@ struct rd_ip }; extern void bgp_mplsvpn_init (void); -extern int bgp_nlri_parse_vpnv4 (struct peer *, struct attr *, struct bgp_nlri *); +extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *); extern u_int32_t decode_label (u_char *); extern int str2prefix_rd (const char *, struct prefix_rd *); extern int str2tag (const char *, u_char *); diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index dc0fd08d70..a2531e21b2 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -715,7 +715,7 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen) } /* IPv6 supported version of BGP server socket setup. */ -#if defined (HAVE_IPV6) && ! defined (NRL) +#ifdef HAVE_IPV6 int bgp_socket (unsigned short port, const char *address) { @@ -815,7 +815,7 @@ bgp_socket (unsigned short port, const char *address) } return sock; } -#endif /* HAVE_IPV6 && !NRL */ +#endif /* HAVE_IPV6 */ void bgp_close (void) diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 06cf8a17b1..54ca5efede 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -175,23 +175,23 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) { switch (afi) { - case AFI_IP: -#ifdef HAVE_IPV6 - case AFI_IP6: -#endif - switch (*safi) - { - /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */ - case SAFI_MPLS_LABELED_VPN: - *safi = SAFI_MPLS_VPN; - case SAFI_UNICAST: - case SAFI_MULTICAST: - case SAFI_MPLS_VPN: - return 1; - } + case AFI_IP: + case AFI_IP6: + switch (*safi) + { + /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */ + case SAFI_MPLS_LABELED_VPN: + *safi = SAFI_MPLS_VPN; + case SAFI_UNICAST: + case SAFI_MULTICAST: + case SAFI_MPLS_VPN: + return 1; + } + break; } + zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi); - + return 0; } @@ -287,7 +287,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) } /* validate number field */ - if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length) + if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length) { zlog_info ("%s ORF Capability entry length error," " Cap length %u, num %u", @@ -699,20 +699,41 @@ static const int capcode_str_max = array_size(capcode_str); /* Minimum sizes for length field of each cap (so not inc. the header) */ static const size_t cap_minsizes[] = { - [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data), + [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN, [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN, - [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry), - [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr), + [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN, + [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN, [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN, [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN, [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN, [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN, [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN, [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN, - [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry), + [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN, [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN, }; +/* value the capability must be a multiple of. + * 0-data capabilities won't be checked against this. + * Other capabilities whose data doesn't fall on convenient boundaries for this + * table should be set to 1. + */ +static const size_t cap_modsizes[] = +{ + [CAPABILITY_CODE_MP] = 4, + [CAPABILITY_CODE_REFRESH] = 1, + [CAPABILITY_CODE_ORF] = 1, + [CAPABILITY_CODE_RESTART] = 1, + [CAPABILITY_CODE_AS4] = 4, + [CAPABILITY_CODE_ADDPATH] = 4, + [CAPABILITY_CODE_DYNAMIC] = 1, + [CAPABILITY_CODE_DYNAMIC_OLD] = 1, + [CAPABILITY_CODE_ENHE] = 6, + [CAPABILITY_CODE_REFRESH_OLD] = 1, + [CAPABILITY_CODE_ORF_OLD] = 1, + [CAPABILITY_CODE_FQDN] = 1, +}; + /** * Parse given capability. * XXX: This is reading into a stream, but not using stream API @@ -790,6 +811,19 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_MALFORMED_ATTR); return -1; } + if (caphdr.length + && caphdr.length % cap_modsizes[caphdr.code] != 0) + { + zlog_info ("%s %s Capability length error: got %u," + " expected a multiple of %u", + peer->host, + LOOKUP (capcode_str, caphdr.code), + caphdr.length, + (unsigned) cap_modsizes[caphdr.code]); + bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_MALFORMED_ATTR); + return -1; + } /* we deliberately ignore unknown codes, see below */ default: break; @@ -1094,7 +1128,8 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]) + && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]) { zlog_err ("%s [Error] Configured AFI/SAFIs do not " "overlap with received MP capabilities", @@ -1286,6 +1321,18 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc (s, 0); stream_putc (s, SAFI_MULTICAST); } + /* IPv6 VPN. */ + if (peer->afc[AFI_IP6][SAFI_MPLS_VPN]) + { + peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1; + stream_putc (s, BGP_OPEN_OPT_CAP); + stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); + stream_putc (s, CAPABILITY_CODE_MP); + stream_putc (s, CAPABILITY_CODE_MP_LEN); + stream_putw (s, AFI_IP6); + stream_putc (s, 0); + stream_putc (s, SAFI_MPLS_LABELED_VPN); + } #endif /* HAVE_IPV6 */ /* Route refresh. */ diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h index bc49de54ff..8ec0a5416b 100644 --- a/bgpd/bgp_open.h +++ b/bgpd/bgp_open.h @@ -89,7 +89,8 @@ struct capability_gr #define CAPABILITY_CODE_AS4_LEN 4 #define CAPABILITY_CODE_ADDPATH_LEN 4 #define CAPABILITY_CODE_ENHE_LEN 6 /* NRLI AFI = 2, SAFI = 2, Nexthop AFI = 2 */ -#define CAPABILITY_CODE_MIN_FQDN_LEN 2 +#define CAPABILITY_CODE_MIN_FQDN_LEN 2 +#define CAPABILITY_CODE_ORF_LEN 5 /* Cooperative Route Filtering Capability. */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 6c1e9e2f96..02f5e82d4c 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "log.h" #include "memory.h" #include "sockunion.h" /* for inet_ntop () */ +#include "sockopt.h" #include "linklist.h" #include "plist.h" #include "queue.h" @@ -1176,6 +1177,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) return -1; } } + peer->rtt = sockopt_tcp_rtt (peer->fd); if ((ret = bgp_event_update(peer, Receive_OPEN_message)) < 0) { @@ -1526,12 +1528,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) if (peer->afc_nego[AFI_IP][SAFI_MULTICAST]) { if (mp_update.length - && mp_update.afi == AFI_IP + && mp_update.afi == AFI_IP && mp_update.safi == SAFI_MULTICAST) bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update); if (mp_withdraw.length - && mp_withdraw.afi == AFI_IP + && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == SAFI_MULTICAST) bgp_nlri_parse (peer, NULL, &mp_withdraw); @@ -1629,12 +1631,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) if (mp_update.length && mp_update.afi == AFI_IP && mp_update.safi == SAFI_MPLS_LABELED_VPN) - bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update); + bgp_nlri_parse_vpn (peer, NLRI_ATTR_ARG, &mp_update); if (mp_withdraw.length && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN) - bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw); + bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw); if (! withdraw_len && mp_withdraw.afi == AFI_IP @@ -1654,6 +1656,35 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) zlog_debug ("rcvd End-of-RIB for VPNv4 Unicast from %s", peer->host); } } + if (peer->afc[AFI_IP6][SAFI_MPLS_VPN]) + { + if (mp_update.length + && mp_update.afi == AFI_IP6 + && mp_update.safi == SAFI_MPLS_LABELED_VPN) + bgp_nlri_parse_vpn (peer, NLRI_ATTR_ARG, &mp_update); + + if (mp_withdraw.length + && mp_withdraw.afi == AFI_IP6 + && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN) + bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw); + + if (! withdraw_len + && mp_withdraw.afi == AFI_IP6 + && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN + && mp_withdraw.length == 0) + { + /* End-of-RIB received */ + if (!CHECK_FLAG (peer->af_sflags[AFI_IP6][SAFI_MPLS_VPN], + PEER_STATUS_EOR_RECEIVED)) + { + SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_MPLS_VPN], PEER_STATUS_EOR_RECEIVED); + bgp_update_explicit_eors(peer); + } + + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("rcvd End-of-RIB for VPNv6 Unicast from %s", peer->host); + } + } /* Everything is done. We unintern temporary structures which interned in bgp_attr_parse(). */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 74969e0ec7..d9dec8772b 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -803,6 +803,12 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist, return 0; } + /* locally configured routes to advertise do not have su_remote */ + if (new->peer->su_remote == NULL) + return 0; + if (exist->peer->su_remote == NULL) + return 1; + ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote); if (ret == 1) @@ -1514,6 +1520,17 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, char pfx_buf[PREFIX2STR_BUFFER]; char path_buf[PATH_ADDPATH_STR_BUFFER]; + result->old = result->new = NULL; + + if (rn->info == NULL) + { + char buf[PREFIX2STR_BUFFER]; + zlog_warn ("%s: Called for route_node %s with no routing entries!", + __func__, + prefix2str (&(bgp_node_to_rnode (rn)->p), buf, sizeof(buf))); + return; + } + bgp_mp_list_init (&mp_list); do_mpath = (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1); @@ -1902,6 +1919,19 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) if (CHECK_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED)) return; + if (rn->info == NULL) + { + /* XXX: Perhaps remove before next release, after we've flushed out + * any obvious cases + */ + assert (rn->info != NULL); + char buf[PREFIX2STR_BUFFER]; + zlog_warn ("%s: Called for route_node %s with no routing entries!", + __func__, + prefix2str (&(bgp_node_to_rnode (rn)->p), buf, sizeof(buf))); + return; + } + if (bm->process_main_queue == NULL) bgp_process_queue_init (); @@ -2531,10 +2561,26 @@ bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id, rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); /* If peer is soft reconfiguration enabled. Record input packet for - further calculation. */ + * further calculation. + * + * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all + * routes that are filtered. This tanks out Quagga RS pretty badly due to + * the iteration over all RS clients. + * Since we need to remove the entry from adj_in anyway, do that first and + * if there was no entry, we don't need to do anything more. + */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) && peer != bgp->peer_self) - bgp_adj_in_unset (rn, peer, addpath_id); + if (!bgp_adj_in_unset (rn, peer, addpath_id)) + { + if (bgp_debug_update (peer, p, NULL, 1)) + zlog_debug ("%s withdrawing route %s/%d " + "not in adj-in", peer->host, + inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + p->prefixlen); + bgp_unlock_node (rn); + return 0; + } /* Lookup withdrawn route. */ for (ri = rn->info; ri; ri = ri->next) @@ -3446,36 +3492,6 @@ bgp_static_update (struct bgp *bgp, struct prefix *p, bgp_static_update_main (bgp, p, bgp_static, afi, safi); } -static void -bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi, - safi_t safi, struct prefix_rd *prd, u_char *tag) -{ - struct bgp_node *rn; - struct bgp_info *new; - - rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); - - /* Make new BGP info. */ - new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, - bgp_attr_default_intern(BGP_ORIGIN_IGP), rn); - - SET_FLAG (new->flags, BGP_INFO_VALID); - new->extra = bgp_info_extra_new(); - memcpy (new->extra->tag, tag, 3); - - /* Aggregate address increment. */ - bgp_aggregate_increment (bgp, p, new, afi, safi); - - /* Register new BGP information. */ - bgp_info_add (rn, new); - - /* route_node_get lock */ - bgp_unlock_node (rn); - - /* Process change. */ - bgp_process (bgp, rn, afi, safi); -} - void bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi) @@ -3505,9 +3521,12 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi, bgp_unlock_node (rn); } +/* + * Used for SAFI_MPLS_VPN and SAFI_ENCAP + */ static void -bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi, - safi_t safi, struct prefix_rd *prd, u_char *tag) +bgp_static_withdraw_safi (struct bgp *bgp, struct prefix *p, afi_t afi, + safi_t safi, struct prefix_rd *prd, u_char *tag) { struct bgp_node *rn; struct bgp_info *ri; @@ -3533,6 +3552,127 @@ bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi, bgp_unlock_node (rn); } +static void +bgp_static_update_safi (struct bgp *bgp, struct prefix *p, + struct bgp_static *bgp_static, afi_t afi, safi_t safi) +{ + struct bgp_node *rn; + struct bgp_info *new; + struct attr *attr_new; + struct attr attr = { 0 }; + struct bgp_info *ri; + + assert (bgp_static); + + rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, &bgp_static->prd); + + bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); + + attr.nexthop = bgp_static->igpnexthop; + attr.med = bgp_static->igpmetric; + attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + + /* Apply route-map. */ + if (bgp_static->rmap.name) + { + struct attr attr_tmp = attr; + struct bgp_info info; + int ret; + + info.peer = bgp->peer_self; + info.attr = &attr_tmp; + + SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); + + ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info); + + bgp->peer_self->rmap_type = 0; + + if (ret == RMAP_DENYMATCH) + { + /* Free uninterned attribute. */ + bgp_attr_flush (&attr_tmp); + + /* Unintern original. */ + aspath_unintern (&attr.aspath); + bgp_attr_extra_free (&attr); + bgp_static_withdraw_safi (bgp, p, afi, safi, &bgp_static->prd, + bgp_static->tag); + return; + } + + attr_new = bgp_attr_intern (&attr_tmp); + } + else + { + attr_new = bgp_attr_intern (&attr); + } + + for (ri = rn->info; ri; ri = ri->next) + if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP + && ri->sub_type == BGP_ROUTE_STATIC) + break; + + if (ri) + { + if (attrhash_cmp (ri->attr, attr_new) && + !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + { + bgp_unlock_node (rn); + bgp_attr_unintern (&attr_new); + aspath_unintern (&attr.aspath); + bgp_attr_extra_free (&attr); + return; + } + else + { + /* The attribute is changed. */ + bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED); + + /* Rewrite BGP route information. */ + if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + bgp_info_restore(rn, ri); + else + bgp_aggregate_decrement (bgp, p, ri, afi, safi); + bgp_attr_unintern (&ri->attr); + ri->attr = attr_new; + ri->uptime = bgp_clock (); + + /* Process change. */ + bgp_aggregate_increment (bgp, p, ri, afi, safi); + bgp_process (bgp, rn, afi, safi); + bgp_unlock_node (rn); + aspath_unintern (&attr.aspath); + bgp_attr_extra_free (&attr); + return; + } + } + + + /* Make new BGP info. */ + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new, + rn); + SET_FLAG (new->flags, BGP_INFO_VALID); + new->extra = bgp_info_extra_new(); + memcpy (new->extra->tag, bgp_static->tag, 3); + + /* Aggregate address increment. */ + bgp_aggregate_increment (bgp, p, new, afi, safi); + + /* Register new BGP information. */ + bgp_info_add (rn, new); + + /* route_node_get lock */ + bgp_unlock_node (rn); + + /* Process change. */ + bgp_process (bgp, rn, afi, safi); + + /* Unintern original. */ + aspath_unintern (&attr.aspath); + bgp_attr_extra_free (&attr); +} + /* Configure static BGP network. When user don't run zebra, static route should be installed as valid. */ static int @@ -3696,10 +3836,7 @@ bgp_static_add (struct bgp *bgp) for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) { bgp_static = rn->info; - bgp_static_update_vpnv4 (bgp, &rm->p, - AFI_IP, SAFI_MPLS_VPN, - (struct prefix_rd *)&rn->p, - bgp_static->tag); + bgp_static_update_safi (bgp, &rm->p, bgp_static, afi, safi); } } else @@ -3733,8 +3870,8 @@ bgp_static_delete (struct bgp *bgp) for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) { bgp_static = rn->info; - bgp_static_withdraw_vpnv4 (bgp, &rm->p, - AFI_IP, SAFI_MPLS_VPN, + bgp_static_withdraw_safi (bgp, &rm->p, + AFI_IP, safi, (struct prefix_rd *)&rn->p, bgp_static->tag); bgp_static_free (bgp_static); @@ -3816,9 +3953,15 @@ bgp_purge_static_redist_routes (struct bgp *bgp) bgp_purge_af_static_redist_routes (bgp, afi, safi); } +/* + * gpz 110624 + * Currently this is used to set static routes for VPN and ENCAP. + * I think it can probably be factored with bgp_static_set. + */ int -bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str, - const char *tag_str) +bgp_static_set_safi (safi_t safi, struct vty *vty, const char *ip_str, + const char *rd_str, const char *tag_str, + const char *rmap_str) { int ret; struct prefix p; @@ -3854,10 +3997,10 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str, return CMD_WARNING; } - prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN], + prn = bgp_node_get (bgp->route[AFI_IP][safi], (struct prefix *)&prd); if (prn->info == NULL) - prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN); + prn->info = bgp_table_init (AFI_IP, safi); else bgp_unlock_node (prn); table = prn->info; @@ -3873,11 +4016,24 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str, { /* New configuration. */ bgp_static = bgp_static_new (); - bgp_static->valid = 1; - memcpy (bgp_static->tag, tag, 3); + bgp_static->backdoor = 0; + bgp_static->valid = 0; + bgp_static->igpmetric = 0; + bgp_static->igpnexthop.s_addr = 0; + memcpy(bgp_static->tag, tag, 3); + bgp_static->prd = prd; + + if (rmap_str) + { + if (bgp_static->rmap.name) + free (bgp_static->rmap.name); + bgp_static->rmap.name = strdup (rmap_str); + bgp_static->rmap.map = route_map_lookup_by_name (rmap_str); + } rn->info = bgp_static; - bgp_static_update_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag); + bgp_static->valid = 1; + bgp_static_update_safi (bgp, &p, bgp_static, AFI_IP, safi); } return CMD_SUCCESS; @@ -3885,8 +4041,8 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str, /* Configure static BGP network. */ int -bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str, - const char *rd_str, const char *tag_str) +bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str, + const char *rd_str, const char *tag_str) { int ret; struct bgp *bgp; @@ -3923,10 +4079,10 @@ bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str, return CMD_WARNING; } - prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN], + prn = bgp_node_get (bgp->route[AFI_IP][safi], (struct prefix *)&prd); if (prn->info == NULL) - prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN); + prn->info = bgp_table_init (AFI_IP, safi); else bgp_unlock_node (prn); table = prn->info; @@ -3935,7 +4091,7 @@ bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str, if (rn) { - bgp_static_withdraw_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag); + bgp_static_withdraw_safi (bgp, &p, AFI_IP, safi, &prd, tag); bgp_static = rn->info; bgp_static_free (bgp_static); @@ -9567,18 +9723,12 @@ ALIAS (show_ip_bgp_ipv4_community, DEFUN (show_bgp_instance_afi_safi_community_all, show_bgp_instance_afi_safi_community_all_cmd, -#ifdef HAVE_IPV6 "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast) community", -#else - "show bgp " BGP_INSTANCE_CMD " ipv4 (unicast|multicast) community", -#endif SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR "Address family\n" -#ifdef HAVE_IPV6 "Address family\n" -#endif "Address Family modifier\n" "Address Family modifier\n" "Display routes matching the communities\n") @@ -9595,30 +9745,19 @@ DEFUN (show_bgp_instance_afi_safi_community_all, return CMD_WARNING; } -#ifdef HAVE_IPV6 afi = (strncmp (argv[2], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP; safi = (strncmp (argv[3], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; -#else - afi = AFI_IP; - safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; -#endif return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL, 0); } DEFUN (show_bgp_instance_afi_safi_community, show_bgp_instance_afi_safi_community_cmd, -#ifdef HAVE_IPV6 "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)", -#else - "show bgp " BGP_INSTANCE_CMD " ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)", -#endif SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR "Address family\n" -#ifdef HAVE_IPV6 "Address family\n" -#endif "Address family modifier\n" "Address family modifier\n" "Display routes matching the communities\n" @@ -9630,31 +9769,19 @@ DEFUN (show_bgp_instance_afi_safi_community, int afi; int safi; -#ifdef HAVE_IPV6 afi = (strncmp (argv[2], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP; safi = (strncmp (argv[3], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; return bgp_show_community (vty, argv[1], argc-4, &argv[4], 0, afi, safi); -#else - afi = AFI_IP; - safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; - return bgp_show_community (vty, argv[1], argc-3, &argv[3], 0, afi, safi); -#endif } ALIAS (show_bgp_instance_afi_safi_community, show_bgp_instance_afi_safi_community2_cmd, -#ifdef HAVE_IPV6 "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", -#else - "show bgp " BGP_INSTANCE_CMD " ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", -#endif SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR "Address family\n" -#ifdef HAVE_IPV6 "Address family\n" -#endif "Address family modifier\n" "Address family modifier\n" "Display routes matching the communities\n" @@ -9669,18 +9796,12 @@ ALIAS (show_bgp_instance_afi_safi_community, ALIAS (show_bgp_instance_afi_safi_community, show_bgp_instance_afi_safi_community3_cmd, -#ifdef HAVE_IPV6 "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", -#else - "show bgp " BGP_INSTANCE_CMD " ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", -#endif SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR "Address family\n" -#ifdef HAVE_IPV6 "Address family\n" -#endif "Address family modifier\n" "Address family modifier\n" "Display routes matching the communities\n" @@ -9699,18 +9820,12 @@ ALIAS (show_bgp_instance_afi_safi_community, ALIAS (show_bgp_instance_afi_safi_community, show_bgp_instance_afi_safi_community4_cmd, -#ifdef HAVE_IPV6 "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", -#else - "show bgp " BGP_INSTANCE_CMD " ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", -#endif SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR "Address family\n" -#ifdef HAVE_IPV6 "Address family\n" -#endif "Address family modifier\n" "Address family modifier\n" "Display routes matching the communities\n" @@ -12389,18 +12504,12 @@ ALIAS (show_ip_bgp_ipv4_neighbor_received_routes, DEFUN (show_bgp_instance_afi_safi_neighbor_adv_recd_routes, show_bgp_instance_afi_safi_neighbor_adv_recd_routes_cmd, -#ifdef HAVE_IPV6 "show bgp " BGP_INSTANCE_CMD " (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) (advertised-routes|received-routes) {json}", -#else - "show bgp " BGP_INSTANCE_CMD " ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X|WORD) (advertised-routes|received-routes) {json}", -#endif SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR "Address family\n" -#ifdef HAVE_IPV6 "Address family\n" -#endif "Address family modifier\n" "Address family modifier\n" "Detailed information on TCP and BGP neighbor connections\n" diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index cc26249686..8d1eb21010 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -145,6 +145,9 @@ struct bgp_static struct route_map *map; } rmap; + /* Route Distinguisher */ + struct prefix_rd prd; + /* MPLS label. */ u_char tag[3]; }; @@ -253,10 +256,10 @@ extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static afi_t, safi_t); extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t); -extern int bgp_static_set_vpnv4 (struct vty *vty, const char *, - const char *, const char *); +extern int bgp_static_set_safi (safi_t safi, struct vty *vty, const char *, + const char *, const char *, const char *); -extern int bgp_static_unset_vpnv4 (struct vty *, const char *, +extern int bgp_static_unset_safi (safi_t safi, struct vty *, const char *, const char *, const char *); /* this is primarily for MPLS-VPN */ diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index ab22a455d2..11b6919bf2 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -108,6 +108,108 @@ o Local extensions */ + /* generic value manipulation to be shared in multiple rules */ + +#define RMAP_VALUE_SET 0 +#define RMAP_VALUE_ADD 1 +#define RMAP_VALUE_SUB 2 + +struct rmap_value +{ + u_int8_t action; + u_int8_t variable; + u_int32_t value; +}; + +static int +route_value_match (struct rmap_value *rv, u_int32_t value) +{ + if (rv->variable == 0 && value == rv->value) + return RMAP_MATCH; + + return RMAP_NOMATCH; +} + +static u_int32_t +route_value_adjust (struct rmap_value *rv, u_int32_t current, struct peer *peer) +{ + u_int32_t value; + + switch (rv->variable) + { + case 1: + value = peer->rtt; + break; + default: + value = rv->value; + break; + } + + switch (rv->action) + { + case RMAP_VALUE_ADD: + if (current > UINT32_MAX-value) + return UINT32_MAX; + return current + value; + case RMAP_VALUE_SUB: + if (current <= value) + return 0; + return current - value; + default: + return value; + } +} + +static void * +route_value_compile (const char *arg) +{ + u_int8_t action = RMAP_VALUE_SET, var = 0; + unsigned long larg = 0; + char *endptr = NULL; + struct rmap_value *rv; + + if (arg[0] == '+') + { + action = RMAP_VALUE_ADD; + arg++; + } + else if (arg[0] == '-') + { + action = RMAP_VALUE_SUB; + arg++; + } + + if (all_digit(arg)) + { + errno = 0; + larg = strtoul (arg, &endptr, 10); + if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX) + return NULL; + } + else + { + if (strcmp(arg, "rtt") == 0) + var = 1; + else + return NULL; + } + + rv = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value)); + if (!rv) + return NULL; + + rv->action = action; + rv->variable = var; + rv->value = larg; + return rv; +} + +static void +route_value_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + /* generic as path object to be shared in multiple rules */ static void * @@ -138,8 +240,8 @@ route_match_peer (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { union sockunion *su; - union sockunion su_def = { .sin.sin_family = AF_INET, - .sin.sin_addr.s_addr = INADDR_ANY }; + union sockunion su_def = { .sin = { .sin_family = AF_INET, + .sin_addr.s_addr = INADDR_ANY } }; struct peer_group *group; struct peer *peer; struct listnode *node, *nnode; @@ -591,62 +693,25 @@ static route_map_result_t route_match_metric (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - u_int32_t *med; + struct rmap_value *rv; struct bgp_info *bgp_info; if (type == RMAP_BGP) { - med = rule; + rv = rule; bgp_info = object; - - if (bgp_info->attr->med == *med) - return RMAP_MATCH; - else - return RMAP_NOMATCH; + return route_value_match(rv, bgp_info->attr->med); } return RMAP_NOMATCH; } -/* Route map `match metric' match statement. `arg' is MED value */ -static void * -route_match_metric_compile (const char *arg) -{ - u_int32_t *med; - char *endptr = NULL; - unsigned long tmpval; - - /* Metric value shoud be integer. */ - if (! all_digit (arg)) - return NULL; - - errno = 0; - tmpval = strtoul (arg, &endptr, 10); - if (*endptr != '\0' || errno || tmpval > UINT32_MAX) - return NULL; - - med = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - - if (!med) - return med; - - *med = tmpval; - return med; -} - -/* Free route map's compiled `match metric' value. */ -static void -route_match_metric_free (void *rule) -{ - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); -} - /* Route map commands for metric matching. */ struct route_map_rule_cmd route_match_metric_cmd = { "metric", route_match_metric, - route_match_metric_compile, - route_match_metric_free + route_value_compile, + route_value_free, }; /* `match as-path ASPATH' */ @@ -892,19 +957,14 @@ static route_map_result_t route_match_probability (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - unsigned long r; -#if _SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500 - r = random(); -#else - r = (unsigned long) rand(); -#endif + long r = random(); switch (*(long *) rule) { case 0: break; case RAND_MAX: return RMAP_MATCH; default: - if (r < *(unsigned long *) rule) + if (r < *(long *) rule) { return RMAP_MATCH; } @@ -919,12 +979,6 @@ route_match_probability_compile (const char *arg) long *lobule; unsigned perc; -#if _SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500 - srandom (time (NULL)); -#else - srand (time (NULL)); -#endif - perc = atoi (arg); lobule = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (long)); @@ -1197,64 +1251,34 @@ static route_map_result_t route_set_local_pref (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - u_int32_t *local_pref; + struct rmap_value *rv; struct bgp_info *bgp_info; + u_int32_t locpref = 0; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ - local_pref = rule; + rv = rule; bgp_info = object; /* Set local preference value. */ + if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) + locpref = bgp_info->attr->local_pref; + bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); - bgp_info->attr->local_pref = *local_pref; + bgp_info->attr->local_pref = route_value_adjust(rv, locpref, bgp_info->peer); } return RMAP_OKAY; } -/* set local preference compilation. */ -static void * -route_set_local_pref_compile (const char *arg) -{ - unsigned long tmp; - u_int32_t *local_pref; - char *endptr = NULL; - - /* Local preference value shoud be integer. */ - if (! all_digit (arg)) - return NULL; - - errno = 0; - tmp = strtoul (arg, &endptr, 10); - if (*endptr != '\0' || errno || tmp > UINT32_MAX) - return NULL; - - local_pref = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - - if (!local_pref) - return local_pref; - - *local_pref = tmp; - - return local_pref; -} - -/* Free route map's local preference value. */ -static void -route_set_local_pref_free (void *rule) -{ - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); -} - /* Set local preference rule structure. */ struct route_map_rule_cmd route_set_local_pref_cmd = { "local-preference", route_set_local_pref, - route_set_local_pref_compile, - route_set_local_pref_free, + route_value_compile, + route_value_free, }; /* `set weight WEIGHT' */ @@ -1264,18 +1288,20 @@ static route_map_result_t route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - u_int32_t *weight; + struct rmap_value *rv; struct bgp_info *bgp_info; + u_int32_t weight; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ - weight = rule; + rv = rule; bgp_info = object; /* Set weight value. */ - if (*weight) - (bgp_attr_extra_get (bgp_info->attr))->weight = *weight; + weight = route_value_adjust(rv, 0, bgp_info->peer); + if (weight) + (bgp_attr_extra_get (bgp_info->attr))->weight = weight; else if (bgp_info->attr->extra) bgp_info->attr->extra->weight = 0; } @@ -1283,47 +1309,13 @@ route_set_weight (void *rule, struct prefix *prefix, route_map_object_t type, return RMAP_OKAY; } -/* set local preference compilation. */ -static void * -route_set_weight_compile (const char *arg) -{ - unsigned long tmp; - u_int32_t *weight; - char *endptr = NULL; - - /* Local preference value shoud be integer. */ - if (! all_digit (arg)) - return NULL; - - errno = 0; - tmp = strtoul (arg, &endptr, 10); - if (*endptr != '\0' || errno || tmp > UINT32_MAX) - return NULL; - - weight = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - - if (weight == NULL) - return weight; - - *weight = tmp; - - return weight; -} - -/* Free route map's local preference value. */ -static void -route_set_weight_free (void *rule) -{ - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); -} - /* Set local preference rule structure. */ struct route_map_rule_cmd route_set_weight_cmd = { "weight", route_set_weight, - route_set_weight_compile, - route_set_weight_free, + route_value_compile, + route_value_free, }; /* `set metric METRIC' */ @@ -1333,94 +1325,32 @@ static route_map_result_t route_set_metric (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - char *metric; - u_int32_t metric_val; + struct rmap_value *rv; struct bgp_info *bgp_info; + u_int32_t med = 0; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ - metric = rule; + rv = rule; bgp_info = object; - if (! (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))) - bgp_info->attr->med = 0; + if (bgp_info->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) + med = bgp_info->attr->med; + + bgp_info->attr->med = route_value_adjust(rv, med, bgp_info->peer); bgp_info->attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); - - if (all_digit (metric)) - { - metric_val = strtoul (metric, (char **)NULL, 10); - bgp_info->attr->med = metric_val; - } - else - { - metric_val = strtoul (metric+1, (char **)NULL, 10); - - if (strncmp (metric, "+", 1) == 0) - { - if (bgp_info->attr->med/2 + metric_val/2 > BGP_MED_MAX/2) - bgp_info->attr->med = BGP_MED_MAX - 1; - else - bgp_info->attr->med += metric_val; - } - else if (strncmp (metric, "-", 1) == 0) - { - if (bgp_info->attr->med <= metric_val) - bgp_info->attr->med = 0; - else - bgp_info->attr->med -= metric_val; - } - } } return RMAP_OKAY; } -/* set metric compilation. */ -static void * -route_set_metric_compile (const char *arg) -{ - unsigned long larg; - char *endptr = NULL; - - if (all_digit (arg)) - { - /* set metric value check*/ - errno = 0; - larg = strtoul (arg, &endptr, 10); - if (*endptr != '\0' || errno || larg > UINT32_MAX) - return NULL; - } - else - { - /* set metric <+/-metric> check */ - if ((strncmp (arg, "+", 1) != 0 - && strncmp (arg, "-", 1) != 0) - || (! all_digit (arg+1))) - return NULL; - - errno = 0; - larg = strtoul (arg+1, &endptr, 10); - if (*endptr != '\0' || errno || larg > UINT32_MAX) - return NULL; - } - - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); -} - -/* Free route map's compiled `set metric' value. */ -static void -route_set_metric_free (void *rule) -{ - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); -} - /* Set metric rule structure. */ struct route_map_rule_cmd route_set_metric_cmd = { "metric", route_set_metric, - route_set_metric_compile, - route_set_metric_free, + route_value_compile, + route_value_free, }; /* `set as-path prepend ASPATH' */ @@ -3732,6 +3662,15 @@ ALIAS (set_metric, "Metric value for destination routing protocol\n" "Add or subtract metric\n") +ALIAS (set_metric, + set_metric_rtt_cmd, + "set metric (rtt|+rtt|-rtt)", + SET_STR + "Metric value for destination routing protocol\n" + "Assign round trip time\n" + "Add round trip time\n" + "Subtract round trip time\n") + DEFUN (no_set_metric, no_set_metric_cmd, "no set metric", @@ -4717,6 +4656,7 @@ bgp_route_map_init (void) install_element (RMAP_NODE, &no_set_weight_val_cmd); install_element (RMAP_NODE, &set_metric_cmd); install_element (RMAP_NODE, &set_metric_addsub_cmd); + install_element (RMAP_NODE, &set_metric_rtt_cmd); install_element (RMAP_NODE, &no_set_metric_cmd); install_element (RMAP_NODE, &no_set_metric_val_cmd); install_element (RMAP_NODE, &set_aspath_prepend_cmd); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 825f5954c2..17588eb3a4 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -62,7 +62,9 @@ listen_range_exists (struct bgp *bgp, struct prefix *range, int exact); afi_t bgp_node_afi (struct vty *vty) { - if (vty->node == BGP_IPV6_NODE || vty->node == BGP_IPV6M_NODE) + if (vty->node == BGP_IPV6_NODE || + vty->node == BGP_IPV6M_NODE || + vty->node == BGP_VPNV6_NODE) return AFI_IP6; return AFI_IP; } @@ -74,6 +76,8 @@ bgp_node_safi (struct vty *vty) { if (vty->node == BGP_VPNV4_NODE) return SAFI_MPLS_VPN; + if (vty->node == BGP_VPNV6_NODE) + return SAFI_MPLS_VPN; if (vty->node == BGP_IPV4M_NODE || vty->node == BGP_IPV6M_NODE) return SAFI_MULTICAST; return SAFI_UNICAST; @@ -5864,6 +5868,23 @@ ALIAS (address_family_vpnv4, "Address family\n" "Address Family Modifier\n") +DEFUN (address_family_vpnv6, + address_family_vpnv6_cmd, + "address-family vpnv6", + "Enter Address Family command mode\n" + "Address family\n") +{ + vty->node = BGP_VPNV6_NODE; + return CMD_SUCCESS; +} + +ALIAS (address_family_vpnv6, + address_family_vpnv6_unicast_cmd, + "address-family vpnv6 unicast", + "Enter Address Family command mode\n" + "Address family\n" + "Address Family Modifier\n") + DEFUN (exit_address_family, exit_address_family_cmd, "exit-address-family", @@ -5873,7 +5894,8 @@ DEFUN (exit_address_family, || vty->node == BGP_IPV4M_NODE || vty->node == BGP_VPNV4_NODE || vty->node == BGP_IPV6_NODE - || vty->node == BGP_IPV6M_NODE) + || vty->node == BGP_IPV6M_NODE + || vty->node == BGP_VPNV6_NODE) vty->node = BGP_NODE; return CMD_SUCCESS; } @@ -9802,7 +9824,7 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi, json_object *json_peers = NULL; /* Header string for each address family. */ - static char header[] = "Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd"; + static char header[] = "Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd"; if (use_json) { @@ -10460,11 +10482,13 @@ afi_safi_print (afi_t afi, safi_t safi) else if (afi == AFI_IP && safi == SAFI_MULTICAST) return "IPv4 Multicast"; else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "VPNv4 Unicast"; + return "VPN-IPv4 Unicast"; else if (afi == AFI_IP6 && safi == SAFI_UNICAST) return "IPv6 Unicast"; else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) return "IPv6 Multicast"; + else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) + return "VPN-IPv6 Unicast"; else return "Unknown"; } @@ -11248,6 +11272,8 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js || p->afc_recv[AFI_IP6][SAFI_UNICAST] || p->afc_adv[AFI_IP6][SAFI_MULTICAST] || p->afc_recv[AFI_IP6][SAFI_MULTICAST] + || p->afc_adv[AFI_IP6][SAFI_MPLS_VPN] + || p->afc_recv[AFI_IP6][SAFI_MPLS_VPN] #endif /* HAVE_IPV6 */ || p->afc_adv[AFI_IP][SAFI_MPLS_VPN] || p->afc_recv[AFI_IP][SAFI_MPLS_VPN]) @@ -12030,6 +12056,11 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js } } + /* TCP metrics. */ + if (p->status == Established && p->rtt) + vty_out (vty, "Estimated round trip time: %d ms%s", + p->rtt, VTY_NEWLINE); + /* Timer information. */ if (use_json) { @@ -12538,7 +12569,7 @@ community_show_all_iterator (struct hash_backet *backet, struct vty *vty) struct community *com; com = (struct community *) backet->data; - vty_out (vty, "[%p] (%ld) %s%s", backet, com->refcnt, + vty_out (vty, "[%p] (%ld) %s%s", (void *)backet, com->refcnt, community_str (com), VTY_NEWLINE); } @@ -13896,6 +13927,13 @@ static struct cmd_node bgp_vpnv4_node = 1 }; +static struct cmd_node bgp_vpnv6_node = +{ + BGP_VPNV6_NODE, + "%s(config-router-af-vpnv6)# ", + 1 +}; + static void community_list_vty (void); void @@ -13908,6 +13946,7 @@ bgp_vty_init (void) install_node (&bgp_ipv6_unicast_node, NULL); install_node (&bgp_ipv6_multicast_node, NULL); install_node (&bgp_vpnv4_node, NULL); + install_node (&bgp_vpnv6_node, NULL); /* Install default VTY commands to new nodes. */ install_default (BGP_NODE); @@ -13916,6 +13955,7 @@ bgp_vty_init (void) install_default (BGP_IPV6_NODE); install_default (BGP_IPV6M_NODE); install_default (BGP_VPNV4_NODE); + install_default (BGP_VPNV6_NODE); /* "bgp multiple-instance" commands. */ install_element (CONFIG_NODE, &bgp_multiple_instance_cmd); @@ -14161,6 +14201,7 @@ bgp_vty_init (void) install_element (BGP_IPV6_NODE, &neighbor_activate_cmd); install_element (BGP_IPV6M_NODE, &neighbor_activate_cmd); install_element (BGP_VPNV4_NODE, &neighbor_activate_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_activate_cmd); /* "no neighbor activate" commands. */ install_element (BGP_NODE, &no_neighbor_activate_cmd); @@ -14169,6 +14210,7 @@ bgp_vty_init (void) install_element (BGP_IPV6_NODE, &no_neighbor_activate_cmd); install_element (BGP_IPV6M_NODE, &no_neighbor_activate_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_activate_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_activate_cmd); /* "neighbor peer-group" set commands. * Long term we should only accept this command under BGP_NODE and not all of @@ -14182,6 +14224,7 @@ bgp_vty_init (void) install_element (BGP_IPV6_NODE, &neighbor_set_peer_group_cmd); install_element (BGP_IPV6M_NODE, &neighbor_set_peer_group_cmd); install_element (BGP_VPNV4_NODE, &neighbor_set_peer_group_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_set_peer_group_cmd); /* "no neighbor peer-group unset" commands. */ install_element (BGP_NODE, &no_neighbor_set_peer_group_cmd); @@ -14190,6 +14233,7 @@ bgp_vty_init (void) install_element (BGP_IPV6_NODE, &no_neighbor_set_peer_group_cmd); install_element (BGP_IPV6M_NODE, &no_neighbor_set_peer_group_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_set_peer_group_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_set_peer_group_cmd); /* "neighbor softreconfiguration inbound" commands.*/ install_element (BGP_NODE, &neighbor_soft_reconfiguration_cmd); @@ -14204,6 +14248,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_soft_reconfiguration_cmd); install_element (BGP_VPNV4_NODE, &neighbor_soft_reconfiguration_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_soft_reconfiguration_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_soft_reconfiguration_cmd); /* "neighbor attribute-unchanged" commands. */ install_element (BGP_NODE, &neighbor_attr_unchanged_cmd); @@ -14338,6 +14384,29 @@ bgp_vty_init (void) install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged8_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged9_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_attr_unchanged10_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged1_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged2_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged3_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged4_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged5_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged6_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged7_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged8_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged9_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_attr_unchanged10_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged1_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged2_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged3_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged4_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged5_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged6_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged7_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged8_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged9_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_attr_unchanged10_cmd); + /* "nexthop-local unchanged" commands */ install_element (BGP_IPV6_NODE, &neighbor_nexthop_local_unchanged_cmd); @@ -14356,6 +14425,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_nexthop_self_cmd); install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_nexthop_self_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_nexthop_self_cmd); /* "neighbor next-hop-self force" commands. */ install_element (BGP_NODE, &neighbor_nexthop_self_force_cmd); @@ -14370,6 +14441,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_nexthop_self_force_cmd); install_element (BGP_VPNV4_NODE, &neighbor_nexthop_self_force_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_nexthop_self_force_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_nexthop_self_force_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_nexthop_self_force_cmd); /* "neighbor as-override" commands. */ install_element (BGP_NODE, &neighbor_as_override_cmd); @@ -14384,6 +14457,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_as_override_cmd); install_element (BGP_VPNV4_NODE, &neighbor_as_override_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_as_override_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_as_override_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_as_override_cmd); /* "neighbor remove-private-AS" commands. */ install_element (BGP_NODE, &neighbor_remove_private_as_cmd); @@ -14434,6 +14509,14 @@ bgp_vty_init (void) install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_replace_as_cmd); install_element (BGP_VPNV4_NODE, &neighbor_remove_private_as_all_replace_as_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_all_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_all_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_replace_as_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_remove_private_as_all_replace_as_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_remove_private_as_all_replace_as_cmd); /* "neighbor send-community" commands.*/ install_element (BGP_NODE, &neighbor_send_community_cmd); @@ -14460,6 +14543,10 @@ bgp_vty_init (void) install_element (BGP_VPNV4_NODE, &neighbor_send_community_type_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_send_community_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_send_community_type_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_send_community_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_send_community_type_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_send_community_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_send_community_type_cmd); /* "neighbor route-reflector" commands.*/ install_element (BGP_NODE, &neighbor_route_reflector_client_cmd); @@ -14474,6 +14561,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_route_reflector_client_cmd); install_element (BGP_VPNV4_NODE, &neighbor_route_reflector_client_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_route_reflector_client_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_route_reflector_client_cmd); /* "neighbor route-server" commands.*/ install_element (BGP_NODE, &neighbor_route_server_client_cmd); @@ -14488,6 +14577,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_route_server_client_cmd); install_element (BGP_VPNV4_NODE, &neighbor_route_server_client_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_route_server_client_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_route_server_client_cmd); /* "neighbor addpath-tx-all-paths" commands.*/ install_element (BGP_NODE, &neighbor_addpath_tx_all_paths_cmd); @@ -14502,6 +14593,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_addpath_tx_all_paths_cmd); install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_all_paths_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_addpath_tx_all_paths_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_addpath_tx_all_paths_cmd); /* "neighbor addpath-tx-bestpath-per-AS" commands.*/ install_element (BGP_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); @@ -14516,6 +14609,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); /* "neighbor passive" commands. */ install_element (BGP_NODE, &neighbor_passive_cmd); @@ -14643,6 +14738,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_distribute_list_cmd); install_element (BGP_VPNV4_NODE, &neighbor_distribute_list_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_distribute_list_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_distribute_list_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_distribute_list_cmd); /* "neighbor prefix-list" commands. */ install_element (BGP_NODE, &neighbor_prefix_list_cmd); @@ -14657,6 +14754,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_prefix_list_cmd); install_element (BGP_VPNV4_NODE, &neighbor_prefix_list_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_prefix_list_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_prefix_list_cmd); /* "neighbor filter-list" commands. */ install_element (BGP_NODE, &neighbor_filter_list_cmd); @@ -14671,6 +14770,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_filter_list_cmd); install_element (BGP_VPNV4_NODE, &neighbor_filter_list_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_filter_list_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_filter_list_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_filter_list_cmd); /* "neighbor route-map" commands. */ install_element (BGP_NODE, &neighbor_route_map_cmd); @@ -14685,6 +14786,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_route_map_cmd); install_element (BGP_VPNV4_NODE, &neighbor_route_map_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_route_map_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_route_map_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_route_map_cmd); /* "neighbor unsuppress-map" commands. */ install_element (BGP_NODE, &neighbor_unsuppress_map_cmd); @@ -14699,6 +14802,8 @@ bgp_vty_init (void) install_element (BGP_IPV6M_NODE, &no_neighbor_unsuppress_map_cmd); install_element (BGP_VPNV4_NODE, &neighbor_unsuppress_map_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_unsuppress_map_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_unsuppress_map_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_unsuppress_map_cmd); /* "neighbor maximum-prefix" commands. */ install_element (BGP_NODE, &neighbor_maximum_prefix_cmd); @@ -14779,6 +14884,19 @@ bgp_vty_init (void) install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_threshold_warning_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_restart_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_maximum_prefix_threshold_restart_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_warning_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_val_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_threshold_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_warning_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_threshold_warning_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_restart_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_threshold_restart_cmd); /* "neighbor allowas-in" */ install_element (BGP_NODE, &neighbor_allowas_in_cmd); @@ -14805,6 +14923,10 @@ bgp_vty_init (void) install_element (BGP_VPNV4_NODE, &neighbor_allowas_in_arg_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_allowas_in_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_allowas_in_val_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_allowas_in_cmd); + install_element (BGP_VPNV6_NODE, &neighbor_allowas_in_arg_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_allowas_in_cmd); + install_element (BGP_VPNV6_NODE, &no_neighbor_allowas_in_val_cmd); /* address-family commands. */ install_element (BGP_NODE, &address_family_ipv4_cmd); @@ -14822,6 +14944,7 @@ bgp_vty_init (void) install_element (BGP_IPV6_NODE, &exit_address_family_cmd); install_element (BGP_IPV6M_NODE, &exit_address_family_cmd); install_element (BGP_VPNV4_NODE, &exit_address_family_cmd); + install_element (BGP_VPNV6_NODE, &exit_address_family_cmd); /* "clear ip bgp commands" */ install_element (ENABLE_NODE, &clear_ip_bgp_all_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1e61b0fa2c..06956b0ad6 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -27,6 +27,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "stream.h" #include "command.h" #include "sockunion.h" +#include "sockopt.h" #include "network.h" #include "memory.h" #include "filter.h" @@ -1544,6 +1545,8 @@ peer_as_change (struct peer *peer, as_t as, int as_specified) PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST], PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN], + PEER_FLAG_REFLECTOR_CLIENT); } /* local-as reset */ @@ -3460,7 +3463,8 @@ peer_active (struct peer *peer) || peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_UNICAST] - || peer->afc[AFI_IP6][SAFI_MULTICAST]) + || peer->afc[AFI_IP6][SAFI_MULTICAST] + || peer->afc[AFI_IP6][SAFI_MPLS_VPN]) return 1; return 0; } @@ -3473,7 +3477,8 @@ peer_active_nego (struct peer *peer) || peer->afc_nego[AFI_IP][SAFI_MULTICAST] || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP6][SAFI_UNICAST] - || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]) + || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]) return 1; return 0; } @@ -5982,6 +5987,8 @@ peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi, if (! peer->afc[afi][safi]) return BGP_ERR_AF_UNCONFIGURED; + peer->rtt = sockopt_tcp_rtt (peer->fd); + if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) { /* Clear the "neighbor x.x.x.x default-originate" flag */ @@ -6897,6 +6904,8 @@ bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi, vty_out (vty, "ipv6 unicast"); else if (safi == SAFI_MULTICAST) vty_out (vty, "ipv6 multicast"); + else if (safi == SAFI_MPLS_VPN) + vty_out (vty, "vpnv6"); } vty_out (vty, "%s", VTY_NEWLINE); @@ -7184,6 +7193,9 @@ bgp_config_write (struct vty *vty) /* IPv6 multicast configuration. */ write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST); + /* IPv6 VPN configuration. */ + write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN); + write++; } return write; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 1e7a00628f..b3e508634e 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -569,6 +569,7 @@ struct peer /* Peer information */ int fd; /* File descriptor */ int ttl; /* TTL of TCP connection to the peer. */ + int rtt; /* Estimated round-trip-time from TCP_INFO */ int gtsm_hops; /* minimum hopcount to peer */ char *desc; /* Description of the peer. */ unsigned short port; /* Destination port for peer */ diff --git a/buildtest.sh b/buildtest.sh index 6277589cfb..eafd57dbf3 100755 --- a/buildtest.sh +++ b/buildtest.sh @@ -4,21 +4,16 @@ # builds some git commit of Quagga in some different configurations # usage: buildtest.sh [commit [configurations...]] -basecfg="--prefix=/usr --enable-user=quagga --enable-group=quagga --enable-vty-group=quagga --enable-configfile-mask=0660 --enable-logfile-mask=0640 --enable-vtysh --sysconfdir=/etc/quagga --enable-exampledir=/etc/quagga/samples --localstatedir=/var/run/quagga --libdir=/usr/lib64/quagga --enable-ipv6 --enable-ripngd --enable-ospf6d --enable-rtadv --disable-static --enable-isisd --enable-multipath=0 --enable-pimd --enable-werror" +basecfg="--prefix=/usr --enable-user=quagga --enable-group=quagga --enable-vty-group=quagga --enable-configfile-mask=0660 --enable-logfile-mask=0640 --enable-vtysh --sysconfdir=/etc/quagga --enable-exampledir=/etc/quagga/samples --localstatedir=/var/run/quagga --libdir=/usr/lib64/quagga --enable-rtadv --disable-static --enable-isisd --enable-multipath=0 --enable-pimd --enable-werror" configs_base="gcc|$basecfg" -configs_nov6="gcc|$basecfg" -configs_nov6="${configs_nov6/enable-ipv6/disable-ipv6}" -configs_nov6="${configs_nov6/enable-ospf6d/disable-ospf6d}" -configs_nov6="${configs_nov6/enable-ripngd/disable-ripngd}" - configs_ext="gcc|$basecfg --enable-opaque-lsa --enable-ospf-te --enable-ospfclient --enable-isis-topology" configs_snmp="gcc|$basecfg --enable-opaque-lsa --enable-ospf-te --enable-ospfclient --enable-isis-topology --enable-snmp" configs_clang="clang|$basecfg --enable-opaque-lsa --enable-ospf-te --enable-ospfclient --enable-isis-topology" configs_icc="icc|$basecfg --enable-opaque-lsa --enable-ospf-te --enable-ospfclient --enable-isis-topology" -defconfigs="base nov6 ext" +defconfigs="base ext" net-snmp-config --version &> /dev/null && defconfigs="$defconfigs snmp" clang --version &> /dev/null && defconfigs="$defconfigs clang" icc --version &> /dev/null && defconfigs="$defconfigs icc" diff --git a/configure.ac b/configure.ac index fa519a59a8..151214b88f 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,9 @@ ## AC_PREREQ(2.60) -AC_INIT(Quagga, 0.99.23.1+cl3u2, [https://bugzilla.quagga.net]) +AC_INIT(Quagga, 0.99.24+cl3u2, [https://bugzilla.quagga.net]) +CONFIG_ARGS="$*" +AC_SUBST(CONFIG_ARGS) AC_CONFIG_SRCDIR(lib/zebra.h) AC_CONFIG_MACRO_DIR([m4]) @@ -33,7 +35,7 @@ AC_ARG_VAR([GAWK],[GNU AWK]) dnl default is to match previous behavior exampledir=${sysconfdir} AC_ARG_ENABLE([exampledir], - AC_HELP_STRING([--enable-exampledir], + AS_HELP_STRING([--enable-exampledir], [specify alternate directory for examples]), exampledir="$enableval",) dnl XXX add --exampledir to autoconf standard directory list somehow @@ -43,7 +45,7 @@ dnl default is to match previous behavior pkgsrcrcdir="" pkgsrcdir="" AC_ARG_ENABLE([pkgsrcrcdir], - AC_HELP_STRING([--enable-pkgsrcrcdir], + AS_HELP_STRING([--enable-pkgsrcrcdir], [specify directory for rc.d scripts]), pkgsrcrcdir="$enableval"; pkgsrcdir="pkgsrc",) dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow @@ -98,20 +100,7 @@ else fi AM_CONDITIONAL([HAVE_LATEX], [test "x$HAVE_LATEX" = "xtrue"]) -dnl ------------------------------------------------------------------ -dnl Intel compiler check. Although Intel tries really hard to make icc -dnl look like gcc, there are some differences. It's very verbose with -dnl -Wall and it doesn't support the individual -W options. -dnl ------------------------------------------------------------------ -if test "x${GCC}" = "xyes" ; then - COMPILER="GCC" - AC_MSG_CHECKING([whether we are using the Intel compiler]) - AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER], - [AC_MSG_RESULT([no])], - [COMPILER="ICC" - AC_MSG_RESULT([yes])] - ) -else +if test "x${GCC}" != "xyes" ; then AC_MSG_CHECKING([whether we are using SunPro compiler]) AC_EGREP_CPP([^__SUNPRO_C.*0x5(7|8|9)], ["__SUNPRO_C" __SUNPRO_C], [AC_MSG_RESULT([no])], @@ -127,41 +116,73 @@ dnl already, eg "-O2 -g" for gcc, "-g" for others dnl (Wall is gcc specific... have to make sure dnl gcc is being used before setting it) dnl -dnl Intel icc 8.0 also sets __GNUC__, -dnl but doesn't support all these fancy -W options. -dnl Intel compiler warnings we ignore: -dnl 279: controlling expression is constant. -dnl 869: parameter "xxx" was never referenced - to avoid massive warnings -dnl about "self", "vty", "argc" and "argv" never referenced in DEFUN -dnl macro. -dnl 981: operands are evaluated in unspecified order. -dnl dnl Sun Studio 10 / SunPro 5.7 is also supported, dnl so lets set some sane CFLAGS for it. dnl --------------------------------------------- +AC_USE_SYSTEM_EXTENSIONS() +AC_DEFUN([AC_C_FLAG], [{ + AC_LANG_PUSH(C) + ac_c_flag_save="$CFLAGS" + CFLAGS="$CFLAGS $1" + AC_MSG_CHECKING([[whether $CC supports $1]]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]])], + [ + AC_MSG_RESULT([yes]) + m4_if([$3], [], [], [ + CFLAGS="$ac_c_flag_save" + $3 + ]) + ], [ + CFLAGS="$ac_c_flag_save" + AC_MSG_RESULT([no]) + $2 + ]) + AC_LANG_POP(C) + }]) + AC_MSG_CHECKING([whether to set a default CFLAGS]) if test "x${cflags_specified}" = "x" ; then case ${COMPILER} in - "ICC") - CFLAGS="-Os -g -Wall" - AC_MSG_RESULT([Intel default]) - ;; - "GCC") - CFLAGS="-Os -fno-omit-frame-pointer -g -std=gnu99 -Wall" - CFLAGS="${CFLAGS} -Wsign-compare -Wpointer-arith" - CFLAGS="${CFLAGS} -Wbad-function-cast -Wwrite-strings" - CFLAGS="${CFLAGS} -Wmissing-prototypes -Wmissing-declarations" - CFLAGS="${CFLAGS} -Wchar-subscripts -Wcast-qual" - # TODO: conditionally addd -Wpacked if handled - AC_MSG_RESULT([gcc default]) - ;; "SUNPRO") - CFLAGS="-xO4 -v -g -xspace -xcode=pic32 -xstrconst -xc99" - AC_MSG_RESULT([SunPro default]) - ;; + CFLAGS="-xO4 -v -g -xspace -xcode=pic32 -xstrconst -xc99" + AC_MSG_RESULT([SunPro default]) + ;; *) - AC_MSG_RESULT([unknown compiler]) + AC_MSG_RESULT([autodetecting]) + + AC_C_FLAG([-diag-error 10006]) + AC_C_FLAG([-std=gnu99]) + AC_C_FLAG([-g]) + AC_C_FLAG([-Os], [ + AC_C_FLAG([-O2]) + ]) + AC_C_FLAG([-fno-omit-frame-pointer]) + AC_C_FLAG([-Wall]) + AC_C_FLAG([-Wextra]) + AC_C_FLAG([-Wmissing-prototypes]) + AC_C_FLAG([-Wmissing-declarations]) + AC_C_FLAG([-Wpointer-arith]) + AC_C_FLAG([-Wbad-function-cast]) + AC_C_FLAG([-Wwrite-strings]) + if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then + AC_C_FLAG([-Wcast-qual]) + AC_C_FLAG([-Wstrict-prototypes]) + AC_C_FLAG([-Wmissing-noreturn]) + AC_C_FLAG([-Wmissing-format-attribute]) + AC_C_FLAG([-Wunreachable-code]) + AC_C_FLAG([-Wpacked]) + AC_C_FLAG([-Wpadded]) + else + AC_C_FLAG([-Wno-unused-result]) + fi + AC_C_FLAG([-Wno-unused-parameter]) + AC_C_FLAG([-Wno-missing-field-initializers]) + # ICC emits a broken warning for const char *x = a ? "b" : "c"; + # for some reason the string consts get 'promoted' to char *, + # triggering a const to non-const conversion warning. + AC_C_FLAG([-diag-disable 3179]) ;; esac else @@ -217,105 +238,90 @@ AC_ARG_WITH(pkg-git-version, AS_HELP_STRING([--with-pkg-git-version], [add git information to MOTD and build version string]), [ test "x$withval" != "xno" && with_pkg_git_version="yes" ]) AC_ARG_ENABLE(vtysh, -[ --disable-vtysh do not build integrated vty shell for Quagga]) -AC_ARG_ENABLE(ipv6, -[ --disable-ipv6 turn off IPv6 related features and daemons]) + AS_HELP_STRING([--disable-vtysh], [do not build integrated vty shell for Quagga])) AC_ARG_ENABLE(doc, -[ --disable-doc do not build docs]) + AS_HELP_STRING([--disable-doc], [do not build docs])) AC_ARG_ENABLE(zebra, -[ --disable-zebra do not build zebra daemon]) + AS_HELP_STRING([--disable-zebra], [do not build zebra daemon])) AC_ARG_ENABLE(bgpd, -[ --disable-bgpd do not build bgpd]) + AS_HELP_STRING([--disable-bgpd], [do not build bgpd])) AC_ARG_ENABLE(ripd, -[ --disable-ripd do not build ripd]) + AS_HELP_STRING([--disable-ripd], [do not build ripd])) AC_ARG_ENABLE(ripngd, -[ --disable-ripngd do not build ripngd]) + AS_HELP_STRING([--disable-ripngd], [do not build ripngd])) AC_ARG_ENABLE(ospfd, -[ --disable-ospfd do not build ospfd]) + AS_HELP_STRING([--disable-ospfd], [do not build ospfd])) AC_ARG_ENABLE(ospf6d, -[ --disable-ospf6d do not build ospf6d]) + AS_HELP_STRING([--disable-ospf6d], [do not build ospf6d])) AC_ARG_ENABLE(watchquagga, -[ --disable-watchquagga do not build watchquagga]) + AS_HELP_STRING([--disable-watchquagga], [do not build watchquagga])) AC_ARG_ENABLE(isisd, -[ --enable-isisd build isisd]) + AS_HELP_STRING([--disable-isisd], [do not build isisd])) AC_ARG_ENABLE(pimd, -[ --disable-pimd do not build pimd]) -AC_ARG_ENABLE(solaris, -[ --enable-solaris build solaris]) + AS_HELP_STRING([--disable-pimd], [do not build pimd])) AC_ARG_ENABLE(bgp-announce, -[ --disable-bgp-announce, turn off BGP route announcement]) -AC_ARG_ENABLE(netlink, -[ --enable-netlink force to use Linux netlink interface]) -AC_ARG_ENABLE(broken-aliases, -[ --enable-broken-aliases enable aliases as distinct interfaces for Linux 2.2.X]) + AS_HELP_STRING([--disable-bgp-announce,], [turn off BGP route announcement])) AC_ARG_ENABLE(snmp, -[ --enable-snmp=ARG enable SNMP support (smux or agentx)]) + AS_HELP_STRING([--enable-snmp=ARG], [enable SNMP support (smux or agentx)])) AC_ARG_WITH(libpam, -[ --with-libpam use libpam for PAM support in vtysh]) + AS_HELP_STRING([--with-libpam], [use libpam for PAM support in vtysh])) AC_ARG_ENABLE(tcp-zebra, -[ --enable-tcp-zebra enable TCP/IP socket connection between zebra and protocol daemon]) + AS_HELP_STRING([--enable-tcp-zebra], [enable TCP/IP socket connection between zebra and protocol daemon])) AC_ARG_ENABLE(opaque-lsa, - AC_HELP_STRING([--disable-opaque-lsa],[do not build OSPF Opaque-LSA with OSPFAPI support (RFC2370)])) + AS_HELP_STRING([--disable-opaque-lsa],[do not build OSPF Opaque-LSA with OSPFAPI support (RFC2370)])) AC_ARG_ENABLE(ospfapi, -[ --disable-ospfapi do not build OSPFAPI to access the OSPF LSA Database]) + AS_HELP_STRING([--disable-ospfapi], [do not build OSPFAPI to access the OSPF LSA Database])) AC_ARG_ENABLE(ospfclient, -[ --disable-ospfclient do not build OSPFAPI client for OSPFAPI, - (this is the default if --disable-ospfapi is set)]) + AS_HELP_STRING([--disable-ospfclient], [do not build OSPFAPI client for OSPFAPI, + (this is the default if --disable-ospfapi is set)])) AC_ARG_ENABLE(ospf-te, - AC_HELP_STRING([--disable-ospf-te],[disable Traffic Engineering Extension to OSPF])) + AS_HELP_STRING([--disable-ospf-te],[disable Traffic Engineering Extension to OSPF])) AC_ARG_ENABLE(multipath, -[ --enable-multipath=ARG enable multipath function, ARG must be digit]) + AS_HELP_STRING([--enable-multipath=ARG], [enable multipath function, ARG must be digit])) AC_ARG_ENABLE(user, - AC_HELP_STRING([--enable-user=user], [user to run Quagga suite as (default quagga)])) + AS_HELP_STRING([--enable-user=USER], [user to run Quagga suite as (default quagga)])) AC_ARG_ENABLE(group, - AC_HELP_STRING([--enable-group=group], [group to run Quagga suite as (default quagga)])) + AS_HELP_STRING([--enable-group=GROUP], [group to run Quagga suite as (default quagga)])) AC_ARG_ENABLE(vty_group, -[ --enable-vty-group=ARG set vty sockets to have specified group as owner]) + AS_HELP_STRING([--enable-vty-group=ARG], [set vty sockets to have specified group as owner])) AC_ARG_ENABLE(configfile_mask, -[ --enable-configfile-mask=ARG set mask for config files]) + AS_HELP_STRING([--enable-configfile-mask=ARG], [set mask for config files])) AC_ARG_ENABLE(logfile_mask, -[ --enable-logfile-mask=ARG set mask for log files]) + AS_HELP_STRING([--enable-logfile-mask=ARG], [set mask for log files])) AC_ARG_ENABLE(shell_access, -[ --enable-shell-access Allow users to access shell/telnet/ssh]) + AS_HELP_STRING([--enable-shell-access], [Allow users to access shell/telnet/ssh])) AC_ARG_ENABLE(rtadv, -[ --disable-rtadv disable IPV6 router advertisement feature]) + AS_HELP_STRING([--disable-rtadv], [disable IPV6 router advertisement feature])) AC_ARG_ENABLE(irdp, -[ --enable-irdp enable IRDP server support in zebra]) + AS_HELP_STRING([--enable-irdp], [enable IRDP server support in zebra])) AC_ARG_ENABLE(isis_topology, -[ --enable-isis-topology enable IS-IS topology generator]) + AS_HELP_STRING([--enable-isis-topology], [enable IS-IS topology generator])) AC_ARG_ENABLE(capabilities, -[ --disable-capabilities disable using POSIX capabilities]) + AS_HELP_STRING([--disable-capabilities], [disable using POSIX capabilities])) AC_ARG_ENABLE(rusage, -[ --disable-rusage disable using getrusage]) + AS_HELP_STRING([--disable-rusage], [disable using getrusage])) AC_ARG_ENABLE(gcc_ultra_verbose, -[ --enable-gcc-ultra-verbose enable ultra verbose GCC warnings]) + AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings])) AC_ARG_ENABLE(linux24_tcp_md5, -[ --enable-linux24-tcp-md5 enable support for old, Linux-2.4 RFC2385 patch]) + AS_HELP_STRING([--enable-linux24-tcp-md5], [enable support for old, Linux-2.4 RFC2385 patch])) AC_ARG_ENABLE(gcc-rdynamic, -[ --enable-gcc-rdynamic enable linking with -rdynamic for better backtraces (default if gcc)]) + AS_HELP_STRING([--enable-gcc-rdynamic], [enable linking with -rdynamic for better backtraces (default if gcc)])) AC_ARG_ENABLE(backtrace, -[ --disable-backtrace, disable crash backtraces (default autodetect)]) + AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)])) AC_ARG_ENABLE(time-check, -[ --disable-time-check disable slow thread warning messages]) + AS_HELP_STRING([--disable-time-check], [disable slow thread warning messages])) AC_ARG_ENABLE(pcreposix, -[ --enable-pcreposix enable using PCRE Posix libs for regex functions]) + AS_HELP_STRING([--enable-pcreposix], [enable using PCRE Posix libs for regex functions])) AC_ARG_ENABLE(fpm, -[ --enable-fpm enable Forwarding Plane Manager support]) + AS_HELP_STRING([--enable-fpm], [enable Forwarding Plane Manager support])) AC_ARG_ENABLE(systemd, -[ --enable-systemd enable Systemd support]) + AS_HELP_STRING([--enable-systemd], [enable Systemd support])) AC_ARG_ENABLE(poll, -[ --enable-poll enable usage of Poll instead of select]) + AS_HELP_STRING([--enable-poll], [enable usage of Poll instead of select])) AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], [enable -Werror (recommended for developers only)])) AC_ARG_ENABLE(cumulus, -[ --enable-cumulus enable Cumulus Switch Special Extensions]) - -if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then - CFLAGS="${CFLAGS} -W -Wcast-qual -Wstrict-prototypes" - CFLAGS="${CFLAGS} -Wmissing-declarations -Wmissing-noreturn" - CFLAGS="${CFLAGS} -Wmissing-format-attribute -Wunreachable-code" - CFLAGS="${CFLAGS} -Wpacked -Wpadded" -fi + AS_HELP_STRING([--enable-cumulus], [enable Cumulus Switch Special Extensions])) if test x"${enable_gcc_rdynamic}" != x"no" ; then if test x"${enable_gcc_rdynamic}" = x"yes" -o x"$COMPILER" = x"GCC"; then @@ -352,15 +358,6 @@ if test "${enable_fpm}" = "yes"; then AC_DEFINE(HAVE_FPM,,Forwarding Plane Manager support) fi -if test "${enable_broken_aliases}" = "yes"; then - if test "${enable_netlink}" = "yes" - then - AC_MSG_FAILURE([Sorry you can not use netlink with broken aliases]) - fi - AC_DEFINE(HAVE_BROKEN_ALIASES,,Broken Alias) - enable_netlink=no -fi - if test "${enable_tcp_zebra}" = "yes"; then AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication) fi @@ -390,7 +387,7 @@ if test "${enable_irdp}" = "yes"; then AC_DEFINE(HAVE_IRDP,, IRDP ) fi -if test "${enable_isisd}" = "yes" && test "${enable_isis_topology}" = yes; then +if test "${enable_isisd}" != "no" && test "${enable_isis_topology}" = yes; then AC_DEFINE(TOPOLOGY_GENERATE,,Enable IS-IS topology generator code) ISIS_TOPOLOGY_INCLUDES="-I\$(srcdir)/topology" ISIS_TOPOLOGY_DIR="topology" @@ -484,7 +481,6 @@ dnl AC_TYPE_PID_T AC_TYPE_UID_T AC_TYPE_MODE_T AC_TYPE_SIZE_T -AC_TYPE_SIGNAL AC_STRUCT_TM dnl ------------------------- @@ -637,6 +633,7 @@ case "$host" in AC_DEFINE(SUNOS_5, 1, SunOS 5) AC_CHECK_LIB(xnet, main) CURSES=-lcurses + SOLARIS="solaris" ;; [*-sunos5.[8-9]] \ | [*-sunos5.1[0-9]] \ @@ -655,34 +652,23 @@ case "$host" in AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality]) ]) CURSES=-lcurses + SOLARIS="solaris" ;; *-sunos5* | *-solaris2*) AC_DEFINE(SUNOS_5,,SunOS 5, Unknown SunOS) AC_CHECK_LIB(socket, main) AC_CHECK_LIB(nsl, main) CURSES=-lcurses + SOLARIS="solaris" ;; *-linux*) opsys=gnu-linux AC_DEFINE(GNU_LINUX,,GNU Linux) ;; - *-nec-sysv4*) - AC_CHECK_LIB(nsl, gethostbyname) - AC_CHECK_LIB(socket, socket) - ;; *-openbsd*) opsys=openbsd AC_DEFINE(OPEN_BSD,,OpenBSD) ;; - *-bsdi*) - opsys=bsdi - OTHER_METHOD="mtu_kvm.o" - AC_CHECK_LIB(kvm, main) - ;; - *-irix6.5) - opsys=irix - AC_DEFINE(IRIX_65,,IRIX 6.5) - ;; esac AC_SYS_LARGEFILE @@ -853,55 +839,18 @@ dnl Determine routing get and set method dnl ------------------------------------ AC_MSG_CHECKING(zebra between kernel interface method) if test x"$opsys" = x"gnu-linux"; then - if test "${enable_netlink}" = "no"; then - AC_MSG_RESULT(ioctl) - RT_METHOD=rt_ioctl.o - netlink=no - else - AC_MSG_RESULT(netlink) - RT_METHOD=rt_netlink.o - AC_DEFINE(HAVE_NETLINK,,netlink) - netlink=yes - AC_CHECK_DECLS([IFLA_INFO_SLAVE_KIND], [], [], [#include ]) - fi -elif test x"$opsys" = x"sol2-6";then - AC_MSG_RESULT(Route socket) - KERNEL_METHOD="kernel_socket.o" - RT_METHOD="rt_socket.o" -elif test x"$opsys" = x"sol8";then - AC_MSG_RESULT(Route socket) - KERNEL_METHOD="kernel_socket.o" - RT_METHOD="rt_socket.o" -elif test "$opsys" = "irix" ; then - AC_MSG_RESULT(Route socket) - KERNEL_METHOD="kernel_socket.o" - RT_METHOD="rt_socket.o" + AC_MSG_RESULT(netlink) + RT_METHOD=rt_netlink.o + AC_DEFINE(HAVE_NETLINK,,netlink) + netlink=yes + AC_CHECK_DECLS([IFLA_INFO_SLAVE_KIND], [], [], [#include ]) else - AC_TRY_RUN([#include -#include -#include - -main () -{ - int ac_sock; - - ac_sock = socket (AF_ROUTE, SOCK_RAW, 0); - if (ac_sock < 0 && errno == EINVAL) - exit (1); - exit (0); -}], - [KERNEL_METHOD=kernel_socket.o - RT_METHOD=rt_socket.o - AC_MSG_RESULT(socket)], - [RT_METHOD=rt_ioctl.o - AC_MSG_RESULT(ioctl)], - [KERNEL_METHOD=kernel_socket.o - RT_METHOD=rt_socket.o - AC_MSG_RESULT(socket)]) + AC_MSG_RESULT(Route socket) + KERNEL_METHOD="kernel_socket.o" + RT_METHOD="rt_socket.o" fi AC_SUBST(RT_METHOD) AC_SUBST(KERNEL_METHOD) -AC_SUBST(OTHER_METHOD) AM_CONDITIONAL([HAVE_NETLINK], [test "x$netlink" = "xyes"]) dnl -------------------------- @@ -976,12 +925,11 @@ AC_CACHE_CHECK([route read method], [quagga_cv_rtread_method], [if test "x$netlink" = xyes; then quagga_cv_rtread_method="netlink" else -for quagga_cv_rtread_method in /proc/net/route /dev/ip /dev/null; +for quagga_cv_rtread_method in /dev/ip /dev/null; do test x`ls $quagga_cv_rtread_method 2>/dev/null` = x"$quagga_cv_rtread_method" && break done case $quagga_cv_rtread_method in - "/proc/net/route") quagga_cv_rtread_method="proc";; "/dev/ip") case "$host" in *-freebsd*) quagga_cv_rtread_method="sysctl";; @@ -1009,9 +957,6 @@ elif test "$opsys" = "sol8";then AC_MSG_RESULT(Solaris GLIF) IF_METHOD=if_ioctl_solaris.o IOCTL_METHOD=ioctl_solaris.o -elif test "$opsys" = "irix" ; then - AC_MSG_RESULT(IRIX) - IF_METHOD=if_ioctl.o elif test "$opsys" = "openbsd";then AC_MSG_RESULT(openbsd) IF_METHOD=if_ioctl.o @@ -1103,21 +1048,6 @@ if test $ac_cv_have_decl_TCP_MD5SIG = no; then AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)]) fi -dnl ----------------------- -dnl check proc file system. -dnl ----------------------- -if test "$netlink" != yes; then - if test -r /proc/net/dev; then - AC_DEFINE(HAVE_PROC_NET_DEV,,/proc/net/dev) - IF_PROC=if_proc.o - fi - if test -r /proc/net/if_inet6; then - AC_DEFINE(HAVE_PROC_NET_IF_INET6,,/proc/net/if_inet6) - IF_PROC=if_proc.o - fi -fi -AC_SUBST(IF_PROC) - dnl ----------------------------- dnl check ipforward detect method dnl ----------------------------- @@ -1138,7 +1068,6 @@ case $quagga_cv_ipforward_method in "/proc/net/snmp") quagga_cv_ipforward_method="proc";; "/dev/ip") case "$host" in - *-nec-sysv4*) quagga_cv_ipforward_method="ews";; *-freebsd*) quagga_cv_ipforward_method="sysctl";; *) quagga_cv_ipforward_method="solaris";; esac;; @@ -1153,111 +1082,22 @@ dnl ---------- dnl IPv6 check dnl ---------- AC_MSG_CHECKING(whether does this OS have IPv6 stack) -if test "${enable_ipv6}" = "no"; then - AC_MSG_RESULT(disabled) -else -dnl ---------- -dnl INRIA IPv6 -dnl ---------- - if grep IPV6_INRIA_VERSION /usr/include/netinet/in.h >/dev/null 2>&1; then - zebra_cv_ipv6=yes - AC_DEFINE(HAVE_IPV6,1,INRIA IPv6) - AC_DEFINE(INRIA_IPV6,1,INRIA IPv6) - RIPNGD="ripngd" - OSPF6D="ospf6d" - LIB_IPV6="" - AC_MSG_RESULT(INRIA IPv6) dnl --------- dnl KAME IPv6 dnl --------- - elif grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then - zebra_cv_ipv6=yes - AC_DEFINE(HAVE_IPV6,1,KAME IPv6) + if grep WIDE /usr/include/netinet6/in6.h >/dev/null 2>&1; then AC_DEFINE(KAME,1,KAME IPv6) - RIPNGD="ripngd" - OSPF6D="ospf6d" - if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then - LIB_IPV6="-L/usr/local/v6/lib -linet6" - fi AC_MSG_RESULT(KAME) -dnl ------------------------- -dnl MUSICA IPv6 -dnl default host check -dnl It is not used by Kheops -dnl ------------------------- - elif grep MUSICA /usr/include6/netinet6/in6.h >/dev/null 2>&1; then - zebra_cv_ipv6=yes - AC_DEFINE(HAVE_IPV6,1,Musicia IPv6) - AC_DEFINE(MUSICA,1,Musica IPv6 stack) - AC_DEFINE(KAME,1,KAME IPv6 stack) - RIPNGD="ripngd" - OSPF6D="ospf6d" - if test -d /usr/local/v6/lib -a -f /usr/local/v6/lib/libinet6.a; then - LIB_IPV6="-L/usr/local/v6/lib -linet6" - fi - AC_MSG_RESULT(MUSICA) -dnl --------- -dnl NRL check -dnl --------- - elif grep NRL /usr/include/netinet6/in6.h >/dev/null 2>&1; then - zebra_cv_ipv6=yes - AC_DEFINE(HAVE_IPV6,1,NRL IPv6) - AC_DEFINE(NRL,1,NRL) - RIPNGD="ripngd" - OSPF6D="ospf6d" - if test x"$opsys" = x"bsdi";then - AC_DEFINE(BSDI_NRL,,BSDI) - AC_MSG_RESULT(BSDI_NRL) - else - AC_MSG_RESULT(NRL) - fi dnl ------------------------------------ dnl Solaris 9, 10 and potentially higher dnl ------------------------------------ elif test x"$opsys" = x"sol8"; then - zebra_cv_ipv6=yes; - AC_DEFINE(HAVE_IPV6, 1, IPv6) AC_DEFINE(SOLARIS_IPV6, 1, Solaris IPv6) - RIPNGD="ripngd" - OSPF6D="ospf6d" AC_MSG_RESULT(Solaris IPv6) dnl ---------- dnl Linux IPv6 dnl ---------- - elif test "${enable_ipv6}" = "yes"; then - AC_EGREP_CPP(yes, [ - #include - /* 2.1.128 or later */ - #if LINUX_VERSION_CODE >= 0x020180 - yes - #endif], - [zebra_cv_ipv6=yes - zebra_cv_linux_ipv6=yes - AC_MSG_RESULT(Linux IPv6)]) - else - if test x`ls /proc/net/ipv6_route 2>/dev/null` = x"/proc/net/ipv6_route" - then - zebra_cv_ipv6=yes - zebra_cv_linux_ipv6=yes - AC_MSG_RESULT(Linux IPv6) - fi - fi - - if test "$zebra_cv_linux_ipv6" = "yes";then - AC_MSG_CHECKING(whether libc has IPv6 support) - AC_TRY_LINK([#include - ],[ int a; a = (int) in6addr_any.s6_addr[0]; if (a != 12345) return a; ], - [AC_MSG_RESULT(yes) - zebra_cv_ipv6=yes - zebra_cv_linux_ipv6=yes], - [AC_MSG_RESULT(no) - zebra_cv_ipv6=no - zebra_cv_linux_ipv6=no]) - fi - - if test "$zebra_cv_linux_ipv6" = "yes";then - AC_MSG_CHECKING(for GNU libc >= 2.1) - AC_DEFINE(HAVE_IPV6,1,Linux IPv6) + elif test x"$opsys" = x"gnu-linux"; then AC_DEFINE(LINUX_IPV6,1,Linux IPv6 stack) dnl Linux has a compilation problem with mixing dnl netinet/in.h and linux/in6.h they are not @@ -1265,45 +1105,20 @@ dnl ---------- dnl how to fix it but no real progress on implementation dnl when they fix it, remove this AC_DEFINE(IPV6_MINHOPCOUNT, 73, Linux ipv6 Min Hop Count) - - AC_EGREP_CPP(yes, [ -#include -#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 - yes -#endif], - [glibc=yes - AC_MSG_RESULT(yes)], - AC_MSG_RESULT(no) - ) - RIPNGD="ripngd" - OSPF6D="ospf6d" - if test "$glibc" != "yes"; then - if test x`ls /usr/inet6/lib/libinet6.a 2>/dev/null` != x;then - INCLUDES="-I/usr/inet6/include" - LIB_IPV6="-L/usr/inet6/lib -linet6" - fi - fi + AC_MSG_RESULT(Linux IPv6) + else + AC_MSG_ERROR([Failed to detect IPv6 stack]) fi -dnl ----------------------- -dnl Set IPv6 related values -dnl ----------------------- - LIBS="$LIB_IPV6 $LIBS" - AC_SUBST(LIB_IPV6) - - if test x"$RIPNGD" = x""; then - AC_MSG_RESULT(IPv4 only) - fi -fi +dnl this is unconditial, for compatibility +AC_DEFINE(HAVE_IPV6,1,IPv6) dnl ------------------ dnl IPv6 header checks dnl ------------------ -if test "x${zebra_cv_ipv6}" = "xyes"; then AC_CHECK_HEADERS([netinet6/in6.h netinet/in6_var.h netinet/icmp6.h \ netinet6/in6_var.h netinet6/nd6.h], [], [], QUAGGA_INCLUDES) -fi m4_define([QUAGGA_INCLUDES],dnl QUAGGA_INCLUDES @@ -1383,23 +1198,20 @@ fi AM_CONDITIONAL(OSPFCLIENT, test "x$OSPFCLIENT" = "xospfclient") case "${enable_ripngd}" in - "yes") RIPNGD="ripngd";; "no" ) RIPNGD="";; - * ) ;; + * ) RIPNGD="ripngd";; esac AM_CONDITIONAL(RIPNGD, test "x$RIPNGD" = "xripngd") case "${enable_ospf6d}" in - "yes") OSPF6D="ospf6d";; "no" ) OSPF6D="";; - * ) ;; + * ) OSPF6D="ospf6d";; esac AM_CONDITIONAL(OSPF6D, test "x$OSPF6D" = "xospf6d") case "${enable_isisd}" in - "yes") ISISD="isisd";; "no" ) ISISD="";; - * ) ;; + * ) ISISD="isisd";; esac AM_CONDITIONAL(ISISD, test "x$ISISD" = "xisisd") @@ -1409,13 +1221,6 @@ case "${enable_pimd}" in esac AM_CONDITIONAL(PIMD, test "x$PIMD" = "xpimd") -# XXX Perhaps auto-enable on Solaris, but that's messy for cross builds. -case "${enable_solaris}" in - "yes") SOLARIS="solaris";; - "no" ) SOLARIS="";; - * ) ;; -esac - if test "${enable_bgp_announce}" = "no";then AC_DEFINE(DISABLE_BGP_ANNOUNCE,1,Disable BGP installation to zebra) else @@ -1434,7 +1239,6 @@ AC_SUBST(ISISD) AC_SUBST(PIMD) AC_SUBST(SOLARIS) AC_SUBST(VTYSH) -AC_SUBST(INCLUDES) AC_SUBST(CURSES) AC_SUBST(OSPFCLIENT) AC_SUBST(OSPFAPI) @@ -1788,7 +1592,6 @@ source code location : ${srcdir} compiler : ${CC} compiler flags : ${CFLAGS} make : ${MAKE-make} -includes : ${INCLUDES} linker flags : ${LDFLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM} state file directory : ${quagga_statedir} config file directory : `eval echo \`echo ${sysconfdir}\`` diff --git a/isisd/Makefile.am b/isisd/Makefile.am index dcb54d5970..5f866638d9 100644 --- a/isisd/Makefile.am +++ b/isisd/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib \ +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib \ @ISIS_TOPOLOGY_INCLUDES@ DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index bfd43d454b..c7ab83ba0b 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -390,7 +390,8 @@ isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail) vty_out (vty, "%-13s", adj_state2string (adj->adj_state)); now = time (NULL); if (adj->last_upd) - vty_out (vty, "%-9lu", adj->last_upd + adj->hold_time - now); + vty_out (vty, "%-9llu", + (unsigned long long)adj->last_upd + adj->hold_time - now); else vty_out (vty, "- "); vty_out (vty, "%-10s", snpa_print (adj->snpa)); diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 61b1e05eb2..889b4c3099 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -302,13 +302,14 @@ int isis_send_pdu_bcast (struct isis_circuit *circuit, int level) { struct ether_header *eth; - int written, buflen; + ssize_t written; + size_t buflen; buflen = stream_get_endp (circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN; if (buflen > sizeof (sock_buff)) { - zlog_warn ("isis_send_pdu_bcast: sock_buff size %lu is less than " - "output pdu size %d on circuit %s", + zlog_warn ("isis_send_pdu_bcast: sock_buff size %zu is less than " + "output pdu size %zu on circuit %s", sizeof (sock_buff), buflen, circuit->interface->name); return ISIS_WARNING; } diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 6c3d7c00ff..7309248611 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -393,7 +393,7 @@ lsp_auth_update (struct isis_lsp *lsp) /* Compute autentication value */ hmac_md5 (STREAM_DATA (lsp->pdu), stream_get_endp(lsp->pdu), (unsigned char *) &passwd->passwd, passwd->len, - (caddr_t) &hmac_md5_hash); + (unsigned char *) &hmac_md5_hash); /* Copy the hash into the stream */ memcpy (STREAM_DATA (lsp->pdu) + lsp->auth_tlv_offset + 3, hmac_md5_hash, ISIS_AUTH_MD5_SIZE); @@ -2742,7 +2742,7 @@ static int top_lsp_refresh (struct thread *thread) { struct isis_lsp *lsp; - u_int16_t rem_lifetime, refresh_time; + u_int16_t rem_lifetime; lsp = THREAD_ARG (thread); assert (lsp); @@ -2767,7 +2767,7 @@ top_lsp_refresh (struct thread *thread) rem_lifetime = lsp_rem_lifetime (lsp->area, IS_LEVEL_1); lsp->lsp_header->rem_lifetime = htons (rem_lifetime); - refresh_time = lsp_refresh_time (lsp, rem_lifetime); + /* refresh_time = lsp_refresh_time (lsp, rem_lifetime); */ THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp, lsp->area->lsp_refresh[0]); diff --git a/isisd/isis_main.c b/isisd/isis_main.c index f2fe4ef71f..343c683f48 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -327,7 +327,7 @@ main (int argc, char **argv, char **envp) master = thread_master_create (); /* random seed from time */ - srand (time (NULL)); + srandom (time (NULL)); /* * initializations diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c index 230fe24387..f19b44155a 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -510,7 +510,7 @@ isis_jitter (unsigned long timer, unsigned long jitter) * most IS-IS timers are no longer than 16 bit */ - j = 1 + (int) ((RANDOM_SPREAD * rand ()) / (RAND_MAX + 1.0)); + j = 1 + (int) ((RANDOM_SPREAD * random ()) / (RAND_MAX + 1.0)); k = timer - (timer * (100 - jitter)) / 100; diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 70bc004b11..0401e44a9a 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -204,7 +204,7 @@ authentication_check (struct isis_passwd *remote, struct isis_passwd *local, /* Compute the digest */ hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream), (unsigned char *) &(local->passwd), local->len, - (caddr_t) &digest); + (unsigned char *) &digest); /* Copy back the authentication value after the check */ memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3, remote->passwd, ISIS_AUTH_MD5_SIZE); @@ -2271,7 +2271,7 @@ send_hello (struct isis_circuit *circuit, int level) struct isis_lan_hello_hdr hello_hdr; struct isis_p2p_hello_hdr p2p_hello_hdr; unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; - unsigned long len_pointer, length, auth_tlv_offset = 0; + size_t len_pointer, length, auth_tlv_offset = 0; u_int32_t interval; int retval; @@ -2416,7 +2416,7 @@ send_hello (struct isis_circuit *circuit, int level) hmac_md5 (STREAM_DATA (circuit->snd_stream), stream_get_endp (circuit->snd_stream), (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, - (caddr_t) &hmac_md5_hash); + (unsigned char *) &hmac_md5_hash); /* Copy the hash into the stream */ memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, hmac_md5_hash, ISIS_AUTH_MD5_SIZE); @@ -2426,16 +2426,14 @@ send_hello (struct isis_circuit *circuit, int level) { if (circuit->circ_type == CIRCUIT_T_BROADCAST) { - zlog_debug ("ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %ld", + zlog_debug ("ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd", circuit->area->area_tag, level, circuit->interface->name, - /* FIXME: use %z when we stop supporting old compilers. */ length); } else { - zlog_debug ("ISIS-Adj (%s): Sending P2P IIH on %s, length %ld", + zlog_debug ("ISIS-Adj (%s): Sending P2P IIH on %s, length %zd", circuit->area->area_tag, circuit->interface->name, - /* FIXME: use %z when we stop supporting old compilers. */ length); } if (isis->debugs & DEBUG_PACKET_DUMP) @@ -2614,7 +2612,7 @@ build_csnp (int level, u_char * start, u_char * stop, struct list *lsps, hmac_md5 (STREAM_DATA (circuit->snd_stream), stream_get_endp(circuit->snd_stream), (unsigned char *) &passwd->passwd, passwd->len, - (caddr_t) &hmac_md5_hash); + (unsigned char *) &hmac_md5_hash); /* Copy the hash into the stream */ memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, hmac_md5_hash, ISIS_AUTH_MD5_SIZE); @@ -2947,7 +2945,7 @@ build_psnp (int level, struct isis_circuit *circuit, struct list *lsps) hmac_md5 (STREAM_DATA (circuit->snd_stream), stream_get_endp(circuit->snd_stream), (unsigned char *) &passwd->passwd, passwd->len, - (caddr_t) &hmac_md5_hash); + (unsigned char *) &hmac_md5_hash); /* Copy the hash into the stream */ memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, hmac_md5_hash, ISIS_AUTH_MD5_SIZE); diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 46c8edd68c..2427047b38 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -55,8 +55,8 @@ u_char ALL_L2_ISS[6] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x15 }; u_char ALL_ISS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x05 }; u_char ALL_ESS[6] = { 0x09, 0x00, 0x2B, 0x00, 0x00, 0x04 }; -static char discard_buff[8192]; -static char sock_buff[8192]; +static uint8_t discard_buff[8192]; +static uint8_t sock_buff[8192]; /* * if level is 0 we are joining p2p multicast diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 84c89bf61e..32026f9b17 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1067,8 +1067,8 @@ isis_spf_preload_tent (struct isis_spftree *spftree, int level, { zlog_warn ("ISIS-Spf: No lsp (%p) found from root " "to L%d DR %s on %s (ID %d)", - lsp, level, rawlspid_print (lsp_id), - circuit->interface->name, circuit->circuit_id); + (void *)lsp, level, rawlspid_print (lsp_id), + circuit->interface->name, circuit->circuit_id); continue; } isis_spf_process_pseudo_lsp (spftree, lsp, @@ -1472,7 +1472,8 @@ isis_spf_schedule6 (struct isis_area *area, int level) if (isis->debugs & DEBUG_SPF_EVENTS) zlog_debug ("ISIS-Spf (%s) L%d SPF scheduled %lld sec from now", - area->area_tag, level, (long long)(area->min_spf_interval[level-1] - diff)); + area->area_tag, level, + (long long)(area->min_spf_interval[level-1] - diff)); spftree->pending = 1; diff --git a/isisd/isisd.c b/isisd/isisd.c index c1f83e1d0e..228d2bcb31 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1364,8 +1364,8 @@ DEFUN (show_isis_summary, vty_out_timestr(vty, spftree->last_run_timestamp); vty_out (vty, "%s", VTY_NEWLINE); - vty_out (vty, " last run duration : %ld msec%s", - spftree->last_run_duration, VTY_NEWLINE); + vty_out (vty, " last run duration : %llu msec%s", + (unsigned long long)spftree->last_run_duration, VTY_NEWLINE); vty_out (vty, " run count : %d%s", spftree->runcount, VTY_NEWLINE); diff --git a/isisd/topology/Makefile.am b/isisd/topology/Makefile.am index ccd2e71744..fe73ae5c68 100644 --- a/isisd/topology/Makefile.am +++ b/isisd/topology/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" AM_CFLAGS = $(PICFLAGS) @@ -18,7 +18,4 @@ libtopology_a_LIBADD = @LIB_REGEX@ ../../lib/libzebra.la noinst_HEADERS = \ spgrid.h -depend: - @$(CPP) -MM $(INCLUDES) $(LDFLAGS) *.c - ## File dependency. diff --git a/isisd/topology/spgrid.c b/isisd/topology/spgrid.c index df09d0b2b6..40147fb5b6 100644 --- a/isisd/topology/spgrid.c +++ b/isisd/topology/spgrid.c @@ -50,8 +50,8 @@ long X, /* horizontal size of grid */ long x, y, - ya1, y2, yp, - dl, dx, xn, yan, count, + yy1, yy2, yyp, + dl, dx, xn, yyn, count, *mess; double n; @@ -670,12 +670,12 @@ gen_spgrid_topology (struct vty *vty, struct list *topology) for ( k = ax; k > 0; k -- ) { - ya1 = nrand ( Y ); + yy1 = nrand ( Y ); do - y2 = nrand ( Y ); - while ( y2 == ya1 ); - i = NODE ( x, ya1 ); - j = NODE ( x, y2 ); + yy2 = nrand ( Y ); + while ( yy2 == yy1 ); + i = NODE ( x, yy1 ); + j = NODE ( x, yy2 ); l = am + nrand ( al ); print_arc (vty, topology, i, j, l ); } @@ -711,13 +711,13 @@ gen_spgrid_topology (struct vty *vty, struct list *topology) dx = xn - x; if ( ip_f ) { - yp = nrand(Y-y); - yan = mess[ yp ]; - mess[ yp ] = mess[ Y - y - 1 ]; + yyp = nrand(Y-y); + yyn = mess[ yyp ]; + mess[ yyp ] = mess[ Y - y - 1 ]; } else - yan = y; - j = NODE ( xn, yan ); + yyn = y; + j = NODE ( xn, yyn ); l = im + nrand ( il ); if ( in != 0 ) l *= (long) ( in * dx ); diff --git a/lib/Makefile.am b/lib/Makefile.am index 5d88a526af..ada31a0d21 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib AM_CFLAGS = $(WERROR) DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" diff --git a/lib/buffer.c b/lib/buffer.c index 45e2e1c508..ee9310100e 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -148,7 +148,7 @@ buffer_add (struct buffer *b) { struct buffer_data *d; - d = XMALLOC(MTYPE_BUFFER_DATA, offsetof(struct buffer_data, data[b->size])); + d = XMALLOC(MTYPE_BUFFER_DATA, offsetof(struct buffer_data, data) + b->size); d->cp = d->sp = 0; d->next = NULL; @@ -322,7 +322,8 @@ buffer_flush_window (struct buffer *b, int fd, int width, int height, /* This should absolutely never occur. */ zlog_err("%s: corruption detected: iov_small overflowed; " "head %p, tail %p, head->next %p", - __func__, b->head, b->tail, b->head->next); + __func__, (void *)b->head, (void *)b->tail, + (void *)b->head->next); iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov)); memcpy(iov, small_iov, sizeof(small_iov)); } diff --git a/lib/command.c b/lib/command.c index a71cb5ddd2..72a2739895 100644 --- a/lib/command.c +++ b/lib/command.c @@ -182,6 +182,7 @@ print_version (const char *progname) { printf ("%s version %s\n", progname, QUAGGA_VERSION); printf ("%s\n", QUAGGA_COPYRIGHT); + printf ("configured with:\n\t%s\n", QUAGGA_CONFIG_ARGS); } @@ -506,6 +507,25 @@ format_parser_read_word(struct format_parser_state *state) token = XCALLOC(MTYPE_CMD_TOKENS, sizeof(*token)); token->type = TOKEN_TERMINAL; + if (strcmp (cmd, "A.B.C.D") == 0) + token->terminal = TERMINAL_IPV4; + else if (strcmp (cmd, "A.B.C.D/M") == 0) + token->terminal = TERMINAL_IPV4_PREFIX; + else if (strcmp (cmd, "X:X::X:X") == 0) + token->terminal = TERMINAL_IPV6; + else if (strcmp (cmd, "X:X::X:X/M") == 0) + token->terminal = TERMINAL_IPV6_PREFIX; + else if (cmd[0] == '[') + token->terminal = TERMINAL_OPTION; + else if (cmd[0] == '.') + token->terminal = TERMINAL_VARARG; + else if (cmd[0] == '<') + token->terminal = TERMINAL_RANGE; + else if (cmd[0] >= 'A' && cmd[0] <= 'Z') + token->terminal = TERMINAL_VARIABLE; + else + token->terminal = TERMINAL_LITERAL; + token->cmd = cmd; token->desc = format_parser_desc_str(state); vector_set(state->curvect, token); @@ -1172,59 +1192,61 @@ cmd_word_match(struct cmd_token *token, if (!word) return no_match; - if (CMD_VARARG(str)) + switch (token->terminal) { - return vararg_match; - } - else if (CMD_RANGE(str)) - { - if (cmd_range_match(str, word)) - return range_match; - } -#ifdef HAVE_IPV6 - else if (CMD_IPV6(str)) - { - match_type = cmd_ipv6_match(word); - if ((filter == FILTER_RELAXED && match_type != no_match) + case TERMINAL_VARARG: + return vararg_match; + + case TERMINAL_RANGE: + if (cmd_range_match(str, word)) + return range_match; + break; + + case TERMINAL_IPV6: + match_type = cmd_ipv6_match(word); + if ((filter == FILTER_RELAXED && match_type != no_match) || (filter == FILTER_STRICT && match_type == exact_match)) - return ipv6_match; - } - else if (CMD_IPV6_PREFIX(str)) - { - match_type = cmd_ipv6_prefix_match(word); - if ((filter == FILTER_RELAXED && match_type != no_match) - || (filter == FILTER_STRICT && match_type == exact_match)) - return ipv6_prefix_match; - } -#endif /* HAVE_IPV6 */ - else if (CMD_IPV4(str)) - { - match_type = cmd_ipv4_match(word); - if ((filter == FILTER_RELAXED && match_type != no_match) - || (filter == FILTER_STRICT && match_type == exact_match)) - return ipv4_match; - } - else if (CMD_IPV4_PREFIX(str)) - { - match_type = cmd_ipv4_prefix_match(word); - if ((filter == FILTER_RELAXED && match_type != no_match) - || (filter == FILTER_STRICT && match_type == exact_match)) - return ipv4_prefix_match; - } - else if (CMD_OPTION(str) || CMD_VARIABLE(str)) - { - return extend_match; - } - else - { - if (filter == FILTER_RELAXED && !strncmp(str, word, strlen(word))) - { - if (!strcmp(str, word)) - return exact_match; - return partly_match; - } - if (filter == FILTER_STRICT && !strcmp(str, word)) - return exact_match; + return ipv6_match; + break; + + case TERMINAL_IPV6_PREFIX: + match_type = cmd_ipv6_prefix_match(word); + if ((filter == FILTER_RELAXED && match_type != no_match) + || (filter == FILTER_STRICT && match_type == exact_match)) + return ipv6_prefix_match; + break; + + case TERMINAL_IPV4: + match_type = cmd_ipv4_match(word); + if ((filter == FILTER_RELAXED && match_type != no_match) + || (filter == FILTER_STRICT && match_type == exact_match)) + return ipv4_match; + break; + + case TERMINAL_IPV4_PREFIX: + match_type = cmd_ipv4_prefix_match(word); + if ((filter == FILTER_RELAXED && match_type != no_match) + || (filter == FILTER_STRICT && match_type == exact_match)) + return ipv4_prefix_match; + break; + + case TERMINAL_OPTION: + case TERMINAL_VARIABLE: + return extend_match; + + case TERMINAL_LITERAL: + if (filter == FILTER_RELAXED && !strncmp(str, word, strlen(word))) + { + if (!strcmp(str, word)) + return exact_match; + return partly_match; + } + if (filter == FILTER_STRICT && !strcmp(str, word)) + return exact_match; + break; + + default: + assert (0); } return no_match; @@ -1308,7 +1330,7 @@ cmd_matcher_match_terminal(struct cmd_matcher *matcher, if (!cmd_matcher_words_left(matcher)) { - if (CMD_OPTION(token->cmd)) + if (token->terminal == TERMINAL_OPTION) return MATCHER_OK; /* missing optional args are NOT pushed as NULL */ else return MATCHER_INCOMPLETE; @@ -1321,9 +1343,7 @@ cmd_matcher_match_terminal(struct cmd_matcher *matcher, /* We have to record the input word as argument if it matched * against a variable. */ - if (CMD_VARARG(token->cmd) - || CMD_VARIABLE(token->cmd) - || CMD_OPTION(token->cmd)) + if (TERMINAL_RECORD (token->terminal)) { if (push_argument(argc, argv, word)) return MATCHER_EXCEED_ARGC_MAX; @@ -1334,7 +1354,7 @@ cmd_matcher_match_terminal(struct cmd_matcher *matcher, matcher->word_index++; /* A vararg token should consume all left over words as arguments */ - if (CMD_VARARG(token->cmd)) + if (token->terminal == TERMINAL_VARARG) while (cmd_matcher_words_left(matcher)) { word = cmd_matcher_get_word(matcher); @@ -1354,7 +1374,7 @@ cmd_matcher_match_multiple(struct cmd_matcher *matcher, enum match_type multiple_match; unsigned int multiple_index; const char *word; - const char *arg; + const char *arg = NULL; struct cmd_token *word_token; enum match_type word_match; @@ -1565,9 +1585,7 @@ cmd_matcher_build_keyword_args(struct cmd_matcher *matcher, { word_token = vector_slot(keyword_vector, j); if ((word_token->type == TOKEN_TERMINAL - && (CMD_VARARG(word_token->cmd) - || CMD_VARIABLE(word_token->cmd) - || CMD_OPTION(word_token->cmd))) + && TERMINAL_RECORD (word_token->terminal)) || word_token->type == TOKEN_MULTIPLE) { if (push_argument(argc, argv, NULL)) @@ -1853,12 +1871,12 @@ is_cmd_ambiguous (vector cmd_vector, switch (type) { case exact_match: - if (!(CMD_OPTION (str) || CMD_VARIABLE (str)) + if (!TERMINAL_RECORD (cmd_token->terminal) && strcmp (command, str) == 0) match++; break; case partly_match: - if (!(CMD_OPTION (str) || CMD_VARIABLE (str)) + if (!TERMINAL_RECORD (cmd_token->terminal) && strncmp (command, str, strlen (command)) == 0) { if (matched && strcmp (matched, str) != 0) @@ -1880,7 +1898,7 @@ is_cmd_ambiguous (vector cmd_vector, break; #ifdef HAVE_IPV6 case ipv6_match: - if (CMD_IPV6 (str)) + if (cmd_token->terminal == TERMINAL_IPV6) match++; break; case ipv6_prefix_match: @@ -1894,7 +1912,7 @@ is_cmd_ambiguous (vector cmd_vector, break; #endif /* HAVE_IPV6 */ case ipv4_match: - if (CMD_IPV4 (str)) + if (cmd_token->terminal == TERMINAL_IPV4) match++; break; case ipv4_prefix_match: @@ -1907,7 +1925,7 @@ is_cmd_ambiguous (vector cmd_vector, } break; case extend_match: - if (CMD_OPTION (str) || CMD_VARIABLE (str)) + if (TERMINAL_RECORD (cmd_token->terminal)) match++; break; case no_match: @@ -1923,11 +1941,12 @@ is_cmd_ambiguous (vector cmd_vector, /* If src matches dst return dst string, otherwise return NULL */ static const char * -cmd_entry_function (const char *src, const char *dst) +cmd_entry_function (const char *src, struct cmd_token *token) { + const char *dst = token->cmd; + /* Skip variable arguments. */ - if (CMD_OPTION (dst) || CMD_VARIABLE (dst) || CMD_VARARG (dst) || - CMD_IPV4 (dst) || CMD_IPV4_PREFIX (dst) || CMD_RANGE (dst)) + if (TERMINAL_RECORD (token->terminal)) return NULL; /* In case of 'command \t', given src is NULL string. */ @@ -1945,65 +1964,64 @@ cmd_entry_function (const char *src, const char *dst) /* This version will return the dst string always if it is CMD_VARIABLE for '?' key processing */ static const char * -cmd_entry_function_desc (const char *src, const char *dst) +cmd_entry_function_desc (const char *src, struct cmd_token *token) { - if (CMD_VARARG (dst)) - return dst; + const char *dst = token->cmd; - if (CMD_RANGE (dst)) + switch (token->terminal) { - if (cmd_range_match (dst, src)) - return dst; - else - return NULL; + case TERMINAL_VARARG: + return dst; + + case TERMINAL_RANGE: + if (cmd_range_match (dst, src)) + return dst; + else + return NULL; + + case TERMINAL_IPV6: + if (cmd_ipv6_match (src)) + return dst; + else + return NULL; + + case TERMINAL_IPV6_PREFIX: + if (cmd_ipv6_prefix_match (src)) + return dst; + else + return NULL; + + case TERMINAL_IPV4: + if (cmd_ipv4_match (src)) + return dst; + else + return NULL; + + case TERMINAL_IPV4_PREFIX: + if (cmd_ipv4_prefix_match (src)) + return dst; + else + return NULL; + + /* Optional or variable commands always match on '?' */ + case TERMINAL_OPTION: + case TERMINAL_VARIABLE: + return dst; + + case TERMINAL_LITERAL: + /* In case of 'command \t', given src is NULL string. */ + if (src == NULL) + return dst; + + if (strncmp (src, dst, strlen (src)) == 0) + return dst; + else + return NULL; + + default: + assert(0); + return NULL; } - -#ifdef HAVE_IPV6 - if (CMD_IPV6 (dst)) - { - if (cmd_ipv6_match (src)) - return dst; - else - return NULL; - } - - if (CMD_IPV6_PREFIX (dst)) - { - if (cmd_ipv6_prefix_match (src)) - return dst; - else - return NULL; - } -#endif /* HAVE_IPV6 */ - - if (CMD_IPV4 (dst)) - { - if (cmd_ipv4_match (src)) - return dst; - else - return NULL; - } - - if (CMD_IPV4_PREFIX (dst)) - { - if (cmd_ipv4_prefix_match (src)) - return dst; - else - return NULL; - } - - /* Optional or variable commands always match on '?' */ - if (CMD_OPTION (dst) || CMD_VARIABLE (dst)) - return dst; - - /* In case of 'command \t', given src is NULL string. */ - if (src == NULL) - return dst; - - if (strncmp (src, dst, strlen (src)) == 0) - return dst; - else - return NULL; } /** @@ -2222,7 +2240,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) struct cmd_token *token = vector_slot(match_vector, j); const char *string; - string = cmd_entry_function_desc(command, token->cmd); + string = cmd_entry_function_desc(command, token); if (string && desc_unique_string(matchvec, string)) vector_set(matchvec, token); } @@ -2348,7 +2366,7 @@ cmd_complete_sort(vector matchvec) /* Command line completion support. */ static char ** -cmd_complete_command_real (vector vline, struct vty *vty, int *status) +cmd_complete_command_real (vector vline, struct vty *vty, int *status, int islib) { unsigned int i; vector cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); @@ -2433,13 +2451,14 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) for (j = 0; j < vector_active (match_vector); j++) if ((token = vector_slot (match_vector, j))) - { - if ((string = - cmd_entry_function (vector_slot (vline, index), - token->cmd))) - if (cmd_unique_string (matchvec, string)) - vector_set (matchvec, XSTRDUP (MTYPE_TMP, string)); - } + { + string = cmd_entry_function (vector_slot (vline, index), + token); + if (string && cmd_unique_string (matchvec, string)) + vector_set (matchvec, (islib != 0 ? + XSTRDUP (MTYPE_TMP, string) : + strdup (string) /* rl freed */)); + } } /* We don't need cmd_vector any more. */ @@ -2484,7 +2503,9 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) { char *lcdstr; - lcdstr = XMALLOC (MTYPE_TMP, lcd + 1); + lcdstr = (islib != 0 ? + XMALLOC (MTYPE_TMP, lcd + 1) : + malloc(lcd + 1)); memcpy (lcdstr, matchvec->index[0], lcd); lcdstr[lcd] = '\0'; @@ -2492,10 +2513,15 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) /* Free matchvec. */ for (i = 0; i < vector_active (matchvec); i++) - { - if (vector_slot (matchvec, i)) - XFREE (MTYPE_TMP, vector_slot (matchvec, i)); - } + { + if (vector_slot (matchvec, i)) + { + if (islib != 0) + XFREE (MTYPE_TMP, vector_slot (matchvec, i)); + else + free (vector_slot (matchvec, i)); + } + } vector_free (matchvec); /* Make new matchvec. */ @@ -2518,7 +2544,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) } char ** -cmd_complete_command (vector vline, struct vty *vty, int *status) +cmd_complete_command_lib (vector vline, struct vty *vty, int *status, int islib) { char **ret; @@ -2539,15 +2565,20 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) vector_set_index (shifted_vline, index-1, vector_lookup(vline, index)); } - ret = cmd_complete_command_real (shifted_vline, vty, status); + ret = cmd_complete_command_real (shifted_vline, vty, status, islib); vector_free(shifted_vline); vty->node = onode; return ret; } + return cmd_complete_command_real (vline, vty, status, islib); +} - return cmd_complete_command_real (vline, vty, status); +char ** +cmd_complete_command (vector vline, struct vty *vty, int *status) +{ + return cmd_complete_command_lib (vline, vty, status, 0); } /* return parent node */ @@ -2562,6 +2593,7 @@ node_parent ( enum node_type node ) switch (node) { case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: @@ -2947,9 +2979,10 @@ DEFUN (config_exit, case VTY_NODE: vty->node = CONFIG_NODE; break; - case BGP_VPNV4_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: + case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: case BGP_IPV6_NODE: case BGP_IPV6M_NODE: vty->node = BGP_NODE; @@ -2990,6 +3023,7 @@ DEFUN (config_end, case RIPNG_NODE: case BGP_NODE: case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: @@ -3022,6 +3056,8 @@ DEFUN (show_version, vty_out (vty, "Quagga %s (%s).%s", QUAGGA_VERSION, host.name?host.name:"", VTY_NEWLINE); vty_out (vty, "%s%s%s", QUAGGA_COPYRIGHT, GIT_INFO, VTY_NEWLINE); + vty_out (vty, "configured with:%s %s%s", VTY_NEWLINE, + QUAGGA_CONFIG_ARGS, VTY_NEWLINE); return CMD_SUCCESS; } @@ -3117,7 +3153,7 @@ DEFUN (config_write_file, /* Make vty for configuration file. */ file_vty = vty_new (); - file_vty->fd = fd; + file_vty->wfd = fd; file_vty->type = VTY_FILE; /* Config file header print. */ @@ -4054,6 +4090,37 @@ DEFUN (no_banner_motd, return CMD_SUCCESS; } +DEFUN (show_commandtree, + show_commandtree_cmd, + "show commandtree", + NO_STR + "Show command tree\n") +{ + /* TBD */ + vector cmd_vector; + unsigned int i; + + vty_out (vty, "Current node id: %d%s", vty->node, VTY_NEWLINE); + + /* vector of all commands installed at this node */ + cmd_vector = vector_copy (cmd_node_vector (cmdvec, vty->node)); + + /* loop over all commands at this node */ + for (i = 0; i < vector_active(cmd_vector); ++i) + { + struct cmd_element *cmd_element; + + /* A cmd_element (seems to be) is an individual command */ + if ((cmd_element = vector_slot (cmd_vector, i)) == NULL) + continue; + + vty_out (vty, " %s%s", cmd_element->string, VTY_NEWLINE); + } + + vector_free (cmd_vector); + return CMD_SUCCESS; +} + /* Set config filename. Called from vty.c */ void host_config_set (const char *filename) @@ -4085,6 +4152,7 @@ cmd_init (int terminal) { command_cr = XSTRDUP(MTYPE_CMD_TOKENS, ""); token_cr.type = TOKEN_TERMINAL; + token_cr.terminal = TERMINAL_LITERAL; token_cr.cmd = command_cr; token_cr.desc = XSTRDUP(MTYPE_CMD_TOKENS, ""); @@ -4121,6 +4189,7 @@ cmd_init (int terminal) install_element (VIEW_NODE, &config_terminal_length_cmd); install_element (VIEW_NODE, &config_terminal_no_length_cmd); install_element (VIEW_NODE, &show_logging_cmd); + install_element (VIEW_NODE, &show_commandtree_cmd); install_element (VIEW_NODE, &echo_cmd); install_element (RESTRICTED_NODE, &config_list_cmd); @@ -4130,6 +4199,7 @@ cmd_init (int terminal) install_element (RESTRICTED_NODE, &config_enable_cmd); install_element (RESTRICTED_NODE, &config_terminal_length_cmd); install_element (RESTRICTED_NODE, &config_terminal_no_length_cmd); + install_element (RESTRICTED_NODE, &show_commandtree_cmd); install_element (RESTRICTED_NODE, &echo_cmd); } @@ -4142,6 +4212,7 @@ cmd_init (int terminal) } install_element (ENABLE_NODE, &show_startup_config_cmd); install_element (ENABLE_NODE, &show_version_cmd); + install_element (ENABLE_NODE, &show_commandtree_cmd); if (terminal) { @@ -4206,7 +4277,8 @@ cmd_init (int terminal) vrf_install_commands (); } - srand(time(NULL)); + install_element (CONFIG_NODE, &show_commandtree_cmd); + srandom(time(NULL)); } static void diff --git a/lib/command.h b/lib/command.h index 7051e1ca5c..523d1a2e4c 100644 --- a/lib/command.h +++ b/lib/command.h @@ -82,6 +82,7 @@ enum node_type RIPNG_NODE, /* RIPng protocol mode node. */ BGP_NODE, /* BGP protocol mode which includes BGP4+ */ BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */ + BGP_VPNV6_NODE, /* BGP MPLS-VPN PE exchange. */ BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */ BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */ BGP_IPV6_NODE, /* BGP IPv6 address family */ @@ -152,10 +153,28 @@ enum cmd_token_type TOKEN_KEYWORD, }; +enum cmd_terminal_type +{ + _TERMINAL_BUG = 0, + TERMINAL_LITERAL, + TERMINAL_OPTION, + TERMINAL_VARIABLE, + TERMINAL_VARARG, + TERMINAL_RANGE, + TERMINAL_IPV4, + TERMINAL_IPV4_PREFIX, + TERMINAL_IPV6, + TERMINAL_IPV6_PREFIX, +}; + +/* argument to be recorded on argv[] if it's not a literal */ +#define TERMINAL_RECORD(t) ((t) >= TERMINAL_OPTION) + /* Command description structure. */ struct cmd_token { enum cmd_token_type type; + enum cmd_terminal_type terminal; /* Used for type == MULTIPLE */ vector multiple; /* vector of cmd_token, type == FINAL */ @@ -454,16 +473,6 @@ struct cmd_token #define CMD_CREATE_STR_HELPER(s) #s #define CMD_RANGE_STR(a,s) "<" CMD_CREATE_STR(a) "-" CMD_CREATE_STR(s) ">" -#define CMD_OPTION(S) ((S[0]) == '[') -#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<')) -#define CMD_VARARG(S) ((S[0]) == '.') -#define CMD_RANGE(S) ((S[0] == '<')) - -#define CMD_IPV4(S) ((strcmp ((S), "A.B.C.D") == 0)) -#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0)) -#define CMD_IPV6(S) ((strcmp ((S), "X:X::X:X") == 0)) -#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0)) - /* Common descriptions. */ #define SHOW_STR "Show running system information\n" #define IP_STR "IP information\n" @@ -550,6 +559,7 @@ extern vector cmd_make_strvec (const char *); extern void cmd_free_strvec (vector); extern vector cmd_describe_command (vector, struct vty *, int *status); extern char **cmd_complete_command (vector, struct vty *, int *status); +extern char **cmd_complete_command_lib (vector, struct vty *, int *status, int islib); extern const char *cmd_prompt (enum node_type); extern int command_config_read_one_line (struct vty *vty, struct cmd_element **, int use_config_node); extern int config_from_file (struct vty *, FILE *, unsigned int *line_num); diff --git a/lib/distribute.h b/lib/distribute.h index 5072016fdc..a2ffffd5fc 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -24,6 +24,7 @@ #include #include "if.h" +#include "filter.h" /* Disctirubte list types. */ enum distribute_type diff --git a/lib/linklist.c b/lib/linklist.c index 370b2fa615..4b16f07dd1 100644 --- a/lib/linklist.c +++ b/lib/linklist.c @@ -159,6 +159,13 @@ listnode_add_after (struct list *list, struct listnode *pp, void *val) list->count++; } +/* Move given listnode to tail of the list */ +void +listnode_move_to_tail (struct list *l, struct listnode *n) +{ + LISTNODE_DETACH(l,n); + LISTNODE_ATTACH(l,n); +} /* Delete specific date pointer from the list. */ void diff --git a/lib/linklist.h b/lib/linklist.h index 88f4a03912..6209c8b9d6 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -68,6 +68,7 @@ extern void list_free (struct list *); extern void listnode_add (struct list *, void *); extern void listnode_add_sort (struct list *, void *); extern void listnode_add_after (struct list *, struct listnode *, void *); +extern void listnode_move_to_tail (struct list *, struct listnode *); extern void listnode_delete (struct list *, void *); extern struct listnode *listnode_lookup (struct list *, void *); extern void *listnode_head (struct list *); diff --git a/lib/log.c b/lib/log.c index 92a1a4ddd4..453a611dcd 100644 --- a/lib/log.c +++ b/lib/log.c @@ -459,6 +459,40 @@ zlog_signal(int signo, const char *action NULL #endif ); + + s = buf; + if (!thread_current) + s = str_append (LOC, "no thread information available\n"); + else + { + s = str_append (LOC, "in thread "); + s = str_append (LOC, thread_current->funcname); + s = str_append (LOC, " scheduled from "); + s = str_append (LOC, thread_current->schedfrom); + s = str_append (LOC, ":"); + s = num_append (LOC, thread_current->schedfrom_line); + s = str_append (LOC, "\n"); + } + +#define DUMP(FD) write_wrapper(FD, buf, s-buf); + /* If no file logging configured, try to write to fallback log file. */ + if (logfile_fd >= 0) + DUMP(logfile_fd) + if (!zlog_default) + DUMP(STDERR_FILENO) + else + { + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) + DUMP(STDOUT_FILENO) + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf,s-buf); + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart); + } +#undef DUMP + #undef PRI #undef LOC } @@ -616,6 +650,16 @@ ZLOG_FUNC(zlog_debug, LOG_DEBUG) #undef ZLOG_FUNC +void zlog_thread_info (int log_level) +{ + if (thread_current) + zlog(NULL, log_level, "Current thread function %s, scheduled from " + "file %s, line %u", thread_current->funcname, + thread_current->schedfrom, thread_current->schedfrom_line); + else + zlog(NULL, log_level, "Current thread not known/applicable"); +} + void _zlog_assert_failed (const char *assertion, const char *file, unsigned int line, const char *function) @@ -628,6 +672,7 @@ _zlog_assert_failed (const char *assertion, const char *file, zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s", assertion,file,line,(function ? function : "?")); zlog_backtrace(LOG_CRIT); + zlog_thread_info(LOG_CRIT); abort(); } diff --git a/lib/log.h b/lib/log.h index 61370f7b82..882080760d 100644 --- a/lib/log.h +++ b/lib/log.h @@ -121,6 +121,8 @@ extern void zlog_info (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); extern void zlog_notice (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); extern void zlog_debug (const char *format, ...) PRINTF_ATTRIBUTE(1, 2); +extern void zlog_thread_info (int log_level); + /* Set logging level for the given destination. If the log_level argument is ZLOG_DISABLED, then the destination is disabled. This function should not be used for file logging (use zlog_set_file diff --git a/lib/md5.c b/lib/md5.c index 80522b6dd8..d758de2a28 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -306,7 +306,7 @@ unsigned char* text; /* pointer to data stream */ int text_len; /* length of data stream */ unsigned char* key; /* pointer to authentication key */ int key_len; /* length of authentication key */ -caddr_t digest; /* caller digest to be filled in */ +uint8_t* digest; /* caller digest to be filled in */ { MD5_CTX context; diff --git a/lib/md5.h b/lib/md5.h index a03bf22a22..4e5ffbd9e3 100644 --- a/lib/md5.h +++ b/lib/md5.h @@ -84,6 +84,6 @@ do { \ /* From RFC 2104 */ void hmac_md5(unsigned char* text, int text_len, unsigned char* key, - int key_len, caddr_t digest); + int key_len, uint8_t *digest); #endif /* ! _LIBZEBRA_MD5_H_*/ diff --git a/lib/plist.c b/lib/plist.c index 12c71791ce..a1289801c4 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -922,8 +922,9 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name, } /* "any" is special token for matching any IPv4 addresses. */ - if (afi == AFI_IP) + switch (afi) { + case AFI_IP: if (strncmp ("any", prefix, strlen (prefix)) == 0) { ret = str2prefix_ipv4 ("0.0.0.0/0", (struct prefix_ipv4 *) &p); @@ -939,10 +940,8 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name, vty_out (vty, "%% Malformed IPv4 prefix%s", VTY_NEWLINE); return CMD_WARNING; } - } -#ifdef HAVE_IPV6 - else if (afi == AFI_IP6) - { + break; + case AFI_IP6: if (strncmp ("any", prefix, strlen (prefix)) == 0) { ret = str2prefix_ipv6 ("::/0", (struct prefix_ipv6 *) &p); @@ -958,8 +957,8 @@ vty_prefix_list_install (struct vty *vty, afi_t afi, const char *name, vty_out (vty, "%% Malformed IPv6 prefix%s", VTY_NEWLINE); return CMD_WARNING; } + break; } -#endif /* HAVE_IPV6 */ /* ge and le check. */ if (genum && (genum <= p.prefixlen)) diff --git a/lib/smux.h b/lib/smux.h index 45e84eead2..dc91cac71a 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -25,6 +25,8 @@ #include #include +#include "thread.h" + /* Structures here are mostly compatible with UCD SNMP 4.1.1 */ #define MATCH_FAILED (-1) #define MATCH_SUCCEEDED 0 diff --git a/lib/sockunion.c b/lib/sockunion.c index 4fd5f1444c..b5a2eb954a 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -117,7 +117,7 @@ inet_ntop (int family, const void *addrptr, char *strptr, size_t len) #endif /* ! HAVE_INET_NTOP */ const char * -inet_sutop (union sockunion *su, char *str) +inet_sutop (const union sockunion *su, char *str) { switch (su->sa.sa_family) { @@ -164,7 +164,7 @@ str2sockunion (const char *str, union sockunion *su) } const char * -sockunion2str (union sockunion *su, char *buf, size_t len) +sockunion2str (const union sockunion *su, char *buf, size_t len) { switch (sockunion_family(su)) { @@ -215,7 +215,7 @@ sockunion_normalise_mapped (union sockunion *su) /* return sockunion structure : this function should be revised. */ static const char * -sockunion_log (union sockunion *su, char *buf, size_t len) +sockunion_log (const union sockunion *su, char *buf, size_t len) { switch (su->sa.sa_family) { @@ -234,7 +234,7 @@ sockunion_log (union sockunion *su, char *buf, size_t len) /* Return socket of sockunion. */ int -sockunion_socket (union sockunion *su) +sockunion_socket (const union sockunion *su) { int sock; @@ -266,7 +266,7 @@ sockunion_accept (int sock, union sockunion *su) /* Return sizeof union sockunion. */ static int -sockunion_sizeof (union sockunion *su) +sockunion_sizeof (const union sockunion *su) { int ret; @@ -290,7 +290,7 @@ sockunion_sizeof (union sockunion *su) 0 : connect success 1 : connect is in progress */ enum connect_result -sockunion_connect (int fd, union sockunion *peersu, unsigned short port, +sockunion_connect (int fd, const union sockunion *peersu, unsigned short port, unsigned int ifindex) { int ret; @@ -312,13 +312,8 @@ sockunion_connect (int fd, union sockunion *peersu, unsigned short port, { #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID su.sin6.sin6_scope_id = ifindex; -#ifdef MUSICA - su.sin6.sin6_scope_id = ifindex; -#endif #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */ -#ifndef MUSICA SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex); -#endif } #endif /* KAME */ break; @@ -402,7 +397,7 @@ sockunion_bind (int sock, union sockunion *su, unsigned short port, #endif /* SIN6_LEN */ if (su_addr == NULL) { -#if defined(LINUX_IPV6) || defined(NRL) +#ifdef LINUX_IPV6 memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr)); #else su->sin6.sin6_addr = in6addr_any; @@ -779,7 +774,7 @@ sockunion_getpeername (int fd) /* Print sockunion structure */ static void __attribute__ ((unused)) -sockunion_print (union sockunion *su) +sockunion_print (const union sockunion *su) { if (su == NULL) return; @@ -818,7 +813,7 @@ sockunion_print (union sockunion *su) #ifdef HAVE_IPV6 static int -in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2) +in6addr_cmp (const struct in6_addr *addr1, const struct in6_addr *addr2) { unsigned int i; const u_char *p1, *p2; @@ -838,7 +833,7 @@ in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2) #endif /* HAVE_IPV6 */ int -sockunion_cmp (union sockunion *su1, union sockunion *su2) +sockunion_cmp (const union sockunion *su1, const union sockunion *su2) { if (su1->sa.sa_family > su2->sa.sa_family) return 1; @@ -863,7 +858,7 @@ sockunion_cmp (union sockunion *su1, union sockunion *su2) /* Duplicate sockunion. */ union sockunion * -sockunion_dup (union sockunion *su) +sockunion_dup (const union sockunion *su) { union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); memcpy (dup, su, sizeof (union sockunion)); diff --git a/lib/sockunion.h b/lib/sockunion.h index c674cb8bb8..a33051ae57 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -69,8 +69,8 @@ enum connect_result /* Prototypes. */ extern int str2sockunion (const char *, union sockunion *); -extern const char *sockunion2str (union sockunion *, char *, size_t); -extern int sockunion_cmp (union sockunion *, union sockunion *); +extern const char *sockunion2str (const union sockunion *, char *, size_t); +extern int sockunion_cmp (const union sockunion *, const union sockunion *); extern int sockunion_same (const union sockunion *, const union sockunion *); extern unsigned int sockunion_hash (const union sockunion *); @@ -91,14 +91,14 @@ extern int sockopt_ttl (int family, int sock, int ttl); extern int sockopt_minttl (int family, int sock, int minttl); extern int sockopt_cork (int sock, int onoff); extern int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *); -extern int sockunion_socket (union sockunion *su); -extern const char *inet_sutop (union sockunion *su, char *str); -extern enum connect_result sockunion_connect (int fd, union sockunion *su, +extern int sockunion_socket (const union sockunion *su); +extern const char *inet_sutop (const union sockunion *su, char *str); +extern enum connect_result sockunion_connect (int fd, const union sockunion *su, unsigned short port, unsigned int); extern union sockunion *sockunion_getsockname (int); extern union sockunion *sockunion_getpeername (int); -extern union sockunion *sockunion_dup (union sockunion *); +extern union sockunion *sockunion_dup (const union sockunion *); extern void sockunion_free (union sockunion *); extern void sockunion_init (union sockunion *); diff --git a/lib/stream.c b/lib/stream.c index 27f13d7698..716f361dc8 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -53,7 +53,7 @@ */ #define STREAM_WARN_OFFSETS(S) \ zlog_warn ("&(struct stream): %p, size: %lu, getp: %lu, endp: %lu\n", \ - (S), \ + (void *)(S), \ (unsigned long) (S)->size, \ (unsigned long) (S)->getp, \ (unsigned long) (S)->endp)\ diff --git a/lib/thread.c b/lib/thread.c index ca54a44563..2b1ca13dee 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -264,7 +264,7 @@ cpu_record_hash_alloc (struct cpu_thread_history *a) struct cpu_thread_history *new; new = XCALLOC (MTYPE_THREAD_STATS, sizeof (struct cpu_thread_history)); new->func = a->func; - strcpy(new->funcname, a->funcname); + new->funcname = a->funcname; return new; } @@ -330,7 +330,7 @@ cpu_record_print(struct vty *vty, thread_type filter) void *args[3] = {&tmp, vty, &filter}; memset(&tmp, 0, sizeof tmp); - strcpy(tmp.funcname, "TOTAL"); + tmp.funcname = "TOTAL"; tmp.types = filter; #ifdef HAVE_RUSAGE @@ -634,7 +634,6 @@ thread_add_unuse (struct thread_master *m, struct thread *thread) assert (thread->prev == NULL); assert (thread->type == THREAD_UNUSED); thread_list_add (&m->unuse, thread); - /* XXX: Should we deallocate funcname here? */ } /* Free all unused thread. */ @@ -739,30 +738,8 @@ thread_timer_remain_second (struct thread *thread) return 0; } -/* Trim blankspace and "()"s */ -static void -strip_funcname (char *dest, const char *funcname) -{ - char buff[FUNCNAME_LEN]; - char tmp, *e, *b = buff; - - strncpy(buff, funcname, sizeof(buff)); - buff[ sizeof(buff) -1] = '\0'; - e = buff +strlen(buff) -1; - - /* Wont work for funcname == "Word (explanation)" */ - - while (*b == ' ' || *b == '(') - ++b; - while (*e == ' ' || *e == ')') - --e; - e++; - - tmp = *e; - *e = '\0'; - strcpy (dest, b); - *e = tmp; -} +#define debugargdef const char *funcname, const char *schedfrom, int fromln +#define debugargpass funcname, schedfrom, fromln struct timeval thread_timer_remain(struct thread *thread) @@ -775,7 +752,7 @@ thread_timer_remain(struct thread *thread) /* Get new thread. */ static struct thread * thread_get (struct thread_master *m, u_char type, - int (*func) (struct thread *), void *arg, const char* funcname) + int (*func) (struct thread *), void *arg, debugargdef) { struct thread *thread = thread_trim_head (&m->unuse); @@ -792,7 +769,9 @@ thread_get (struct thread_master *m, u_char type, thread->index = -1; thread->yield = THREAD_YIELD_TIME_SLOT; /* default */ - strip_funcname (thread->funcname, funcname); + thread->funcname = funcname; + thread->schedfrom = schedfrom; + thread->schedfrom_line = fromln; return thread; } @@ -804,7 +783,7 @@ thread_get (struct thread_master *m, u_char type, /* generic add thread function */ static struct thread * generic_thread_add(struct thread_master *m, int (*func) (struct thread *), - void *arg, int fd, const char* funcname, int dir) + void *arg, int fd, int dir, debugargdef) { struct thread *thread; @@ -834,7 +813,7 @@ generic_thread_add(struct thread_master *m, int (*func) (struct thread *), /* is there enough space for a new fd? */ assert (queuepos < m->handler.pfdsize); - thread = thread_get (m, type, func, arg, funcname); + thread = thread_get (m, type, func, arg, debugargpass); m->handler.pfds[queuepos].fd = fd; m->handler.pfds[queuepos].events |= event; if (queuepos == m->handler.pfdcount) @@ -899,7 +878,8 @@ fd_clear_read_write (struct thread *thread) /* Add new read thread. */ struct thread * funcname_thread_add_read_write (int dir, struct thread_master *m, - int (*func) (struct thread *), void *arg, int fd, const char* funcname) + int (*func) (struct thread *), void *arg, int fd, + debugargdef) { struct thread *thread = NULL; @@ -912,7 +892,7 @@ funcname_thread_add_read_write (int dir, struct thread_master *m, #endif #if defined (HAVE_POLL) - thread = generic_thread_add(m, func, arg, fd, funcname, dir); + thread = generic_thread_add(m, func, arg, fd, dir, debugargpass); if (thread == NULL) return NULL; @@ -924,7 +904,7 @@ funcname_thread_add_read_write (int dir, struct thread_master *m, } FD_SET (fd, fdset); - thread = thread_get (m, dir, func, arg, funcname); + thread = thread_get (m, dir, func, arg, debugargpass); #endif thread->u.fd = fd; @@ -941,8 +921,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m, int (*func) (struct thread *), int type, void *arg, - struct timeval *time_relative, - const char* funcname) + struct timeval *time_relative, + debugargdef) { struct thread *thread; struct pqueue *queue; @@ -954,7 +934,7 @@ funcname_thread_add_timer_timeval (struct thread_master *m, assert (time_relative); queue = ((type == THREAD_TIMER) ? m->timer : m->background); - thread = thread_get (m, type, func, arg, funcname); + thread = thread_get (m, type, func, arg, debugargpass); /* Do we need jitter here? */ quagga_get_relative (NULL); @@ -971,7 +951,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m, struct thread * funcname_thread_add_timer (struct thread_master *m, int (*func) (struct thread *), - void *arg, long timer, const char* funcname) + void *arg, long timer, + debugargdef) { struct timeval trel; @@ -981,14 +962,15 @@ funcname_thread_add_timer (struct thread_master *m, trel.tv_usec = 0; return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, - &trel, funcname); + &trel, debugargpass); } /* Add timer event thread with "millisecond" resolution */ struct thread * funcname_thread_add_timer_msec (struct thread_master *m, int (*func) (struct thread *), - void *arg, long timer, const char* funcname) + void *arg, long timer, + debugargdef) { struct timeval trel; @@ -998,15 +980,15 @@ funcname_thread_add_timer_msec (struct thread_master *m, trel.tv_usec = 1000*(timer % 1000); return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, - arg, &trel, funcname); + arg, &trel, debugargpass); } /* Add a background thread, with an optional millisec delay */ struct thread * funcname_thread_add_background (struct thread_master *m, int (*func) (struct thread *), - void *arg, long delay, - const char *funcname) + void *arg, long delay, + debugargdef) { struct timeval trel; @@ -1024,19 +1006,20 @@ funcname_thread_add_background (struct thread_master *m, } return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND, - arg, &trel, funcname); + arg, &trel, debugargpass); } /* Add simple event thread. */ struct thread * funcname_thread_add_event (struct thread_master *m, - int (*func) (struct thread *), void *arg, int val, const char* funcname) + int (*func) (struct thread *), void *arg, int val, + debugargdef) { struct thread *thread; assert (m != NULL); - thread = thread_get (m, THREAD_EVENT, func, arg, funcname); + thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass); thread->u.val = val; thread_list_add (&m->event, thread); @@ -1543,6 +1526,8 @@ thread_getrusage (RUSAGE_T *r) #endif /* HAVE_CLOCK_MONOTONIC */ } +struct thread *thread_current = NULL; + /* We check thread consumed time. If the system has getrusage, we'll use that to get in-depth stats on the performance of the thread in addition to wall clock time stats from gettimeofday. */ @@ -1563,7 +1548,7 @@ thread_call (struct thread *thread) struct cpu_thread_history tmp; tmp.func = thread->func; - strcpy(tmp.funcname, thread->funcname); + tmp.funcname = thread->funcname; thread->hist = hash_get (cpu_record, &tmp, (void * (*) (void *))cpu_record_hash_alloc); @@ -1572,7 +1557,9 @@ thread_call (struct thread *thread) GETRUSAGE (&before); thread->real = before.real; + thread_current = thread; (*thread->func) (thread); + thread_current = NULL; GETRUSAGE (&after); @@ -1611,7 +1598,7 @@ funcname_thread_execute (struct thread_master *m, int (*func)(struct thread *), void *arg, int val, - const char* funcname) + debugargdef) { struct thread dummy; @@ -1623,7 +1610,11 @@ funcname_thread_execute (struct thread_master *m, dummy.func = func; dummy.arg = arg; dummy.u.val = val; - strip_funcname (dummy.funcname, funcname); + + dummy.funcname = funcname; + dummy.schedfrom = schedfrom; + dummy.schedfrom_line = fromln; + thread_call (&dummy); return NULL; diff --git a/lib/thread.h b/lib/thread.h index 853ef3fb78..8b42ffe58a 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -89,9 +89,6 @@ struct thread_master typedef unsigned char thread_type; -/* ISO C99 maximum function name length is 63 */ -#define FUNCNAME_LEN 64 - /* Thread itself. */ struct thread { @@ -111,7 +108,9 @@ struct thread struct timeval real; struct cpu_thread_history *hist; /* cache pointer to cpu_history */ unsigned long yield; /* yield time in us */ - char funcname[FUNCNAME_LEN]; + const char *funcname; + const char *schedfrom; + int schedfrom_line; }; struct cpu_thread_history @@ -126,7 +125,7 @@ struct cpu_thread_history struct time_stats cpu; #endif thread_type types; - char funcname[FUNCNAME_LEN]; + const char *funcname; }; /* Clocks supported by Quagga */ @@ -194,15 +193,17 @@ enum quagga_clkid { #define THREAD_WRITE_OFF(thread) THREAD_OFF(thread) #define THREAD_TIMER_OFF(thread) THREAD_OFF(thread) -#define thread_add_read(m,f,a,v) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,#f) -#define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f) -#define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f) -#define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f) -#define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f) -#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f) +#define debugargdef const char *funcname, const char *schedfrom, int fromln + +#define thread_add_read(m,f,a,v) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,#f,__FILE__,__LINE__) +#define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f,__FILE__,__LINE__) +#define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__) +#define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__) +#define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__) +#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__) /* The 4th arg to thread_add_background is the # of milliseconds to delay. */ -#define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f) +#define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f,__FILE__,__LINE__) /* Prototypes. */ extern struct thread_master *thread_master_create (void); @@ -211,24 +212,26 @@ extern void thread_master_free_unused(struct thread_master *); extern struct thread *funcname_thread_add_read_write (int dir, struct thread_master *, int (*)(struct thread *), - void *, int, const char*); + void *, int, debugargdef); extern struct thread *funcname_thread_add_timer (struct thread_master *, int (*)(struct thread *), - void *, long, const char*); + void *, long, debugargdef); extern struct thread *funcname_thread_add_timer_msec (struct thread_master *, int (*)(struct thread *), - void *, long, const char*); + void *, long, debugargdef); extern struct thread *funcname_thread_add_event (struct thread_master *, int (*)(struct thread *), - void *, int, const char*); + void *, int, debugargdef); extern struct thread *funcname_thread_add_background (struct thread_master *, int (*func)(struct thread *), void *arg, long milliseconds_to_delay, - const char *funcname); + debugargdef); extern struct thread *funcname_thread_execute (struct thread_master *, int (*)(struct thread *), - void *, int, const char *); + void *, int, debugargdef); +#undef debugargdef + extern void thread_cancel (struct thread *); extern unsigned int thread_cancel_event (struct thread_master *, void *); extern struct thread *thread_fetch (struct thread_master *, struct thread *); @@ -262,4 +265,8 @@ extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, extern struct timeval recent_time; /* Similar to recent_time, but a monotonically increasing time value */ extern struct timeval recent_relative_time (void); + +/* only for use in logging functions! */ +extern struct thread *thread_current; + #endif /* _ZEBRA_THREAD_H */ diff --git a/lib/version.h.in b/lib/version.h.in index 7e9985f008..aef1d090b6 100644 --- a/lib/version.h.in +++ b/lib/version.h.in @@ -45,6 +45,8 @@ #define QUAGGA_COPYRIGHT "Copyright 1996-2005 Kunihiro Ishiguro, et al." +#define QUAGGA_CONFIG_ARGS "@CONFIG_ARGS@" + pid_t pid_output (const char *); #ifndef HAVE_DAEMON diff --git a/lib/vty.c b/lib/vty.c index a38a7523ca..504067ee39 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -38,6 +38,7 @@ #include "network.h" #include +#include /* Vty events */ enum event @@ -184,7 +185,7 @@ vty_log_out (struct vty *vty, const char *level, const char *proto_str, buf[len++] = '\r'; buf[len++] = '\n'; - if (write(vty->fd, buf, len) < 0) + if (write(vty->wfd, buf, len) < 0) { if (ERRNO_IO_RETRY(errno)) /* Kernel buffer is full, probably too much debugging output, so just @@ -703,6 +704,7 @@ vty_end_config (struct vty *vty) case RIPNG_NODE: case BGP_NODE: case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: @@ -873,7 +875,7 @@ vty_complete_command (struct vty *vty) if (isspace ((int) vty->buf[vty->length - 1])) vector_set (vline, NULL); - matched = cmd_complete_command (vline, vty, &ret); + matched = cmd_complete_command_lib (vline, vty, &ret, 1); cmd_free_strvec (vline); @@ -1363,8 +1365,8 @@ vty_read (struct thread *thread) vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ zlog_warn("%s: read error on vty client fd %d, closing: %s", __func__, vty->fd, safe_strerror(errno)); + buffer_reset(vty->obuf); } - buffer_reset(vty->obuf); vty->status = VTY_CLOSE; } @@ -1542,7 +1544,7 @@ vty_read (struct thread *thread) vty_close (vty); else { - vty_event (VTY_WRITE, vty_sock, vty); + vty_event (VTY_WRITE, vty->wfd, vty); vty_event (VTY_READ, vty_sock, vty); } return 0; @@ -1571,12 +1573,12 @@ vty_flush (struct thread *thread) /* N.B. if width is 0, that means we don't know the window size. */ if ((vty->lines == 0) || (vty->width == 0)) - flushrc = buffer_flush_available(vty->obuf, vty->fd); + flushrc = buffer_flush_available(vty->obuf, vty_sock); else if (vty->status == VTY_MORELINE) - flushrc = buffer_flush_window(vty->obuf, vty->fd, vty->width, + flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, 1, erase, 0); else - flushrc = buffer_flush_window(vty->obuf, vty->fd, vty->width, + flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, vty->lines >= 0 ? vty->lines : vty->height, erase, 0); @@ -1610,6 +1612,34 @@ vty_flush (struct thread *thread) return 0; } +/* allocate and initialise vty */ +static struct vty * +vty_new_init (int vty_sock) +{ + struct vty *vty; + + vty = vty_new (); + vty->fd = vty_sock; + vty->wfd = vty_sock; + vty->type = VTY_TERM; + vty->node = AUTH_NODE; + vty->fail = 0; + vty->cp = 0; + vty_clear_buf (vty); + vty->length = 0; + memset (vty->hist, 0, sizeof (vty->hist)); + vty->hp = 0; + vty->hindex = 0; + vector_set_index (vtyvec, vty_sock, vty); + vty->status = VTY_NORMAL; + vty->lines = -1; + vty->iac = 0; + vty->iac_sb_in_progress = 0; + vty->sb_len = 0; + + return vty; +} + /* Create new vty structure. */ static struct vty * vty_create (int vty_sock, union sockunion *su) @@ -1620,9 +1650,10 @@ vty_create (int vty_sock, union sockunion *su) sockunion2str(su, buf, SU_ADDRSTRLEN); /* Allocate new vty structure and set up default values. */ - vty = vty_new (); - vty->fd = vty_sock; - vty->type = VTY_TERM; + vty = vty_new_init (vty_sock); + + /* configurable parameters not part of basic init */ + vty->v_timeout = vty_timeout_val; strcpy (vty->address, buf); if (no_password_check) { @@ -1633,25 +1664,8 @@ vty_create (int vty_sock, union sockunion *su) else vty->node = VIEW_NODE; } - else - vty->node = AUTH_NODE; - vty->fail = 0; - vty->cp = 0; - vty_clear_buf (vty); - vty->length = 0; - memset (vty->hist, 0, sizeof (vty->hist)); - vty->hp = 0; - vty->hindex = 0; - vector_set_index (vtyvec, vty_sock, vty); - vty->status = VTY_NORMAL; - vty->v_timeout = vty_timeout_val; if (host.lines >= 0) vty->lines = host.lines; - else - vty->lines = -1; - vty->iac = 0; - vty->iac_sb_in_progress = 0; - vty->sb_len = 0; if (! no_password_check) { @@ -1687,6 +1701,66 @@ vty_create (int vty_sock, union sockunion *su) return vty; } +/* create vty for stdio */ +static struct termios stdio_orig_termios; +static struct vty *stdio_vty = NULL; +static void (*stdio_vty_atclose)(void); + +static void +vty_stdio_reset (void) +{ + if (stdio_vty) + { + tcsetattr (0, TCSANOW, &stdio_orig_termios); + stdio_vty = NULL; + + if (stdio_vty_atclose) + stdio_vty_atclose (); + stdio_vty_atclose = NULL; + } +} + +struct vty * +vty_stdio (void (*atclose)()) +{ + struct vty *vty; + struct termios termios; + + /* refuse creating two vtys on stdio */ + if (stdio_vty) + return NULL; + + vty = stdio_vty = vty_new_init (0); + stdio_vty_atclose = atclose; + vty->wfd = 1; + + /* always have stdio vty in a known _unchangeable_ state, don't want config + * to have any effect here to make sure scripting this works as intended */ + vty->node = ENABLE_NODE; + vty->v_timeout = 0; + strcpy (vty->address, "console"); + + if (!tcgetattr (0, &stdio_orig_termios)) + { + termios = stdio_orig_termios; + termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP + | INLCR | IGNCR | ICRNL | IXON); + termios.c_oflag &= ~OPOST; + termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + termios.c_cflag &= ~(CSIZE | PARENB); + termios.c_cflag |= CS8; + tcsetattr (0, TCSANOW, &termios); + } + + vty_prompt (vty); + + /* Add read/write thread. */ + vty_event (VTY_WRITE, 1, vty); + vty_event (VTY_READ, 0, vty); + + return vty; +} + /* Accept connection from the network. */ static int vty_accept (struct thread *thread) @@ -1775,7 +1849,7 @@ vty_accept (struct thread *thread) return 0; } -#if defined(HAVE_IPV6) && !defined(NRL) +#ifdef HAVE_IPV6 static void vty_serv_sock_addrinfo (const char *hostname, unsigned short port) { @@ -1840,7 +1914,7 @@ vty_serv_sock_addrinfo (const char *hostname, unsigned short port) freeaddrinfo (ainfo_save); } -#else /* HAVE_IPV6 && ! NRL */ +#else /* HAVE_IPV6 */ /* Make vty server socket. */ static void @@ -1908,7 +1982,7 @@ vty_serv_sock_family (const char* addr, unsigned short port, int family) /* Add vty server event. */ vty_event (VTY_SERV, accept_sock, NULL); } -#endif /* HAVE_IPV6 && ! NRL */ +#endif /* HAVE_IPV6 */ #ifdef VTYSH /* For sockaddr_un. */ @@ -2022,6 +2096,7 @@ vtysh_accept (struct thread *thread) vty = vty_new (); vty->fd = sock; + vty->wfd = sock; vty->type = VTY_SHELL_SERV; vty->node = VIEW_NODE; @@ -2033,10 +2108,10 @@ vtysh_accept (struct thread *thread) static int vtysh_flush(struct vty *vty) { - switch (buffer_flush_available(vty->obuf, vty->fd)) + switch (buffer_flush_available(vty->obuf, vty->wfd)) { case BUFFER_PENDING: - vty_event(VTYSH_WRITE, vty->fd, vty); + vty_event(VTYSH_WRITE, vty->wfd, vty); break; case BUFFER_ERROR: vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ @@ -2143,12 +2218,7 @@ vty_serv_sock (const char *addr, unsigned short port, const char *path) { #ifdef HAVE_IPV6 -#ifdef NRL - vty_serv_sock_family (addr, port, AF_INET); - vty_serv_sock_family (addr, port, AF_INET6); -#else /* ! NRL */ vty_serv_sock_addrinfo (addr, port); -#endif /* NRL*/ #else /* ! HAVE_IPV6 */ vty_serv_sock_family (addr,port, AF_INET); #endif /* HAVE_IPV6 */ @@ -2177,7 +2247,7 @@ vty_close (struct vty *vty) thread_cancel (vty->t_timeout); /* Flush buffer. */ - buffer_flush_all (vty->obuf, vty->fd); + buffer_flush_all (vty->obuf, vty->wfd); /* Free input buffer. */ buffer_free (vty->obuf); @@ -2193,6 +2263,8 @@ vty_close (struct vty *vty) /* Close socket. */ if (vty->fd > 0) close (vty->fd); + else + vty_stdio_reset (); if (vty->buf) XFREE (MTYPE_VTY, vty->buf); @@ -2237,12 +2309,13 @@ vty_read_file (FILE *confp) unsigned int line_num = 0; vty = vty_new (); - vty->fd = dup(STDERR_FILENO); /* vty_close() will close this */ - if (vty->fd < 0) + vty->wfd = dup(STDERR_FILENO); /* vty_close() will close this */ + if (vty->wfd < 0) { /* Fine, we couldn't make a new fd. vty_close doesn't close stdout. */ - vty->fd = STDOUT_FILENO; + vty->wfd = STDOUT_FILENO; } + vty->fd = STDIN_FILENO; vty->type = VTY_FILE; vty->node = CONFIG_NODE; @@ -2497,7 +2570,7 @@ vty_log_fixed (char *buf, size_t len) if (((vty = vector_slot (vtyvec, i)) != NULL) && vty->monitor) /* N.B. We don't care about the return code, since process is most likely just about to die anyway. */ - if (writev(vty->fd, iov, 2) == -1) + if (writev(vty->wfd, iov, 2) == -1) { fprintf(stderr, "Failure to writev: %d\n", errno); exit(-1); @@ -3005,6 +3078,8 @@ vty_init (struct thread_master *master_thread) vty_master = master_thread; + atexit (vty_stdio_reset); + /* Initilize server thread vector. */ Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE); diff --git a/lib/vty.h b/lib/vty.h index f0286202bd..81251e07bb 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -34,6 +34,9 @@ struct vty /* File descripter of this vty. */ int fd; + /* output FD, to support stdin/stdout combination */ + int wfd; + /* Is this vty connect to file or not */ enum {VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV} type; @@ -270,6 +273,7 @@ extern void vty_init_vtysh (void); extern void vty_terminate (void); extern void vty_reset (void); extern struct vty *vty_new (void); +extern struct vty *vty_stdio (void (*atclose)(void)); extern int vty_out (struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); extern void vty_read_config (char *, char *); extern void vty_time_print (struct vty *, int); diff --git a/lib/workqueue.c b/lib/workqueue.c index a45a6fc097..3100b99383 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -108,6 +108,12 @@ work_queue_free (struct work_queue *wq) return; } +bool +work_queue_is_scheduled (struct work_queue *wq) +{ + return (wq->thread != NULL); +} + static int work_queue_schedule (struct work_queue *wq, unsigned int delay) { diff --git a/lib/workqueue.h b/lib/workqueue.h index 7d9a877d10..19b44041d7 100644 --- a/lib/workqueue.h +++ b/lib/workqueue.h @@ -122,6 +122,8 @@ extern void work_queue_plug (struct work_queue *wq); /* unplug the queue, allow it to be drained again */ extern void work_queue_unplug (struct work_queue *wq); +bool work_queue_is_scheduled (struct work_queue *); + /* Helpers, exported for thread.c and command.c */ extern int work_queue_run (struct thread *); extern struct cmd_element show_work_queues_cmd; diff --git a/lib/zclient.c b/lib/zclient.c index 4fe5398e65..ea663329ca 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -39,7 +39,7 @@ enum event {ZCLIENT_SCHEDULE, ZCLIENT_READ, ZCLIENT_CONNECT}; /* Prototype for event manager. */ static void zclient_event (enum event, struct zclient *); -char *zclient_serv_path = NULL; +const char *zclient_serv_path = NULL; /* This file local debug flag. */ int zclient_debug = 0; @@ -1601,7 +1601,7 @@ zclient_event (enum event event, struct zclient *zclient) } } -const char *const zclient_serv_path_get() +const char *zclient_serv_path_get() { return zclient_serv_path ? zclient_serv_path : ZEBRA_SERV_PATH; } diff --git a/lib/zclient.h b/lib/zclient.h index 6bb1725963..f30190c1b4 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -167,7 +167,7 @@ extern void zclient_free (struct zclient *); extern int zclient_socket_connect (struct zclient *); extern void zclient_serv_path_set (char *path); -extern const char *const zclient_serv_path_get (void); +extern const char *zclient_serv_path_get (void); extern int redist_check_instance (struct redist_proto *, u_short); extern void redist_add_instance (struct redist_proto *, u_short); diff --git a/lib/zebra.h b/lib/zebra.h index 9a2b5441fc..59c154ba46 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -246,20 +246,6 @@ typedef int socklen_t; #include #endif /* HAVE_GLIBC_BACKTRACE */ -#ifdef BSDI_NRL - -#ifdef HAVE_NETINET6_IN6_H -#include -#endif /* HAVE_NETINET6_IN6_H */ - -#ifdef NRL -#include -#endif /* NRL */ - -#define IN6_ARE_ADDR_EQUAL IN6_IS_ADDR_EQUAL - -#endif /* BSDI_NRL */ - /* Local includes: */ #if !(defined(__GNUC__) || defined(VTYSH_EXTRACT_PL)) #define __attribute__(x) @@ -489,11 +475,6 @@ extern int proto_redistnum(int afi, const char *s); extern const char *zserv_command_string (unsigned int command); -/* Zebra's family types. */ -#define ZEBRA_FAMILY_IPV4 1 -#define ZEBRA_FAMILY_IPV6 2 -#define ZEBRA_FAMILY_MAX 3 - /* Error codes of zebra. */ #define ZEBRA_ERR_NOERROR 0 #define ZEBRA_ERR_RTEXIST -1 @@ -527,9 +508,11 @@ extern const char *zserv_command_string (unsigned int command); #endif /* Address family numbers from RFC1700. */ -#define AFI_IP 1 -#define AFI_IP6 2 -#define AFI_MAX 3 +typedef enum { + AFI_IP = 1, + AFI_IP6 = 2, +#define AFI_MAX 3 +} afi_t; /* Subsequent Address Family Identifier. */ #define SAFI_UNICAST 1 @@ -563,8 +546,6 @@ extern const char *zserv_command_string (unsigned int command); #define UNSET_FLAG(V,F) (V) &= ~(F) #define RESET_FLAG(V) (V) = 0 -/* AFI and SAFI type. */ -typedef u_int16_t afi_t; typedef u_int8_t safi_t; /* Zebra types. Used in Zserv message header. */ diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 84f433171b..f4181167e1 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index b192d6850b..39942d7b18 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -41,6 +41,7 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_spf.h" +#include "ospf6_snmp.h" #include "ospf6d.h" #include "ospf6_bfd.h" diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 1ecac2813f..5b92212daa 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1502,7 +1502,8 @@ ospf6_brouter_debug_print (struct ospf6_route *brouter) zlog_info ("Brouter: %s via area %s", brouter_name, area_name); zlog_info (" memory: prev: %p this: %p next: %p parent rnode: %p", - brouter->prev, brouter, brouter->next, brouter->rnode); + (void *)brouter->prev, (void *)brouter, (void *)brouter->next, + (void *)brouter->rnode); zlog_info (" type: %d prefix: %s installed: %s changed: %s", brouter->type, destination, installed, changed); zlog_info (" lock: %d flags: %s%s%s%s", brouter->lock, @@ -1550,7 +1551,7 @@ ospf6_intra_brouter_calculation (struct ospf6_area *oa) IS_OSPF6_DEBUG_ROUTE (MEMORY)) { zlog_info ("%p: mark as removing: area %s brouter %s", - brouter, oa->name, brouter_name); + (void *)brouter, oa->name, brouter_name); ospf6_brouter_debug_print (brouter); } } @@ -1582,7 +1583,7 @@ ospf6_intra_brouter_calculation (struct ospf6_area *oa) IS_OSPF6_DEBUG_ROUTE (MEMORY)) { zlog_info ("%p: transfer: area %s brouter %s", - brouter, oa->name, brouter_name); + (void *)brouter, oa->name, brouter_name); ospf6_brouter_debug_print (brouter); } } diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 317e33ba7b..3f008d3d9f 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -493,8 +493,8 @@ ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa) vty_out (vty, "Flag: %x %s", lsa->flag, VNL); vty_out (vty, "Lock: %d %s", lsa->lock, VNL); vty_out (vty, "ReTx Count: %d%s", lsa->retrans_count, VNL); - vty_out (vty, "Threads: Expire: %p, Refresh: %p %s", - lsa->expire, lsa->refresh, VNL); + vty_out (vty, "Threads: Expire: 0x%p, Refresh: 0x%p %s", + (void *)lsa->expire, (void *)lsa->refresh, VNL); vty_out (vty, "%s", VNL); return; } diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 52dc6677f0..84c98b885f 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -243,7 +243,7 @@ main (int argc, char *argv[], char *envp[]) progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]); /* Seed random number for LSA ID */ - srand (time(NULL)); + srandom (time(NULL)); /* Command line argument treatment. */ while (1) diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 49b4aceaeb..9b0285eee9 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -38,6 +38,7 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_flood.h" +#include "ospf6_snmp.h" #include "ospf6d.h" #include "ospf6_bfd.h" #include "ospf6_abr.h" diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 86c908bb38..d174cfbb91 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -597,7 +597,7 @@ ospf6_route_add (struct ospf6_route *route, if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_debug ("%s %p: route add %p: %s", ospf6_route_table_name (table), - table, route, buf); + (void *)table, (void *)route, buf); else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("%s: route add: %s", ospf6_route_table_name (table), buf); @@ -631,7 +631,8 @@ ospf6_route_add (struct ospf6_route *route, { if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_debug ("%s %p: route add %p: needless update of %p", - ospf6_route_table_name (table), table, route, old); + ospf6_route_table_name (table), + (void *)table, (void *)route, (void *)old); else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("%s: route add: needless update", ospf6_route_table_name (table)); @@ -645,7 +646,8 @@ ospf6_route_add (struct ospf6_route *route, if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_debug ("%s %p: route add %p: update of %p", - ospf6_route_table_name (table), table, route, old); + ospf6_route_table_name (table), + (void *)table, (void *)route, (void *)old); else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("%s: route add: update", ospf6_route_table_name (table)); @@ -686,7 +688,8 @@ ospf6_route_add (struct ospf6_route *route, { if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_debug ("%s %p: route add %p: another path: prev %p, next %p", - ospf6_route_table_name (table), table, route, prev, next); + ospf6_route_table_name (table), + (void *)table, (void *)route, (void *)prev, (void *)next); else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("%s: route add: another path found", ospf6_route_table_name (table)); @@ -711,7 +714,8 @@ ospf6_route_add (struct ospf6_route *route, SET_FLAG (route->flag, OSPF6_ROUTE_BEST); if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_info ("%s %p: route add %p: replacing previous best: %p", - ospf6_route_table_name (table), table, route, next); + ospf6_route_table_name (table), + (void *)table, (void *)route, (void *)next); } route->installed = now; @@ -733,7 +737,7 @@ ospf6_route_add (struct ospf6_route *route, /* Else, this is the brand new route regarding to the prefix */ if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_debug ("%s %p: route add %p: brand new route", - ospf6_route_table_name (table), table, route); + ospf6_route_table_name (table), (void *)table, (void *)route); else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("%s: route add: brand new route", ospf6_route_table_name (table)); @@ -812,7 +816,8 @@ ospf6_route_remove (struct ospf6_route *route, if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_debug ("%s %p: route remove %p: %s", - ospf6_route_table_name (table), table, route, buf); + ospf6_route_table_name (table), + (void *)table, (void *)route, buf); else if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("%s: route remove: %s", ospf6_route_table_name (table), buf); @@ -884,8 +889,8 @@ ospf6_route_head (struct ospf6_route_table *table) if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_info ("%s %p: route head: %p<-[%p]->%p", - ospf6_route_table_name (table), table, - route->prev, route, route->next); + ospf6_route_table_name (table), (void *)table, + (void *)route->prev, (void *)route, (void *)route->next); return route; } @@ -897,8 +902,8 @@ ospf6_route_next (struct ospf6_route *route) if (IS_OSPF6_DEBUG_ROUTE (MEMORY)) zlog_info ("%s %p: route next: %p<-[%p]->%p", - ospf6_route_table_name (route->table), route->table, - route->prev, route, route->next); + ospf6_route_table_name (route->table), (void *)route->table, + (void *)route->prev, (void *)route, (void *)route->next); ospf6_route_unlock (route); if (next) @@ -1099,7 +1104,7 @@ ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route) (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"), VNL); vty_out (vty, "Memory: prev: %p this: %p next: %p%s", - route->prev, route, route->next, VNL); + (void *)route->prev, (void *)route, (void *)route->next, VNL); /* Path section */ diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index b3be66c28e..e783b72d8e 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -251,14 +251,13 @@ extern const char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX]; #define ospf6_route_is_best(r) (CHECK_FLAG ((r)->flag, OSPF6_ROUTE_BEST)) -/* XXX: This gives GCC heartburn aboutbreaking aliasing rules. */ #define ospf6_linkstate_prefix_adv_router(x) \ - ((x)->u.prefix4.s_addr) + ((x)->u.lp.id.s_addr) #define ospf6_linkstate_prefix_id(x) \ - ((x)->u.prefix6.s6_addr32[1]) + ((x)->u.lp.adv_router.s_addr) #define ADV_ROUTER_IN_PREFIX(x) \ - ((x)->u.prefix4.s_addr) + ((x)->u.lp.id.s_addr) /* Function prototype */ extern void ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id, diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index ed1917c3a8..307d420ece 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -40,6 +40,8 @@ #include "ospf6_interface.h" #include "ospf6_message.h" #include "ospf6_neighbor.h" +#include "ospf6_abr.h" +#include "ospf6_asbr.h" #include "ospf6d.h" #include "ospf6_snmp.h" diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index fda3bb5fb8..5b77bf00a6 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -651,11 +651,12 @@ ospf6_spf_calculation_thread (struct thread *t) ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf)); if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) - zlog_debug ("SPF runtime: %ld sec %ld usec", - runtime.tv_sec, runtime.tv_usec); + zlog_debug ("SPF runtime: %lld sec %lld usec", + (long long)runtime.tv_sec, (long long)runtime.tv_usec); - zlog_info("SPF processing: # Areas: %d, SPF runtime: %ld sec %ld usec, " - "Reason: %s\n", areas_processed, runtime.tv_sec, runtime.tv_usec, + zlog_info("SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, " + "Reason: %s\n", areas_processed, + (long long)runtime.tv_sec, (long long)runtime.tv_usec, rbuf); ospf6->last_spf_reason = ospf6->spf_reason; ospf6_reset_spf_reason(ospf6); @@ -688,7 +689,7 @@ ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason) { if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) zlog_debug ("SPF: calculation timer is already scheduled: %p", - ospf6->t_spf_calc); + (void *)ospf6->t_spf_calc); return; } diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 350e8ac9fd..b4e937a63a 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -725,8 +725,9 @@ ospf6_show (struct vty *vty, struct ospf6 *o) timerstring(&result, buf, sizeof(buf)); ospf6_spf_reason_string(o->last_spf_reason, rbuf, sizeof(rbuf)); vty_out(vty, "last executed %s ago, reason %s%s", buf, rbuf, VNL); - vty_out (vty, " Last SPF duration %ld sec %ld usec%s", - o->ts_spf_duration.tv_sec, o->ts_spf_duration.tv_usec, VNL); + vty_out (vty, " Last SPF duration %lld sec %lld usec%s", + (long long)o->ts_spf_duration.tv_sec, + (long long)o->ts_spf_duration.tv_usec, VNL); } else vty_out(vty, "has not been run$%s", VNL); diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h index 78ae1a14b2..9e2efb41d7 100644 --- a/ospf6d/ospf6d.h +++ b/ospf6d/ospf6d.h @@ -30,12 +30,6 @@ /* global variables */ extern struct thread_master *master; -#ifdef INRIA_IPV6 -#ifndef IPV6_PKTINFO -#define IPV6_PKTINFO IPV6_RECVPKTINFO -#endif /* IPV6_PKTINFO */ -#endif /* INRIA_IPV6 */ - /* Historical for KAME. */ #ifndef IPV6_JOIN_GROUP #ifdef IPV6_ADD_MEMBERSHIP @@ -77,19 +71,19 @@ extern struct thread_master *master; } \ } while (0) #endif /*timersub*/ -#define timerstring(tv, buf, size) \ - do { \ - if ((tv)->tv_sec / 60 / 60 / 24) \ - snprintf (buf, size, "%ldd%02ld:%02ld:%02ld", \ - (tv)->tv_sec / 60 / 60 / 24, \ - (tv)->tv_sec / 60 / 60 % 24, \ - (tv)->tv_sec / 60 % 60, \ - (tv)->tv_sec % 60); \ - else \ - snprintf (buf, size, "%02ld:%02ld:%02ld", \ - (tv)->tv_sec / 60 / 60 % 24, \ - (tv)->tv_sec / 60 % 60, \ - (tv)->tv_sec % 60); \ +#define timerstring(tv, buf, size) \ + do { \ + if ((tv)->tv_sec / 60 / 60 / 24) \ + snprintf (buf, size, "%lldd%02lld:%02lld:%02lld", \ + (tv)->tv_sec / 60LL / 60 / 24, \ + (tv)->tv_sec / 60LL / 60 % 24, \ + (tv)->tv_sec / 60LL % 60, \ + (tv)->tv_sec % 60LL); \ + else \ + snprintf (buf, size, "%02lld:%02lld:%02lld", \ + (tv)->tv_sec / 60LL / 60 % 24, \ + (tv)->tv_sec / 60LL % 60, \ + (tv)->tv_sec % 60LL); \ } while (0) #define timerstring_local(tv, buf, size) \ do { \ diff --git a/ospfclient/Makefile.am b/ospfclient/Makefile.am index f54481c924..1fca431a10 100644 --- a/ospfclient/Makefile.am +++ b/ospfclient/Makefile.am @@ -1,6 +1,6 @@ ## Automake.am for OSPF API client -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib AM_CFLAGS = $(WERROR) lib_LTLIBRARIES = libospfapiclient.la diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 207941e3a7..9eb166a3d6 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib AM_CFLAGS = $(WERROR) DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index db1ccda72a..92f68f75f8 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -244,7 +244,8 @@ static int ospf_apiserver_new_lsa_hook (struct ospf_lsa *lsa) { if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total); + zlog_debug ("API: Put LSA(%p)[%s] into reserve, total=%ld", (void *)lsa, + dump_lsa_key (lsa), lsa->lsdb->total); return 0; } @@ -252,7 +253,8 @@ static int ospf_apiserver_del_lsa_hook (struct ospf_lsa *lsa) { if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", lsa, dump_lsa_key (lsa), lsa->lsdb->total); + zlog_debug ("API: Get LSA(%p)[%s] from reserve, total=%ld", (void *)lsa, + dump_lsa_key (lsa), lsa->lsdb->total); return 0; } @@ -395,7 +397,8 @@ ospf_apiserver_free (struct ospf_apiserver *apiserv) listnode_delete (apiserver_list, apiserv); if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: Delete apiserv(%p), total#(%d)", apiserv, apiserver_list->count); + zlog_debug ("API: Delete apiserv(%p), total#(%d)", + (void *)apiserv, apiserver_list->count); /* And free instance. */ XFREE (MTYPE_OSPF_APISERVER, apiserv); @@ -755,7 +758,8 @@ ospf_apiserver_accept (struct thread *thread) #endif /* USE_ASYNC_READ */ if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("API: New apiserv(%p), total#(%d)", apiserv, apiserver_list->count); + zlog_debug ("API: New apiserv(%p), total#(%d)", + (void *)apiserv, apiserver_list->count); return 0; } @@ -944,7 +948,7 @@ ospf_apiserver_register_opaque_type (struct ospf_apiserver *apiserv, if (IS_DEBUG_OSPF_EVENT) zlog_debug ("API: Add LSA-type(%d)/Opaque-type(%d) into" " apiserv(%p), total#(%d)", - lsa_type, opaque_type, apiserv, + lsa_type, opaque_type, (void *)apiserv, listcount (apiserv->opaque_types)); return 0; @@ -976,7 +980,7 @@ ospf_apiserver_unregister_opaque_type (struct ospf_apiserver *apiserv, if (IS_DEBUG_OSPF_EVENT) zlog_debug ("API: Del LSA-type(%d)/Opaque-type(%d)" " from apiserv(%p), total#(%d)", - lsa_type, opaque_type, apiserv, + lsa_type, opaque_type, (void *)apiserv, listcount (apiserv->opaque_types)); return 0; diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index af1abfbc93..74c1711ef1 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -679,8 +679,8 @@ ospf_ase_calculate_timer (struct thread *t) quagga_gettime(QUAGGA_CLK_MONOTONIC, &stop_time); - zlog_info ("SPF Processing Time(usecs): External Routes: %ld\n", - (stop_time.tv_sec - start_time.tv_sec)*1000000L+ + zlog_info ("SPF Processing Time(usecs): External Routes: %lld\n", + (stop_time.tv_sec - start_time.tv_sec)*1000000LL+ (stop_time.tv_usec - start_time.tv_usec)); } return 0; diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 4c1f0549eb..56dac83b7c 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -299,13 +299,13 @@ ospf_timeval_dump (struct timeval *t, char *buf, size_t size) else if (d) snprintf (buf, size, "%1ldd%02ldh%02ldm", d, h, m); else if (h) - snprintf (buf, size, "%ldh%02ldm%02lds", h, m, t->tv_sec); + snprintf (buf, size, "%ldh%02ldm%02lds", h, m, (long)t->tv_sec); else if (m) - snprintf (buf, size, "%ldm%02lds", m, t->tv_sec); + snprintf (buf, size, "%ldm%02lds", m, (long)t->tv_sec); else if (ms) - snprintf (buf, size, "%ld.%03lds", t->tv_sec, ms); + snprintf (buf, size, "%ld.%03lds", (long)t->tv_sec, ms); else - snprintf (buf, size, "%ld usecs", t->tv_usec); + snprintf (buf, size, "%ld usecs", (long)t->tv_usec); return buf; } diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index c641b190fb..d0d446f7a6 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -262,7 +262,7 @@ ospf_flood (struct ospf *ospf, struct ospf_neighbor *nbr, zlog_debug ("LSA[Flooding]: start, NBR %s (%s), cur(%p), New-LSA[%s]", inet_ntoa (nbr->router_id), LOOKUP (ospf_nsm_state_msg, nbr->state), - current, + (void *)current, dump_lsa_key (new)); lsa_ack_flag = 0; @@ -448,16 +448,6 @@ ospf_flood_through_interface (struct ospf_interface *oi, zlog_debug ("Skip this neighbor: Not Opaque-capable."); continue; } - - if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (oi->ospf->opaque) - && IS_LSA_SELF (lsa) - && onbr->state == NSM_Full) - { - /* Small attempt to reduce unnecessary retransmission. */ - if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Skip this neighbor: Initial flushing done."); - continue; - } } #endif /* HAVE_OPAQUE_LSA */ @@ -602,7 +592,8 @@ ospf_flood_through_area (struct ospf_area *area, * for the link on which the LSA has received. */ if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", lsa->oi, oi); + zlog_debug ("Type-9 Opaque-LSA: lsa->oi(%p) != oi(%p)", + (void *)lsa->oi, (void *)oi); continue; } #endif /* HAVE_OPAQUE_LSA */ diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index b2c738f146..62c455e774 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -259,7 +259,7 @@ ospf_lsa_dup (struct ospf_lsa *lsa) new->refresh_list = -1; if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("LSA: duplicated %p (new: %p)", lsa, new); + zlog_debug ("LSA: duplicated %p (new: %p)", (void *)lsa, (void *)new); return new; } @@ -271,7 +271,7 @@ ospf_lsa_free (struct ospf_lsa *lsa) assert (lsa->lock == 0); if (IS_DEBUG_OSPF (lsa, LSA)) - zlog_debug ("LSA: freed %p", lsa); + zlog_debug ("LSA: freed %p", (void *)lsa); /* Delete LSA data. */ if (lsa->data != NULL) @@ -347,7 +347,7 @@ ospf_lsa_data_free (struct lsa_header *lsah) { if (IS_DEBUG_OSPF (lsa, LSA)) zlog_debug ("LSA[Type%d:%s]: data freed %p", - lsah->type, inet_ntoa (lsah->id), lsah); + lsah->type, inet_ntoa (lsah->id), (void *)lsah); XFREE (MTYPE_OSPF_LSA_DATA, lsah); } @@ -914,7 +914,7 @@ ospf_router_lsa_originate (struct ospf_area *area) if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_debug ("LSA[Type%d:%s]: Originate router-LSA %p", - new->data->type, inet_ntoa (new->data->id), new); + new->data->type, inet_ntoa (new->data->id), (void *)new); ospf_lsa_header_dump (new->data); } @@ -1149,7 +1149,7 @@ ospf_network_lsa_update (struct ospf_interface *oi) if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_debug ("LSA[Type%d:%s]: Originate network-LSA %p", - new->data->type, inet_ntoa (new->data->id), new); + new->data->type, inet_ntoa (new->data->id), (void *)new); ospf_lsa_header_dump (new->data); } @@ -1326,7 +1326,7 @@ ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_debug ("LSA[Type%d:%s]: Originate summary-LSA %p", - new->data->type, inet_ntoa (new->data->id), new); + new->data->type, inet_ntoa (new->data->id), (void *)new); ospf_lsa_header_dump (new->data); } @@ -1469,7 +1469,7 @@ ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_debug ("LSA[Type%d:%s]: Originate summary-ASBR-LSA %p", - new->data->type, inet_ntoa (new->data->id), new); + new->data->type, inet_ntoa (new->data->id), (void *)new); ospf_lsa_header_dump (new->data); } @@ -2110,7 +2110,7 @@ ospf_external_lsa_originate (struct ospf *ospf, struct external_info *ei) if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_debug ("LSA[Type%d:%s]: Originate AS-external-LSA %p", - new->data->type, inet_ntoa (new->data->id), new); + new->data->type, inet_ntoa (new->data->id), (void *)new); ospf_lsa_header_dump (new->data); } @@ -2316,7 +2316,8 @@ ospf_external_lsa_refresh_default (struct ospf *ospf) if (lsa) { if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", lsa); + zlog_debug ("LSA[Type5:0.0.0.0]: Refresh AS-external-LSA %p", + (void *)lsa); ospf_external_lsa_refresh (ospf, lsa, ei, LSA_REFRESH_FORCE); } else @@ -2746,7 +2747,7 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, { zlog_debug ("ospf_lsa_install() Premature Aging " "lsa 0x%p, seqnum 0x%x", - lsa, ntohl(lsa->data->ls_seqnum)); + (void *)lsa, ntohl(lsa->data->ls_seqnum)); ospf_lsa_header_dump (lsa->data); } } @@ -2849,9 +2850,9 @@ ospf_lsa_install (struct ospf *ospf, struct ospf_interface *oi, { if (IS_DEBUG_OSPF (lsa, LSA_INSTALL)) zlog_debug ("LSA[Type%d:%s]: Install LSA 0x%p, MaxAge", - new->data->type, - inet_ntoa (new->data->id), - lsa); + new->data->type, + inet_ntoa (new->data->id), + (void *)lsa); ospf_lsa_maxage (ospf, lsa); } @@ -2938,7 +2939,7 @@ ospf_maxage_lsa_remover (struct thread *thread) if (CHECK_FLAG (lsa->flags, OSPF_LSA_PREMATURE_AGE)) { if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) - zlog_debug ("originating new lsa for lsa 0x%p\n", lsa); + zlog_debug ("originating new lsa for lsa 0x%p\n", (void *)lsa); ospf_lsa_refresh (ospf, lsa); } @@ -3005,7 +3006,7 @@ ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa) { if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_debug ("LSA[Type%d:%s]: %p already exists on MaxAge LSA list", - lsa->data->type, inet_ntoa (lsa->data->id), lsa); + lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa); return; } @@ -3020,7 +3021,8 @@ ospf_lsa_maxage (struct ospf *ospf, struct ospf_lsa *lsa) { if (IS_DEBUG_OSPF (lsa, LSA_FLOODING)) zlog_debug ("LSA[%s]: found LSA (%p) in table for LSA %p %d", - dump_lsa_key (lsa), rn->info, lsa, lsa_prefix.prefixlen); + dump_lsa_key (lsa), rn->info, (void *)lsa, + lsa_prefix.prefixlen); route_unlock_node (rn); } else @@ -3747,9 +3749,9 @@ ospf_refresher_register_lsa (struct ospf *ospf, struct ospf_lsa *lsa) lsa->refresh_list = index; if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) - zlog_debug ("LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa() " - "setting refresh_list on lsa %p (slot %d)", - lsa->data->type, inet_ntoa (lsa->data->id), lsa, index); + zlog_debug ("LSA[Refresh:Type%d:%s]: ospf_refresher_register_lsa(): " + "setting refresh_list on lsa %p (slod %d)", + lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa, index); } } @@ -3820,9 +3822,9 @@ ospf_lsa_refresh_walker (struct thread *t) { if (IS_DEBUG_OSPF (lsa, LSA_REFRESH)) zlog_debug ("LSA[Refresh:Type%d:%s]: ospf_lsa_refresh_walker(): " - "refresh lsa %p (slot %d)", - lsa->data->type, inet_ntoa (lsa->data->id), lsa, i); - + "refresh lsa %p (slot %d)", + lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa, i); + assert (lsa->lock > 0); list_delete_node (refresh_list, node); lsa->refresh_list = -1; diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c index f7cf60fd09..b92e7494ad 100644 --- a/ospfd/ospf_lsdb.c +++ b/ospfd/ospf_lsdb.c @@ -158,7 +158,7 @@ ospf_lsdb_delete (struct ospf_lsdb *lsdb, struct ospf_lsa *lsa) if (lsa) zlog_warn ("LSA[Type%d:%s]: LSA %p, lsa->lsdb %p", lsa->data->type, inet_ntoa (lsa->data->id), - lsa, lsa->lsdb); + (void *)lsa, (void *)lsa->lsdb); return; } diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 758deaf3e5..62eb41e770 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -218,7 +218,7 @@ main (int argc, char **argv) { case 'n': instance = atoi(optarg); - if (instance < 1 || instance > 65535) + if (instance < 1) exit(0); break; case 0: diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 00868dd5c1..4c05c77252 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -1317,13 +1317,7 @@ ospf_opaque_lsa_originate_schedule (struct ospf_interface *oi, int *delay0) zlog_debug ("ospf_opaque_lsa_originate_schedule: Not operational."); goto out; /* This is not an error. */ } - if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_opaque_lsa_originate_schedule: Under blockade."); - goto out; /* This is not an error, too. */ - } - + if (delay0 != NULL) delay = *delay0; @@ -1765,13 +1759,7 @@ ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent, zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Not operational."); goto out; /* This is not an error. */ } - if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("ospf_opaque_lsa_reoriginate_schedule: Under blockade."); - goto out; /* This is not an error, too. */ - } - + /* Generate a dummy lsa to be passed for a lookup function. */ lsa = pseudo_lsa (oi, area, lsa_type, opaque_type); @@ -2127,132 +2115,15 @@ out: return; } -/*------------------------------------------------------------------------* - * Followings are control functions to block origination after restart. - *------------------------------------------------------------------------*/ - -static void ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa); -#ifdef BUGGY_UNLOCK -static void ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi); -static void ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area); -static void ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top); -static unsigned long ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type); -#endif /* BUGGY_UNLOCK */ - -void -ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas) -{ - struct ospf *top; - struct ospf_area *area; - struct ospf_interface *oi; - struct listnode *node1, *nnode1; - struct listnode *node2, *nnode2; - struct ospf_lsa *lsa; - - if ((top = oi_to_top (nbr->oi)) == NULL) - goto out; - - /* - * If an instance of self-originated Opaque-LSA is found in the given - * LSA list, and it is not installed to LSDB yet, exclude it from the - * list "nbr->ls_req". In this way, it is assured that an LSReq message, - * which might be sent in the process of flooding, will not request for - * the LSA to be flushed immediately; otherwise, depending on timing, - * an LSUpd message will carry instances of target LSAs with MaxAge, - * while other LSUpd message might carry old LSA instances (non-MaxAge). - * Obviously, the latter would trigger miserable situations that repeat - * installation and removal of unwanted LSAs indefinitely. - */ - for (ALL_LIST_ELEMENTS (lsas, node1, nnode1, lsa)) - { - /* Filter out unwanted LSAs. */ - if (! IS_OPAQUE_LSA (lsa->data->type)) - continue; - if (! IPV4_ADDR_SAME (&lsa->data->adv_router, &top->router_id)) - continue; - - /* - * Don't touch an LSA which has MaxAge; two possible cases. - * - * 1) This LSA has originally flushed by myself (received LSUpd - * message's router-id is equal to my router-id), and flooded - * back by an opaque-capable router. - * - * 2) This LSA has expired in an opaque-capable router and thus - * flushed by the router. - */ - if (IS_LSA_MAXAGE (lsa)) - continue; - - /* If the LSA has installed in the LSDB, nothing to do here. */ - if (ospf_lsa_lookup_by_header (nbr->oi->area, lsa->data) != NULL) - continue; - - /* Ok, here we go. */ - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - oi = nbr->oi; - ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa); - break; - case OSPF_OPAQUE_AREA_LSA: - area = nbr->oi->area; - for (ALL_LIST_ELEMENTS (area->oiflist, node2, nnode2, oi)) - ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa); - break; - case OSPF_OPAQUE_AS_LSA: - for (ALL_LIST_ELEMENTS (top->oiflist, node2, nnode2, oi)) - ospf_opaque_exclude_lsa_from_lsreq (oi->nbrs, nbr, lsa); - break; - default: - break; - } - } - -out: - return; -} - -static void -ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, - struct ospf_neighbor *inbr, - struct ospf_lsa *lsa) -{ - struct route_node *rn; - struct ospf_neighbor *onbr; - struct ospf_lsa *ls_req; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - { - if ((onbr = rn->info) == NULL) - continue; - if (onbr == inbr) - continue; - if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL) - continue; - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("LSA[%s]: Exclude this entry from LSReq to send.", dump_lsa_key (lsa)); - - ospf_ls_request_delete (onbr, ls_req); -/* ospf_check_nbr_loading (onbr);*//* XXX */ - } - - return; -} - void ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) { struct ospf *top; - u_char before; - + if ((top = oi_to_top (nbr->oi)) == NULL) return; - before = IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque); - /* * Since these LSA entries are not yet installed into corresponding * LSDB, just flush them without calling ospf_ls_maxage() afterward. @@ -2261,197 +2132,21 @@ ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, switch (lsa->data->type) { case OSPF_OPAQUE_LINK_LSA: - SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT); ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa); break; case OSPF_OPAQUE_AREA_LSA: - SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT); ospf_flood_through_area (nbr->oi->area, NULL/*inbr*/, lsa); break; case OSPF_OPAQUE_AS_LSA: - SET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT); ospf_flood_through_as (top, NULL/*inbr*/, lsa); break; default: zlog_warn ("ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)", lsa->data->type); return; } - - ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */ - - if (before == 0 && IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque)) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Block Opaque-LSA origination: OFF -> ON"); - } + ospf_lsa_discard (lsa); /* List "lsas" will be deleted by caller. */ } -void -ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) -{ - struct ospf *top; - int delay; - struct ospf_interface *oi; - struct listnode *node, *nnode; - - if ((top = oi_to_top (nbr->oi)) == NULL) - return; - - if (!IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque)) - return; - - switch (lsa->data->type) - { - case OSPF_OPAQUE_LINK_LSA: - if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT)) - UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT); - /* BUGGY_UNLOCK: ospf_opaque_type9_lsa_rxmt_nbr_check (nbr->oi); */ - /* Callback function... */ - break; - case OSPF_OPAQUE_AREA_LSA: - if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT)) - UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT); - /* BUGGY_UNLOCK: ospf_opaque_type10_lsa_rxmt_nbr_check (nbr->oi->area); */ - /* Callback function... */ - break; - case OSPF_OPAQUE_AS_LSA: - if (CHECK_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT)) - UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT); - /* BUGGY_UNLOCK: ospf_opaque_type11_lsa_rxmt_nbr_check (top); */ - /* Callback function... */ - break; - default: - zlog_warn ("ospf_opaque_ls_ack_received: Unexpected LSA-type(%u)", lsa->data->type); - return; - } - - if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (top->opaque)) - return; /* Blocking still in progress. */ - - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Block Opaque-LSA origination: ON -> OFF"); - - if (! CHECK_FLAG (top->config, OSPF_OPAQUE_CAPABLE)) - return; /* Opaque capability condition must have changed. */ - - /* Ok, let's start origination of Opaque-LSAs. */ - delay = OSPF_MIN_LS_INTERVAL; - - for (ALL_LIST_ELEMENTS (top->oiflist, node, nnode, oi)) - { - if (! ospf_if_is_enable (oi) - || ospf_nbr_count_opaque_capable (oi) == 0) - continue; - - ospf_opaque_lsa_originate_schedule (oi, &delay); - } - - return; -} - -#ifdef BUGGY_UNLOCK -static void -ospf_opaque_type9_lsa_rxmt_nbr_check (struct ospf_interface *oi) -{ - unsigned long n; - - n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_LINK_LSA); - if (n == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Self-originated type-9 Opaque-LSAs: OI(%s): Flush completed", IF_NAME (oi)); - - UNSET_FLAG (oi->area->ospf->opaque, OPAQUE_BLOCK_TYPE_09_LSA_BIT); - } - return; -} - -static void -ospf_opaque_type10_lsa_rxmt_nbr_check (struct ospf_area *area) -{ - struct listnode *node; - struct ospf_interface *oi; - unsigned long n = 0; - - for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) - { - if (area->area_id.s_addr != OSPF_AREA_BACKBONE - && oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - - n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AREA_LSA); - if (n > 0) - break; - } - - if (n == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Self-originated type-10 Opaque-LSAs: AREA(%s): Flush completed", inet_ntoa (area->area_id)); - - UNSET_FLAG (area->ospf->opaque, OPAQUE_BLOCK_TYPE_10_LSA_BIT); - } - - return; -} - -static void -ospf_opaque_type11_lsa_rxmt_nbr_check (struct ospf *top) -{ - struct listnode *node; - struct ospf_interface *oi; - unsigned long n = 0; - - for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi)) - { - switch (oi->type) - { - case OSPF_IFTYPE_VIRTUALLINK: - continue; - default: - break; - } - - n = ospf_opaque_nrxmt_self (oi->nbrs, OSPF_OPAQUE_AS_LSA); - if (n > 0) - goto out; - } - - if (n == 0) - { - if (IS_DEBUG_OSPF_EVENT) - zlog_debug ("Self-originated type-11 Opaque-LSAs: Flush completed"); - - UNSET_FLAG (top->opaque, OPAQUE_BLOCK_TYPE_11_LSA_BIT); - } - -out: - return; -} - -static unsigned long -ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type) -{ - struct route_node *rn; - struct ospf_neighbor *nbr; - struct ospf *top; - unsigned long n = 0; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - { - if ((nbr = rn->info) == NULL) - continue; - if ((top = oi_to_top (nbr->oi)) == NULL) - continue; - if (IPV4_ADDR_SAME (&nbr->router_id, &top->router_id)) - continue; - n += ospf_ls_retransmit_count_self (nbr, lsa_type); - } - - return n; -} -#endif /* BUGGY_UNLOCK */ - /*------------------------------------------------------------------------* * Followings are util functions; probably be used by Opaque-LSAs only... *------------------------------------------------------------------------*/ diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index 2273064566..b9490a0ff2 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -31,23 +31,6 @@ (type) == OSPF_OPAQUE_AREA_LSA || \ (type) == OSPF_OPAQUE_AS_LSA) -/* - * Usage of Opaque-LSA administrative flags in "struct ospf". - * - * 7 6 5 4 3 2 1 0 - * +---+---+---+---+---+---+---+---+ - * |///|///|///|///|B11|B10|B09| O | - * +---+---+---+---+---+---+---+---+ - * |<--------->| A - * | +--- Operation status (operational = 1) - * +----------- Blocking status for each LSA type - */ - -#define IS_OPAQUE_LSA_ORIGINATION_BLOCKED(V) \ - CHECK_FLAG((V), (OPAQUE_BLOCK_TYPE_09_LSA_BIT | \ - OPAQUE_BLOCK_TYPE_10_LSA_BIT | \ - OPAQUE_BLOCK_TYPE_11_LSA_BIT)) - /* * Opaque LSA's link state ID is redefined as follows. * @@ -151,14 +134,9 @@ extern void ospf_opaque_lsa_reoriginate_schedule (void *lsa_type_dependent, extern void ospf_opaque_lsa_refresh_schedule (struct ospf_lsa *lsa); extern void ospf_opaque_lsa_flush_schedule (struct ospf_lsa *lsa); -extern void ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, - struct list *lsas); extern void ospf_opaque_self_originated_lsa_received (struct ospf_neighbor *nbr, struct ospf_lsa *lsa); -extern void ospf_opaque_ls_ack_received (struct ospf_neighbor *nbr, - struct ospf_lsa *lsa); - extern void htonf (float *src, float *dst); extern void ntohf (float *src, float *dst); extern struct ospf *oi_to_top (struct ospf_interface *oi); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 2126ea3c93..4b9f1c651a 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1714,7 +1714,7 @@ ospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s, if (IS_DEBUG_OSPF_EVENT) zlog_debug("LSA[Type%d:%s]: %p new LSA created with Link State Update", - lsa->data->type, inet_ntoa (lsa->data->id), lsa); + lsa->data->type, inet_ntoa (lsa->data->id), (void *)lsa); listnode_add (lsas, lsa); } @@ -1779,24 +1779,10 @@ ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, */ lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size); -#ifdef HAVE_OPAQUE_LSA - /* - * If self-originated Opaque-LSAs that have flooded before restart - * are contained in the received LSUpd message, corresponding LSReq - * messages to be sent may have to be modified. - * To eliminate possible race conditions such that flushing and normal - * updating for the same LSA would take place alternately, this trick - * must be done before entering to the loop below. - */ - /* XXX: Why is this Opaque specific? Either our core code is deficient - * and this should be fixed generally, or Opaque is inventing strawman - * problems */ - ospf_opaque_adjust_lsreq (nbr, lsas); -#endif /* HAVE_OPAQUE_LSA */ - #define DISCARD_LSA(L,N) {\ if (IS_DEBUG_OSPF_EVENT) \ - zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \ + zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p" \ + " Type-%d", N, (void *)lsa, (int) lsa->data->type); \ ospf_lsa_discard (L); \ continue; } @@ -1981,7 +1967,7 @@ ospf_ls_upd (struct ospf *ospf, struct ip *iph, struct ospf_header *ospfh, ospf_lsa_flush_area(lsa,out_if->area); if(IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_lsa_discard() in ospf_ls_upd() point 9: lsa %p Type-%d", - lsa, (int) lsa->data->type); + (void *)lsa, (int) lsa->data->type); ospf_lsa_discard (lsa); Flag = 1; } @@ -2159,14 +2145,7 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, lsr = ospf_ls_retransmit_lookup (nbr, lsa); if (lsr != NULL && ospf_lsa_more_recent (lsr, lsa) == 0) - { -#ifdef HAVE_OPAQUE_LSA - if (IS_OPAQUE_LSA (lsr->data->type)) - ospf_opaque_ls_ack_received (nbr, lsr); -#endif /* HAVE_OPAQUE_LSA */ - - ospf_ls_retransmit_delete (nbr, lsr); - } + ospf_ls_retransmit_delete (nbr, lsr); lsa->data = NULL; ospf_lsa_discard (lsa); diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index bcd5e6193c..5f8ef6f993 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -590,8 +590,7 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) { - struct in_addr nexthop; - nexthop.s_addr = 0; + struct in_addr nexthop = { .s_addr = 0 }; /* If the destination is a router which connects to the calculating router via a Point-to-MultiPoint @@ -1008,7 +1007,7 @@ ospf_spf_dump (struct vertex *v, int i) for (ALL_LIST_ELEMENTS_RO (v->parents, nnode, parent)) { zlog_debug (" nexthop %p %s %s", - parent->nexthop, + (void *)parent->nexthop, inet_ntoa (parent->nexthop->router), parent->nexthop->oi ? IF_NAME(parent->nexthop->oi) : "NULL"); @@ -1438,7 +1437,7 @@ ospf_spf_calculate_schedule (struct ospf *ospf, ospf_spf_reason_t reason) { if (IS_DEBUG_OSPF_EVENT) zlog_debug ("SPF: calculation timer is already scheduled: %p", - ospf->t_spf_calc); + (void *)ospf->t_spf_calc); return; } diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 565a61aaae..db06623ddf 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -557,7 +557,7 @@ ospf_mpls_te_new_if (struct interface *ifp) if (lookup_linkparams_by_ifp (ifp) != NULL) { - zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp); + zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", (void *)ifp); rc = 0; /* Do nothing here. */ goto out; } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index c7137ab524..03cde1c55d 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3373,16 +3373,11 @@ show_ip_ospf_common (struct vty *vty, struct ospf *ospf, u_char use_json) { json_object_boolean_true_add(json, "opaqueCapable"); } - if (IS_OPAQUE_LSA_ORIGINATION_BLOCKED (ospf->opaque)) - { - json_object_boolean_true_add(json, "lsaOpaqueOriginationBlocked"); - } } else { - vty_out (vty, " OpaqueCapability flag is %s%s%s", + vty_out (vty, " OpaqueCapability flag is %s%s", CHECK_FLAG (ospf->config, OSPF_OPAQUE_CAPABLE) ? "enabled" : "disabled", - IS_OPAQUE_LSA_ORIGINATION_BLOCKED (ospf->opaque) ? " (origination blocked)" : "", VTY_NEWLINE); } #endif /* HAVE_OPAQUE_LSA */ diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 4c140cf5bc..0dc90c8ae0 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -169,9 +169,6 @@ struct ospf /* Opaque-LSA administrative flags. */ u_char opaque; #define OPAQUE_OPERATION_READY_BIT (1 << 0) -#define OPAQUE_BLOCK_TYPE_09_LSA_BIT (1 << 1) -#define OPAQUE_BLOCK_TYPE_10_LSA_BIT (1 << 2) -#define OPAQUE_BLOCK_TYPE_11_LSA_BIT (1 << 3) #endif /* HAVE_OPAQUE_LSA */ /* RFC3137 stub router. Configured time to stay stub / max-metric */ diff --git a/pimd/Makefile.am b/pimd/Makefile.am index b4d94d2f3c..115d73678d 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -34,7 +34,7 @@ PIM_DEFS += -DPIM_ZCLIENT_DEBUG PIM_DEFS += -DPIM_ENFORCE_LOOPFREE_MFC #PIM_DEFS += -DPIM_UNEXPECTED_KERNEL_UPCALL -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" $(PIM_DEFS) INSTALL_SDATA=@INSTALL@ -m 600 LIBS = @LIBS@ diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 4fd3edcb88..2b9bb0fdeb 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -621,7 +621,7 @@ static int igmp_v2_report(struct igmp_sock *igmp, memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr, ifp->name); + group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { return -1; } @@ -678,7 +678,7 @@ static int igmp_v1_report(struct igmp_sock *igmp, memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr, ifp->name); + group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { return -1; } @@ -1356,8 +1356,7 @@ static struct igmp_group *find_group_by_addr(struct igmp_sock *igmp, } struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, - struct in_addr group_addr, - const char *ifname) + struct in_addr group_addr) { struct igmp_group *group; @@ -1395,8 +1394,8 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, } group->group_source_list->del = (void (*)(void *)) igmp_source_free; - group->t_group_timer = 0; - group->t_group_query_retransmit_timer = 0; + group->t_group_timer = NULL; + group->t_group_query_retransmit_timer = NULL; group->group_specific_query_retransmit_count = 0; group->group_addr = group_addr; group->group_igmp_sock = igmp; @@ -1413,7 +1412,7 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, char group_str[100]; pim_inet4_dump("", group->group_addr, group_str, sizeof(group_str)); zlog_debug("Creating new IGMP group %s on socket %d interface %s", - group_str, group->group_igmp_sock->fd, ifname); + group_str, igmp->fd, igmp->interface->name); } /* diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index d45f223ba8..ab396159e3 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -163,8 +163,7 @@ struct igmp_group { }; struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, - struct in_addr group_addr, - const char *ifname); + struct in_addr group_addr); void igmp_group_delete_empty_include(struct igmp_group *group); @@ -173,4 +172,7 @@ void igmp_startup_mode_on(struct igmp_sock *igmp); void igmp_group_timer_on(struct igmp_group *group, long interval_msec, const char *ifname); +struct igmp_source * +source_new (struct igmp_group *group, + struct in_addr src_addr); #endif /* PIM_IGMP_H */ diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 3657f2f946..8a32a32729 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -477,9 +477,9 @@ struct igmp_source *igmp_find_source_by_addr(struct igmp_group *group, return 0; } -static struct igmp_source *source_new(struct igmp_group *group, - struct in_addr src_addr, - const char *ifname) +struct igmp_source * +source_new (struct igmp_group *group, + struct in_addr src_addr) { struct igmp_source *src; @@ -491,7 +491,7 @@ static struct igmp_source *source_new(struct igmp_group *group, zlog_debug("Creating new IGMP source %s for group %s on socket %d interface %s", source_str, group_str, group->group_igmp_sock->fd, - ifname); + group->group_igmp_sock->interface->name); } src = XMALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); @@ -501,13 +501,13 @@ static struct igmp_source *source_new(struct igmp_group *group, return 0; /* error, not found, could not create */ } - src->t_source_timer = 0; + src->t_source_timer = NULL; src->source_group = group; /* back pointer */ src->source_addr = src_addr; src->source_creation = pim_time_monotonic_sec(); src->source_flags = 0; src->source_query_retransmit_count = 0; - src->source_channel_oil = 0; + src->source_channel_oil = NULL; listnode_add(group->group_source_list, src); @@ -521,8 +521,7 @@ static struct igmp_source *source_new(struct igmp_group *group, static struct igmp_source *add_source_by_addr(struct igmp_sock *igmp, struct igmp_group *group, - struct in_addr src_addr, - const char *ifname) + struct in_addr src_addr) { struct igmp_source *src; @@ -531,7 +530,7 @@ static struct igmp_source *add_source_by_addr(struct igmp_sock *igmp, return src; } - src = source_new(group, src_addr, ifname); + src = source_new(group, src_addr); if (!src) { return 0; } @@ -543,12 +542,11 @@ static void allow(struct igmp_sock *igmp, struct in_addr from, struct in_addr group_addr, int num_sources, struct in_addr *sources) { - struct interface *ifp = igmp->interface; struct igmp_group *group; int i; /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr, ifp->name); + group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { return; } @@ -560,7 +558,7 @@ static void allow(struct igmp_sock *igmp, struct in_addr from, src_addr = sources + i; - source = add_source_by_addr(igmp, group, *src_addr, ifp->name); + source = add_source_by_addr(igmp, group, *src_addr); if (!source) { continue; } @@ -616,8 +614,7 @@ static void isex_excl(struct igmp_group *group, } else { /* E.4: if not found, create source with timer=GMI: (A-X-Y) */ - source = source_new(group, *src_addr, - group->group_igmp_sock->interface->name); + source = source_new(group, *src_addr); if (!source) { /* ugh, internal malloc failure, skip source */ continue; @@ -659,8 +656,7 @@ static void isex_incl(struct igmp_group *group, } else { /* I.4: if not found, create source with timer=0 (B-A) */ - source = source_new(group, *src_addr, - group->group_igmp_sock->interface->name); + source = source_new(group, *src_addr); if (!source) { /* ugh, internal malloc failure, skip source */ continue; @@ -691,7 +687,7 @@ void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from, ifp, from, group_addr, num_sources, sources); /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr, ifp->name); + group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { return; } @@ -737,8 +733,7 @@ static void toin_incl(struct igmp_group *group, } else { /* If not found, create new source */ - source = source_new(group, *src_addr, - group->group_igmp_sock->interface->name); + source = source_new(group, *src_addr); if (!source) { /* ugh, internal malloc failure, skip source */ continue; @@ -783,8 +778,7 @@ static void toin_excl(struct igmp_group *group, } else { /* If not found, create new source */ - source = source_new(group, *src_addr, - group->group_igmp_sock->interface->name); + source = source_new(group, *src_addr); if (!source) { /* ugh, internal malloc failure, skip source */ continue; @@ -815,7 +809,7 @@ void igmpv3_report_toin(struct igmp_sock *igmp, struct in_addr from, ifp, from, group_addr, num_sources, sources); /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr, ifp->name); + group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { return; } @@ -862,8 +856,7 @@ static void toex_incl(struct igmp_group *group, } else { /* If source not found, create source with timer=0: (B-A)=0 */ - source = source_new(group, *src_addr, - group->group_igmp_sock->interface->name); + source = source_new(group, *src_addr); if (!source) { /* ugh, internal malloc failure, skip source */ continue; @@ -916,8 +909,7 @@ static void toex_excl(struct igmp_group *group, else { /* if not found, create source with Group Timer: (A-X-Y)=Group Timer */ long group_timer_msec; - source = source_new(group, *src_addr, - group->group_igmp_sock->interface->name); + source = source_new(group, *src_addr); if (!source) { /* ugh, internal malloc failure, skip source */ continue; @@ -967,7 +959,7 @@ void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from, ifp, from, group_addr, num_sources, sources); /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr, ifp->name); + group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { return; } @@ -1421,8 +1413,7 @@ static void block_excl(struct igmp_group *group, if (!source) { /* 3: if not found, create source with Group Timer: (A-X-Y)=Group Timer */ long group_timer_msec; - source = source_new(group, *src_addr, - group->group_igmp_sock->interface->name); + source = source_new(group, *src_addr); if (!source) { /* ugh, internal malloc failure, skip source */ continue; @@ -1489,7 +1480,7 @@ void igmpv3_report_block(struct igmp_sock *igmp, struct in_addr from, ifp, from, group_addr, num_sources, sources); /* non-existant group is created as INCLUDE {empty} */ - group = igmp_add_group_by_addr(igmp, group_addr, ifp->name); + group = igmp_add_group_by_addr(igmp, group_addr); if (!group) { return; } diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 5e1ab94b7c..00051719ac 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -87,7 +87,7 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg */ if ((rpg->rpf_addr.s_addr == INADDR_NONE) || (!pim_ifp) || - (!PIM_I_am_DR(pim_ifp)) || + (!(PIM_I_am_DR(pim_ifp))) || (pim_ifp->itype == PIM_INTERFACE_SSM)) return 0; @@ -154,7 +154,7 @@ pim_mroute_msg_wholepkt (int fd, struct interface *ifp, const char *buf, if ((rpg->rpf_addr.s_addr == INADDR_NONE) || (!pim_ifp) || - (!PIM_I_am_DR(pim_ifp)) || + (!(PIM_I_am_DR(pim_ifp))) || (pim_ifp->itype == PIM_INTERFACE_SSM)) { if (PIM_DEBUG_PIM_TRACE) { zlog_debug("%s: Failed Check send packet", __PRETTY_FUNCTION__); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 406f91494a..2d0de586d7 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -88,7 +88,7 @@ pim_register_send (const struct ip *ip_hdr, struct pim_rpf *rpg) plen = ntohs(ip_hdr->ip_len); memcpy(b1, (const unsigned char *)ip_hdr, plen); - pim_msg_build_header(buffer, plen + PIM_MSG_HEADER_LEN, PIM_MSG_TYPE_REGISTER); + pim_msg_build_header(buffer, plen + PIM_MSG_REGISTER_LEN, PIM_MSG_TYPE_REGISTER); if (pim_msg_send(pinfo->pim_sock_fd, rpg->rpf_addr, diff --git a/pimd/pim_util.c b/pimd/pim_util.c index fdfed2bf23..57a8488eca 100644 --- a/pimd/pim_util.c +++ b/pimd/pim_util.c @@ -100,23 +100,8 @@ uint16_t igmp_msg_decode8to16(uint8_t code) void pim_pkt_dump(const char *label, const uint8_t *buf, int size) { - char dump_buf[1000]; - int i = 0; - int j = 0; - - for (; i < size; ++i, j += 2) { - int left = sizeof(dump_buf) - j; - if (left < 4) { - if (left > 1) { - strcat(dump_buf + j, "!"); /* mark as truncated */ - } - break; - } - snprintf(dump_buf + j, left, "%02x", buf[i]); - } - - zlog_debug("%s: pkt dump size=%d: %s", + zlog_debug("%s: pkt dump size=%d", label, - size, - dump_buf); + size); + zlog_hexdump(buf, size); } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b3e61f2b06..c48629f05a 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -52,23 +52,6 @@ static int del_oif(struct channel_oil *channel_oil, struct interface *oif, uint32_t proto_mask); -#if 0 -static void zclient_broken(struct zclient *zclient) -{ - struct listnode *ifnode; - struct interface *ifp; - - zlog_warn("%s %s: broken zclient connection", - __FILE__, __PRETTY_FUNCTION__); - - for (ALL_LIST_ELEMENTS_RO(iflist, ifnode, ifp)) { - pim_if_addr_del_all(ifp); - } - - /* upon return, zclient will discard connected addresses */ -} -#endif - /* Router-id update message from zebra. */ static int pim_router_id_update_zebra(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) @@ -548,6 +531,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, /* Type, flags, message. */ api.type = stream_getc(s); + api.instance = stream_getw (s); api.flags = stream_getc(s); api.message = stream_getc(s); @@ -605,7 +589,13 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, stream_getl(s) : 0; + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; + switch (command) { + case ZEBRA_REDISTRIBUTE_IPV4_ADD: case ZEBRA_IPV4_ROUTE_ADD: if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; @@ -623,6 +613,7 @@ static int redist_read_ipv4_route(int command, struct zclient *zclient, api.distance); } break; + case ZEBRA_REDISTRIBUTE_IPV4_DEL: case ZEBRA_IPV4_ROUTE_DELETE: if (PIM_DEBUG_ZEBRA) { char buf[2][INET_ADDRSTRLEN]; @@ -681,6 +672,8 @@ void pim_zebra_init(char *zebra_sock_path) qpim_zclient_update->interface_address_delete = pim_zebra_if_address_del; qpim_zclient_update->ipv4_route_add = redist_read_ipv4_route; qpim_zclient_update->ipv4_route_delete = redist_read_ipv4_route; + qpim_zclient_update->redistribute_route_ipv4_add = redist_read_ipv4_route; + qpim_zclient_update->redistribute_route_ipv4_del = redist_read_ipv4_route; zclient_init(qpim_zclient_update, ZEBRA_ROUTE_PIM, 0); if (PIM_DEBUG_PIM_TRACE) { @@ -719,14 +712,20 @@ void pim_zebra_init(char *zebra_sock_path) void igmp_anysource_forward_start(struct igmp_group *group) { + struct igmp_source *source; + struct in_addr src_addr = { .s_addr = 0 }; /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ zassert(group->group_filtermode_isexcl); zassert(listcount(group->group_source_list) < 1); - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s %s: UNIMPLEMENTED", - __FILE__, __PRETTY_FUNCTION__); - } + source = source_new (group, src_addr); + if (!source) + { + zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__); + return; + } + + igmp_source_forward_start (source); } void igmp_anysource_forward_stop(struct igmp_group *group) diff --git a/ripd/Makefile.am b/ripd/Makefile.am index da9b2e3afc..571a4993dd 100644 --- a/ripd/Makefile.am +++ b/ripd/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 diff --git a/ripd/ripd.c b/ripd/ripd.c index fc3ad3adb3..42f1015453 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2867,7 +2867,7 @@ rip_update_jitter (unsigned long time) if (jitter_input < JITTER_BOUND) jitter_input = JITTER_BOUND; - jitter = (((rand () % ((jitter_input * 2) + 1)) - jitter_input)); + jitter = (((random () % ((jitter_input * 2) + 1)) - jitter_input)); return jitter/JITTER_BOUND; } @@ -4140,7 +4140,7 @@ void rip_init (void) { /* Randomize for triggered update random(). */ - srand (time (NULL)); + srandom (time (NULL)); /* Install top nodes. */ install_node (&rip_node, config_write_rip); diff --git a/ripngd/Makefile.am b/ripngd/Makefile.am index d5736ee526..df0f7d377e 100644 --- a/ripngd/Makefile.am +++ b/ripngd/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 15ce0a238d..0061c0e803 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -164,38 +164,15 @@ ripng_if_down (struct interface *ifp) struct route_node *rp; struct ripng_info *rinfo; struct ripng_interface *ri; + struct list *list = NULL; + struct listnode *listnode = NULL, *nextnode = NULL; if (ripng) - { - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((rinfo = rp->info) != NULL) - { - /* Routes got through this interface. */ - if (rinfo->ifindex == ifp->ifindex - && rinfo->type == ZEBRA_ROUTE_RIPNG - && rinfo->sub_type == RIPNG_ROUTE_RTE) - { - ripng_zebra_ipv6_delete ((struct prefix_ipv6 *) &rp->p, - &rinfo->nexthop, - rinfo->ifindex); - - ripng_redistribute_delete (rinfo->type, rinfo->sub_type, - (struct prefix_ipv6 *)&rp->p, - rinfo->ifindex); - } - else - { - /* All redistributed routes got through this interface, - * but the static and system ones are kept. */ - if ((rinfo->ifindex == ifp->ifindex) && - (rinfo->type != ZEBRA_ROUTE_STATIC) && - (rinfo->type != ZEBRA_ROUTE_SYSTEM)) - ripng_redistribute_delete (rinfo->type, rinfo->sub_type, - (struct prefix_ipv6 *) &rp->p, - rinfo->ifindex); - } - } - } + for (rp = route_top (ripng->table); rp; rp = route_next (rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS (list, listnode, nextnode, rinfo)) + if (rinfo->ifindex == ifp->ifindex) + ripng_ecmp_delete (rinfo); ri = ifp->info; diff --git a/ripngd/ripng_route.c b/ripngd/ripng_route.c index ab37dfcdbb..8538b07a98 100644 --- a/ripngd/ripng_route.c +++ b/ripngd/ripng_route.c @@ -40,7 +40,7 @@ ripng_aggregate_new (void) return new; } -static void +void ripng_aggregate_free (struct ripng_aggregate *aggregate) { XFREE (MTYPE_RIPNG_AGGREGATE, aggregate); @@ -76,6 +76,23 @@ ripng_aggregate_decrement (struct route_node *child, struct ripng_info *rinfo) } } +/* Aggregate count decrement check for a list. */ +void +ripng_aggregate_decrement_list (struct route_node *child, struct list *list) +{ + struct route_node *np; + struct ripng_aggregate *aggregate; + struct ripng_info *rinfo = NULL; + struct listnode *node = NULL; + + for (np = child; np; np = np->parent) + if ((aggregate = np->aggregate) != NULL) + aggregate->count -= listcount (list); + + for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) + rinfo->suppress--; +} + /* RIPng routes treatment. */ int ripng_aggregate_add (struct prefix *p) @@ -85,6 +102,8 @@ ripng_aggregate_add (struct prefix *p) struct ripng_info *rinfo; struct ripng_aggregate *aggregate; struct ripng_aggregate *sub; + struct list *list = NULL; + struct listnode *node = NULL; /* Get top node for aggregation. */ top = route_node_get (ripng->table, p); @@ -99,11 +118,12 @@ ripng_aggregate_add (struct prefix *p) for (rp = route_lock_node (top); rp; rp = route_next_until (rp, top)) { /* Suppress normal route. */ - if ((rinfo = rp->info) != NULL) - { - aggregate->count++; - rinfo->suppress++; - } + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) + { + aggregate->count++; + rinfo->suppress++; + } /* Suppress aggregate route. This may not need. */ if (rp != top && (sub = rp->aggregate) != NULL) { @@ -124,6 +144,8 @@ ripng_aggregate_delete (struct prefix *p) struct ripng_info *rinfo; struct ripng_aggregate *aggregate; struct ripng_aggregate *sub; + struct list *list = NULL; + struct listnode *node = NULL; /* Get top node for aggregation. */ top = route_node_get (ripng->table, p); @@ -135,11 +157,12 @@ ripng_aggregate_delete (struct prefix *p) for (rp = route_lock_node (top); rp; rp = route_next_until (rp, top)) { /* Suppress normal route. */ - if ((rinfo = rp->info) != NULL) - { - aggregate->count--; - rinfo->suppress--; - } + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) + { + aggregate->count--; + rinfo->suppress--; + } if (rp != top && (sub = rp->aggregate) != NULL) { diff --git a/ripngd/ripng_route.h b/ripngd/ripng_route.h index 2f5b757542..fe65c88363 100644 --- a/ripngd/ripng_route.h +++ b/ripngd/ripng_route.h @@ -48,7 +48,10 @@ extern void ripng_aggregate_increment (struct route_node *rp, struct ripng_info *rinfo); extern void ripng_aggregate_decrement (struct route_node *rp, struct ripng_info *rinfo); +extern void ripng_aggregate_decrement_list (struct route_node *rp, + struct list *list); extern int ripng_aggregate_add (struct prefix *p); extern int ripng_aggregate_delete (struct prefix *p); +extern void ripng_aggregate_free (struct ripng_aggregate *aggregate); #endif /* _ZEBRA_RIPNG_ROUTE_H */ diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index afd6580204..ecfe2d5154 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -24,21 +24,32 @@ #include "command.h" #include "prefix.h" +#include "table.h" #include "stream.h" +#include "memory.h" #include "routemap.h" #include "zclient.h" #include "log.h" #include "ripngd/ripngd.h" +#include "ripngd/ripng_debug.h" /* All information about zebra. */ struct zclient *zclient = NULL; -void -ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop, - unsigned int ifindex, u_char metric) +/* Send ECMP routes to zebra. */ +static void +ripng_zebra_ipv6_send (struct route_node *rp, u_char cmd) { + static struct in6_addr **nexthops = NULL; + static unsigned int *ifindexes = NULL; + static unsigned int nexthops_len = 0; + + struct list *list = (struct list *)rp->info; struct zapi_ipv6 api; + struct listnode *listnode = NULL; + struct ripng_info *rinfo = NULL; + int count = 0; if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT)) { @@ -48,42 +59,70 @@ ripng_zebra_ipv6_add (struct prefix_ipv6 *p, struct in6_addr *nexthop, api.flags = 0; api.message = 0; api.safi = SAFI_UNICAST; + + if (nexthops_len < listcount (list)) + { + nexthops_len = listcount (list); + nexthops = XREALLOC (MTYPE_TMP, nexthops, + nexthops_len * sizeof (struct in6_addr *)); + ifindexes = XREALLOC (MTYPE_TMP, ifindexes, + nexthops_len * sizeof (unsigned int)); + } + SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; + for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) + { + nexthops[count] = &rinfo->nexthop; + ifindexes[count] = rinfo->ifindex; + count++; + if (cmd == ZEBRA_IPV6_ROUTE_ADD) + SET_FLAG (rinfo->flags, RIPNG_RTF_FIB); + else + UNSET_FLAG (rinfo->flags, RIPNG_RTF_FIB); + } + + api.nexthop = nexthops; + api.nexthop_num = count; + api.ifindex = ifindexes; + api.ifindex_num = count; + + rinfo = listgetdata (listhead (list)); + SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = metric; - - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, p, &api); + api.metric = rinfo->metric; + + zapi_ipv6_route (cmd, zclient, + (struct prefix_ipv6 *)&rp->p, &api); + + if (IS_RIPNG_DEBUG_ZEBRA) + { + if (ripng->ecmp) + zlog_debug ("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \ + "Install into zebra" : "Delete from zebra", + inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen, count); + else + zlog_debug ("%s: %s/%d", + (cmd == ZEBRA_IPV6_ROUTE_ADD) ? \ + "Install into zebra" : "Delete from zebra", + inet6_ntoa (rp->p.u.prefix6), rp->p.prefixlen); + } } } +/* Add/update ECMP routes to zebra. */ void -ripng_zebra_ipv6_delete (struct prefix_ipv6 *p, struct in6_addr *nexthop, - unsigned int ifindex) +ripng_zebra_ipv6_add (struct route_node *rp) { - struct zapi_ipv6 api; + ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_ADD); +} - if (vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_RIPNG], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIPNG; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &nexthop; - SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); - api.ifindex_num = 1; - api.ifindex = &ifindex; - - zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, p, &api); - } +/* Delete ECMP routes from zebra. */ +void +ripng_zebra_ipv6_delete (struct route_node *rp) +{ + ripng_zebra_ipv6_send (rp, ZEBRA_IPV6_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 8b71269c04..b786c6f938 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -236,7 +236,7 @@ ripng_recv_packet (int sock, u_char *buf, int bufsize, struct msghdr msg; struct iovec iov; struct cmsghdr *cmsgptr; - struct in6_addr dst; + struct in6_addr dst = { .s6_addr = { 0 } }; memset(&dst, 0, sizeof(struct in6_addr)); @@ -423,8 +423,13 @@ ripng_garbage_collect (struct thread *t) rp = rinfo->rp; /* Unlock route_node. */ - rp->info = NULL; - route_unlock_node (rp); + listnode_delete (rp->info, rinfo); + if (list_isempty ((struct list *)rp->info)) + { + list_free (rp->info); + rp->info = NULL; + route_unlock_node (rp); + } /* Free RIPng routing information. */ ripng_info_free (rinfo); @@ -432,41 +437,165 @@ ripng_garbage_collect (struct thread *t) return 0; } +static void ripng_timeout_update (struct ripng_info *rinfo); + +/* Add new route to the ECMP list. + * RETURN: the new entry added in the list, or NULL if it is not the first + * entry and ECMP is not allowed. + */ +struct ripng_info * +ripng_ecmp_add (struct ripng_info *rinfo_new) +{ + struct route_node *rp = rinfo_new->rp; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; + + if (rp->info == NULL) + rp->info = list_new (); + list = (struct list *)rp->info; + + /* If ECMP is not allowed and some entry already exists in the list, + * do nothing. */ + if (listcount (list) && !ripng->ecmp) + return NULL; + + rinfo = ripng_info_new (); + memcpy (rinfo, rinfo_new, sizeof (struct ripng_info)); + listnode_add (list, rinfo); + + if (ripng_route_rte (rinfo)) + { + ripng_timeout_update (rinfo); + ripng_zebra_ipv6_add (rp); + } + + ripng_aggregate_increment (rp, rinfo); + + /* Set the route change flag on the first entry. */ + rinfo = listgetdata (listhead (list)); + SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + + return rinfo; +} + +/* Replace the ECMP list with the new route. + * RETURN: the new entry added in the list + */ +struct ripng_info * +ripng_ecmp_replace (struct ripng_info *rinfo_new) +{ + struct route_node *rp = rinfo_new->rp; + struct list *list = (struct list *)rp->info; + struct ripng_info *rinfo = NULL, *tmp_rinfo = NULL; + struct listnode *node = NULL, *nextnode = NULL; + + if (list == NULL || listcount (list) == 0) + return ripng_ecmp_add (rinfo_new); + + /* Get the first entry */ + rinfo = listgetdata (listhead (list)); + + /* Learnt route replaced by a local one. Delete it from zebra. */ + if (ripng_route_rte (rinfo) && !ripng_route_rte (rinfo_new)) + if (CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete (rp); + + if (rinfo->metric != RIPNG_METRIC_INFINITY) + ripng_aggregate_decrement_list (rp, list); + + /* Re-use the first entry, and delete the others. */ + for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) + { + RIPNG_TIMER_OFF (tmp_rinfo->t_timeout); + RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect); + list_delete_node (list, node); + ripng_info_free (tmp_rinfo); + } + + RIPNG_TIMER_OFF (rinfo->t_timeout); + RIPNG_TIMER_OFF (rinfo->t_garbage_collect); + memcpy (rinfo, rinfo_new, sizeof (struct ripng_info)); + + if (ripng_route_rte (rinfo)) + { + ripng_timeout_update (rinfo); + /* The ADD message implies an update. */ + ripng_zebra_ipv6_add (rp); + } + + ripng_aggregate_increment (rp, rinfo); + + /* Set the route change flag. */ + SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + + return rinfo; +} + +/* Delete one route from the ECMP list. + * RETURN: + * null - the entry is freed, and other entries exist in the list + * the entry - the entry is the last one in the list; its metric is set + * to INFINITY, and the garbage collector is started for it + */ +struct ripng_info * +ripng_ecmp_delete (struct ripng_info *rinfo) +{ + struct route_node *rp = rinfo->rp; + struct list *list = (struct list *)rp->info; + + RIPNG_TIMER_OFF (rinfo->t_timeout); + + if (rinfo->metric != RIPNG_METRIC_INFINITY) + ripng_aggregate_decrement (rp, rinfo); + + if (listcount (list) > 1) + { + /* Some other ECMP entries still exist. Just delete this entry. */ + RIPNG_TIMER_OFF (rinfo->t_garbage_collect); + listnode_delete (list, rinfo); + if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) + /* The ADD message implies the update. */ + ripng_zebra_ipv6_add (rp); + ripng_info_free (rinfo); + rinfo = NULL; + } + else + { + assert (rinfo == listgetdata (listhead (list))); + + /* This is the only entry left in the list. We must keep it in + * the list for garbage collection time, with INFINITY metric. */ + + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON (rinfo->t_garbage_collect, + ripng_garbage_collect, ripng->garbage_time); + + if (ripng_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIPNG_RTF_FIB)) + ripng_zebra_ipv6_delete (rp); + } + + /* Set the route change flag on the first entry. */ + rinfo = listgetdata (listhead (list)); + SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + + return rinfo; +} + /* Timeout RIPng routes. */ static int ripng_timeout (struct thread *t) { - struct ripng_info *rinfo; - struct route_node *rp; - - rinfo = THREAD_ARG (t); - rinfo->t_timeout = NULL; - - /* Get route_node pointer. */ - rp = rinfo->rp; - - /* - The garbage-collection timer is set for 120 seconds. */ - RIPNG_TIMER_ON (rinfo->t_garbage_collect, ripng_garbage_collect, - ripng->garbage_time); - - /* Delete this route from the kernel. */ - ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop, - rinfo->ifindex); - /* - The metric for the route is set to 16 (infinity). This causes - the route to be removed from service. */ - rinfo->metric = RIPNG_METRIC_INFINITY; - rinfo->flags &= ~RIPNG_RTF_FIB; - - /* Aggregate count decrement. */ - ripng_aggregate_decrement (rp, rinfo); - - /* - The route change flag is to indicate that this entry has been - changed. */ - rinfo->flags |= RIPNG_RTF_CHANGED; - - /* - The output process is signalled to trigger a response. */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - + ripng_ecmp_delete ((struct ripng_info *)THREAD_ARG (t)); return 0; } @@ -630,11 +759,12 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, int ret; struct prefix_ipv6 p; struct route_node *rp; - struct ripng_info *rinfo; + struct ripng_info *rinfo = NULL, newinfo; struct ripng_interface *ri; struct in6_addr *nexthop; - u_char oldmetric; int same = 0; + struct list *list = NULL; + struct listnode *node = NULL; /* Make prefix structure. */ memset (&p, 0, sizeof (struct prefix_ipv6)); @@ -655,24 +785,23 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, if (ret < 0) return; + memset (&newinfo, 0, sizeof (newinfo)); + newinfo.type = ZEBRA_ROUTE_RIPNG; + newinfo.sub_type = RIPNG_ROUTE_RTE; + if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) + newinfo.nexthop = ripng_nexthop->address; + else + newinfo.nexthop = from->sin6_addr; + newinfo.from = from->sin6_addr; + newinfo.ifindex = ifp->ifindex; + newinfo.metric = rte->metric; + newinfo.metric_out = rte->metric; /* XXX */ + newinfo.tag = ntohs (rte->tag); /* XXX */ + /* Modify entry. */ if (ri->routemap[RIPNG_FILTER_IN]) { int ret; - struct ripng_info newinfo; - - memset (&newinfo, 0, sizeof (struct ripng_info)); - newinfo.type = ZEBRA_ROUTE_RIPNG; - newinfo.sub_type = RIPNG_ROUTE_RTE; - if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS) - newinfo.nexthop = ripng_nexthop->address; - else - newinfo.nexthop = from->sin6_addr; - newinfo.from = from->sin6_addr; - newinfo.ifindex = ifp->ifindex; - newinfo.metric = rte->metric; - newinfo.metric_out = rte->metric; /* XXX */ - newinfo.tag = ntohs(rte->tag); /* XXX */ ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN], (struct prefix *)&p, RMAP_RIPNG, &newinfo); @@ -733,24 +862,66 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, /* Lookup RIPng routing table. */ rp = route_node_get (ripng->table, (struct prefix *) &p); - /* Sanity check */ - rinfo = rp->info; + newinfo.rp = rp; + newinfo.nexthop = *nexthop; + newinfo.metric = rte->metric; + newinfo.tag = ntohs (rte->tag); + + /* Check to see whether there is already RIPng route on the table. */ + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) + { + /* Need to compare with redistributed entry or local entry */ + if (!ripng_route_rte (rinfo)) + break; + + if (IPV6_ADDR_SAME (&rinfo->from, &from->sin6_addr) && + IPV6_ADDR_SAME (&rinfo->nexthop, nexthop)) + break; + + if (!listnextnode (node)) + { + /* Not found in the list */ + + if (rte->metric > rinfo->metric) + { + /* New route has a greater metric. Discard it. */ + route_unlock_node (rp); + return; + } + + if (rte->metric < rinfo->metric) + /* New route has a smaller metric. Replace the ECMP list + * with the new one in below. */ + break; + + /* Metrics are same. Keep "rinfo" null and the new route + * is added in the ECMP list in below. */ + } + } + if (rinfo) { /* Redistributed route check. */ if (rinfo->type != ZEBRA_ROUTE_RIPNG && rinfo->metric != RIPNG_METRIC_INFINITY) - return; + { + route_unlock_node (rp); + return; + } /* Local static route. */ if (rinfo->type == ZEBRA_ROUTE_RIPNG && ((rinfo->sub_type == RIPNG_ROUTE_STATIC) || (rinfo->sub_type == RIPNG_ROUTE_DEFAULT)) && rinfo->metric != RIPNG_METRIC_INFINITY) - return; + { + route_unlock_node (rp); + return; + } } - if (rp->info == NULL) + if (!rinfo) { /* Now, check to see whether there is already an explicit route for the destination prefix. If there is no such route, add @@ -758,53 +929,10 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, infinity (there is no point in adding a route which unusable). */ if (rte->metric != RIPNG_METRIC_INFINITY) - { - rinfo = ripng_info_new (); - - /* - Setting the destination prefix and length to those in - the RTE. */ - rp->info = rinfo; - rinfo->rp = rp; - - /* - Setting the metric to the newly calculated metric (as - described above). */ - rinfo->metric = rte->metric; - rinfo->tag = ntohs (rte->tag); - - /* - Set the next hop address to be the address of the router - from which the datagram came or the next hop address - specified by a next hop RTE. */ - IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); - IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr); - rinfo->ifindex = ifp->ifindex; - - /* - Initialize the timeout for the route. If the - garbage-collection timer is running for this route, stop it. */ - ripng_timeout_update (rinfo); - - /* - Set the route change flag. */ - rinfo->flags |= RIPNG_RTF_CHANGED; - - /* - Signal the output process to trigger an update (see section - 2.5). */ - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - - /* Finally, route goes into the kernel. */ - rinfo->type = ZEBRA_ROUTE_RIPNG; - rinfo->sub_type = RIPNG_ROUTE_RTE; - - ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex, - rinfo->metric); - rinfo->flags |= RIPNG_RTF_FIB; - - /* Aggregate check. */ - ripng_aggregate_increment (rp, rinfo); - } + ripng_ecmp_add (&newinfo); } else { - rinfo = rp->info; - /* If there is an existing route, compare the next hop address to the address of the router from which the datagram came. If this datagram is from the same router as the existing @@ -812,9 +940,6 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) && (rinfo->ifindex == ifp->ifindex)); - if (same) - ripng_timeout_update (rinfo); - /* Next, compare the metrics. If the datagram is from the same router as the existing route, and the new metric is different than the old one; or, if the new metric is lower than the old @@ -822,96 +947,24 @@ ripng_route_process (struct rte *rte, struct sockaddr_in6 *from, if ((same && rinfo->metric != rte->metric) || rte->metric < rinfo->metric) { - /* - Adopt the route from the datagram. That is, put the - new metric in, and adjust the next hop address (if - necessary). */ - oldmetric = rinfo->metric; - rinfo->metric = rte->metric; - rinfo->tag = ntohs (rte->tag); - IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr); - rinfo->ifindex = ifp->ifindex; - - /* Should a new route to this network be established - while the garbage-collection timer is running, the - new route will replace the one that is about to be - deleted. In this case the garbage-collection timer - must be cleared. */ - - if (oldmetric == RIPNG_METRIC_INFINITY && - rinfo->metric < RIPNG_METRIC_INFINITY) - { - rinfo->type = ZEBRA_ROUTE_RIPNG; - rinfo->sub_type = RIPNG_ROUTE_RTE; - - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - - if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop)) - IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); - - ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex, rinfo->metric); - rinfo->flags |= RIPNG_RTF_FIB; - - /* The aggregation counter needs to be updated because - the prefixes, which are into the gc, have been - removed from the aggregator (see ripng_timout). */ - ripng_aggregate_increment (rp, rinfo); - } - - /* Update nexthop and/or metric value. */ - if (oldmetric != RIPNG_METRIC_INFINITY) - { - ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex); - ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex, rinfo->metric); - rinfo->flags |= RIPNG_RTF_FIB; - - if (! IPV6_ADDR_SAME (&rinfo->nexthop, nexthop)) - IPV6_ADDR_COPY (&rinfo->nexthop, nexthop); - } - - /* - Set the route change flag and signal the output process - to trigger an update. */ - rinfo->flags |= RIPNG_RTF_CHANGED; - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - - /* - If the new metric is infinity, start the deletion - process (described above); */ - if (rinfo->metric == RIPNG_METRIC_INFINITY) - { - /* If the new metric is infinity, the deletion process - begins for the route, which is no longer used for - routing packets. Note that the deletion process is - started only when the metric is first set to - infinity. If the metric was already infinity, then a - new deletion process is not started. */ - if (oldmetric != RIPNG_METRIC_INFINITY) - { - /* - The garbage-collection timer is set for 120 seconds. */ - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - RIPNG_TIMER_OFF (rinfo->t_timeout); - - /* - The metric for the route is set to 16 - (infinity). This causes the route to be removed - from service.*/ - ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex); - rinfo->flags &= ~RIPNG_RTF_FIB; - - /* Aggregate count decrement. */ - ripng_aggregate_decrement (rp, rinfo); - - /* - The route change flag is to indicate that this - entry has been changed. */ - /* - The output process is signalled to trigger a - response. */ - ; /* Above processes are already done previously. */ - } - } - else - { - /* otherwise, re-initialize the timeout. */ - ripng_timeout_update (rinfo); - } + if (listcount (list) == 1) + { + if (newinfo.metric != RIPNG_METRIC_INFINITY) + ripng_ecmp_replace (&newinfo); + else + ripng_ecmp_delete (rinfo); + } + else + { + if (newinfo.metric < rinfo->metric) + ripng_ecmp_replace (&newinfo); + else /* newinfo.metric > rinfo->metric */ + ripng_ecmp_delete (rinfo); + } } + else /* same & no change */ + ripng_timeout_update (rinfo); + /* Unlock tempolary lock of the route. */ route_unlock_node (rp); } @@ -923,28 +976,30 @@ ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, unsigned int ifindex, struct in6_addr *nexthop) { struct route_node *rp; - struct ripng_info *rinfo; + struct ripng_info *rinfo = NULL, newinfo; + struct list *list = NULL; /* Redistribute route */ if (IN6_IS_ADDR_LINKLOCAL (&p->prefix)) return; if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) return; -#if defined (MUSICA) || defined (LINUX) - /* XXX As long as the RIPng redistribution is applied to all the connected - * routes, one needs to filter the ::/96 prefixes. - * However it could be a wanted case, it will be removed soon. - */ - if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) || - (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96))) - return; -#endif /* MUSICA or LINUX */ rp = route_node_get (ripng->table, (struct prefix *) p); - rinfo = rp->info; - if (rinfo) + memset (&newinfo, 0, sizeof (struct ripng_info)); + newinfo.type = type; + newinfo.sub_type = sub_type; + newinfo.ifindex = ifindex; + newinfo.metric = 1; + newinfo.rp = rp; + if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop)) + newinfo.nexthop = *nexthop; + + if ((list = rp->info) != NULL && listcount (list) != 0) { + rinfo = listgetdata (listhead (list)); + if (rinfo->type == ZEBRA_ROUTE_CONNECT && rinfo->sub_type == RIPNG_ROUTE_INTERFACE && rinfo->metric != RIPNG_METRIC_INFINITY) { @@ -964,42 +1019,12 @@ ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, return; } } - - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); - - /* Tells the other daemons about the deletion of - * this RIPng route - **/ - if (ripng_route_rte (rinfo)) - ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, &rinfo->nexthop, - rinfo->metric); - - rp->info = NULL; - ripng_info_free (rinfo); + rinfo = ripng_ecmp_replace (&newinfo); route_unlock_node (rp); - } - - rinfo = ripng_info_new (); - - rinfo->type = type; - rinfo->sub_type = sub_type; - rinfo->ifindex = ifindex; - rinfo->metric = 1; - rinfo->rp = rp; - - if (nexthop && IN6_IS_ADDR_LINKLOCAL(nexthop)) - rinfo->nexthop = *nexthop; - - rinfo->flags |= RIPNG_RTF_FIB; - rp->info = rinfo; - - /* Aggregate check. */ - ripng_aggregate_increment (rp, rinfo); - - rinfo->flags |= RIPNG_RTF_CHANGED; + else + rinfo = ripng_ecmp_add (&newinfo); if (IS_RIPNG_DEBUG_EVENT) { if (!nexthop) @@ -1027,45 +1052,42 @@ ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, return; if (IN6_IS_ADDR_LOOPBACK (&p->prefix)) return; -#if defined (MUSICA) || defined (LINUX) - /* XXX As long as the RIPng redistribution is applied to all the connected - * routes, one needs to filter the ::/96 prefixes. - * However it could be a wanted case, it will be removed soon. - */ - if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) || - (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96))) - return; -#endif /* MUSICA or LINUX */ rp = route_node_lookup (ripng->table, (struct prefix *) p); if (rp) { - rinfo = rp->info; + struct list *list = rp->info; - if (rinfo != NULL - && rinfo->type == type - && rinfo->sub_type == sub_type - && rinfo->ifindex == ifindex) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIPNG_METRIC_INFINITY; - RIPNG_TIMER_ON (rinfo->t_garbage_collect, - ripng_garbage_collect, ripng->garbage_time); - RIPNG_TIMER_OFF (rinfo->t_timeout); + if (list != NULL && listcount (list) != 0) + { + rinfo = listgetdata (listhead (list)); + if (rinfo != NULL + && rinfo->type == type + && rinfo->sub_type == sub_type + && rinfo->ifindex == ifindex) + { + /* Perform poisoned reverse. */ + rinfo->metric = RIPNG_METRIC_INFINITY; + RIPNG_TIMER_ON (rinfo->t_garbage_collect, + ripng_garbage_collect, ripng->garbage_time); + RIPNG_TIMER_OFF (rinfo->t_timeout); - /* Aggregate count decrement. */ - ripng_aggregate_decrement (rp, rinfo); + /* Aggregate count decrement. */ + ripng_aggregate_decrement (rp, rinfo); - rinfo->flags |= RIPNG_RTF_CHANGED; - - if (IS_RIPNG_DEBUG_EVENT) - zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [delete]", - inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex)); + rinfo->flags |= RIPNG_RTF_CHANGED; - ripng_event (RIPNG_TRIGGERED_UPDATE, 0); - } + if (IS_RIPNG_DEBUG_EVENT) + zlog_debug ("Poisone %s/%d on the interface %s with an " + "infinity metric [delete]", + inet6_ntoa (p->prefix), p->prefixlen, + ifindex2ifname (ifindex)); + + ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + } + } + route_unlock_node (rp); } } @@ -1074,14 +1096,16 @@ void ripng_redistribute_withdraw (int type) { struct route_node *rp; - struct ripng_info *rinfo; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; if (!ripng) return; for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((rinfo = rp->info) != NULL) + if ((list = rp->info) != NULL) { + rinfo = listgetdata (listhead (list)); if ((rinfo->type == type) && (rinfo->sub_type != RIPNG_ROUTE_INTERFACE)) { @@ -1316,7 +1340,7 @@ ripng_request_process (struct ripng_packet *packet,int size, if (rp) { - rinfo = rp->info; + rinfo = listgetdata (listhead ((struct list *)rp->info)); rte->metric = rinfo->metric; route_unlock_node (rp); } @@ -1337,7 +1361,7 @@ ripng_read (struct thread *thread) int sock; struct sockaddr_in6 from; struct ripng_packet *packet; - unsigned int ifindex; + unsigned int ifindex = 0; struct interface *ifp; int hoplimit = -1; @@ -1424,12 +1448,18 @@ static void ripng_clear_changed_flag (void) { struct route_node *rp; - struct ripng_info *rinfo; + struct ripng_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; for (rp = route_top (ripng->table); rp; rp = route_next (rp)) - if ((rinfo = rp->info) != NULL) - if (rinfo->flags & RIPNG_RTF_CHANGED) - rinfo->flags &= ~RIPNG_RTF_CHANGED; + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) + { + UNSET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + /* This flag can be set only on the first entry. */ + break; + } } /* Regular update of RIPng route. Send all routing formation to RIPng @@ -1607,6 +1637,8 @@ ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to, struct ripng_aggregate *aggregate; struct prefix_ipv6 *p; struct list * ripng_rte_list; + struct list *list = NULL; + struct listnode *listnode = NULL; if (IS_RIPNG_DEBUG_EVENT) { if (to) @@ -1623,7 +1655,9 @@ ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to, for (rp = route_top (ripng->table); rp; rp = route_next (rp)) { - if ((rinfo = rp->info) != NULL && rinfo->suppress == 0) + if ((list = rp->info) != NULL && + (rinfo = listgetdata (listhead (list))) != NULL && + rinfo->suppress == 0) { /* If no route-map are applied, the RTE will be these following * informations. @@ -1655,8 +1689,17 @@ ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to, if (ri->split_horizon == RIPNG_SPLIT_HORIZON) { /* We perform split horizon for RIPng routes. */ - if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && - rinfo->ifindex == ifp->ifindex) + int suppress = 0; + struct ripng_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) + if (tmp_rinfo->type == ZEBRA_ROUTE_RIPNG && + tmp_rinfo->ifindex == ifp->ifindex) + { + suppress = 1; + break; + } + if (suppress) continue; } @@ -1735,9 +1778,12 @@ ripng_output_process (struct interface *ifp, struct sockaddr_in6 *to, * for RIPng routes. **/ if (ri->split_horizon == RIPNG_SPLIT_HORIZON_POISONED_REVERSE) { - if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && - rinfo->ifindex == ifp->ifindex) - rinfo->metric_out = RIPNG_METRIC_INFINITY; + struct ripng_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) + if ((tmp_rinfo->type == ZEBRA_ROUTE_RIPNG) && + tmp_rinfo->ifindex == ifp->ifindex) + rinfo->metric_out = RIPNG_METRIC_INFINITY; } /* Add RTE to the list */ @@ -1892,7 +1938,7 @@ ripng_request (struct interface *ifp) static int ripng_update_jitter (int time) { - return ((rand () % (time + 1)) - (time / 2)); + return ((random () % (time + 1)) - (time / 2)); } void @@ -2003,6 +2049,8 @@ DEFUN (show_ipv6_ripng, struct ripng_info *rinfo; struct ripng_aggregate *aggregate; struct prefix_ipv6 *p; + struct list *list = NULL; + struct listnode *listnode = NULL; int len; if (! ripng) @@ -2040,7 +2088,8 @@ DEFUN (show_ipv6_ripng, VTY_NEWLINE); } - if ((rinfo = rp->info) != NULL) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) { p = (struct prefix_ipv6 *) &rp->p; @@ -2595,6 +2644,80 @@ DEFUN (no_ripng_default_information_originate, return CMD_SUCCESS; } +/* Update ECMP routes to zebra when ECMP is disabled. */ +static void +ripng_ecmp_disable (void) +{ + struct route_node *rp; + struct ripng_info *rinfo, *tmp_rinfo; + struct list *list; + struct listnode *node, *nextnode; + + if (!ripng) + return; + + for (rp = route_top (ripng->table); rp; rp = route_next (rp)) + if ((list = rp->info) != NULL && listcount (list) > 1) + { + rinfo = listgetdata (listhead (list)); + if (!ripng_route_rte (rinfo)) + continue; + + /* Drop all other entries, except the first one. */ + for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) + { + RIPNG_TIMER_OFF (tmp_rinfo->t_timeout); + RIPNG_TIMER_OFF (tmp_rinfo->t_garbage_collect); + list_delete_node (list, node); + ripng_info_free (tmp_rinfo); + } + + /* Update zebra. */ + ripng_zebra_ipv6_add (rp); + + /* Set the route change flag. */ + SET_FLAG (rinfo->flags, RIPNG_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + ripng_event (RIPNG_TRIGGERED_UPDATE, 0); + } +} + +DEFUN (ripng_allow_ecmp, + ripng_allow_ecmp_cmd, + "allow-ecmp", + "Allow Equal Cost MultiPath\n") +{ + if (ripng->ecmp) + { + vty_out (vty, "ECMP is already enabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ripng->ecmp = 1; + zlog_info ("ECMP is enabled."); + return CMD_SUCCESS; +} + +DEFUN (no_ripng_allow_ecmp, + no_ripng_allow_ecmp_cmd, + "no allow-ecmp", + NO_STR + "Allow Equal Cost MultiPath\n") +{ + if (!ripng->ecmp) + { + vty_out (vty, "ECMP is already disabled.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ripng->ecmp = 0; + zlog_info ("ECMP is disabled."); + ripng_ecmp_disable (); + return CMD_SUCCESS; +} + /* RIPng configuration write function. */ static int ripng_config_write (struct vty *vty) @@ -2634,6 +2757,10 @@ ripng_config_write (struct vty *vty) VTY_NEWLINE); + /* ECMP configuration. */ + if (ripng->ecmp) + vty_out (vty, " allow-ecmp%s", VTY_NEWLINE); + /* RIPng static routes. */ for (rp = route_top (ripng->route); rp; rp = route_next (rp)) if (rp->info != NULL) @@ -2777,24 +2904,37 @@ ripng_clean() int i; struct route_node *rp; struct ripng_info *rinfo; + struct ripng_aggregate *aggregate; + struct list *list = NULL; + struct listnode *listnode = NULL; if (ripng) { /* Clear RIPng routes */ - for (rp = route_top (ripng->table); rp; rp = route_next (rp)) { - if ((rinfo = rp->info) != NULL) { - if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && - (rinfo->sub_type == RIPNG_ROUTE_RTE)) - ripng_zebra_ipv6_delete ((struct prefix_ipv6 *)&rp->p, - &rinfo->nexthop, rinfo->metric); + for (rp = route_top (ripng->table); rp; rp = route_next (rp)) + { + if ((list = rp->info) != NULL) + { + rinfo = listgetdata (listhead (list)); + if (ripng_route_rte (rinfo)) + ripng_zebra_ipv6_delete (rp); - RIPNG_TIMER_OFF (rinfo->t_timeout); - RIPNG_TIMER_OFF (rinfo->t_garbage_collect); + for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) + { + RIPNG_TIMER_OFF (rinfo->t_timeout); + RIPNG_TIMER_OFF (rinfo->t_garbage_collect); + ripng_info_free (rinfo); + } + list_delete (list); + rp->info = NULL; + route_unlock_node (rp); + } - rp->info = NULL; - route_unlock_node (rp); - - ripng_info_free(rinfo); - } + if ((aggregate = rp->aggregate) != NULL) + { + ripng_aggregate_free (aggregate); + rp->aggregate = NULL; + route_unlock_node (rp); + } } /* Cancel the RIPng timers */ @@ -2946,7 +3086,7 @@ void ripng_init () { /* Randomize. */ - srand (time (NULL)); + srandom (time (NULL)); /* Install RIPNG_NODE. */ install_node (&cmd_ripng_node, ripng_config_write); @@ -2986,6 +3126,9 @@ ripng_init () install_element (RIPNG_NODE, &ripng_default_information_originate_cmd); install_element (RIPNG_NODE, &no_ripng_default_information_originate_cmd); + install_element (RIPNG_NODE, &ripng_allow_ecmp_cmd); + install_element (RIPNG_NODE, &no_ripng_allow_ecmp_cmd); + ripng_if_init (); ripng_debug_init (); diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h index fb0318d5cb..1496de08bf 100644 --- a/ripngd/ripngd.h +++ b/ripngd/ripngd.h @@ -129,6 +129,9 @@ struct ripng struct thread *t_triggered_update; struct thread *t_triggered_interval; + /* RIPng ECMP flag */ + unsigned int ecmp; + /* For redistribute route map. */ struct { @@ -386,12 +389,8 @@ extern void ripng_redistribute_withdraw (int type); extern void ripng_distribute_update_interface (struct interface *); extern void ripng_if_rmap_update_interface (struct interface *); -extern void ripng_zebra_ipv6_add (struct prefix_ipv6 *p, - struct in6_addr *nexthop, - unsigned int ifindex, u_char metric); -extern void ripng_zebra_ipv6_delete (struct prefix_ipv6 *p, - struct in6_addr *nexthop, - unsigned int ifindex); +extern void ripng_zebra_ipv6_add (struct route_node *); +extern void ripng_zebra_ipv6_delete (struct route_node *); extern void ripng_redistribute_clean (void); extern int ripng_redistribute_check (int); @@ -421,4 +420,8 @@ extern int ripng_interface_address_delete (int command, struct zclient *, zebra_ extern int ripng_network_write (struct vty *, int); +extern struct ripng_info *ripng_ecmp_add (struct ripng_info *); +extern struct ripng_info *ripng_ecmp_replace (struct ripng_info *); +extern struct ripng_info *ripng_ecmp_delete (struct ripng_info *); + #endif /* _ZEBRA_RIPNG_RIPNGD_H */ diff --git a/tests/.gitignore b/tests/.gitignore index 1cb28c9fd3..3002b27149 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -29,6 +29,7 @@ testbgpmpath testbgpmpattr testbuffer testchecksum +testcli testmemory testprivs testsegv diff --git a/tests/Makefile.am b/tests/Makefile.am index bf1a912f2e..16c9e4c3db 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -11,9 +11,11 @@ EXTRA_DIST = \ lib/libzebra.exp \ global-conf.exp \ testcommands.in \ - testcommands.refout + testcommands.refout \ + testcli.in \ + testcli.refout -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ $(LOCAL_OPTS) -DSYSCONFDIR=\"$(sysconfdir)/\" if BGPD @@ -26,6 +28,7 @@ endif check_PROGRAMS = testsig testsegv testbuffer testmemory heavy heavywq heavythread \ testprivs teststream testchecksum tabletest testnexthopiter \ testcommands test-timer-correctness test-timer-performance \ + testcli \ $(TESTS_BGPD) ../vtysh/vtysh_cmd.c: @@ -40,8 +43,9 @@ test-commands-defun.c: ../vtysh/vtysh_cmd.c > test-commands-defun.c BUILT_SOURCES = test-commands-defun.c -noinst_HEADERS = prng.h tests.h +noinst_HEADERS = prng.h tests.h common-cli.h +testcli_SOURCES = test-cli.c common-cli.c testsig_SOURCES = test-sig.c testsegv_SOURCES = test-segv.c testbuffer_SOURCES = test-buffer.c @@ -63,6 +67,7 @@ testcommands_SOURCES = test-commands-defun.c test-commands.c prng.c test_timer_correctness_SOURCES = test-timer-correctness.c prng.c test_timer_performance_SOURCES = test-timer-performance.c prng.c +testcli_LDADD = ../lib/libzebra.la @LIBCAP@ testsig_LDADD = ../lib/libzebra.la @LIBCAP@ testsegv_LDADD = ../lib/libzebra.la @LIBCAP@ testbuffer_LDADD = ../lib/libzebra.la @LIBCAP@ diff --git a/tests/common-cli.c b/tests/common-cli.c new file mode 100644 index 0000000000..7135856e99 --- /dev/null +++ b/tests/common-cli.c @@ -0,0 +1,90 @@ +/* + * generic CLI test helper functions + * + * Copyright (C) 2015 by David Lamparter, + * for Open Source Routing / NetDEF, Inc. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "thread.h" +#include "vty.h" +#include "command.h" +#include "memory.h" +#include "log.h" + +#include "common-cli.h" + +struct thread_master *master; + +int dump_args(struct vty *vty, const char *descr, + int argc, const char **argv) +{ + int i; + vty_out (vty, "%s with %d args.%s", descr, argc, VTY_NEWLINE); + for (i = 0; i < argc; i++) + { + vty_out (vty, "[%02d]: %s%s", i, argv[i], VTY_NEWLINE); + } + + return CMD_SUCCESS; +} + +static void vty_do_exit(void) +{ + printf ("\nend.\n"); + exit (0); +} + +/* main routine. */ +int +main (int argc, char **argv) +{ + struct thread thread; + + /* Set umask before anything for security */ + umask (0027); + + /* master init. */ + master = thread_master_create (); + + zlog_default = openzlog ("common-cli", ZLOG_NONE, + LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED); + zlog_set_level (NULL, ZLOG_DEST_MONITOR, LOG_DEBUG); + + /* Library inits. */ + cmd_init (1); + host.name = strdup ("test"); + + vty_init (master); + memory_init (); + + test_init (); + + vty_stdio (vty_do_exit); + + /* Fetch next active thread. */ + while (thread_fetch (master, &thread)) + thread_call (&thread); + + /* Not reached. */ + exit (0); +} + diff --git a/tests/common-cli.h b/tests/common-cli.h new file mode 100644 index 0000000000..8f6751512e --- /dev/null +++ b/tests/common-cli.h @@ -0,0 +1,49 @@ +/* + * generic CLI test helper functions + * + * Copyright (C) 2015 by David Lamparter, + * for Open Source Routing / NetDEF, Inc. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _COMMON_CLI_H +#define _COMMON_CLI_H + +#include "zebra.h" +#include "vty.h" +#include "command.h" + +/* function to be implemented by test */ +extern void test_init (void); + +/* functions provided by common cli + * (includes main()) + */ +extern struct thread_master *master; + +extern int dump_args(struct vty *vty, const char *descr, + int argc, const char **argv); + +#define DUMMY_HELPSTR \ + "00\n01\n02\n03\n04\n05\n06\n07\n08\n09\n" \ + "10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n" \ + "20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n" +#define DUMMY_DEFUN(name, cmdstr) \ + DEFUN (name, name ## _cmd, cmdstr, DUMMY_HELPSTR) \ + { return dump_args(vty, #name, argc, argv); } + +#endif /* _COMMON_CLI_H */ diff --git a/tests/libzebra.tests/Makefile.am b/tests/libzebra.tests/Makefile.am index 819cce2fed..4b74e2d3fb 100644 --- a/tests/libzebra.tests/Makefile.am +++ b/tests/libzebra.tests/Makefile.am @@ -2,4 +2,5 @@ EXTRA_DIST = \ tabletest.exp \ test-timer-correctness.exp \ testcommands.exp \ + testcli.exp \ testnexthopiter.exp diff --git a/tests/libzebra.tests/testcli.exp b/tests/libzebra.tests/testcli.exp new file mode 100644 index 0000000000..778bd0caa3 --- /dev/null +++ b/tests/libzebra.tests/testcli.exp @@ -0,0 +1,23 @@ +set timeout 30 +set test_name "testcli" + +spawn sh -c "./testcli < $env(srcdir)/testcli.in | diff -au $env(srcdir)/testcli.refout -" + +expect { + eof { + } + timeout { + exp_close + fail "$test_name: timeout" + } +} + +catch wait result +set os_error [lindex $result 2] +set exit_status [lindex $result 3] + +if { $os_error == 0 && $exit_status == 0 } { + pass "$test_name" +} else { + fail "$test_name" +} diff --git a/tests/test-cli.c b/tests/test-cli.c new file mode 100644 index 0000000000..3db44eec82 --- /dev/null +++ b/tests/test-cli.c @@ -0,0 +1,56 @@ +/* + * CLI/command dummy handling tester + * + * Copyright (C) 2015 by David Lamparter, + * for Open Source Routing / NetDEF, Inc. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "common-cli.h" + +DUMMY_DEFUN(cmd0, "arg ipv4 A.B.C.D"); +DUMMY_DEFUN(cmd1, "arg ipv4m A.B.C.D/M"); +DUMMY_DEFUN(cmd2, "arg ipv6 X:X::X:X"); +DUMMY_DEFUN(cmd3, "arg ipv6m X:X::X:X/M"); +DUMMY_DEFUN(cmd4, "arg range <5-15>"); +DUMMY_DEFUN(cmd5, "pat a ( a|b)"); +DUMMY_DEFUN(cmd6, "pat b (a|)"); +DUMMY_DEFUN(cmd7, "pat c (a | b|c) A.B.C.D"); +DUMMY_DEFUN(cmd8, "pat d { foo A.B.C.D|bar X:X::X:X| baz }"); +DUMMY_DEFUN(cmd9, "pat e [ WORD ]"); +DUMMY_DEFUN(cmd10, "pat f [key]"); +DUMMY_DEFUN(cmd11, "alt a WORD"); +DUMMY_DEFUN(cmd12, "alt a A.B.C.D"); +DUMMY_DEFUN(cmd13, "alt a X:X::X:X"); + +void test_init(void) +{ + install_element (ENABLE_NODE, &cmd0_cmd); + install_element (ENABLE_NODE, &cmd1_cmd); + install_element (ENABLE_NODE, &cmd2_cmd); + install_element (ENABLE_NODE, &cmd3_cmd); + install_element (ENABLE_NODE, &cmd4_cmd); + install_element (ENABLE_NODE, &cmd5_cmd); + install_element (ENABLE_NODE, &cmd6_cmd); + install_element (ENABLE_NODE, &cmd7_cmd); + install_element (ENABLE_NODE, &cmd8_cmd); + install_element (ENABLE_NODE, &cmd9_cmd); + install_element (ENABLE_NODE, &cmd10_cmd); + install_element (ENABLE_NODE, &cmd11_cmd); + install_element (ENABLE_NODE, &cmd12_cmd); + install_element (ENABLE_NODE, &cmd13_cmd); +} diff --git a/tests/testcli.in b/tests/testcli.in new file mode 100644 index 0000000000..f4212b9758 --- /dev/null +++ b/tests/testcli.in @@ -0,0 +1,93 @@ +echo this is a test message +echo foo bla ? baz +echo + +arg ipv4 1.2.3.4 +arg ipv4 1.2.?3.4 +arg ipv4 1.2.3 +arg ipv4 1.2.3.4.5 +arg ipv4 1.a.3.4 +arg ipv4 blah + +arg ipv4m 1.2.3.0/24 +arg ipv4m 1.2.?3.0/24 +arg ipv4m 1.2.3/9 +arg ipv4m 1.2.3.4.5/6 +arg ipv4m 1.a.3.4 +arg ipv4m blah +arg ipv4m 1.2.3.0/999 +arg ipv4m 1.2.3.0/a9 +arg ipv4m 1.2.3.0/9a + +arg ipv6 de4d:b33f::cafe +arg ipv6 de4d:b3?3f::caf?e +arg ipv6 de4d:b3 3f::caf?e +arg ipv6 de4d:b33f:z::cafe +arg ipv6 de4d:b33f:cafe: +arg ipv6 :: +arg ipv6 ::/ +arg ipv6 1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0 +arg ipv6 12::34::56 +arg ipv6m dead:beef:cafe::/64 +arg ipv6m dead:be?ef:cafe:?:/64 + +arg range 4 +arg range 5 +arg range 9? +arg range 15 +arg range 16 +arg range -1 +arg range 99999999999999999999999999999999999999999 + +arg ? + +pa +pat + +pat a +pat a a +pat a ?b +pat a c? +pat a a x + +pat b +pat b ?a +pat b x +pat b x y + +pat c a +pat c a 1.2.3.4 +pat c b 2.3.4 +pat c c ?x + +pat d +pat d +pat d foo 1.2.3.4 +pat d foo +pat d noooo +pat d bar 1::2 +pat d bar 1::2 foo 3.4.5.6 +pat d ba?z +pat d foo 3.4.5.6 baz + +pat e +pat e f +pat e f g +pat e 1.2.3.4 + +pat f +pat f foo +pat f key + +alt a a?b +alt a 1 .2?.3.4 +alt a 1 :2? ::?3 + +conf t +do pat d baz +exit + +show run +conf t +hostname foohost +do show run diff --git a/tests/testcli.refout b/tests/testcli.refout new file mode 100644 index 0000000000..1515ea2c65 --- /dev/null +++ b/tests/testcli.refout @@ -0,0 +1,290 @@ +test# echo this is a test message +this is a test message +test# echo foo bla + MESSAGE The message to echo + +test# echo foo bla baz +foo bla baz +test# echo +% Command incomplete. +test# +test# arg ipv4 1.2.3.4 +cmd0 with 1 args. +[00]: 1.2.3.4 +test# arg ipv4 1.2. + A.B.C.D 02 +test# arg ipv4 1.2.3.4 +cmd0 with 1 args. +[00]: 1.2.3.4 +test# arg ipv4 1.2.3 +cmd0 with 1 args. +[00]: 1.2.3 +test# arg ipv4 1.2.3.4.5 +% [NONE] Unknown command: arg ipv4 1.2.3.4.5 +test# arg ipv4 1.a.3.4 +% [NONE] Unknown command: arg ipv4 1.a.3.4 +test# arg ipv4 blah +% [NONE] Unknown command: arg ipv4 blah +test# +test# arg ipv4m 1.2.3.0/24 +cmd1 with 1 args. +[00]: 1.2.3.0/24 +test# arg ipv4m 1.2. + A.B.C.D/M 02 +test# arg ipv4m 1.2.3.0/24 +cmd1 with 1 args. +[00]: 1.2.3.0/24 +test# arg ipv4m 1.2.3/9 +% [NONE] Unknown command: arg ipv4m 1.2.3/9 +test# arg ipv4m 1.2.3.4.5/6 +% [NONE] Unknown command: arg ipv4m 1.2.3.4.5/6 +test# arg ipv4m 1.a.3.4 +% [NONE] Unknown command: arg ipv4m 1.a.3.4 +test# arg ipv4m blah +% [NONE] Unknown command: arg ipv4m blah +test# arg ipv4m 1.2.3.0/999 +% [NONE] Unknown command: arg ipv4m 1.2.3.0/999 +test# arg ipv4m 1.2.3.0/a9 +% [NONE] Unknown command: arg ipv4m 1.2.3.0/a9 +test# arg ipv4m 1.2.3.0/9a +% [NONE] Unknown command: arg ipv4m 1.2.3.0/9a +test# +test# arg ipv6 de4d:b33f::cafe +cmd2 with 1 args. +[00]: de4d:b33f::cafe +test# arg ipv6 de4d:b3 +% There is no matched command. +test# arg ipv6 de4d:b33f::caf + X:X::X:X 02 +test# arg ipv6 de4d:b33f::cafe +cmd2 with 1 args. +[00]: de4d:b33f::cafe +test# arg ipv6 de4d:b3 +test# arg ipv6 de4d:b33f::caf + X:X::X:X 02 +test# arg ipv6 de4d:b33f::cafe +cmd2 with 1 args. +[00]: de4d:b33f::cafe +test# arg ipv6 de4d:b33f:z::cafe +% [NONE] Unknown command: arg ipv6 de4d:b33f:z::cafe +test# arg ipv6 de4d:b33f:cafe: +% [NONE] Unknown command: arg ipv6 de4d:b33f:cafe: +test# arg ipv6 :: +cmd2 with 1 args. +[00]: :: +test# arg ipv6 ::/ +% [NONE] Unknown command: arg ipv6 ::/ +test# arg ipv6 1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0 +% [NONE] Unknown command: arg ipv6 1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0:1:2:3:4:5:6:7:8:9:0 +test# arg ipv6 12::34::56 +% [NONE] Unknown command: arg ipv6 12::34::56 +test# arg ipv6m dead:beef:cafe::/64 +cmd3 with 1 args. +[00]: dead:beef:cafe::/64 +test# arg ipv6m dead:be + X:X::X:X/M 02 +test# arg ipv6m dead:beef:cafe: + X:X::X:X/M 02 +test# arg ipv6m dead:beef:cafe::/64 +cmd3 with 1 args. +[00]: dead:beef:cafe::/64 +test# +test# arg range 4 +% [NONE] Unknown command: arg range 4 +test# arg range 5 +cmd4 with 1 args. +[00]: 5 +test# arg range 9 + <5-15> 02 +test# arg range 9 +cmd4 with 1 args. +[00]: 9 +test# arg range 15 +cmd4 with 1 args. +[00]: 15 +test# arg range 16 +% [NONE] Unknown command: arg range 16 +test# arg range -1 +% [NONE] Unknown command: arg range -1 +test# arg range 99999999999999999999999999999999999999999 +% [NONE] Unknown command: arg range 99999999999999999999999999999999999999999 +test# +test# arg + ipv4 01 + ipv4m 01 + ipv6 01 + ipv6m 01 + range 01 +test# arg +% Command incomplete. +test# +test# pa +test# papat +% Command incomplete. +test# pat +a b c d e f +test# pat +% Command incomplete. +test# +test# pat a +% Command incomplete. +test# pat a a +cmd5 with 1 args. +[00]: a +test# pat a + a 02 + b 03 +test# pat a b +cmd5 with 1 args. +[00]: b +test# pat a c +% There is no matched command. +test# pat a c +% [NONE] Unknown command: pat a c +test# pat a a x +% [NONE] Unknown command: pat a a x +test# +test# pat b +% Command incomplete. +test# pat b + a 02 +test# pat b a +cmd6 with 1 args. +[00]: a +test# pat b x +% [NONE] Unknown command: pat b x +test# pat b x y +% [NONE] Unknown command: pat b x y +test# +test# pat c a +% Command incomplete. +test# pat c a 1.2.3.4 +cmd7 with 2 args. +[00]: a +[01]: 1.2.3.4 +test# pat c b 2.3.4 +cmd7 with 2 args. +[00]: b +[01]: 2.3.4 +test# pat c c + A.B.C.D 05 +test# pat c c x +% [NONE] Unknown command: pat c c x +test# +test# pat d +cmd8 with 3 args. +[00]: (null) +[01]: (null) +[02]: (null) +test# pat d +bar baz foo +test# pat d +cmd8 with 3 args. +[00]: (null) +[01]: (null) +[02]: (null) +test# pat d foo 1.2.3.4 +cmd8 with 3 args. +[00]: 1.2.3.4 +[01]: (null) +[02]: (null) +test# pat d foo +% Command incomplete. +test# pat d noooo +% [NONE] Unknown command: pat d noooo +test# pat d bar 1::2 +cmd8 with 3 args. +[00]: (null) +[01]: 1::2 +[02]: (null) +test# pat d bar 1::2 foo 3.4.5.6 +cmd8 with 3 args. +[00]: 3.4.5.6 +[01]: 1::2 +[02]: (null) +test# pat d ba + bar 04 + baz 06 +test# pat d baz +cmd8 with 3 args. +[00]: (null) +[01]: (null) +[02]: baz +test# pat d foo 3.4.5.6 baz +cmd8 with 3 args. +[00]: 3.4.5.6 +[01]: (null) +[02]: baz +test# +test# pat e +% Command incomplete. +test# pat e f +% Command incomplete. +test# pat e f g +% Command incomplete. +test# pat e 1.2.3.4 +% Command incomplete. +test# +test# pat f +cmd10 with 0 args. +test# pat f foo +cmd10 with 1 args. +[00]: foo +test# pat f key +cmd10 with 1 args. +[00]: key +test# +test# alt a +test# alt a a + WORD 02 +test# alt a ab +cmd11 with 1 args. +[00]: ab +test# alt a 1 +test# alt a 1.2 + A.B.C.D 02 + WORD 02 +test# alt a 1.2.3.4 +cmd12 with 1 args. +[00]: 1.2.3.4 +test# alt a 1 +test# alt a 1:2 + WORD 02 +test# alt a 1:2 +test# alt a 1:2:: + WORD 02 + X:X::X:X 02 +test# alt a 1:2::3 +cmd13 with 1 args. +[00]: 1:2::3 +test# +test# conf t +test(config)# do pat d baz +cmd8 with 3 args. +[00]: (null) +[01]: (null) +[02]: baz +test(config)# exit +test# +test# show run + +Current configuration: +! +hostname test +! +line vty +! +end +test# conf t +test(config)# hostname foohost +foohost(config)# do show run + +Current configuration: +! +hostname foohost +! +line vty +! +end +foohost(config)# +end. diff --git a/vtysh/Makefile.am b/vtysh/Makefile.am index eaf19a28c4..5b9e5abd09 100644 --- a/vtysh/Makefile.am +++ b/vtysh/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with Automake to create Makefile.in -INCLUDES = @INCLUDES@ -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" LIBS = @LIBS@ @CURSES@ @LIBPAM@ diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 2621cf8f56..0043c745f1 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -25,7 +25,10 @@ print < + #include "command.h" +#include "linklist.h" + #include "vtysh.h" EOF @@ -63,6 +66,8 @@ $ignore{'"terminal monitor"'} = "ignore"; $ignore{'"terminal no monitor"'} = "ignore"; $ignore{'"show history"'} = "ignore"; +my $cli_stomp = 0; + foreach (@ARGV) { $file = $_; @@ -151,7 +156,13 @@ foreach (@ARGV) { $defun_array[1] = $cmd . "_vtysh"; $defun_body = join (", ", @defun_array); - # $cmd -> $str hash for lookup + # $cmd -> $str hash for lookup + if (exists($cmd2str{$cmd})) { + warn "Duplicate CLI Function: $cmd\n"; + warn "\tFrom cli: $cmd2str{$cmd} to New cli: $str\n"; + warn "\tOriginal Protocol: $cmd2proto{$cmd} to New Protocol: $protocol\n"; + $cli_stomp++; + } $cmd2str{$cmd} = $str; $cmd2defun{$cmd} = $defun_body; $cmd2proto{$cmd} = $protocol; @@ -192,6 +203,27 @@ foreach (@ARGV) { } } +my $bad_cli_stomps = 109; +# Currently we have $bad_cli_stomps. This was determined by +# running this script and counting up the collisions from what +# was returned. +# +# When we have cli commands that map to the same function name, we +# can introduce subtle bugs due to code not being called when +# we think it is. +# +# If extract.pl fails with a error message and you've been +# modifying the cli, then go back and fix your code to +# not have cli command function collisions. +# +# If you've removed a cli overwrite, you can safely subtract +# one from $bad_cli_stomps. If you've added to the problem +# please fix your code before submittal +if ($cli_stomp != $bad_cli_stomps) { + warn "Expected $bad_cli_stomps command line stomps, but got $cli_stomp instead\n"; + exit $cli_stomp; +} + # Check finaly alive $cmd; foreach (keys %odefun) { my ($node, $str) = (split (/,/)); diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 8e39e9349e..75ce584818 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -34,6 +34,7 @@ #include #include +#include "linklist.h" #include "command.h" #include "memory.h" #include "vtysh/vtysh.h" @@ -69,21 +70,6 @@ struct vtysh_client vtysh_client[] = { .fd = -1, .name = "pimd", .flag = VTYSH_PIMD, .path = PIM_VTYSH_PATH, .next = NULL}, }; -/* - * Compiler is warning about prototypes not being declared. - * The DEFUNSH and DEFUN macro's are messing with the - * compiler I believe. This is just to make it happy. - */ -int vtysh_end(void); -int vtysh_rl_describe(void); -void vtysh_exit_ripd_only(void); -int vtysh_connect_all_instances(struct vtysh_client *); - - -/* We need direct access to ripd to implement vtysh_exit_ripd_only. */ -static struct vtysh_client *ripd_client = NULL; - - /* Using integrated config from Quagga.conf. Default is no. */ int vtysh_writeconfig_integrated = 0; @@ -323,14 +309,6 @@ vtysh_client_execute (struct vtysh_client *head_client, const char *line, FILE * return CMD_SUCCESS; } -void -vtysh_exit_ripd_only (void) -{ - if (ripd_client) - vtysh_client_execute (ripd_client, "exit", stdout); -} - - void vtysh_pager_init (void) { @@ -383,7 +361,8 @@ vtysh_execute_func (const char *line, int pager) * to move into node in the vtysh where it succeeded. */ if (ret == CMD_SUCCESS || ret == CMD_SUCCESS_DAEMON || ret == CMD_WARNING) { - if ((saved_node == BGP_VPNV4_NODE || saved_node == BGP_IPV4_NODE + if ((saved_node == BGP_VPNV4_NODE || saved_node == BGP_VPNV6_NODE + || saved_node == BGP_IPV4_NODE || saved_node == BGP_IPV6_NODE || saved_node == BGP_IPV4M_NODE || saved_node == BGP_IPV6M_NODE) && (tried == 1)) @@ -753,7 +732,7 @@ vtysh_config_from_file (struct vty *vty, FILE *fp) } /* We don't care about the point of the cursor when '?' is typed. */ -int +static int vtysh_rl_describe (void) { int ret; @@ -941,6 +920,12 @@ static struct cmd_node bgp_vpnv4_node = "%s(config-router-af)# " }; +static struct cmd_node bgp_vpnv6_node = +{ + BGP_VPNV6_NODE, + "%s(config-router-af)# " +}; + static struct cmd_node bgp_ipv4_node = { BGP_IPV4_NODE, @@ -999,7 +984,7 @@ static struct cmd_node keychain_key_node = extern struct cmd_node vty_node; /* When '^Z' is received from vty, move down to the enable mode. */ -int +static int vtysh_end (void) { switch (vty->node) @@ -1076,6 +1061,29 @@ DEFUNSH (VTYSH_BGPD, return CMD_SUCCESS; } +DEFUNSH (VTYSH_BGPD, + address_family_vpnv6, + address_family_vpnv6_cmd, + "address-family vpnv6", + "Enter Address Family command mode\n" + "Address family\n") +{ + vty->node = BGP_VPNV6_NODE; + return CMD_SUCCESS; +} + +DEFUNSH (VTYSH_BGPD, + address_family_vpnv6_unicast, + address_family_vpnv6_unicast_cmd, + "address-family vpnv6 unicast", + "Enter Address Family command mode\n" + "Address family\n" + "Address Family Modifier\n") +{ + vty->node = BGP_VPNV6_NODE; + return CMD_SUCCESS; +} + DEFUNSH (VTYSH_BGPD, address_family_ipv4_unicast, address_family_ipv4_unicast_cmd, @@ -1309,6 +1317,7 @@ vtysh_exit (struct vty *vty) vty->node = CONFIG_NODE; break; case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: @@ -1347,6 +1356,7 @@ DEFUNSH (VTYSH_BGPD, if (vty->node == BGP_IPV4_NODE || vty->node == BGP_IPV4M_NODE || vty->node == BGP_VPNV4_NODE + || vty->node == BGP_VPNV6_NODE || vty->node == BGP_IPV6_NODE || vty->node == BGP_IPV6M_NODE) vty->node = BGP_NODE; @@ -2648,7 +2658,7 @@ vtysh_update_all_insances(struct vtysh_client * head_client) } } -int +static int vtysh_connect_all_instances (struct vtysh_client *head_client) { struct vtysh_client *client; @@ -2681,9 +2691,6 @@ vtysh_connect_all(const char *daemon_name) matches++; if (vtysh_connect(&vtysh_client[i]) == 0) rc++; - /* We need direct access to ripd in vtysh_exit_ripd_only. */ - if (vtysh_client[i].flag == VTYSH_RIPD) - ripd_client = &vtysh_client[i]; rc += vtysh_connect_all_instances(&vtysh_client[i]); } @@ -2750,6 +2757,7 @@ vtysh_init_vty (void) install_node (&rmap_node, NULL); install_node (&zebra_node, NULL); install_node (&bgp_vpnv4_node, NULL); + install_node (&bgp_vpnv6_node, NULL); install_node (&bgp_ipv4_node, NULL); install_node (&bgp_ipv4m_node, NULL); /* #ifdef HAVE_IPV6 */ @@ -2776,6 +2784,7 @@ vtysh_init_vty (void) vtysh_install_default (RMAP_NODE); vtysh_install_default (ZEBRA_NODE); vtysh_install_default (BGP_VPNV4_NODE); + vtysh_install_default (BGP_VPNV6_NODE); vtysh_install_default (BGP_IPV4_NODE); vtysh_install_default (BGP_IPV4M_NODE); vtysh_install_default (BGP_IPV6_NODE); @@ -2811,6 +2820,8 @@ vtysh_init_vty (void) install_element (BGP_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_VPNV4_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_VPNV4_NODE, &vtysh_quit_bgpd_cmd); + install_element (BGP_VPNV6_NODE, &vtysh_exit_bgpd_cmd); + install_element (BGP_VPNV6_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_IPV4_NODE, &vtysh_exit_bgpd_cmd); install_element (BGP_IPV4_NODE, &vtysh_quit_bgpd_cmd); install_element (BGP_IPV4M_NODE, &vtysh_exit_bgpd_cmd); @@ -2841,6 +2852,7 @@ vtysh_init_vty (void) install_element (BGP_IPV4_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV4M_NODE, &vtysh_end_all_cmd); install_element (BGP_VPNV4_NODE, &vtysh_end_all_cmd); + install_element (BGP_VPNV6_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV6_NODE, &vtysh_end_all_cmd); install_element (BGP_IPV6M_NODE, &vtysh_end_all_cmd); install_element (ISIS_NODE, &vtysh_end_all_cmd); @@ -2874,6 +2886,8 @@ vtysh_init_vty (void) install_element (CONFIG_NODE, &router_bgp_view_cmd); install_element (BGP_NODE, &address_family_vpnv4_cmd); install_element (BGP_NODE, &address_family_vpnv4_unicast_cmd); + install_element (BGP_NODE, &address_family_vpnv6_cmd); + install_element (BGP_NODE, &address_family_vpnv6_unicast_cmd); install_element (BGP_NODE, &address_family_ipv4_unicast_cmd); install_element (BGP_NODE, &address_family_ipv4_multicast_cmd); #ifdef HAVE_IPV6 @@ -2882,6 +2896,7 @@ vtysh_init_vty (void) install_element (BGP_NODE, &address_family_ipv6_multicast_cmd); #endif install_element (BGP_VPNV4_NODE, &exit_address_family_cmd); + install_element (BGP_VPNV6_NODE, &exit_address_family_cmd); install_element (BGP_IPV4_NODE, &exit_address_family_cmd); install_element (BGP_IPV4M_NODE, &exit_address_family_cmd); install_element (BGP_IPV6_NODE, &exit_address_family_cmd); diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index 9bc9f6d1b4..e974cf331c 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -55,6 +55,8 @@ void vtysh_config_write (void); int vtysh_config_from_file (struct vty *, FILE *); +void config_add_line (struct list *, const char *); + int vtysh_mark_file(const char *filename); int vtysh_read_config (const char *); diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 9497241d7f..fcad333b9f 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -27,21 +27,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "vtysh/vtysh.h" #include "vtysh/vtysh_user.h" -/* - * Compiler is warning about prototypes not being declared. - * The DEFUNSH and DEFUN macro's are messing with the - * compiler I believe. This is just to make it happy. - */ -int line_cmp(char *, char*); -void line_del(char *); -struct config *config_new(void); -int config_cmp(struct config *, struct config *); -void config_del(struct config *); -struct config *config_get(int, const char *); -void config_add_line(struct list *, const char *); -void config_add_line_uniq(struct list *, const char *); -void vtysh_config_parse_line(const char *); - vector configvec; extern int vtysh_writeconfig_integrated; @@ -63,19 +48,19 @@ struct config struct list *config_top; -int +static int line_cmp (char *c1, char *c2) { return strcmp (c1, c2); } -void +static void line_del (char *line) { XFREE (MTYPE_VTYSH_CONFIG_LINE, line); } -struct config * +static struct config * config_new (void) { struct config *config; @@ -83,13 +68,13 @@ config_new (void) return config; } -int +static int config_cmp (struct config *c1, struct config *c2) { return strcmp (c1->name, c2->name); } -void +static void config_del (struct config* config) { list_delete (config->line); @@ -98,7 +83,7 @@ config_del (struct config* config) XFREE (MTYPE_VTYSH_CONFIG, config); } -struct config * +static struct config * config_get (int index, const char *line) { struct config *config; @@ -143,7 +128,7 @@ config_add_line (struct list *config, const char *line) listnode_add (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line)); } -void +static void config_add_line_uniq (struct list *config, const char *line) { struct listnode *node, *nnode; @@ -157,7 +142,7 @@ config_add_line_uniq (struct list *config, const char *line) listnode_add_sort (config, XSTRDUP (MTYPE_VTYSH_CONFIG_LINE, line)); } -void +static void vtysh_config_parse_line (const char *line) { char c; diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 1d40ab4cca..cd21c94efd 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -36,6 +36,7 @@ #include "command.h" #include "memory.h" #include "privs.h" +#include "linklist.h" #include "vtysh/vtysh.h" #include "vtysh/vtysh_user.h" @@ -123,10 +124,9 @@ sigint (int sig) /* Signale wrapper for vtysh. We don't use sigevent because * vtysh doesn't use threads. TODO */ -static RETSIGTYPE * +static void vtysh_signal_set (int signo, void (*func)(int)) { - int ret; struct sigaction sig; struct sigaction osig; @@ -137,12 +137,7 @@ vtysh_signal_set (int signo, void (*func)(int)) sig.sa_flags |= SA_RESTART; #endif /* SA_RESTART */ - ret = sigaction (signo, &sig, &osig); - - if (ret < 0) - return (SIG_ERR); - else - return (osig.sa_handler); + sigaction (signo, &sig, &osig); } /* Initialization of signal handles. */ @@ -231,9 +226,12 @@ static void log_it(const char *line) { time_t t = time(NULL); struct tm *tmp = localtime(&t); - const char *user = getenv("USER") ? : "boot"; + const char *user = getenv("USER"); char tod[64]; + if (!user) + user = "boot"; + strftime(tod, sizeof tod, "%Y%m%d-%H:%M.%S", tmp); fprintf(logfile, "%s:%s %s\n", tod, user, line); diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c index e65b7bb118..0d72c378a3 100644 --- a/vtysh/vtysh_user.c +++ b/vtysh/vtysh_user.c @@ -47,10 +47,6 @@ #ifdef USE_PAM static int vtysh_pam(const char *); #endif -struct vtysh_user *user_new(void); -void user_free(struct vtysh_user *); -struct vtysh_user *user_lookup(const char *); -struct vtysh_user *user_get(const char *); int vtysh_auth(void); void vtysh_user_init(void); @@ -117,19 +113,13 @@ struct vtysh_user struct list *userlist; -struct vtysh_user * +static struct vtysh_user * user_new (void) { return XCALLOC (0, sizeof (struct vtysh_user)); } -void -user_free (struct vtysh_user *user) -{ - XFREE (0, user); -} - -struct vtysh_user * +static struct vtysh_user * user_lookup (const char *name) { struct listnode *node, *nnode; @@ -160,7 +150,7 @@ user_config_write () } } -struct vtysh_user * +static struct vtysh_user * user_get (const char *name) { struct vtysh_user *user; @@ -200,7 +190,7 @@ DEFUN (username_nopassword, } int -vtysh_auth () +vtysh_auth (void) { struct vtysh_user *user; struct passwd *passwd; diff --git a/vtysh/vtysh_user.h b/vtysh/vtysh_user.h index b0686a9699..16fcdd03a5 100644 --- a/vtysh/vtysh_user.h +++ b/vtysh/vtysh_user.h @@ -22,7 +22,8 @@ #ifndef _VTYSH_USER_H #define _VTYSH_USER_H -int vtysh_auth (); +int vtysh_auth (void); +void vtysh_user_init (void); void user_config_write(void); char *vtysh_get_home (void); diff --git a/watchquagga/Makefile.am b/watchquagga/Makefile.am index 3f7d8954fa..1f05f26ced 100644 --- a/watchquagga/Makefile.am +++ b/watchquagga/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with Automake to create Makefile.in -INCLUDES = @INCLUDES@ -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSTATEDIR=\"$(localstatedir)/\" AM_CFLAGS = $(WERROR) diff --git a/watchquagga/watchquagga.c b/watchquagga/watchquagga.c index 5cb224a45a..e882653e38 100644 --- a/watchquagga/watchquagga.c +++ b/watchquagga/watchquagga.c @@ -389,7 +389,7 @@ restart_kill(struct thread *t_kill) time_elapsed(&delay,&restart->time); zlog_warn("Warning: %s %s child process %d still running after " "%ld seconds, sending signal %d", - restart->what,restart->name,(int)restart->pid,delay.tv_sec, + restart->what,restart->name,(int)restart->pid, (long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM)); kill(-restart->pid,(restart->kills ? SIGKILL : SIGTERM)); restart->kills++; @@ -662,15 +662,17 @@ handle_read(struct thread *t_read) { dmn->state = DAEMON_UP; zlog_warn("%s state -> up : echo response received after %ld.%06ld " - "seconds", dmn->name,delay.tv_sec,delay.tv_usec); + "seconds", dmn->name, + (long)delay.tv_sec, (long)delay.tv_usec); } else zlog_warn("%s: slow echo response finally received after %ld.%06ld " - "seconds", dmn->name,delay.tv_sec,delay.tv_usec); + "seconds", dmn->name, + (long)delay.tv_sec, (long)delay.tv_usec); } else if (gs.loglevel > LOG_DEBUG+1) zlog_debug("%s: echo response received after %ld.%06ld seconds", - dmn->name,delay.tv_sec,delay.tv_usec); + dmn->name, (long)delay.tv_sec, (long)delay.tv_usec); SET_READ_HANDLER(dmn); if (dmn->t_wakeup) diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 875d2673c7..f03a3b375e 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -1,23 +1,20 @@ ## Process this file with automake to produce Makefile.in. -INCLUDES = @INCLUDES@ -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib +AM_CPPFLAGS = -I.. -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_builddir)/lib DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" INSTALL_SDATA=@INSTALL@ -m 600 -LIB_IPV6 = @LIB_IPV6@ LIBCAP = @LIBCAP@ ipforward = @IPFORWARD@ if_method = @IF_METHOD@ -if_proc = @IF_PROC@ rt_method = @RT_METHOD@ rtread_method = @RTREAD_METHOD@ kernel_method = @KERNEL_METHOD@ -other_method = @OTHER_METHOD@ ioctl_method = @IOCTL_METHOD@ -otherobj = $(ioctl_method) $(ipforward) $(if_method) $(if_proc) \ - $(rt_method) $(rtread_method) $(kernel_method) $(other_method) +otherobj = $(ioctl_method) $(ipforward) $(if_method) \ + $(rt_method) $(rtread_method) $(kernel_method) if HAVE_NETLINK othersrc = zebra_fpm_netlink.c @@ -48,17 +45,17 @@ noinst_HEADERS = \ zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \ zebra_ns.h zebra_vrf.h -zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) $(LIB_IPV6) +zebra_LDADD = $(otherobj) ../lib/libzebra.la $(LIBCAP) -testzebra_LDADD = ../lib/libzebra.la $(LIBCAP) $(LIB_IPV6) +testzebra_LDADD = ../lib/libzebra.la $(LIBCAP) zebra_DEPENDENCIES = $(otherobj) -EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c if_proc.c \ - if_sysctl.c ipforward_aix.c ipforward_ews.c ipforward_proc.c \ - ipforward_solaris.c ipforward_sysctl.c rt_ioctl.c rt_netlink.c \ - rt_socket.c rtread_netlink.c rtread_proc.c rtread_sysctl.c \ - rtread_getmsg.c kernel_socket.c kernel_netlink.c mtu_kvm.c \ +EXTRA_DIST = if_ioctl.c if_ioctl_solaris.c if_netlink.c \ + if_sysctl.c ipforward_proc.c \ + ipforward_solaris.c ipforward_sysctl.c rt_netlink.c \ + rt_socket.c rtread_netlink.c rtread_sysctl.c \ + rtread_getmsg.c kernel_socket.c kernel_netlink.c \ ioctl.c ioctl_solaris.c \ GNOME-SMI GNOME-PRODUCT-ZEBRA-MIB diff --git a/zebra/connected.c b/zebra/connected.c index 7da40ce03a..42b5a8ab9c 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -372,7 +372,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) /* Apply mask to the network. */ apply_mask_ipv6 (&p); -#if ! defined (MUSICA) && ! defined (LINUX) +#ifndef LINUX /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */ if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) return; diff --git a/zebra/if_proc.c b/zebra/if_proc.c deleted file mode 100644 index eab511c845..0000000000 --- a/zebra/if_proc.c +++ /dev/null @@ -1,248 +0,0 @@ -/* Interface name and statistics get function using proc file system - * Copyright (C) 1999 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include - -#include "if.h" -#include "prefix.h" -#include "log.h" - -#include "zebra/ioctl.h" -#include "zebra/connected.h" -#include "zebra/interface.h" - -/* Proc filesystem one line buffer. */ -#define PROCBUFSIZ 1024 - -/* Path to device proc file system. */ -#ifndef _PATH_PROC_NET_DEV -#define _PATH_PROC_NET_DEV "/proc/net/dev" -#endif /* _PATH_PROC_NET_DEV */ - -/* Return statistics data pointer. */ -static char * -interface_name_cut (char *buf, char **name) -{ - char *stat; - - /* Skip white space. Line will include header spaces. */ - while (*buf == ' ') - buf++; - *name = buf; - - /* Cut interface name. */ - stat = strrchr (buf, ':'); - *stat++ = '\0'; - - return stat; -} - -/* Fetch each statistics field. */ -static int -ifstat_dev_fields (int version, char *buf, struct interface *ifp) -{ - switch (version) - { - case 3: - sscanf(buf, - "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", - &ifp->stats.rx_bytes, - &ifp->stats.rx_packets, - &ifp->stats.rx_errors, - &ifp->stats.rx_dropped, - &ifp->stats.rx_fifo_errors, - &ifp->stats.rx_frame_errors, - &ifp->stats.rx_compressed, - &ifp->stats.rx_multicast, - - &ifp->stats.tx_bytes, - &ifp->stats.tx_packets, - &ifp->stats.tx_errors, - &ifp->stats.tx_dropped, - &ifp->stats.tx_fifo_errors, - &ifp->stats.collisions, - &ifp->stats.tx_carrier_errors, - &ifp->stats.tx_compressed); - break; - case 2: - sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", - &ifp->stats.rx_bytes, - &ifp->stats.rx_packets, - &ifp->stats.rx_errors, - &ifp->stats.rx_dropped, - &ifp->stats.rx_fifo_errors, - &ifp->stats.rx_frame_errors, - - &ifp->stats.tx_bytes, - &ifp->stats.tx_packets, - &ifp->stats.tx_errors, - &ifp->stats.tx_dropped, - &ifp->stats.tx_fifo_errors, - &ifp->stats.collisions, - &ifp->stats.tx_carrier_errors); - ifp->stats.rx_multicast = 0; - break; - case 1: - sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", - &ifp->stats.rx_packets, - &ifp->stats.rx_errors, - &ifp->stats.rx_dropped, - &ifp->stats.rx_fifo_errors, - &ifp->stats.rx_frame_errors, - - &ifp->stats.tx_packets, - &ifp->stats.tx_errors, - &ifp->stats.tx_dropped, - &ifp->stats.tx_fifo_errors, - &ifp->stats.collisions, - &ifp->stats.tx_carrier_errors); - ifp->stats.rx_bytes = 0; - ifp->stats.tx_bytes = 0; - ifp->stats.rx_multicast = 0; - break; - } - return 0; -} - -/* Update interface's statistics. */ -static void -ifstat_update_proc (void) -{ - FILE *fp; - char buf[PROCBUFSIZ]; - int version; - struct interface *ifp; - char *stat; - char *name; - - /* Open /proc/net/dev. */ - fp = fopen (_PATH_PROC_NET_DEV, "r"); - if (fp == NULL) - { - zlog_warn ("Can't open proc file %s: %s", - _PATH_PROC_NET_DEV, safe_strerror (errno)); - return; - } - - /* Drop header lines. */ - fgets (buf, PROCBUFSIZ, fp); - fgets (buf, PROCBUFSIZ, fp); - - /* To detect proc format veresion, parse second line. */ - if (strstr (buf, "compressed")) - version = 3; - else if (strstr (buf, "bytes")) - version = 2; - else - version = 1; - - /* Update each interface's statistics. */ - while (fgets (buf, PROCBUFSIZ, fp) != NULL) - { - stat = interface_name_cut (buf, &name); - ifp = if_get_by_name (name); - ifstat_dev_fields (version, stat, ifp); - } - fclose(fp); - return; -} - -/* Interface structure allocation by proc filesystem. */ -int -interface_list_proc () -{ - FILE *fp; - char buf[PROCBUFSIZ]; - struct interface *ifp; - char *name; - - /* Open /proc/net/dev. */ - fp = fopen (_PATH_PROC_NET_DEV, "r"); - if (fp == NULL) - { - zlog_warn ("Can't open proc file %s: %s", - _PATH_PROC_NET_DEV, safe_strerror (errno)); - return -1; - } - - /* Drop header lines. */ - fgets (buf, PROCBUFSIZ, fp); - fgets (buf, PROCBUFSIZ, fp); - - /* Only allocate interface structure. Other jobs will be done in - if_ioctl.c. */ - while (fgets (buf, PROCBUFSIZ, fp) != NULL) - { - interface_name_cut (buf, &name); - ifp = if_get_by_name (name); - if_add_update (ifp); - } - fclose(fp); - return 0; -} - -#if defined(HAVE_IPV6) && defined(HAVE_PROC_NET_IF_INET6) - -#ifndef _PATH_PROC_NET_IF_INET6 -#define _PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6" -#endif /* _PATH_PROC_NET_IF_INET6 */ - -int -ifaddr_proc_ipv6 () -{ - FILE *fp; - char buf[PROCBUFSIZ]; - int n; - char addr[33]; - char ifname[21]; - int ifindex, plen, scope, status; - struct interface *ifp; - struct prefix_ipv6 p; - - /* Open proc file system. */ - fp = fopen (_PATH_PROC_NET_IF_INET6, "r"); - if (fp == NULL) - { - zlog_warn ("Can't open proc file %s: %s", - _PATH_PROC_NET_IF_INET6, safe_strerror (errno)); - return -1; - } - - /* Get interface's IPv6 address. */ - while (fgets (buf, PROCBUFSIZ, fp) != NULL) - { - n = sscanf (buf, "%32s %02x %02x %02x %02x %20s", - addr, &ifindex, &plen, &scope, &status, ifname); - if (n != 6) - continue; - - ifp = if_get_by_name (ifname); - - /* Fetch interface's IPv6 address. */ - str2in6_addr (addr, &p.prefix); - p.prefixlen = plen; - - connected_add_ipv6 (ifp, 0, &p.prefix, p.prefixlen, NULL, ifname); - } - fclose (fp); - return 0; -} -#endif /* HAVE_IPV6 && HAVE_PROC_NET_IF_INET6 */ diff --git a/zebra/interface.h b/zebra/interface.h index 3784253e6d..f58596db2d 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -259,8 +259,4 @@ extern int interface_list_proc (void); extern int ifaddr_proc_ipv6 (void); #endif /* HAVE_PROC_NET_IF_INET6 */ -#ifdef BSDI -extern int if_kvm_get_mtu (struct interface *); -#endif /* BSDI */ - #endif /* _ZEBRA_INTERFACE_H */ diff --git a/zebra/ioctl.c b/zebra/ioctl.c index 24df98557d..f91ee2438d 100644 --- a/zebra/ioctl.c +++ b/zebra/ioctl.c @@ -52,7 +52,7 @@ if_ioctl (u_long request, caddr_t buffer) { int sock; int ret; - int err; + int err = 0; if (zserv_privs.change(ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); @@ -85,7 +85,7 @@ if_ioctl_ipv6 (u_long request, caddr_t buffer) { int sock; int ret; - int err; + int err = 0; if (zserv_privs.change(ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); diff --git a/zebra/ipforward_aix.c b/zebra/ipforward_aix.c deleted file mode 100644 index c79e7f1c74..0000000000 --- a/zebra/ipforward_aix.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ipforward value get function for aix. - * Copyright (C) 1997 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include - -int -ipforward () -{ - int fd, ret; - int af = AF_INET; - char netopt[] = "ipforwarding"; - struct optreq oq; - - fd = socket(af, SOCK_DGRAM, 0); - if (fd < 0) { - /* need logging here */ - return -1; - } - - strcpy (oq.name, netopt); - oq.getnext = 0; - - ret = ioctl (fd, SIOCGNETOPT, (caddr_t)&oq); - close(fd); - - if (ret < 0) { - /* need logging here */ - return -1; - } - - ret = atoi (oq.data); - return ret; -} - -int -ipforward_on () -{ - ; -} - -int -ipforward_off () -{ - ; -} diff --git a/zebra/ipforward_ews.c b/zebra/ipforward_ews.c deleted file mode 100644 index c872000a82..0000000000 --- a/zebra/ipforward_ews.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Ipforward value get function for NEC EWS. - * Copyright (C) 1997 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include - -int -ipforward () -{ - int fd; - char buf[BUFSIZ]; - struct mioc_rksym rks; - - fd = open ("/dev/kmem", O_RDWR); - if (fd < 0) { - /* need logging here */ - return -1; - } - - rks.mirk_symname = "ipforwarding"; - rks.mirk_buf = buf; - rks.mirk_buflen = sizeof (int); - - if (ioctl (fd, MIOC_READKSYM, &rks) < 0) { - /* need logging here */ - return -1; - } - close (fd); - return *(int *)buf; -} - -int -ipforward_on () -{ - ; -} - -int -ipforward_off () -{ - ; -} diff --git a/zebra/ipforward_sysctl.c b/zebra/ipforward_sysctl.c index 185aee3ee0..57ed185785 100644 --- a/zebra/ipforward_sysctl.c +++ b/zebra/ipforward_sysctl.c @@ -23,10 +23,6 @@ #include "privs.h" #include "zebra/ipforward.h" -#ifdef NRL -#include -#endif /* NRL */ - #include "log.h" #define MIB_SIZ 4 @@ -106,7 +102,7 @@ int mib_ipv6[MIB_SIZ] = { CTL_NET, PF_INET6, -#if defined(KAME) || (defined(__bsdi__) && _BSDI_VERSION >= 199802 ) || defined(NRL) +#if defined(KAME) IPPROTO_IPV6, IPV6CTL_FORWARDING #else /* NOT KAME */ diff --git a/zebra/misc_null.c b/zebra/misc_null.c index 4137dc0038..a83c307413 100644 --- a/zebra/misc_null.c +++ b/zebra/misc_null.c @@ -29,6 +29,12 @@ void rtadv_config_write (struct vty *vty, struct interface *ifp) { return; } void irdp_config_write (struct vty *vty, struct interface *ifp) { return; } +#ifdef HAVE_PROC_NET_DEV +void ifstat_update_proc (void) { return; } +#endif +#ifdef HAVE_NET_RT_IFLIST +void ifstat_update_sysctl (void) { return; } +#endif void zfpm_trigger_update (struct route_node *rn, const char *reason) diff --git a/zebra/mtu_kvm.c b/zebra/mtu_kvm.c deleted file mode 100644 index d37bb9bb7e..0000000000 --- a/zebra/mtu_kvm.c +++ /dev/null @@ -1,97 +0,0 @@ -/* MTU get using kvm_read. - * Copyright (C) 1999 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include - -#include -#include -#include - -#include "if.h" - -/* get interface MTU to use kvm_read */ -void -if_kvm_get_mtu (struct interface *ifp) -{ - kvm_t *kvmd; - struct ifnet ifnet; - unsigned long ifnetaddr; - int len; - - char ifname[IFNAMSIZ]; - char tname[INTERFACE_NAMSIZ + 1]; - char buf[_POSIX2_LINE_MAX]; - - struct nlist nl[] = - { - {"_ifnet"}, - {""} - }; - - ifp->mtu6 = ifp->mtu = -1; - - kvmd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, buf); - - if (kvmd == NULL) - return ; - - kvm_nlist(kvmd, nl); - - ifnetaddr = nl[0].n_value; - - if (kvm_read(kvmd, ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr) < 0) - { - kvm_close (kvmd); - return ; - } - - while(ifnetaddr != 0) - { - if (kvm_read (kvmd, ifnetaddr, (char *)&ifnet, sizeof ifnet) < 0) - { - kvm_close (kvmd); - return ; - } - - if (kvm_read (kvmd, (u_long)ifnet.if_name, ifname, IFNAMSIZ) < 0) - { - kvm_close (kvmd); - return ; - } - - len = snprintf (tname, INTERFACE_NAMSIZ + 1, - "%s%d", ifname, ifnet.if_unit); - - if (strncmp (tname, ifp->name, len) == 0) - break; - - ifnetaddr = (u_long)ifnet.if_next; - } - - kvm_close (kvmd); - - if (ifnetaddr == 0) - { - return ; - } - - ifp->mtu6 = ifp->mtu = ifnet.if_mtu; -} diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 4d94ddf622..a383fdde7c 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -263,6 +263,7 @@ redistribute_delete (struct prefix *p, struct rib *rib) struct listnode *node, *nnode; struct zserv *client; char buf[INET6_ADDRSTRLEN]; + int afi; if (IS_ZEBRA_DEBUG_RIB) { @@ -275,47 +276,28 @@ redistribute_delete (struct prefix *p, struct rib *rib) if (rib->distance == DISTANCE_INFINITY) return; + afi = family2afi(p->family); + if (!afi) + { + zlog_warn("%s: Unknown AFI/SAFI prefix received\n", __FUNCTION__); + return; + } + for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) { - if (is_default (p)) + if ((is_default (p) && + vrf_bitmap_check (client->redist_default, rib->vrf_id)) || + (rib->instance && + redist_check_instance(&client->mi_redist[afi][rib->type], + rib->instance)) || + vrf_bitmap_check (client->redist[afi][rib->type], rib->vrf_id)) { - if ((p->family == AF_INET) && - (vrf_bitmap_check (client->redist_default, rib->vrf_id) || - (rib->instance && - redist_check_instance(&client->mi_redist[AFI_IP][rib->type], - rib->instance)) || - vrf_bitmap_check (client->redist[AFI_IP][rib->type], rib->vrf_id))) + if (p->family == AF_INET) zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_DEL, client, p, rib); -#ifdef HAVE_IPV6 - if ((p->family == AF_INET6) && - (vrf_bitmap_check (client->redist_default, rib->vrf_id) || - (rib->instance && - redist_check_instance(&client->mi_redist[AFI_IP6][rib->type], - rib->instance)) || - vrf_bitmap_check (client->redist[AFI_IP6][rib->type], rib->vrf_id))) + if (p->family == AF_INET6) zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p, rib); -#endif /* HAVE_IPV6 */ - } - else - { - if ((p->family == AF_INET) && - ((rib->instance && - redist_check_instance(&client->mi_redist[AFI_IP][rib->type], - rib->instance)) || - vrf_bitmap_check (client->redist[AFI_IP][rib->type], rib->vrf_id))) - zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV4_DEL, client, p, - rib); -#ifdef HAVE_IPV6 - if ((p->family == AF_INET6) && - ((rib->instance && - redist_check_instance(&client->mi_redist[AFI_IP6][rib->type], - rib->instance)) || - vrf_bitmap_check (client->redist[AFI_IP6][rib->type], rib->vrf_id))) - zsend_redistribute_route (ZEBRA_REDISTRIBUTE_IPV6_DEL, client, p, - rib); -#endif /* HAVE_IPV6 */ } } } diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index ee1c696fb6..23e219be97 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -263,13 +263,8 @@ sin6_masklen (struct in6_addr mask) char *p, *lim; int len; -#if defined (INRIA) - if (IN_ANYADDR6 (mask)) - return sizeof (long); -#else /* ! INRIA */ if (IN6_IS_ADDR_UNSPECIFIED (&mask)) return sizeof (long); -#endif /* ! INRIA */ sin6.sin6_addr = mask; len = sizeof (struct sockaddr_in6); @@ -284,67 +279,6 @@ sin6_masklen (struct in6_addr mask) } #endif /* SIN6_LEN */ -/* Interface between zebra message and rtm message. */ -static int -kernel_rtm_ipv6 (int message, struct prefix_ipv6 *dest, - struct in6_addr *gate, int index, int flags) -{ - struct sockaddr_in6 *mask; - struct sockaddr_in6 sin_dest, sin_mask, sin_gate; - - memset (&sin_dest, 0, sizeof (struct sockaddr_in6)); - sin_dest.sin6_family = AF_INET6; -#ifdef SIN6_LEN - sin_dest.sin6_len = sizeof (struct sockaddr_in6); -#endif /* SIN6_LEN */ - - memset (&sin_mask, 0, sizeof (struct sockaddr_in6)); - - memset (&sin_gate, 0, sizeof (struct sockaddr_in6)); - sin_gate.sin6_family = AF_INET6; -#ifdef SIN6_LEN - sin_gate.sin6_len = sizeof (struct sockaddr_in6); -#endif /* SIN6_LEN */ - - sin_dest.sin6_addr = dest->prefix; - - if (gate) - memcpy (&sin_gate.sin6_addr, gate, sizeof (struct in6_addr)); - - /* Under kame set interface index to link local address. */ -#ifdef KAME - -#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ - do { \ - (a).s6_addr[2] = ((i) >> 8) & 0xff; \ - (a).s6_addr[3] = (i) & 0xff; \ - } while (0) - - if (gate && IN6_IS_ADDR_LINKLOCAL(gate)) - SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, index); -#endif /* KAME */ - - if (gate && dest->prefixlen == 128) - mask = NULL; - else - { - masklen2ip6 (dest->prefixlen, &sin_mask.sin6_addr); - sin_mask.sin6_family = AF_INET6; -#ifdef SIN6_LEN - sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr); -#endif /* SIN6_LEN */ - mask = &sin_mask; - } - - return rtm_write (message, - (union sockunion *) &sin_dest, - (union sockunion *) mask, - gate ? (union sockunion *)&sin_gate : NULL, - index, - flags, - 0); -} - /* Interface between zebra message and rtm message. */ static int kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib, diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 3011505dbc..e4c2c6b36d 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -111,5 +111,4 @@ extern void rtadv_cmd_init (void); extern void zebra_interface_radv_set (struct zserv *client, int sock, u_short length, struct zebra_vrf *zvrf, int enable); - #endif /* _ZEBRA_RTADV_H */ diff --git a/zebra/rtread_proc.c b/zebra/rtread_proc.c deleted file mode 100644 index b365d958f9..0000000000 --- a/zebra/rtread_proc.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Kernel routing readup by /proc filesystem - * Copyright (C) 1997 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include - -#include "prefix.h" -#include "log.h" -#include "if.h" -#include "rib.h" - -#include "zebra/zserv.h" -#include "zebra/rt.h" - -/* Proc file system to read IPv4 routing table. */ -#ifndef _PATH_PROCNET_ROUTE -#define _PATH_PROCNET_ROUTE "/proc/net/route" -#endif /* _PATH_PROCNET_ROUTE */ - -/* Proc file system to read IPv6 routing table. */ -#ifndef _PATH_PROCNET_ROUTE6 -#define _PATH_PROCNET_ROUTE6 "/proc/net/ipv6_route" -#endif /* _PATH_PROCNET_ROUTE6 */ - -/* To read interface's name */ -#define INTERFACE_NAMSIZ 20 - -/* Reading buffer for one routing entry. */ -#define RT_BUFSIZ 1024 - -/* Kernel routing table read up by /proc filesystem. */ -static int -proc_route_read (void) -{ - FILE *fp; - char buf[RT_BUFSIZ]; - char iface[INTERFACE_NAMSIZ], dest[9], gate[9], mask[9]; - int flags, refcnt, use, metric, mtu, window, rtt; - - /* Open /proc filesystem */ - fp = fopen (_PATH_PROCNET_ROUTE, "r"); - if (fp == NULL) - { - zlog_warn ("Can't open %s : %s\n", _PATH_PROCNET_ROUTE, safe_strerror (errno)); - return -1; - } - - /* Drop first label line. */ - fgets (buf, RT_BUFSIZ, fp); - - while (fgets (buf, RT_BUFSIZ, fp) != NULL) - { - int n; - struct prefix_ipv4 p; - struct in_addr tmpmask; - struct in_addr gateway; - u_char zebra_flags = 0; - - n = sscanf (buf, "%s %s %s %x %d %d %d %s %d %d %d", - iface, dest, gate, &flags, &refcnt, &use, &metric, - mask, &mtu, &window, &rtt); - if (n != 11) - { - zlog_warn ("can't read all of routing information\n"); - continue; - } - if (! (flags & RTF_UP)) - continue; - if (! (flags & RTF_GATEWAY)) - continue; - - if (flags & RTF_DYNAMIC) - zebra_flags |= ZEBRA_FLAG_SELFROUTE; - - p.family = AF_INET; - sscanf (dest, "%lX", (unsigned long *)&p.prefix); - sscanf (mask, "%lX", (unsigned long *)&tmpmask); - p.prefixlen = ip_masklen (tmpmask); - sscanf (gate, "%lX", (unsigned long *)&gateway); - - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, &gateway, NULL, 0, 0, 0, 0, SAFI_UNICAST); - } - - fclose (fp); - return 0; -} - -#ifdef HAVE_IPV6 -static int -proc_ipv6_route_read () -{ - FILE *fp; - char buf [RT_BUFSIZ]; - - /* Open /proc filesystem */ - fp = fopen (_PATH_PROCNET_ROUTE6, "r"); - if (fp == NULL) - { - zlog_warn ("Can't open %s : %s", _PATH_PROCNET_ROUTE6, - safe_strerror (errno)); - return -1; - } - - /* There is no title line, so we don't drop first line. */ - while (fgets (buf, RT_BUFSIZ, fp) != NULL) - { - int n; - char dest[33], src[33], gate[33]; - char iface[INTERFACE_NAMSIZ]; - int dest_plen, src_plen; - int metric, use, refcnt, flags; - struct prefix_ipv6 p; - struct in6_addr gateway; - u_char zebra_flags = 0; - - /* Linux 2.1.x write this information at net/ipv6/route.c - rt6_info_node () */ - n = sscanf (buf, "%32s %02x %32s %02x %32s %08x %08x %08x %08x %s", - dest, &dest_plen, src, &src_plen, gate, - &metric, &use, &refcnt, &flags, iface); - - if (n != 10) - { - /* zlog_warn ("can't read all of routing information %d\n%s\n", n, buf); */ - continue; - } - - if (! (flags & RTF_UP)) - continue; - if (! (flags & RTF_GATEWAY)) - continue; - - if (flags & RTF_DYNAMIC) - zebra_flags |= ZEBRA_FLAG_SELFROUTE; - - p.family = AF_INET6; - str2in6_addr (dest, &p.prefix); - str2in6_addr (gate, &gateway); - p.prefixlen = dest_plen; - - rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, 0, 0, - metric, 0); - } - - fclose (fp); - return 0; -} -#endif /* HAVE_IPV6 */ - -void -route_read (void) -{ - proc_route_read (); -#ifdef HAVE_IPV6 - proc_ipv6_route_read (); -#endif /* HAVE_IPV6 */ -} diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index f7290caea9..656f5bb752 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -82,7 +82,8 @@ static const struct /* RPF lookup behaviour */ static enum multicast_mode ipv4_multicast_mode = MCAST_NO_CONFIG; -static void + +static void __attribute__((format (printf, 5, 6))) _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn, int priority, const char *msgfmt, ...) { @@ -1678,7 +1679,8 @@ rib_process (struct route_node *rn) if (rib != fib) { if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, vrf_id, "rn %p, removing rib %p", rn, rib); + rnode_debug (rn, vrf_id, "rn %p, removing rib %p", + (void *)rn, (void *)rib); rib_unlink (rn, rib); } else @@ -1813,7 +1815,7 @@ rib_process (struct route_node *rn) { if (IS_ZEBRA_DEBUG_RIB) rnode_debug (rn, vrf_id, "Updating existing route, select %p, fib %p", - select, fib); + (void *)select, (void *)fib); if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) { if (info->safi == SAFI_UNICAST) @@ -1886,7 +1888,7 @@ rib_process (struct route_node *rn) if (fib) { if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, vrf_id, "Removing existing route, fib %p", fib); + rnode_debug (rn, vrf_id, "Removing existing route, fib %p", (void *)fib); if (info->safi == SAFI_UNICAST) zfpm_trigger_update (rn, "removing existing route"); @@ -1919,7 +1921,7 @@ rib_process (struct route_node *rn) if (select) { if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, "Adding route, select %p", select); + rnode_debug (rn, "Adding route, select %p", (void *)select); if (info->safi == SAFI_UNICAST) zfpm_trigger_update (rn, "new route selected"); @@ -1987,7 +1989,7 @@ rib_process (struct route_node *rn) if (del) { if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, vrf_id, "Deleting fib %p, rn %p", del, rn); + rnode_debug (rn, vrf_id, "Deleting fib %p, rn %p", (void *)del, (void *)rn); rib_unlink (rn, del); } @@ -2126,7 +2128,7 @@ rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) rnode_debug (rn, rib->vrf_id, "rn %p is already queued in sub-queue %u", - rn, qindex); + (void *)rn, qindex); continue; } @@ -2137,7 +2139,7 @@ rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn) if (IS_ZEBRA_DEBUG_RIB_DETAILED) rnode_debug (rn, rib->vrf_id, "queued rn %p into sub-queue %u", - rn, qindex); + (void *)rn, qindex); zvrf = zebra_vrf_lookup (rib->vrf_id); if (zvrf) @@ -2155,7 +2157,7 @@ rib_queue_add (struct route_node *rn) if (!rnode_to_ribs (rn)) { zlog_debug ("%s: called for route_node (%p, %d) with no ribs", - __func__, rn, rn->lock); + __func__, (void *)rn, rn->lock); zlog_backtrace(LOG_DEBUG); return; } @@ -2321,7 +2323,7 @@ rib_addnode (struct route_node *rn, struct rib *rib, int process) if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) { if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, rib->vrf_id, "rn %p, un-removed rib %p", rn, rib); + rnode_debug (rn, rib->vrf_id, "rn %p, un-removed rib %p", (void *)rn, (void *)rib); UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED); return; @@ -2346,7 +2348,7 @@ rib_unlink (struct route_node *rn, struct rib *rib) assert (rn && rib); if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, rib->vrf_id, "rn %p, rib %p", rn, rib); + rnode_debug (rn, rib->vrf_id, "rn %p, rib %p", (void *)rn, (void *)rib); dest = rib_dest_from_rnode (rn); @@ -2373,7 +2375,7 @@ rib_delnode (struct route_node *rn, struct rib *rib) afi_t afi; if (IS_ZEBRA_DEBUG_RIB) - rnode_debug (rn, rib->vrf_id, "rn %p, rib %p, removing", rn, rib); + rnode_debug (rn, rib->vrf_id, "rn %p, rib %p, removing", (void *)rn, (void *)rib); SET_FLAG (rib->status, RIB_ENTRY_REMOVED); afi = (rn->p.family == AF_INET) ? AFI_IP : @@ -2502,7 +2504,7 @@ rib_add_ipv4 (int type, u_short instance, int flags, struct prefix_ipv4 *p, inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " "existing %p", - vrf_id, buf, p->prefixlen, rn, rib, rib->type, same); + vrf_id, buf, p->prefixlen, (void *)rn, (void *)rib, rib->type, (void *)same); } if (IS_ZEBRA_DEBUG_RIB_DETAILED) @@ -2531,7 +2533,7 @@ void _rib_dump (const char * func, struct nexthop *nexthop, *tnexthop; int recursing; - zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, rib, + zlog_debug ("%s: dumping RIB entry %p for %s vrf %u", func, (const void *)rib, prefix2str(pp, straddr, sizeof(straddr)), rib->vrf_id); zlog_debug ( @@ -2618,8 +2620,8 @@ void rib_lookup_and_dump (struct prefix_ipv4 * p, vrf_id_t vrf_id) ( "%s: rn %p, rib %p: %s, %s", __func__, - rn, - rib, + (void *)rn, + (void *)rib, (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED) ? "removed" : "NOT removed"), (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) ? "selected" : "NOT selected") ); @@ -2738,7 +2740,8 @@ rib_add_ipv4_multipath (struct prefix_ipv4 *p, struct rib *rib, safi_t safi) inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " "existing %p", - rib->vrf_id, buf, p->prefixlen, rn, rib, rib->type, same); + rib->vrf_id, buf, p->prefixlen, (void *)rn, + (void *)rib, rib->type, (void *)same); } if (IS_ZEBRA_DEBUG_RIB_DETAILED) @@ -3423,7 +3426,8 @@ rib_add_ipv6 (int type, u_short instance, int flags, struct prefix_ipv6 *p, inet_ntop (p->family, &p->prefix, buf, INET6_ADDRSTRLEN); zlog_debug ("%u:%s/%d: Inserting route rn %p, rib %p (type %d) " "existing %p", - vrf_id, buf, p->prefixlen, rn, rib, rib->type, same); + vrf_id, buf, p->prefixlen, (void *)rn, + (void *)rib, rib->type, (void *)same); } if (IS_ZEBRA_DEBUG_RIB_DETAILED) diff --git a/zebra/zserv.c b/zebra/zserv.c index 8bc90130be..0207a3722f 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -108,7 +108,7 @@ zebra_server_send_message(struct zserv *client) return -1; stream_set_getp(client->obuf, 0); - client->last_write_cmd = stream_getw_from(client->obuf, 4); + client->last_write_cmd = stream_getw_from(client->obuf, 6); switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf), stream_get_endp(client->obuf))) { @@ -1161,7 +1161,7 @@ zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf * } void -zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const u_char nexthop_num) +zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const unsigned int nexthop_num) { if (nexthop_num > MULTIPATH_NUM) { diff --git a/zebra/zserv.h b/zebra/zserv.h index 16700ee523..737795ad54 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -168,7 +168,7 @@ extern int zsend_interface_vrf_update (struct zserv *, struct interface *, extern pid_t pid; extern void zserv_create_header(struct stream *s, uint16_t cmd, vrf_id_t vrf_id); -extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const u_char); +extern void zserv_nexthop_num_warn(const char *, const struct prefix *, const unsigned int); extern int zebra_server_send_message(struct zserv *client); #endif /* _ZEBRA_ZEBRA_H */