diff options
67 files changed, 3019 insertions, 1244 deletions
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 487ebddb..e18fc8cd 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -704,7 +704,7 @@ bgp_start (struct peer *peer) peer->fd); return -1; } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); + BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); break; } diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 1a8587e9..83b1142e 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -150,6 +150,7 @@ bgp_accept (struct thread *thread) zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno)); return -1; } + set_nonblocking (bgp_sock); if (BGP_DEBUG (events, EVENTS)) zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf)); @@ -233,46 +234,36 @@ bgp_bind (struct peer *peer) } static int -bgp_bind_address (int sock, struct in_addr *addr) +bgp_update_address (struct interface *ifp, const union sockunion *dst, + union sockunion *addr) { - int ret; - struct sockaddr_in local; - - memset (&local, 0, sizeof (struct sockaddr_in)); - local.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - local.sin_len = sizeof(struct sockaddr_in); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - memcpy (&local.sin_addr, addr, sizeof (struct in_addr)); - - if ( bgpd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("bgp_bind_address: could not raise privs"); - - ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in)); - if (ret < 0) - ; - - if (bgpd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("bgp_bind_address: could not lower privs"); - - return 0; -} - -static struct in_addr * -bgp_update_address (struct interface *ifp) -{ - struct prefix_ipv4 *p; + struct prefix *p, *sel, *d; struct connected *connected; struct listnode *node; + int common; + + d = sockunion2hostprefix (dst); + sel = NULL; + common = -1; for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) { - p = (struct prefix_ipv4 *) connected->address; - - if (p->family == AF_INET) - return &p->prefix; + p = connected->address; + if (p->family != d->family) + continue; + if (prefix_common_bits (p, d) > common) + { + sel = p; + common = prefix_common_bits (sel, d); + } } - return NULL; + + prefix_free (d); + if (!sel) + return 1; + + prefix2sockunion (sel, addr); + return 0; } /* Update source selection. */ @@ -280,7 +271,7 @@ static void bgp_update_source (struct peer *peer) { struct interface *ifp; - struct in_addr *addr; + union sockunion addr; /* Source is specified with interface name. */ if (peer->update_if) @@ -289,11 +280,10 @@ bgp_update_source (struct peer *peer) if (! ifp) return; - addr = bgp_update_address (ifp); - if (! addr) + if (bgp_update_address (ifp, &peer->su, &addr)) return; - bgp_bind_address (peer->fd, addr); + sockunion_bind (peer->fd, &addr, 0, &addr); } /* Source is specified with IP address. */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index b29bc1f0..1e2f95e3 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -107,8 +107,7 @@ bgp_connect_check (struct peer *peer) socklen_t slen; int ret; - /* Anyway I have to reset read and write thread. */ - BGP_READ_OFF (peer->t_read); + /* Anyway I have to reset write thread. */ BGP_WRITE_OFF (peer->t_write); /* Check file descriptor. */ @@ -597,7 +596,6 @@ bgp_write (struct thread *thread) struct stream *s; int num; unsigned int count = 0; - int write_errno; /* Yes first of all get peer pointer. */ peer = THREAD_ARG (thread); @@ -610,46 +608,37 @@ bgp_write (struct thread *thread) return 0; } - /* Nonblocking write until TCP output buffer is full. */ - while (1) + s = bgp_write_packet (peer); + if (!s) + return 0; /* nothing to send */ + + sockopt_cork (peer->fd, 1); + + /* Nonblocking write until TCP output buffer is full. */ + do { int writenum; - int val; - - s = bgp_write_packet (peer); - if (! s) - return 0; - - /* XXX: FIXME, the socket should be NONBLOCK from the start - * status shouldnt need to be toggled on each write - */ - val = fcntl (peer->fd, F_GETFL, 0); - fcntl (peer->fd, F_SETFL, val|O_NONBLOCK); /* Number of bytes to be sent. */ writenum = stream_get_endp (s) - stream_get_getp (s); /* Call write() system call. */ num = write (peer->fd, STREAM_PNT (s), writenum); - write_errno = errno; - fcntl (peer->fd, F_SETFL, val); - if (num <= 0) + if (num < 0) { - /* Partial write. */ - if (write_errno == EWOULDBLOCK || write_errno == EAGAIN) - break; + /* write failed either retry needed or error */ + if (ERRNO_IO_RETRY(errno)) + break; BGP_EVENT_ADD (peer, TCP_fatal_error); return 0; } + if (num != writenum) { + /* Partial write */ stream_forward_getp (s, num); - - if (write_errno == EAGAIN) - break; - - continue; + break; } /* Retrieve BGP packet type. */ @@ -690,13 +679,14 @@ bgp_write (struct thread *thread) /* OK we send packet so delete it. */ bgp_packet_delete (peer); - - if (++count >= BGP_WRITE_PACKET_MAX) - break; } + while (++count < BGP_WRITE_PACKET_MAX && + (s = bgp_write_packet (peer)) != NULL); if (bgp_write_proceed (peer)) BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd); + else + sockopt_cork (peer->fd, 0); return 0; } @@ -705,7 +695,7 @@ bgp_write (struct thread *thread) static int bgp_write_notify (struct peer *peer) { - int ret; + int ret, val; u_char type; struct stream *s; @@ -715,7 +705,10 @@ bgp_write_notify (struct peer *peer) return 0; assert (stream_get_endp (s) >= BGP_HEADER_SIZE); - /* I'm not sure fd is writable. */ + /* Put socket in blocking mode. */ + val = fcntl (peer->fd, F_GETFL, 0); + fcntl (peer->fd, F_SETFL, val & ~O_NONBLOCK); + ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s)); if (ret <= 0) { @@ -2237,12 +2230,13 @@ bgp_read_packet (struct peer *peer) return 0; /* Read packet from fd. */ - nbytes = stream_read_unblock (peer->ibuf, peer->fd, readsize); + nbytes = stream_read_try (peer->ibuf, peer->fd, readsize); /* If read byte is smaller than zero then error occured. */ if (nbytes < 0) { - if (errno == EAGAIN) + /* Transient error should retry */ + if (nbytes == -2) return -1; plog_err (peer->log, "%s [Error] bgp_read_packet error: %s", @@ -2319,22 +2313,14 @@ bgp_read (struct thread *thread) peer = THREAD_ARG (thread); peer->t_read = NULL; - /* For non-blocking IO check. */ - if (peer->status == Connect) - { - bgp_connect_check (peer); - goto done; - } - else + if (peer->fd < 0) { - if (peer->fd < 0) - { - zlog_err ("bgp_read peer's fd is negative value %d", peer->fd); - return -1; - } - BGP_READ_ON (peer->t_read, bgp_read, peer->fd); + zlog_err ("bgp_read peer's fd is negative value %d", peer->fd); + return -1; } + BGP_READ_ON (peer->t_read, bgp_read, peer->fd); + /* Read packet header to determine type of the packet */ if (peer->packet_size == 0) peer->packet_size = BGP_HEADER_SIZE; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index a92ca4e2..8e068fc4 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5613,23 +5613,7 @@ route_vty_out_route (struct prefix *p, struct vty *vty) u_int32_t destination; char buf[BUFSIZ]; - if (p->family == AF_INET) - { - len = vty_out (vty, "%s", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ)); - destination = ntohl (p->u.prefix4.s_addr); - - if ((IN_CLASSC (destination) && p->prefixlen == 24) - || (IN_CLASSB (destination) && p->prefixlen == 16) - || (IN_CLASSA (destination) && p->prefixlen == 8) - || p->u.prefix4.s_addr == 0) - { - /* When mask is natural, mask is not displayed. */ - } - else - len += vty_out (vty, "/%d", p->prefixlen); - } - else - len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), + len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); len = 17 - len; @@ -6663,6 +6647,15 @@ DEFUN (show_ip_bgp_ipv4, return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL); } +ALIAS (show_ip_bgp_ipv4, + show_bgp_ipv4_safi_cmd, + "show bgp ipv4 (unicast|multicast)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n") + DEFUN (show_ip_bgp_route, show_ip_bgp_route_cmd, "show ip bgp A.B.C.D", @@ -6691,6 +6684,16 @@ DEFUN (show_ip_bgp_ipv4_route, return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0); } +ALIAS (show_ip_bgp_ipv4_route, + show_bgp_ipv4_safi_route_cmd, + "show bgp ipv4 (unicast|multicast) A.B.C.D", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Network in the BGP routing table to display\n") + DEFUN (show_ip_bgp_vpnv4_all_route, show_ip_bgp_vpnv4_all_route_cmd, "show ip bgp vpnv4 all A.B.C.D", @@ -6755,6 +6758,16 @@ DEFUN (show_ip_bgp_ipv4_prefix, return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1); } +ALIAS (show_ip_bgp_ipv4_prefix, + show_bgp_ipv4_safi_prefix_cmd, + "show bgp ipv4 (unicast|multicast) A.B.C.D/M", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") + DEFUN (show_ip_bgp_vpnv4_all_prefix, show_ip_bgp_vpnv4_all_prefix_cmd, "show ip bgp vpnv4 all A.B.C.D/M", @@ -6857,6 +6870,22 @@ ALIAS (show_bgp, BGP_STR "Address family\n") +DEFUN (show_bgp_ipv6_safi, + show_bgp_ipv6_safi_cmd, + "show bgp ipv6 (unicast|multicast)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal, + NULL); + + return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL); +} + /* old command */ DEFUN (show_ipv6_bgp, show_ipv6_bgp_cmd, @@ -6887,6 +6916,22 @@ ALIAS (show_bgp_route, "Address family\n" "Network in the BGP routing table to display\n") +DEFUN (show_bgp_ipv6_safi_route, + show_bgp_ipv6_safi_route_cmd, + "show bgp ipv6 (unicast|multicast) X:X::X:X", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Network in the BGP routing table to display\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0); + + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0); +} + /* old command */ DEFUN (show_ipv6_bgp_route, show_ipv6_bgp_route_cmd, @@ -6917,6 +6962,22 @@ ALIAS (show_bgp_prefix, "Address family\n" "IPv6 prefix <network>/<length>\n") +DEFUN (show_bgp_ipv6_safi_prefix, + show_bgp_ipv6_safi_prefix_cmd, + "show bgp ipv6 (unicast|multicast) X:X::X:X/M", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1); + + return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1); +} + /* old command */ DEFUN (show_ipv6_bgp_prefix, show_ipv6_bgp_prefix_cmd, @@ -7621,15 +7682,36 @@ DEFUN (show_ipv6_mbgp_community_all, #endif /* HAVE_IPV6 */ static int -bgp_show_community (struct vty *vty, int argc, const char **argv, int exact, - u_int16_t afi, u_char safi) +bgp_show_community (struct vty *vty, const char *view_name, int argc, + const char **argv, int exact, afi_t afi, safi_t safi) { struct community *com; struct buffer *b; + struct bgp *bgp; int i; char *str; int first = 0; + /* BGP structure lookup */ + if (view_name) + { + bgp = bgp_lookup_by_name (view_name); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + b = buffer_new (1024); for (i = 0; i < argc; i++) { @@ -7657,7 +7739,7 @@ bgp_show_community (struct vty *vty, int argc, const char **argv, int exact, return CMD_WARNING; } - return bgp_show (vty, NULL, afi, safi, + return bgp_show (vty, bgp, afi, safi, (exact ? bgp_show_type_community_exact : bgp_show_type_community), com); } @@ -7674,7 +7756,7 @@ DEFUN (show_ip_bgp_community, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") { - return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST); } ALIAS (show_ip_bgp_community, @@ -7753,9 +7835,9 @@ DEFUN (show_ip_bgp_ipv4_community, "Do not export to next AS (well-known community)\n") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_MULTICAST); + return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_MULTICAST); - return bgp_show_community (vty, argc, argv, 0, AFI_IP, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST); } ALIAS (show_ip_bgp_ipv4_community, @@ -7827,6 +7909,177 @@ ALIAS (show_ip_bgp_ipv4_community, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") +DEFUN (show_bgp_view_afi_safi_community_all, + show_bgp_view_afi_safi_community_all_cmd, +#ifdef HAVE_IPV6 + "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community", +#else + "show bgp view WORD ipv4 (unicast|multicast) community", +#endif + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" +#ifdef HAVE_IPV6 + "Address family\n" +#endif + "Address Family modifier\n" + "Address Family modifier\n" + "Display routes containing communities\n") +{ + int afi; + int safi; + struct bgp *bgp; + + /* BGP structure lookup. */ + bgp = bgp_lookup_by_name (argv[0]); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + +#ifdef HAVE_IPV6 + afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP; + safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; +#else + afi = AFI_IP; + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; +#endif + return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL); +} + +DEFUN (show_bgp_view_afi_safi_community, + show_bgp_view_afi_safi_community_cmd, +#ifdef HAVE_IPV6 + "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)", +#else + "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)", +#endif + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" +#ifdef HAVE_IPV6 + "Address family\n" +#endif + "Address family modifier\n" + "Address family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") +{ + int afi; + int safi; + +#ifdef HAVE_IPV6 + afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP; + safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + return bgp_show_community (vty, argv[0], argc-3, &argv[3], 0, afi, safi); +#else + afi = AFI_IP; + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + return bgp_show_community (vty, argv[0], argc-2, &argv[2], 0, afi, safi); +#endif +} + +ALIAS (show_bgp_view_afi_safi_community, + show_bgp_view_afi_safi_community2_cmd, +#ifdef HAVE_IPV6 + "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)", +#else + "show bgp view WORD 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 view\n" + "BGP view name\n" + "Address family\n" +#ifdef HAVE_IPV6 + "Address family\n" +#endif + "Address family modifier\n" + "Address family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_view_afi_safi_community, + show_bgp_view_afi_safi_community3_cmd, +#ifdef HAVE_IPV6 + "show bgp view WORD (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 view WORD 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 view\n" + "BGP view name\n" + "Address family\n" +#ifdef HAVE_IPV6 + "Address family\n" +#endif + "Address family modifier\n" + "Address family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + +ALIAS (show_bgp_view_afi_safi_community, + show_bgp_view_afi_safi_community4_cmd, +#ifdef HAVE_IPV6 + "show bgp view WORD (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 view WORD 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 view\n" + "BGP view name\n" + "Address family\n" +#ifdef HAVE_IPV6 + "Address family\n" +#endif + "Address family modifier\n" + "Address family modifier\n" + "Display routes matching the communities\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "community number\n" + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n") + DEFUN (show_ip_bgp_community_exact, show_ip_bgp_community_exact_cmd, "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match", @@ -7840,7 +8093,7 @@ DEFUN (show_ip_bgp_community_exact, "Do not export to next AS (well-known community)\n" "Exact match of the communities") { - return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST); } ALIAS (show_ip_bgp_community_exact, @@ -7923,9 +8176,9 @@ DEFUN (show_ip_bgp_ipv4_community_exact, "Exact match of the communities") { if (strncmp (argv[0], "m", 1) == 0) - return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_MULTICAST); + return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_MULTICAST); - return bgp_show_community (vty, argc, argv, 1, AFI_IP, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST); } ALIAS (show_ip_bgp_ipv4_community_exact, @@ -8012,7 +8265,7 @@ DEFUN (show_bgp_community, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") { - return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST); } ALIAS (show_bgp_community, @@ -8157,7 +8410,7 @@ DEFUN (show_ipv6_bgp_community, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") { - return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST); } /* old command */ @@ -8235,7 +8488,7 @@ DEFUN (show_bgp_community_exact, "Do not export to next AS (well-known community)\n" "Exact match of the communities") { - return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST); } ALIAS (show_bgp_community_exact, @@ -8388,7 +8641,7 @@ DEFUN (show_ipv6_bgp_community_exact, "Do not export to next AS (well-known community)\n" "Exact match of the communities") { - return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_UNICAST); + return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST); } /* old command */ @@ -8470,7 +8723,7 @@ DEFUN (show_ipv6_mbgp_community, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n") { - return bgp_show_community (vty, argc, argv, 0, AFI_IP6, SAFI_MULTICAST); + return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_MULTICAST); } /* old command */ @@ -8550,7 +8803,7 @@ DEFUN (show_ipv6_mbgp_community_exact, "Do not export to next AS (well-known community)\n" "Exact match of the communities") { - return bgp_show_community (vty, argc, argv, 1, AFI_IP6, SAFI_MULTICAST); + return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_MULTICAST); } /* old command */ @@ -9959,6 +10212,56 @@ DEFUN (show_ip_bgp_ipv4_neighbor_received_routes, return peer_adj_routes (vty, peer, AFI_IP, SAFI_UNICAST, 1); } +DEFUN (show_bgp_view_afi_safi_neighbor_adv_recd_routes, + show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd, +#ifdef HAVE_IPV6 + "show bgp view WORD (ipv4|ipv6) (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)", +#else + "show bgp view WORD ipv4 (unicast|multicast) neighbors (A.B.C.D|X:X::X:X) (advertised-routes|received-routes)", +#endif + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "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" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Display the advertised routes to neighbor\n" + "Display the received routes from neighbor\n") +{ + int afi; + int safi; + int in; + struct peer *peer; + +#ifdef HAVE_IPV6 + peer = peer_lookup_in_view (vty, argv[0], argv[3]); +#else + peer = peer_lookup_in_view (vty, argv[0], argv[2]); +#endif + + if (! peer) + return CMD_WARNING; + +#ifdef HAVE_IPV6 + afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP; + safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + in = (strncmp (argv[4], "r", 1) == 0) ? 1 : 0; +#else + afi = AFI_IP; + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + in = (strncmp (argv[3], "r", 1) == 0) ? 1 : 0; +#endif + + return peer_adj_routes (vty, peer, afi, safi, in); +} + DEFUN (show_ip_bgp_neighbor_received_prefix_filter, show_ip_bgp_neighbor_received_prefix_filter_cmd, "show ip bgp neighbors (A.B.C.D|X:X::X:X) received prefix-filter", @@ -10366,6 +10669,65 @@ ALIAS (show_ip_bgp_view_rsclient, "Information about Route Server Client\n" NEIGHBOR_ADDR_STR) +DEFUN (show_bgp_view_ipv4_safi_rsclient, + show_bgp_view_ipv4_safi_rsclient_cmd, + "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR) +{ + struct bgp_table *table; + struct peer *peer; + safi_t safi; + + if (argc == 3) { + peer = peer_lookup_in_view (vty, argv[0], argv[2]); + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } else { + peer = peer_lookup_in_view (vty, NULL, argv[1]); + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } + + if (! peer) + return CMD_WARNING; + + if (! peer->afc[AFI_IP][safi]) + { + vty_out (vty, "%% Activate the neighbor for the address family first%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi], + PEER_FLAG_RSERVER_CLIENT)) + { + vty_out (vty, "%% Neighbor is not a Route-Server client%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + table = peer->rib[AFI_IP][safi]; + + return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL); +} + +ALIAS (show_bgp_view_ipv4_safi_rsclient, + show_bgp_ipv4_safi_rsclient_cmd, + "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR) + DEFUN (show_ip_bgp_view_rsclient_route, show_ip_bgp_view_rsclient_route_cmd, "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D", @@ -10439,6 +10801,87 @@ ALIAS (show_ip_bgp_view_rsclient_route, NEIGHBOR_ADDR_STR "Network in the BGP routing table to display\n") +DEFUN (show_bgp_view_ipv4_safi_rsclient_route, + show_bgp_view_ipv4_safi_rsclient_route_cmd, + "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D", + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "Network in the BGP routing table to display\n") +{ + struct bgp *bgp; + struct peer *peer; + safi_t safi; + + /* BGP structure lookup. */ + if (argc == 4) + { + bgp = bgp_lookup_by_name (argv[0]); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + if (argc == 4) { + peer = peer_lookup_in_view (vty, argv[0], argv[2]); + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } else { + peer = peer_lookup_in_view (vty, NULL, argv[1]); + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } + + if (! peer) + return CMD_WARNING; + + if (! peer->afc[AFI_IP][safi]) + { + vty_out (vty, "%% Activate the neighbor for the address family first%s", + VTY_NEWLINE); + return CMD_WARNING; +} + + if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi], + PEER_FLAG_RSERVER_CLIENT)) + { + vty_out (vty, "%% Neighbor is not a Route-Server client%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi], + (argc == 4) ? argv[3] : argv[2], + AFI_IP, safi, NULL, 0); +} + +ALIAS (show_bgp_view_ipv4_safi_rsclient_route, + show_bgp_ipv4_safi_rsclient_route_cmd, + "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "Network in the BGP routing table to display\n") + DEFUN (show_ip_bgp_view_rsclient_prefix, show_ip_bgp_view_rsclient_prefix_cmd, "show ip bgp view WORD rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M", @@ -10512,6 +10955,86 @@ ALIAS (show_ip_bgp_view_rsclient_prefix, NEIGHBOR_ADDR_STR "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") +DEFUN (show_bgp_view_ipv4_safi_rsclient_prefix, + show_bgp_view_ipv4_safi_rsclient_prefix_cmd, + "show bgp view WORD ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M", + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") +{ + struct bgp *bgp; + struct peer *peer; + safi_t safi; + + /* BGP structure lookup. */ + if (argc == 4) + { + bgp = bgp_lookup_by_name (argv[0]); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + if (argc == 4) { + peer = peer_lookup_in_view (vty, argv[0], argv[2]); + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } else { + peer = peer_lookup_in_view (vty, NULL, argv[1]); + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } + + if (! peer) + return CMD_WARNING; + + if (! peer->afc[AFI_IP][safi]) + { + vty_out (vty, "%% Activate the neighbor for the address family first%s", + VTY_NEWLINE); + return CMD_WARNING; +} + + if ( ! CHECK_FLAG (peer->af_flags[AFI_IP][safi], + PEER_FLAG_RSERVER_CLIENT)) +{ + vty_out (vty, "%% Neighbor is not a Route-Server client%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP][safi], + (argc == 4) ? argv[3] : argv[2], + AFI_IP, safi, NULL, 1); +} + +ALIAS (show_bgp_view_ipv4_safi_rsclient_prefix, + show_bgp_ipv4_safi_rsclient_prefix_cmd, + "show bgp ipv4 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) A.B.C.D/M", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n") #ifdef HAVE_IPV6 DEFUN (show_bgp_view_neighbor_routes, @@ -10778,6 +11301,65 @@ ALIAS (show_bgp_view_rsclient, "Information about Route Server Client\n" NEIGHBOR_ADDR_STR) +DEFUN (show_bgp_view_ipv6_safi_rsclient, + show_bgp_view_ipv6_safi_rsclient_cmd, + "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR) +{ + struct bgp_table *table; + struct peer *peer; + safi_t safi; + + if (argc == 3) { + peer = peer_lookup_in_view (vty, argv[0], argv[2]); + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } else { + peer = peer_lookup_in_view (vty, NULL, argv[1]); + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } + + if (! peer) + return CMD_WARNING; + + if (! peer->afc[AFI_IP6][safi]) + { + vty_out (vty, "%% Activate the neighbor for the address family first%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi], + PEER_FLAG_RSERVER_CLIENT)) + { + vty_out (vty, "%% Neighbor is not a Route-Server client%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + table = peer->rib[AFI_IP6][safi]; + + return bgp_show_table (vty, table, &peer->remote_id, bgp_show_type_normal, NULL); +} + +ALIAS (show_bgp_view_ipv6_safi_rsclient, + show_bgp_ipv6_safi_rsclient_cmd, + "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X)", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR) + DEFUN (show_bgp_view_rsclient_route, show_bgp_view_rsclient_route_cmd, "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X", @@ -10849,6 +11431,87 @@ ALIAS (show_bgp_view_rsclient_route, NEIGHBOR_ADDR_STR "Network in the BGP routing table to display\n") +DEFUN (show_bgp_view_ipv6_safi_rsclient_route, + show_bgp_view_ipv6_safi_rsclient_route_cmd, + "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "Network in the BGP routing table to display\n") +{ + struct bgp *bgp; + struct peer *peer; + safi_t safi; + + /* BGP structure lookup. */ + if (argc == 4) + { + bgp = bgp_lookup_by_name (argv[0]); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + if (argc == 4) { + peer = peer_lookup_in_view (vty, argv[0], argv[2]); + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } else { + peer = peer_lookup_in_view (vty, NULL, argv[1]); + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } + + if (! peer) + return CMD_WARNING; + + if (! peer->afc[AFI_IP6][safi]) + { + vty_out (vty, "%% Activate the neighbor for the address family first%s", + VTY_NEWLINE); + return CMD_WARNING; +} + + if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi], + PEER_FLAG_RSERVER_CLIENT)) + { + vty_out (vty, "%% Neighbor is not a Route-Server client%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi], + (argc == 4) ? argv[3] : argv[2], + AFI_IP6, safi, NULL, 0); +} + +ALIAS (show_bgp_view_ipv6_safi_rsclient_route, + show_bgp_ipv6_safi_rsclient_route_cmd, + "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "Network in the BGP routing table to display\n") + DEFUN (show_bgp_view_rsclient_prefix, show_bgp_view_rsclient_prefix_cmd, "show bgp view WORD rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", @@ -10920,6 +11583,87 @@ ALIAS (show_bgp_view_rsclient_prefix, NEIGHBOR_ADDR_STR "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n") +DEFUN (show_bgp_view_ipv6_safi_rsclient_prefix, + show_bgp_view_ipv6_safi_rsclient_prefix_cmd, + "show bgp view WORD ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + SHOW_STR + BGP_STR + "BGP view\n" + "BGP view name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "IP prefix <network>/<length>, e.g., 3ffe::/16\n") +{ + struct bgp *bgp; + struct peer *peer; + safi_t safi; + + /* BGP structure lookup. */ + if (argc == 4) + { + bgp = bgp_lookup_by_name (argv[0]); + if (bgp == NULL) + { + vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + else + { + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + + if (argc == 4) { + peer = peer_lookup_in_view (vty, argv[0], argv[2]); + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } else { + peer = peer_lookup_in_view (vty, NULL, argv[1]); + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + } + + if (! peer) + return CMD_WARNING; + + if (! peer->afc[AFI_IP6][safi]) + { + vty_out (vty, "%% Activate the neighbor for the address family first%s", + VTY_NEWLINE); + return CMD_WARNING; +} + + if ( ! CHECK_FLAG (peer->af_flags[AFI_IP6][safi], + PEER_FLAG_RSERVER_CLIENT)) +{ + vty_out (vty, "%% Neighbor is not a Route-Server client%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show_route_in_table (vty, bgp, peer->rib[AFI_IP6][safi], + (argc == 4) ? argv[3] : argv[2], + AFI_IP6, safi, NULL, 1); +} + +ALIAS (show_bgp_view_ipv6_safi_rsclient_prefix, + show_bgp_ipv6_safi_rsclient_prefix_cmd, + "show bgp ipv6 (unicast|multicast) rsclient (A.B.C.D|X:X::X:X) X:X::X:X/M", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Client\n" + NEIGHBOR_ADDR_STR + "IP prefix <network>/<length>, e.g., 3ffe::/16\n") + #endif /* HAVE_IPV6 */ struct bgp_table *bgp_distance_table; @@ -11521,18 +12265,9 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, destination = ntohl (p->u.prefix4.s_addr); masklen2ip (p->prefixlen, &netmask); - vty_out (vty, " network %s", - inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN)); - - if ((IN_CLASSC (destination) && p->prefixlen == 24) - || (IN_CLASSB (destination) && p->prefixlen == 16) - || (IN_CLASSA (destination) && p->prefixlen == 8) - || p->u.prefix4.s_addr == 0) - { - /* Natural mask is not display. */ - } - else - vty_out (vty, " mask %s", inet_ntoa (netmask)); + vty_out (vty, " network %s mask %s", + inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), + inet_ntoa (netmask)); } else { @@ -11773,12 +12508,15 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_cmd); install_element (VIEW_NODE, &show_ip_bgp_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_cmd); @@ -11804,6 +12542,11 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_ipv4_community2_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_community3_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_community4_cmd); + install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_all_cmd); + install_element (VIEW_NODE, &show_bgp_view_afi_safi_community_cmd); + install_element (VIEW_NODE, &show_bgp_view_afi_safi_community2_cmd); + install_element (VIEW_NODE, &show_bgp_view_afi_safi_community3_cmd); + install_element (VIEW_NODE, &show_bgp_view_afi_safi_community4_cmd); install_element (VIEW_NODE, &show_ip_bgp_community_exact_cmd); install_element (VIEW_NODE, &show_ip_bgp_community2_exact_cmd); install_element (VIEW_NODE, &show_ip_bgp_community3_exact_cmd); @@ -11822,6 +12565,7 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd); + install_element (VIEW_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); @@ -11839,20 +12583,28 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_ip_bgp_neighbor_flap_cmd); install_element (VIEW_NODE, &show_ip_bgp_neighbor_damp_cmd); install_element (VIEW_NODE, &show_ip_bgp_rsclient_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_cmd); install_element (VIEW_NODE, &show_ip_bgp_rsclient_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_rsclient_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_route_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd); install_element (VIEW_NODE, &show_ip_bgp_view_rsclient_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd); /* Restricted node: VIEW_NODE - (set of dangerous commands) */ install_element (RESTRICTED_NODE, &show_ip_bgp_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_route_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_view_route_cmd); @@ -11865,6 +12617,11 @@ bgp_route_init (void) install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community2_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_all_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community2_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community3_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_afi_safi_community4_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_community_exact_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_community2_exact_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_community3_exact_cmd); @@ -11874,18 +12631,25 @@ bgp_route_init (void) install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community3_exact_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_community4_exact_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_route_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_prefix_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_route_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_view_rsclient_prefix_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_cmd); install_element (ENABLE_NODE, &show_ip_bgp_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_cmd); @@ -11911,6 +12675,11 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community2_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community3_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_community4_cmd); + install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_all_cmd); + install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community_cmd); + install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community2_cmd); + install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community3_cmd); + install_element (ENABLE_NODE, &show_bgp_view_afi_safi_community4_cmd); install_element (ENABLE_NODE, &show_ip_bgp_community_exact_cmd); install_element (ENABLE_NODE, &show_ip_bgp_community2_exact_cmd); install_element (ENABLE_NODE, &show_ip_bgp_community3_exact_cmd); @@ -11929,6 +12698,7 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_advertised_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_routes_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_received_routes_cmd); + install_element (ENABLE_NODE, &show_bgp_view_afi_safi_neighbor_adv_recd_routes_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_neighbor_routes_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); @@ -11946,13 +12716,19 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_ip_bgp_neighbor_flap_cmd); install_element (ENABLE_NODE, &show_ip_bgp_neighbor_damp_cmd); install_element (ENABLE_NODE, &show_ip_bgp_rsclient_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_cmd); install_element (ENABLE_NODE, &show_ip_bgp_rsclient_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_rsclient_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_prefix_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_advertised_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_neighbor_received_routes_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_route_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_route_cmd); install_element (ENABLE_NODE, &show_ip_bgp_view_rsclient_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv4_safi_rsclient_prefix_cmd); /* BGP dampening clear commands */ install_element (ENABLE_NODE, &clear_ip_bgp_dampening_cmd); @@ -11991,10 +12767,13 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_cmd); install_element (VIEW_NODE, &show_bgp_route_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_route_cmd); install_element (VIEW_NODE, &show_bgp_prefix_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_prefix_cmd); install_element (VIEW_NODE, &show_bgp_regexp_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_regexp_cmd); install_element (VIEW_NODE, &show_bgp_prefix_list_cmd); @@ -12040,8 +12819,11 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_neighbor_damp_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_neighbor_damp_cmd); install_element (VIEW_NODE, &show_bgp_rsclient_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_cmd); install_element (VIEW_NODE, &show_bgp_rsclient_route_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd); install_element (VIEW_NODE, &show_bgp_rsclient_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd); install_element (VIEW_NODE, &show_bgp_view_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_cmd); install_element (VIEW_NODE, &show_bgp_view_route_cmd); @@ -12061,16 +12843,21 @@ bgp_route_init (void) install_element (VIEW_NODE, &show_bgp_view_neighbor_damp_cmd); install_element (VIEW_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd); install_element (VIEW_NODE, &show_bgp_view_rsclient_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd); install_element (VIEW_NODE, &show_bgp_view_rsclient_route_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd); install_element (VIEW_NODE, &show_bgp_view_rsclient_prefix_cmd); + install_element (VIEW_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd); /* Restricted: * VIEW_NODE - (set of dangerous commands) - (commands dependent on prev) */ install_element (RESTRICTED_NODE, &show_bgp_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_ipv6_route_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_prefix_cmd); install_element (RESTRICTED_NODE, &show_bgp_ipv6_prefix_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_prefix_cmd); install_element (RESTRICTED_NODE, &show_bgp_community_cmd); install_element (RESTRICTED_NODE, &show_bgp_ipv6_community_cmd); install_element (RESTRICTED_NODE, &show_bgp_community2_cmd); @@ -12088,7 +12875,9 @@ bgp_route_init (void) install_element (RESTRICTED_NODE, &show_bgp_community4_exact_cmd); install_element (RESTRICTED_NODE, &show_bgp_ipv6_community4_exact_cmd); install_element (RESTRICTED_NODE, &show_bgp_rsclient_route_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_rsclient_prefix_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd); install_element (RESTRICTED_NODE, &show_bgp_view_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_view_prefix_cmd); @@ -12096,14 +12885,19 @@ bgp_route_init (void) install_element (RESTRICTED_NODE, &show_bgp_view_neighbor_received_prefix_filter_cmd); install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_neighbor_received_prefix_filter_cmd); install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_route_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd); install_element (RESTRICTED_NODE, &show_bgp_view_rsclient_prefix_cmd); + install_element (RESTRICTED_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd); install_element (ENABLE_NODE, &show_bgp_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_cmd); install_element (ENABLE_NODE, &show_bgp_route_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_route_cmd); install_element (ENABLE_NODE, &show_bgp_prefix_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_prefix_cmd); install_element (ENABLE_NODE, &show_bgp_regexp_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_regexp_cmd); install_element (ENABLE_NODE, &show_bgp_prefix_list_cmd); @@ -12149,8 +12943,11 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_neighbor_damp_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_neighbor_damp_cmd); install_element (ENABLE_NODE, &show_bgp_rsclient_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_cmd); install_element (ENABLE_NODE, &show_bgp_rsclient_route_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_route_cmd); install_element (ENABLE_NODE, &show_bgp_rsclient_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_prefix_cmd); install_element (ENABLE_NODE, &show_bgp_view_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_cmd); install_element (ENABLE_NODE, &show_bgp_view_route_cmd); @@ -12170,8 +12967,11 @@ bgp_route_init (void) install_element (ENABLE_NODE, &show_bgp_view_neighbor_damp_cmd); install_element (ENABLE_NODE, &show_bgp_view_ipv6_neighbor_damp_cmd); install_element (ENABLE_NODE, &show_bgp_view_rsclient_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_cmd); install_element (ENABLE_NODE, &show_bgp_view_rsclient_route_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_route_cmd); install_element (ENABLE_NODE, &show_bgp_view_rsclient_prefix_cmd); + install_element (ENABLE_NODE, &show_bgp_view_ipv6_safi_rsclient_prefix_cmd); /* Statistics */ install_element (ENABLE_NODE, &show_bgp_statistics_cmd); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index c442baab..959f45c6 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6864,6 +6864,16 @@ DEFUN (show_ip_bgp_ipv4_summary, return bgp_show_summary_vty (vty, NULL, AFI_IP, SAFI_UNICAST); } +ALIAS (show_ip_bgp_ipv4_summary, + show_bgp_ipv4_safi_summary_cmd, + "show bgp ipv4 (unicast|multicast) summary", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Summary of BGP neighbor status\n") + DEFUN (show_ip_bgp_instance_ipv4_summary, show_ip_bgp_instance_ipv4_summary_cmd, "show ip bgp view WORD ipv4 (unicast|multicast) summary", @@ -6883,6 +6893,18 @@ DEFUN (show_ip_bgp_instance_ipv4_summary, return bgp_show_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST); } +ALIAS (show_ip_bgp_instance_ipv4_summary, + show_bgp_instance_ipv4_safi_summary_cmd, + "show bgp view WORD ipv4 (unicast|multicast) summary", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Summary of BGP neighbor status\n") + DEFUN (show_ip_bgp_vpnv4_all_summary, show_ip_bgp_vpnv4_all_summary_cmd, "show ip bgp vpnv4 all summary", @@ -6961,6 +6983,40 @@ ALIAS (show_bgp_instance_summary, "Address family\n" "Summary of BGP neighbor status\n") +DEFUN (show_bgp_ipv6_safi_summary, + show_bgp_ipv6_safi_summary_cmd, + "show bgp ipv6 (unicast|multicast) summary", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Summary of BGP neighbor status\n") +{ + if (strncmp (argv[0], "m", 1) == 0) + return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_MULTICAST); + + return bgp_show_summary_vty (vty, NULL, AFI_IP6, SAFI_UNICAST); +} + +DEFUN (show_bgp_instance_ipv6_safi_summary, + show_bgp_instance_ipv6_safi_summary_cmd, + "show bgp view WORD ipv6 (unicast|multicast) summary", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Summary of BGP neighbor status\n") +{ + if (strncmp (argv[1], "m", 1) == 0) + return bgp_show_summary_vty (vty, argv[0], AFI_IP6, SAFI_MULTICAST); + + return bgp_show_summary_vty (vty, argv[0], AFI_IP6, SAFI_UNICAST); +} + /* old command */ DEFUN (show_ipv6_bgp_summary, show_ipv6_bgp_summary_cmd, @@ -8162,6 +8218,41 @@ DEFUN (show_ip_bgp_instance_ipv4_rsclient_summary, return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, SAFI_UNICAST); } +DEFUN (show_bgp_instance_ipv4_safi_rsclient_summary, + show_bgp_instance_ipv4_safi_rsclient_summary_cmd, + "show bgp view WORD ipv4 (unicast|multicast) rsclient summary", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Clients\n" + "Summary of all Route Server Clients\n") +{ + safi_t safi; + + if (argc == 2) { + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP, safi); + } else { + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP, safi); + } +} + +ALIAS (show_bgp_instance_ipv4_safi_rsclient_summary, + show_bgp_ipv4_safi_rsclient_summary_cmd, + "show bgp ipv4 (unicast|multicast) rsclient summary", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Clients\n" + "Summary of all Route Server Clients\n") + #ifdef HAVE_IPV6 DEFUN (show_bgp_rsclient_summary, show_bgp_rsclient_summary_cmd, @@ -8206,6 +8297,42 @@ ALIAS (show_bgp_instance_rsclient_summary, "Address family\n" "Information about Route Server Clients\n" "Summary of all Route Server Clients\n") + +DEFUN (show_bgp_instance_ipv6_safi_rsclient_summary, + show_bgp_instance_ipv6_safi_rsclient_summary_cmd, + "show bgp view WORD ipv6 (unicast|multicast) rsclient summary", + SHOW_STR + BGP_STR + "BGP view\n" + "View name\n" + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Clients\n" + "Summary of all Route Server Clients\n") +{ + safi_t safi; + + if (argc == 2) { + safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + return bgp_show_rsclient_summary_vty (vty, argv[0], AFI_IP6, safi); + } else { + safi = (strncmp (argv[0], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST; + return bgp_show_rsclient_summary_vty (vty, NULL, AFI_IP6, safi); + } +} + +ALIAS (show_bgp_instance_ipv6_safi_rsclient_summary, + show_bgp_ipv6_safi_rsclient_summary_cmd, + "show bgp ipv6 (unicast|multicast) rsclient summary", + SHOW_STR + BGP_STR + "Address family\n" + "Address Family modifier\n" + "Address Family modifier\n" + "Information about Route Server Clients\n" + "Summary of all Route Server Clients\n") + #endif /* HAVE IPV6 */ /* Redistribute VTY commands. */ @@ -9635,38 +9762,50 @@ bgp_vty_init (void) install_element (VIEW_NODE, &show_ip_bgp_summary_cmd); install_element (VIEW_NODE, &show_ip_bgp_instance_summary_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_summary_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_summary_cmd); install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_summary_cmd); + install_element (VIEW_NODE, &show_bgp_instance_ipv4_safi_summary_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_all_summary_cmd); install_element (VIEW_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd); #ifdef HAVE_IPV6 install_element (VIEW_NODE, &show_bgp_summary_cmd); install_element (VIEW_NODE, &show_bgp_instance_summary_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_summary_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_summary_cmd); install_element (VIEW_NODE, &show_bgp_instance_ipv6_summary_cmd); + install_element (VIEW_NODE, &show_bgp_instance_ipv6_safi_summary_cmd); #endif /* HAVE_IPV6 */ install_element (RESTRICTED_NODE, &show_ip_bgp_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_instance_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_instance_ipv4_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_instance_ipv4_safi_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_all_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd); #ifdef HAVE_IPV6 install_element (RESTRICTED_NODE, &show_bgp_summary_cmd); install_element (RESTRICTED_NODE, &show_bgp_instance_summary_cmd); install_element (RESTRICTED_NODE, &show_bgp_ipv6_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_summary_cmd); install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_safi_summary_cmd); #endif /* HAVE_IPV6 */ install_element (ENABLE_NODE, &show_ip_bgp_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_instance_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_instance_ipv4_safi_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_all_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_vpnv4_rd_summary_cmd); #ifdef HAVE_IPV6 install_element (ENABLE_NODE, &show_bgp_summary_cmd); install_element (ENABLE_NODE, &show_bgp_instance_summary_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_summary_cmd); install_element (ENABLE_NODE, &show_bgp_instance_ipv6_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_instance_ipv6_safi_summary_cmd); #endif /* HAVE_IPV6 */ /* "show ip bgp neighbors" commands. */ @@ -9730,28 +9869,40 @@ bgp_vty_init (void) install_element (VIEW_NODE, &show_ip_bgp_instance_rsclient_summary_cmd); install_element (VIEW_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd); install_element (VIEW_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd); + install_element (VIEW_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd); + install_element (VIEW_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_instance_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_instance_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_ipv4_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_ip_bgp_instance_ipv4_rsclient_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_instance_ipv4_safi_rsclient_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv4_safi_rsclient_summary_cmd); #ifdef HAVE_IPV6 install_element (VIEW_NODE, &show_bgp_rsclient_summary_cmd); install_element (VIEW_NODE, &show_bgp_ipv6_rsclient_summary_cmd); install_element (VIEW_NODE, &show_bgp_instance_rsclient_summary_cmd); install_element (VIEW_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd); + install_element (VIEW_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd); + install_element (VIEW_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_bgp_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_bgp_ipv6_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_bgp_instance_rsclient_summary_cmd); install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd); + install_element (RESTRICTED_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_bgp_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_bgp_ipv6_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_bgp_instance_rsclient_summary_cmd); install_element (ENABLE_NODE, &show_bgp_instance_ipv6_rsclient_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_instance_ipv6_safi_rsclient_summary_cmd); + install_element (ENABLE_NODE, &show_bgp_ipv6_safi_rsclient_summary_cmd); #endif /* HAVE_IPV6 */ /* "show ip bgp paths" commands. */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 882fe37c..a03025f6 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -2257,6 +2257,9 @@ peer_change_action (struct peer *peer, afi_t afi, safi_t safi, if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) return; + if (peer->status != Established) + return; + if (type == peer_change_reset) bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); diff --git a/configure.ac b/configure.ac index ace5d29c..de6b8e82 100755 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ ## $Id$ AC_PREREQ(2.53) -AC_INIT(Quagga, 0.99.15, [http://bugzilla.quagga.net]) +AC_INIT(Quagga, [1.1.0-dn42.11], [http://bugzilla.quagga.net]) AC_CONFIG_SRCDIR(lib/zebra.h) AC_CONFIG_MACRO_DIR([m4]) @@ -782,15 +782,18 @@ AC_SUBST(OTHER_METHOD) dnl -------------------------- dnl Determine IS-IS I/O method dnl -------------------------- +AC_DEFINE(ISIS_METHOD_PFPACKET, 1, [ constant value for isis method pfpacket ]) +AC_DEFINE(ISIS_METHOD_DLPI, 2, [ constant value for isis method dlpi ]) +AC_DEFINE(ISIS_METHOD_BPF, 3, [ constant value for isis method bpf ]) AC_CHECK_HEADER(net/bpf.h) AC_CHECK_HEADER(sys/dlpi.h) AC_MSG_CHECKING(zebra IS-IS I/O method) if test x"$opsys" = x"gnu-linux"; then AC_MSG_RESULT(pfpacket) - ISIS_METHOD=isis_pfpacket.o + ISIS_METHOD_MACRO="ISIS_METHOD_PFPACKET" elif test x"$opsys" = x"sol2-6" -o x"$opsys" = x"sol8"; then AC_MSG_RESULT(DLPI) - ISIS_METHOD="isis_dlpi.o" + ISIS_METHOD_MACRO="ISIS_METHOD_DLPI" else if test $ac_cv_header_net_bpf_h = no; then if test $ac_cv_header_sys_dlpi_h = no; then @@ -800,13 +803,13 @@ else else AC_MSG_RESULT(DLPI) fi - ISIS_METHOD="isis_dlpi.o" + ISIS_METHOD_MACRO="ISIS_METHOD_DLPI" else AC_MSG_RESULT(BPF) - ISIS_METHOD="isis_bpf.o" + ISIS_METHOD_MACRO="ISIS_METHOD_BPF" fi fi -AC_SUBST(ISIS_METHOD) +AC_DEFINE_UNQUOTED(ISIS_METHOD, $ISIS_METHOD_MACRO, [ selected method for isis, == one of the constants ]) dnl ------------------------------------ dnl check for broken CMSG_FIRSTHDR macro diff --git a/doc/ipv6.texi b/doc/ipv6.texi index a78a92fe..519b7798 100644 --- a/doc/ipv6.texi +++ b/doc/ipv6.texi @@ -157,15 +157,25 @@ Set default router preference in IPv6 router advertisements per RFC4191. Default: medium @end deffn +@deffn {Interface Command} {ipv6 nd rdnss ipv6prefix [lifetime]} {} Include +RDNSS options to advertise recursive DNS server addresses. Additionally a +maximum lifetime (in seconds) can be specified to limit the lifetime of this +option. The valid range is between @code{<0-4294967295>} where 0 means that the +RDNSS address must no longer be used. The default lifetime - without explicitly +specify a lifetime - is unlimited. +@end deffn + @example @group interface eth0 no ipv6 nd suppress-ra ipv6 nd prefix 2001:0DB8:5009::/64 + ipv6 nd rdnss 2001:0DB8:5009::1 @end group @end example For more information see @cite{RFC2462 (IPv6 Stateless Address Autoconfiguration)} , @cite{RFC2461 (Neighbor Discovery for IP Version 6 (IPv6))} , @cite{RFC3775 (Mobility Support in IPv6 (Mobile IPv6))} +, @cite{RFC5006 (IPv6 Router Advertisement Option for DNS Configuration)} and @cite{RFC4191 (Default Router Preferences and More-Specific Routes)}. diff --git a/isisd/Makefile.am b/isisd/Makefile.am index a7117fd6..8a682a49 100644 --- a/isisd/Makefile.am +++ b/isisd/Makefile.am @@ -12,8 +12,6 @@ noinst_LIBRARIES = libisis.a sbin_PROGRAMS = isisd SUBDIRS = topology -isis_method = @ISIS_METHOD@ - libisis_a_SOURCES = \ isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \ isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \ @@ -29,13 +27,10 @@ noinst_HEADERS = \ include-netbsd/clnp.h include-netbsd/esis.h include-netbsd/iso.h isisd_SOURCES = \ - isis_main.c $(libisis_a_SOURCES) - -isisd_LDADD = $(isis_method) @ISIS_TOPOLOGY_LIB@ ../lib/libzebra.la @LIBCAP@ - -isisd_DEPENDENCIES = $(isis_method) + isis_main.c $(libisis_a_SOURCES) \ + isis_bpf.c isis_dlpi.c isis_pfpacket.c -EXTRA_DIST = isis_bpf.c isis_dlpi.c isis_pfpacket.c +isisd_LDADD = @ISIS_TOPOLOGY_LIB@ ../lib/libzebra.la @LIBCAP@ examplesdir = $(exampledir) dist_examples_DATA = isisd.conf.sample diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index aab8d1a3..de34bea9 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -172,7 +172,7 @@ isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state, circuit->upadjcount[level - 1]++; if (state == ISIS_ADJ_DOWN) { - isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]); + listnode_delete (adj->circuit->u.bc.adjdb[level - 1], adj); circuit->upadjcount[level - 1]--; } diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index 8c3602db..05f11386 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -21,6 +21,7 @@ */ #include <zebra.h> +#if ISIS_METHOD == ISIS_METHOD_BPF #include <net/if.h> #include <netinet/if_ether.h> #include <sys/time.h> @@ -339,3 +340,5 @@ isis_send_pdu_p2p (struct isis_circuit *circuit, int level) { return ISIS_OK; } + +#endif /* ISIS_METHOD == ISIS_METHOD_BPF */ diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index d2923b57..99e2bf6f 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -142,6 +142,11 @@ isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area) { + /* destroy adjacencies */ + if (circuit->u.bc.adjdb[0]) + isis_adjdb_iterate (circuit->u.bc.adjdb[0], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[0]); + if (circuit->u.bc.adjdb[1]) + isis_adjdb_iterate (circuit->u.bc.adjdb[1], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[1]); /* Remove circuit from area */ listnode_delete (area->circuit_list, circuit); /* Free the index of SRM and SSN flags */ @@ -602,6 +607,13 @@ isis_circuit_down (struct isis_circuit *circuit) { THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello); } + + if (circuit->t_send_psnp[0]) { + THREAD_TIMER_OFF (circuit->t_send_psnp[0]); + } + if (circuit->t_send_psnp[1]) { + THREAD_TIMER_OFF (circuit->t_send_psnp[1]); + } /* close the socket */ close (circuit->fd); @@ -818,6 +830,21 @@ isis_interface_config_write (struct vty *vty) } } } + if (c->passwd.type==ISIS_PASSWD_TYPE_HMAC_MD5) + { + vty_out (vty, " isis password md5 %s%s", c->passwd.passwd, + VTY_NEWLINE); + write++; + } + else + { + if (c->passwd.type==ISIS_PASSWD_TYPE_CLEARTXT) + { + vty_out (vty, " isis password clear %s%s", c->passwd.passwd, + VTY_NEWLINE); + write++; + } + } } } @@ -1010,11 +1037,44 @@ DEFUN (no_isis_circuit_type, return CMD_SUCCESS; } -DEFUN (isis_passwd, - isis_passwd_cmd, - "isis password WORD", +DEFUN (isis_passwd_md5, + isis_passwd_md5_cmd, + "isis password md5 WORD", + "IS-IS commands\n" + "Configure the authentication password for interface\n" + "Authentication Type\n" + "Password\n") +{ + struct isis_circuit *circuit; + struct interface *ifp; + int len; + + ifp = vty->index; + circuit = ifp->info; + if (circuit == NULL) + { + return CMD_WARNING; + } + + len = strlen (argv[0]); + if (len > 254) + { + vty_out (vty, "Too long circuit password (>254)%s", VTY_NEWLINE); + return CMD_WARNING; + } + circuit->passwd.len = len; + circuit->passwd.type = ISIS_PASSWD_TYPE_HMAC_MD5; + strncpy ((char *)circuit->passwd.passwd, argv[0], 255); + + return CMD_SUCCESS; +} + +DEFUN (isis_passwd_clear, + isis_passwd_clear_cmd, + "isis password clear WORD", "IS-IS commands\n" "Configure the authentication password for interface\n" + "Authentication Type\n" "Password\n") { struct isis_circuit *circuit; @@ -1063,7 +1123,6 @@ DEFUN (no_isis_passwd, return CMD_SUCCESS; } - DEFUN (isis_priority, isis_priority_cmd, "isis priority <0-127>", @@ -2074,7 +2133,8 @@ isis_circuit_init () install_element (INTERFACE_NODE, &isis_circuit_type_cmd); install_element (INTERFACE_NODE, &no_isis_circuit_type_cmd); - install_element (INTERFACE_NODE, &isis_passwd_cmd); + install_element (INTERFACE_NODE, &isis_passwd_clear_cmd); + install_element (INTERFACE_NODE, &isis_passwd_md5_cmd); install_element (INTERFACE_NODE, &no_isis_passwd_cmd); install_element (INTERFACE_NODE, &isis_priority_cmd); diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index a7e719f6..f32d1dda 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -65,6 +65,7 @@ struct isis_p2p_info struct isis_circuit { int state; + int connected; u_char circuit_id; /* l1/l2 p2p/bcast CircuitID */ struct isis_area *area; /* back pointer to the area */ struct interface *interface; /* interface info from z */ diff --git a/isisd/isis_common.h b/isisd/isis_common.h index 26338556..334d3394 100644 --- a/isisd/isis_common.h +++ b/isisd/isis_common.h @@ -35,6 +35,7 @@ struct isis_passwd u_char len; #define ISIS_PASSWD_TYPE_UNUSED 0 #define ISIS_PASSWD_TYPE_CLEARTXT 1 +#define ISIS_PASSWD_TYPE_HMAC_MD5 54 #define ISIS_PASSWD_TYPE_PRIVATE 255 u_char type; /* Authenticate SNPs? */ diff --git a/isisd/isis_csm.c b/isisd/isis_csm.c index 80d0c906..6cdde46a 100644 --- a/isisd/isis_csm.c +++ b/isisd/isis_csm.c @@ -112,6 +112,7 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) isis_circuit_configure (circuit, (struct isis_area *) arg); isis_circuit_up (circuit); circuit->state = C_STATE_UP; + circuit->connected = 1; isis_event_circuit_state_change (circuit, 1); listnode_delete (isis->init_circ_list, circuit); break; @@ -136,9 +137,12 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) zlog_warn ("circuit already enabled"); break; case IF_UP_FROM_Z: - isis_circuit_if_add (circuit, (struct interface *) arg); - isis_circuit_up (circuit); + if (!circuit->connected) { + isis_circuit_if_add (circuit, (struct interface *) arg); + isis_circuit_up (circuit); + } circuit->state = C_STATE_UP; + circuit->connected = 1; isis_event_circuit_state_change (circuit, 1); break; case ISIS_DISABLE: @@ -167,7 +171,6 @@ isis_csm_state_change (int event, struct isis_circuit *circuit, void *arg) isis_event_circuit_state_change (circuit, 0); break; case IF_DOWN_FROM_Z: - isis_circuit_if_del (circuit); circuit->state = C_STATE_CONF; isis_event_circuit_state_change (circuit, 0); break; diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c index 3cbe0b4f..fe872a95 100644 --- a/isisd/isis_dlpi.c +++ b/isisd/isis_dlpi.c @@ -21,6 +21,7 @@ */ #include <zebra.h> +#if ISIS_METHOD == ISIS_METHOD_DLPI #include <net/if.h> #include <netinet/if_ether.h> #include <sys/types.h> @@ -622,3 +623,5 @@ isis_send_pdu_bcast (struct isis_circuit *circuit, int level) sock_buff, stream_get_endp (circuit->snd_stream) + LLC_LEN, 0); return ISIS_OK; } + +#endif /* ISIS_METHOD == ISIS_METHOD_DLPI */ diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 50289db3..fd40bb37 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -353,10 +353,25 @@ isis_lsp_authinfo_check (struct stream *stream, struct isis_area *area, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN, pdulen - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, &expected, &found, &tlvs); + if (retval || !(found & TLVFLAG_AUTH_INFO)) return 1; /* Auth fail (parsing failed or no auth-tlv) */ - return authentication_check (passwd, &tlvs.auth_info); + switch (tlvs.auth_info.type) + { + case ISIS_PASSWD_TYPE_HMAC_MD5: + zlog_debug("Got LSP with ISIS_PASSWD_TYPE_HMAC_MD5"); + break; + case ISIS_PASSWD_TYPE_CLEARTXT: + zlog_debug("Got LSP with ISIS_PASSWD_TYPE_CLEARTXT"); + break; + default: + zlog_debug("Unknown authentication type in LSP"); + break; + } + + return 0; + /* return authentication_check (passwd, &tlvs.auth_info);*/ } static void @@ -1640,7 +1655,7 @@ lsp_regenerate_schedule (struct isis_area *area) if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[0] = 1; - thread_add_timer (master, lsp_l1_regenerate, area, + area->t_lsp_l1_regenerate=thread_add_timer (master, lsp_l1_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); goto L2; } @@ -1663,7 +1678,7 @@ L2: if (diff < MIN_LSP_GEN_INTERVAL) { area->lsp_regenerate_pending[1] = 1; - thread_add_timer (master, lsp_l2_regenerate, area, + area->t_lsp_l2_regenerate=thread_add_timer (master, lsp_l2_regenerate, area, MIN_LSP_GEN_INTERVAL - diff); return ISIS_OK; } @@ -2037,6 +2052,8 @@ lsp_tick (struct thread *thread) { for (ALL_LIST_ELEMENTS_RO (area->circuit_list, cnode, circuit)) { + if (circuit->state != C_STATE_UP) + continue; for (ALL_LIST_ELEMENTS_RO (lsp_list, lspnode, lsp)) { if (ISIS_CHECK_FLAG (lsp->SRMflags, circuit)) diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index adbde78e..8d648d05 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -58,7 +58,6 @@ struct isis_lsp #endif /* used for 60 second counting when rem_lifetime is zero */ int age_out; - struct isis_adjacency *adj; /* FIXME: For now only topology LSP's use this. Is it helpful for others? */ struct isis_area *area; struct tlvs tlv_data; /* Simplifies TLV access */ diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index a2ab0649..d67df31b 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -29,10 +29,11 @@ #include "log.h" #include "stream.h" #include "vty.h" -#include "hash.c" +#include "hash.h" #include "prefix.h" #include "if.h" #include "checksum.h" +#include "md5.h" #include "isisd/dict.h" #include "isisd/include-netbsd/iso.h" @@ -168,26 +169,38 @@ accept_level (int level, int circuit_t) return retval; } + +/* + * Verify authentication information + * Support cleartext and HMAC MD5 authentication + */ int -authentication_check (struct isis_passwd *one, struct isis_passwd *theother) +authentication_check (struct isis_passwd *remote, struct isis_passwd *local, struct isis_circuit* c) { - if (one->type != theother->type) + unsigned char digest[ISIS_AUTH_MD5_SIZE]; + + if (c->passwd.type) { - zlog_warn ("Unsupported authentication type %d", theother->type); - return 1; /* Auth fail (different authentication types) */ - } - switch (one->type) + switch (c->passwd.type) { + case ISIS_PASSWD_TYPE_HMAC_MD5: + /* HMAC MD5 (RFC 3567) */ + /* MD5 computation according to RFC 2104 */ + hmac_md5(c->rcv_stream->data, stream_get_endp(c->rcv_stream), (unsigned char *) &(local->passwd), c->passwd.len, (unsigned char *) &digest); + return memcmp (digest, remote->passwd, ISIS_AUTH_MD5_SIZE); + break; case ISIS_PASSWD_TYPE_CLEARTXT: - if (one->len != theother->len) + /* Cleartext (ISO 10589) */ + if (local->len != remote->len) return 1; /* Auth fail () - passwd len mismatch */ - return memcmp (one->passwd, theother->passwd, one->len); + return memcmp (local->passwd, remote->passwd, local->len); break; default: zlog_warn ("Unsupported authentication type"); break; } - return 0; /* Auth pass */ + } + return 0; /* Authentication pass when no authentication is configured */ } /* @@ -372,7 +385,7 @@ process_p2p_hello (struct isis_circuit *circuit) if (circuit->passwd.type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&circuit->passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, &circuit->passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "P2P hello authentication failure", @@ -744,10 +757,11 @@ process_lan_hello (int level, struct isis_circuit *circuit, u_char * ssnpa) goto out; } + /* Verify authentication, either cleartext of HMAC MD5 */ if (circuit->passwd.type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (&circuit->passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, &circuit->passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "LAN hello authentication failure", @@ -1187,6 +1201,7 @@ dontcheckadj: /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */ if ((!lsp || comp == LSP_NEWER)) { + int regenerate = (lsp == NULL); /* i */ if (lsp) { @@ -1221,7 +1236,6 @@ dontcheckadj: ntohs (hdr->pdu_len), lsp0, circuit->area); lsp->level = level; - lsp->adj = adj; lsp_insert (lsp, circuit->area->lspdb[level - 1]); /* ii */ ISIS_FLAGS_SET_ALL (lsp->SRMflags); @@ -1232,6 +1246,9 @@ dontcheckadj: if (circuit->circ_type != CIRCUIT_T_BROADCAST) ISIS_SET_FLAG (lsp->SSNflags, circuit); /* FIXME: v) */ + if (regenerate && circuit->u.bc.is_dr[level - 1]) { + lsp_l1_pseudo_generate (circuit); + } } /* 7.3.15.1 e) 2) LSP equal to the one in db */ else if (comp == LSP_EQUAL) @@ -1250,8 +1267,7 @@ dontcheckadj: ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); } } - if (lsp) - lsp->adj = adj; + return retval; } @@ -1414,7 +1430,7 @@ process_snp (int snp_type, int level, struct isis_circuit *circuit, if (passwd->type) { if (!(found & TLVFLAG_AUTH_INFO) || - authentication_check (passwd, &tlvs.auth_info)) + authentication_check (&tlvs.auth_info, passwd, circuit)) { isis_event_auth_failure (circuit->area->area_tag, "SNP authentication" " failure", @@ -1781,6 +1797,9 @@ isis_receive (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); + if (!circuit->area) + return ISIS_OK; + if (circuit->rcv_stream == NULL) circuit->rcv_stream = stream_new (ISO_MTU (circuit)); else @@ -1908,11 +1927,15 @@ send_hello (struct isis_circuit *circuit, int level) struct isis_fixed_hdr fixed_hdr; struct isis_lan_hello_hdr hello_hdr; struct isis_p2p_hello_hdr p2p_hello_hdr; + char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; u_int32_t interval; - unsigned long len_pointer, length; + unsigned long len_pointer, length, auth_tlv; int retval; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + if (circuit->interface->mtu == 0) { zlog_warn ("circuit has zero MTU"); @@ -1940,6 +1963,9 @@ send_hello (struct isis_circuit *circuit, int level) memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr)); interval = circuit->hello_multiplier[level - 1] * circuit->hello_interval[level - 1]; + /* If we are the DIS then hello interval is divided by three, as is the hold-timer */ + if (circuit->u.bc.is_dr[level - 1]) + interval=interval/3; if (interval > USHRT_MAX) interval = USHRT_MAX; hello_hdr.circuit_t = circuit->circuit_is_type; @@ -1976,34 +2002,36 @@ send_hello (struct isis_circuit *circuit, int level) /* * Then the variable length part */ + /* add circuit password */ - if (circuit->passwd.type) - if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len, + /* Cleartext */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_CLEARTXT) + if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, circuit->passwd.len, circuit->passwd.passwd, circuit->snd_stream)) return ISIS_WARNING; - /* Area Addresses TLV */ - assert (circuit->area); - if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0) - if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) - return ISIS_WARNING; - /* LAN Neighbors TLV */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) + /* or HMAC MD5 */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) { - if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], - circuit->snd_stream)) - return ISIS_WARNING; - if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0) - if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], - circuit->snd_stream)) - return ISIS_WARNING; + /* Remember where TLV is written so we can later overwrite the MD5 hash */ + auth_tlv = stream_get_endp (circuit->snd_stream); + memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); + if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE, + hmac_md5_hash, circuit->snd_stream)) + return ISIS_WARNING; } /* Protocols Supported TLV */ if (circuit->nlpids.count > 0) if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) return ISIS_WARNING; + + /* Area Addresses TLV */ + assert (circuit->area); + if (circuit->area->area_addrs && circuit->area->area_addrs->count > 0) + if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) + return ISIS_WARNING; + /* IP interface Address TLV */ if (circuit->ip_router && circuit->ip_addrs && circuit->ip_addrs->count > 0) if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream)) @@ -2017,6 +2045,22 @@ send_hello (struct isis_circuit *circuit, int level) return ISIS_WARNING; #endif /* HAVE_IPV6 */ + /* Restart signaling, vendor C sends it too */ + retval = add_tlv (211, 3, 0, circuit->snd_stream); + + /* LAN Neighbors TLV */ + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + { + if (level == 1 && circuit->u.bc.lan_neighs[0]->count > 0) + if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], + circuit->snd_stream)) + return ISIS_WARNING; + if (level == 2 && circuit->u.bc.lan_neighs[1]->count > 0) + if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], + circuit->snd_stream)) + return ISIS_WARNING; + } + if (circuit->u.bc.pad_hellos) if (tlv_add_padding (circuit->snd_stream)) return ISIS_WARNING; @@ -2025,6 +2069,14 @@ send_hello (struct isis_circuit *circuit, int level) /* Update PDU length */ stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length); + /* For HMAC MD5 we need to compute the md5 hash and store it */ + if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) + { + hmac_md5(circuit->snd_stream->data, stream_get_endp(circuit->snd_stream), (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, (unsigned char *) &hmac_md5_hash); + /* Copy the hash into the stream */ + memcpy(circuit->snd_stream->data+auth_tlv+3,hmac_md5_hash,ISIS_AUTH_MD5_SIZE); + } + retval = circuit->tx (circuit, level); if (retval) zlog_warn ("sending of LAN Level %d Hello failed", level); @@ -2062,9 +2114,21 @@ send_lan_l1_hello (struct thread *thread) { struct isis_circuit *circuit; int retval; + unsigned long next_hello; circuit = THREAD_ARG (thread); assert (circuit); + + if (!circuit->area) { + return ISIS_OK; + } + + /* Pseudonode sends hellos three times more than the other nodes */ + if (circuit->u.bc.is_dr[0]) + next_hello=circuit->hello_interval[0]/3+1; + else + next_hello=circuit->hello_interval[0]; + circuit->u.bc.t_send_lan_hello[0] = NULL; if (circuit->u.bc.run_dr_elect[0]) @@ -2075,7 +2139,7 @@ send_lan_l1_hello (struct thread *thread) /* set next timer thread */ THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0], send_lan_l1_hello, circuit, - isis_jitter (circuit->hello_interval[0], IIH_JITTER)); + isis_jitter (next_hello, IIH_JITTER)); return retval; } @@ -2085,9 +2149,21 @@ send_lan_l2_hello (struct thread *thread) { struct isis_circuit *circuit; int retval; + unsigned long next_hello; circuit = THREAD_ARG (thread); assert (circuit); + + if (!circuit->area) { + return ISIS_OK; + } + + /* Pseudonode sends hellos three times more than the other nodes */ + if (circuit->u.bc.is_dr[1]) + next_hello=circuit->hello_interval[1]/3+1; + else + next_hello=circuit->hello_interval[1]; + circuit->u.bc.t_send_lan_hello[1] = NULL; if (circuit->u.bc.run_dr_elect[1]) @@ -2098,7 +2174,7 @@ send_lan_l2_hello (struct thread *thread) /* set next timer thread */ THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[1], send_lan_l2_hello, circuit, - isis_jitter (circuit->hello_interval[1], IIH_JITTER)); + isis_jitter (next_hello, IIH_JITTER)); return retval; } @@ -2192,6 +2268,9 @@ send_csnp (struct isis_circuit *circuit, int level) struct listnode *node; struct isis_lsp *lsp; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + memset (start, 0x00, ISIS_SYS_ID_LEN + 2); memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); @@ -2246,9 +2325,7 @@ send_l1_csnp (struct thread *thread) circuit->t_send_csnp[0] = NULL; if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0]) - { send_csnp (circuit, 1); - } /* set next timer thread */ THREAD_TIMER_ON (master, circuit->t_send_csnp[0], send_l1_csnp, circuit, isis_jitter (circuit->csnp_interval[0], CSNP_JITTER)); @@ -2268,9 +2345,7 @@ send_l2_csnp (struct thread *thread) circuit->t_send_csnp[1] = NULL; if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1]) - { send_csnp (circuit, 2); - } /* set next timer thread */ THREAD_TIMER_ON (master, circuit->t_send_csnp[1], send_l2_csnp, circuit, isis_jitter (circuit->csnp_interval[1], CSNP_JITTER)); @@ -2357,6 +2432,9 @@ send_psnp (int level, struct isis_circuit *circuit) struct list *list = NULL; struct listnode *node; + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + if ((circuit->circ_type == CIRCUIT_T_BROADCAST && !circuit->u.bc.is_dr[level - 1]) || circuit->circ_type != CIRCUIT_T_BROADCAST) @@ -2463,85 +2541,85 @@ send_lsp (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); - if (circuit->state == C_STATE_UP) + if (circuit->state != C_STATE_UP || circuit->interface == NULL) + return ISIS_WARNING; + + lsp = listgetdata ((node = listhead (circuit->lsp_queue))); + + /* + * Do not send if levels do not match + */ + if (!(lsp->level & circuit->circuit_is_type)) + goto dontsend; + + /* + * Do not send if we do not have adjacencies in state up on the circuit + */ + if (circuit->upadjcount[lsp->level - 1] == 0) + goto dontsend; + /* only send if it needs sending */ + if ((time (NULL) - lsp->last_sent) >= + circuit->area->lsp_gen_interval[lsp->level - 1]) { - lsp = listgetdata ((node = listhead (circuit->lsp_queue))); - /* - * Do not send if levels do not match - */ - if (!(lsp->level & circuit->circuit_is_type)) - goto dontsend; + if (isis->debugs & DEBUG_UPDATE_PACKETS) + { + zlog_debug + ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x," + " lifetime %us on %s", circuit->area->area_tag, lsp->level, + rawlspid_print (lsp->lsp_header->lsp_id), + ntohl (lsp->lsp_header->seq_num), + ntohs (lsp->lsp_header->checksum), + ntohs (lsp->lsp_header->rem_lifetime), + circuit->interface->name); + } + /* copy our lsp to the send buffer */ + stream_copy (circuit->snd_stream, lsp->pdu); + + retval = circuit->tx (circuit, lsp->level); /* - * Do not send if we do not have adjacencies in state up on the circuit + * If the sending succeeded, we can del the lsp from circuits + * lsp_queue */ - if (circuit->upadjcount[lsp->level - 1] == 0) - goto dontsend; - /* only send if it needs sending */ - if ((time (NULL) - lsp->last_sent) >= - circuit->area->lsp_gen_interval[lsp->level - 1]) + if (retval == ISIS_OK) { - - if (isis->debugs & DEBUG_UPDATE_PACKETS) - { - zlog_debug - ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x," - " lifetime %us on %s", circuit->area->area_tag, lsp->level, - rawlspid_print (lsp->lsp_header->lsp_id), - ntohl (lsp->lsp_header->seq_num), - ntohs (lsp->lsp_header->checksum), - ntohs (lsp->lsp_header->rem_lifetime), - circuit->interface->name); - } - /* copy our lsp to the send buffer */ - stream_copy (circuit->snd_stream, lsp->pdu); - - retval = circuit->tx (circuit, lsp->level); + list_delete_node (circuit->lsp_queue, node); /* - * If the sending succeeded, we can del the lsp from circuits - * lsp_queue + * On broadcast circuits also the SRMflag can be cleared */ - if (retval == ISIS_OK) - { - list_delete_node (circuit->lsp_queue, node); + if (circuit->circ_type == CIRCUIT_T_BROADCAST) + ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); + if (flags_any_set (lsp->SRMflags) == 0) + { /* - * On broadcast circuits also the SRMflag can be cleared + * need to remember when we were last sent */ - if (circuit->circ_type == CIRCUIT_T_BROADCAST) - ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - - if (flags_any_set (lsp->SRMflags) == 0) - { - /* - * need to remember when we were last sent - */ - lsp->last_sent = time (NULL); - } - } - else - { - zlog_debug ("sending of level %d link state failed", lsp->level); + lsp->last_sent = time (NULL); } } else { - /* my belief is that if it wasn't his time, the lsp can be removed - * from the queue - */ - dontsend: - list_delete_node (circuit->lsp_queue, node); + zlog_debug ("sending of level %d link state failed", lsp->level); } -#if 0 - /* - * If there are still LSPs send next one after lsp-interval (33 msecs) + } + else + { + /* my belief is that if it wasn't his time, the lsp can be removed + * from the queue */ - if (listcount (circuit->lsp_queue) > 0) - thread_add_timer (master, send_lsp, circuit, 1); -#endif + dontsend: + list_delete_node (circuit->lsp_queue, node); } +#if 0 + /* + * If there are still LSPs send next one after lsp-interval (33 msecs) + */ + if (listcount (circuit->lsp_queue) > 0) + thread_add_timer (master, send_lsp, circuit, 1); +#endif return retval; } diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h index 95c1ee4f..c4c38e22 100644 --- a/isisd/isis_pdu.h +++ b/isisd/isis_pdu.h @@ -258,8 +258,7 @@ int ack_lsp (struct isis_link_state_hdr *hdr, void fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type); int send_hello (struct isis_circuit *circuit, int level); - -int authentication_check (struct isis_passwd *one, - struct isis_passwd *theother); +#define ISIS_AUTH_MD5_SIZE 16U +int authentication_check (struct isis_passwd *remote, struct isis_passwd *local, struct isis_circuit *c); #endif /* _ZEBRA_ISIS_PDU_H */ diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c index 8752dba5..8a5c3ed0 100644 --- a/isisd/isis_pfpacket.c +++ b/isisd/isis_pfpacket.c @@ -21,6 +21,7 @@ */ #include <zebra.h> +#if ISIS_METHOD == ISIS_METHOD_PFPACKET #include <net/ethernet.h> /* the L2 protocols */ #include <netpacket/packet.h> @@ -231,6 +232,10 @@ isis_recv_pdu_bcast (struct isis_circuit *circuit, u_char * ssnpa) LLC_LEN, MSG_PEEK, (struct sockaddr *) &s_addr, (socklen_t *) &addr_len); + if (!circuit->area) { + return ISIS_OK; + } + if (bytesread < 0) { zlog_warn ("isis_recv_packet_bcast(): fd %d, recvfrom (): %s", @@ -371,3 +376,5 @@ isis_send_pdu_p2p (struct isis_circuit *circuit, int level) return ISIS_OK; } + +#endif /* ISIS_METHOD == ISIS_METHOD_PFPACKET */ diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 5d7e9da4..5d0b161f 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -405,12 +405,13 @@ isis_spf_add2tent (struct isis_spftree *spftree, enum vertextype vtype, if (adj) listnode_add (vertex->Adj_N, adj); + #ifdef EXTREME_DEBUG zlog_debug ("ISIS-Spf: add to TENT %s %s depth %d dist %d", vtype2string (vertex->type), vid2string (vertex, buff), vertex->depth, vertex->d_N); #endif /* EXTREME_DEBUG */ - listnode_add (spftree->tents, vertex); + if (list_isempty (spftree->tents)) { listnode_add (spftree->tents, vertex); @@ -549,7 +550,8 @@ process_N (struct isis_spftree *spftree, enum vertextype vtype, void *id, */ static int isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, - uint32_t cost, uint16_t depth, int family) + uint32_t cost, uint16_t depth, int family, + struct isis_adjacency *adj) { struct listnode *node, *fragnode = NULL; u_int16_t dist; @@ -563,9 +565,6 @@ isis_spf_process_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, struct ipv6_reachability *ip6reach; #endif /* HAVE_IPV6 */ - - if (!lsp->adj) - return ISIS_WARNING; if (lsp->tlv_data.nlpids == NULL || !speaks (lsp->tlv_data.nlpids, family)) return ISIS_OK; @@ -591,7 +590,7 @@ lspfragloop: vtype = LSP_PSEUDO_ID (is_neigh->neigh_id) ? VTYPE_PSEUDO_IS : VTYPE_NONPSEUDO_IS; process_N (spftree, vtype, (void *) is_neigh->neigh_id, dist, - depth + 1, lsp->adj, family); + depth + 1, adj, family); } } if (lsp->tlv_data.te_is_neighs) @@ -607,7 +606,7 @@ lspfragloop: vtype = LSP_PSEUDO_ID (te_is_neigh->neigh_id) ? VTYPE_PSEUDO_TE_IS : VTYPE_NONPSEUDO_TE_IS; process_N (spftree, vtype, (void *) te_is_neigh->neigh_id, dist, - depth + 1, lsp->adj, family); + depth + 1, adj, family); } } if (family == AF_INET && lsp->tlv_data.ipv4_int_reachs) @@ -621,7 +620,7 @@ lspfragloop: prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } @@ -636,7 +635,7 @@ lspfragloop: prefix.u.prefix4 = ipreach->prefix; prefix.prefixlen = ip_masklen (ipreach->mask); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } if (family == AF_INET && lsp->tlv_data.te_ipv4_reachs) @@ -651,7 +650,7 @@ lspfragloop: te_ipv4_reach->control); prefix.prefixlen = (te_ipv4_reach->control & 0x3F); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } #ifdef HAVE_IPV6 @@ -668,7 +667,7 @@ lspfragloop: memcpy (&prefix.u.prefix6.s6_addr, ip6reach->prefix, PSIZE (ip6reach->prefix_len)); process_N (spftree, vtype, (void *) &prefix, dist, depth + 1, - lsp->adj, family); + adj, family); } } #endif /* HAVE_IPV6 */ @@ -691,7 +690,8 @@ lspfragloop: static int isis_spf_process_pseudo_lsp (struct isis_spftree *spftree, struct isis_lsp *lsp, uint16_t cost, - uint16_t depth, int family) + uint16_t depth, int family, + struct isis_adjacency *adj) { struct listnode *node, *fragnode = NULL; struct is_neigh *is_neigh; @@ -715,13 +715,13 @@ pseudofragloop: /* Two way connectivity */ if (!memcmp (is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; - if (isis_find_vertex - (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL + if ((depth > 0 || isis_find_vertex + (spftree->tents, (void *) is_neigh->neigh_id, vtype) == NULL) && isis_find_vertex (spftree->paths, (void *) is_neigh->neigh_id, vtype) == NULL) { /* C.2.5 i) */ - isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, lsp->adj, + isis_spf_add2tent (spftree, vtype, is_neigh->neigh_id, adj, cost, depth, family); } } @@ -733,13 +733,13 @@ pseudofragloop: /* Two way connectivity */ if (!memcmp (te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN)) continue; - if (isis_find_vertex - (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL + if ((depth > 0 || isis_find_vertex + (spftree->tents, (void *) te_is_neigh->neigh_id, vtype) == NULL) && isis_find_vertex (spftree->paths, (void *) te_is_neigh->neigh_id, vtype) == NULL) { /* C.2.5 i) */ - isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, lsp->adj, + isis_spf_add2tent (spftree, vtype, te_is_neigh->neigh_id, adj, cost, depth, family); } } @@ -860,9 +860,6 @@ isis_spf_preload_tent (struct isis_spftree *spftree, lsp = lsp_search (lsp_id, area->lspdb[level - 1]); if (!lsp) zlog_warn ("No lsp found for IS adjacency"); - /* else { - isis_spf_process_lsp (spftree, lsp, vertex->d_N, 1, family); - } */ break; case ISIS_SYSTYPE_UNKNOWN: default: @@ -885,14 +882,14 @@ isis_spf_preload_tent (struct isis_spftree *spftree, { zlog_warn ("ISIS-Spf: No adjacency found for DR"); } - if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) + else if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) { zlog_warn ("ISIS-Spf: No lsp found for DR"); } else { isis_spf_process_pseudo_lsp (spftree, lsp, - circuit->te_metric[level - 1], 0, family); + circuit->te_metric[level - 1], 0, family, adj); } } @@ -982,6 +979,7 @@ isis_run_spf (struct isis_area *area, int level, int family) struct isis_spftree *spftree = NULL; u_char lsp_id[ISIS_SYS_ID_LEN + 2]; struct isis_lsp *lsp; + struct isis_adjacency *adj = NULL; struct route_table *table = NULL; struct route_node *rode; struct isis_route_info *rinfo; @@ -1032,16 +1030,28 @@ isis_run_spf (struct isis_area *area, int level, int family) while (listcount (spftree->tents) > 0) { + /* C.2.7 a) 1) */ node = listhead (spftree->tents); vertex = listgetdata (node); - /* Remove from tent list */ + + /* C.2.7 a) 2) */ list_delete_node (spftree->tents, node); + + /* C.2.7 a) 3) */ if (isis_find_vertex (spftree->paths, vertex->N.id, vertex->type)) continue; add_to_paths (spftree, vertex, area, level); + if (vertex->type == VTYPE_PSEUDO_IS || - vertex->type == VTYPE_NONPSEUDO_IS) + vertex->type == VTYPE_NONPSEUDO_IS || + vertex->type == VTYPE_PSEUDO_TE_IS || + vertex->type == VTYPE_NONPSEUDO_TE_IS ) { + if (listcount(vertex->Adj_N) == 0) { + continue; + } + adj = listgetdata(vertex->Adj_N->head); + memcpy (lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1); LSP_FRAGMENT (lsp_id) = 0; lsp = lsp_search (lsp_id, area->lspdb[level - 1]); @@ -1050,13 +1060,12 @@ isis_run_spf (struct isis_area *area, int level, int family) if (LSP_PSEUDO_ID (lsp_id)) { isis_spf_process_pseudo_lsp (spftree, lsp, vertex->d_N, - vertex->depth, family); - + vertex->depth, family, adj); } else { isis_spf_process_lsp (spftree, lsp, vertex->d_N, - vertex->depth, family); + vertex->depth, family, adj); } } else diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c index 94fa65ed..3fc717e3 100644 --- a/isisd/isis_tlv.c +++ b/isisd/isis_tlv.c @@ -446,6 +446,10 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected, tlvs->auth_info.len = length-1; pnt++; memcpy (tlvs->auth_info.passwd, pnt, length - 1); + /* Fill authentication with 0 for later computation + * of MD5 (RFC 5304, 2) + */ + memset (pnt, 0, length - 1); pnt += length - 1; } else @@ -741,7 +745,7 @@ add_tlv (u_char tag, u_char len, u_char * value, struct stream *stream) stream_putc (stream, len); /* LENGTH */ stream_put (stream, value, (int) len); /* VALUE */ -#ifdef EXTREME_DEBUG +#ifdef EXTREME_TLV_DEBUG zlog_debug ("Added TLV %d len %d", tag, len); #endif /* EXTREME DEBUG */ return ISIS_OK; @@ -878,7 +882,7 @@ tlv_add_authinfo (char auth_type, char auth_len, u_char *auth_value, { u_char value[255]; u_char *pos = value; - *pos++ = ISIS_PASSWD_TYPE_CLEARTXT; + *pos++ = auth_type; memcpy (pos, auth_value, auth_len); return add_tlv (AUTH_INFO, auth_len + 1, value, stream); diff --git a/isisd/isisd.c b/isisd/isisd.c index 1e84a1ce..20a32809 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -52,6 +52,7 @@ #include "isisd/isis_route.h" #include "isisd/isis_zebra.h" #include "isisd/isis_events.h" +#include "isisd/isis_csm.h" #ifdef TOPOLOGY_GENERATE #include "spgrid.h" @@ -217,21 +218,31 @@ isis_area_destroy (struct vty *vty, const char *area_tag) for (ALL_LIST_ELEMENTS (area->circuit_list, node, nnode, circuit)) { /* The fact that it's in circuit_list means that it was configured */ + isis_csm_state_change (ISIS_DISABLE, circuit, area); + isis_circuit_down (circuit); isis_circuit_deconfigure (circuit, area); - isis_circuit_del (circuit); } list_delete (area->circuit_list); } listnode_delete (isis->area_list, area); + THREAD_TIMER_OFF (area->t_tick); if (area->t_remove_aged) thread_cancel (area->t_remove_aged); THREAD_TIMER_OFF (area->t_lsp_refresh[0]); THREAD_TIMER_OFF (area->t_lsp_refresh[1]); + THREAD_TIMER_OFF (area->spftree[0]->t_spf); + THREAD_TIMER_OFF (area->spftree[1]->t_spf); + + THREAD_TIMER_OFF (area->t_lsp_l1_regenerate); + THREAD_TIMER_OFF (area->t_lsp_l2_regenerate); + XFREE (MTYPE_ISIS_AREA, area); + isis->sysid_set=0; + return CMD_SUCCESS; } diff --git a/isisd/isisd.h b/isisd/isisd.h index 2277f27c..b17982e2 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -93,6 +93,8 @@ struct isis_area struct flags flags; struct thread *t_tick; /* LSP walker */ struct thread *t_remove_aged; + struct thread *t_lsp_l1_regenerate; + struct thread *t_lsp_l2_regenerate; int lsp_regenerate_pending[ISIS_LEVELS]; struct thread *t_lsp_refresh[ISIS_LEVELS]; diff --git a/lib/checksum.c b/lib/checksum.c index 3ddde815..af4f2550 100644 --- a/lib/checksum.c +++ b/lib/checksum.c @@ -14,27 +14,20 @@ in_cksum(void *parg, int nbytes) { u_short *ptr = parg; register long sum; /* assumes long == 32 bits */ - u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ - + register int count; /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ - sum = 0; - while (nbytes > 1) { - sum += *ptr++; - nbytes -= 2; - } - - /* mop up an odd byte, if necessary */ - if (nbytes == 1) { - oddbyte = 0; /* make sure top half is zero */ - *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ - sum += oddbyte; - } + count = nbytes >> 1; /* div by 2 */ + for(ptr--; count; --count) + sum += *++ptr; + + if (nbytes & 1) /* Odd */ + sum += *(u_char *)(++ptr); /* one byte only */ /* * Add back carry outs from top 16 bits to low 16 bits. @@ -56,11 +49,8 @@ fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset) { u_int8_t *p; int x, y, c0, c1; - u_int16_t checksum; u_int16_t *csum; size_t partial_len, i, left = len; - - checksum = 0; assert (offset < len); @@ -68,47 +58,42 @@ fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset) * Zero the csum in the packet. */ csum = (u_int16_t *) (buffer + offset); - *(csum) = 0; + *csum = 0; - p = buffer; + p = buffer - 1; c0 = 0; c1 = 0; while (left != 0) { partial_len = MIN(left, MODX); + left -= partial_len; - for (i = 0; i < partial_len; i++) + do { - c0 = c0 + *(p++); + c0 = c0 + *(++p); c1 += c0; - } + } while (--partial_len); c0 = c0 % 255; c1 = c1 % 255; - - left -= partial_len; } - + /* The cast is important, to ensure the mod is taken as a signed value. */ x = (int)((len - offset - 1) * c0 - c1) % 255; if (x <= 0) x += 255; y = 510 - c0 - x; - if (y > 255) + if (y > 255) y -= 255; - + /* * Now we write this to the packet. * We could skip this step too, since the checksum returned would * be stored into the checksum field by the caller. + * Checksum is always big endian. */ - buffer[offset] = x; - buffer[offset + 1] = y; - - /* Take care of the endian issue */ - checksum = htons((x << 8) | (y & 0xFF)); - - return checksum; + *csum = htons((x << 8) | (y & 0xFF)); + return *csum; } diff --git a/lib/command.c b/lib/command.c index c432b323..290f1be0 100644 --- a/lib/command.c +++ b/lib/command.c @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ #include "vty.h" #include "command.h" #include "workqueue.h" +#include <stdbool.h> /* Command vector which includes some level of command lists. Normally each daemon maintains each own cmdvec. */ @@ -84,9 +85,9 @@ static struct cmd_node config_node = /* Default motd string. */ static const char *default_motd = "\r\n\ -Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ -" QUAGGA_COPYRIGHT "\r\n\ -\r\n"; +This is " QUAGGA_PROGNAME " " QUAGGA_VERSION "\r\n\r\n\ +You're using the dn42 branch. Send bug reports to equinox@diac24.net\r\n\ +The 1.1.0 version number is for package management purposes only.\r\n"; static const struct facility_map { @@ -686,7 +687,8 @@ cmd_filter_by_symbol (char *command, char *symbol) /* Completion match types. */ enum match_type { - no_match, +no_match = 0, +any_match, extend_match, ipv4_prefix_match, ipv4_match, @@ -695,7 +697,7 @@ enum match_type range_match, vararg_match, partly_match, - exact_match +exact_match, }; static enum match_type @@ -1132,12 +1134,100 @@ cmd_range_match (const char *range, const char *str) return 1; } -/* Make completion match and return match type flag. */ +/* helper to retrieve the 'real' argument string from an optional argument */ +static char * +cmd_deopt (const char *str) +{ +/* we've got "[blah]". We want to strip off the []s and redo the +* match check for "blah" +*/ +size_t len = strlen (str); +char *tmp; + +if (len < 3) +return NULL; + +/* tmp will hold a string of len-2 chars, so 'len' size is fine */ +tmp = XMALLOC(MTYPE_TMP, len); + +memcpy (tmp, (str + 1), len - 2); +tmp[len - 2] = '\0'; + +return tmp; +} + +static enum match_type +cmd_match (const char *str, const char *command, +enum match_type min, bool recur) +{ + +if (recur && CMD_OPTION(str)) +{ +enum match_type ret; +char *tmp = cmd_deopt (str); + +/* this would be a bug in a command, however handle it gracefully +* as it we only discover it if a user tries to run it +*/ +if (tmp == NULL) +return no_match; + +ret = cmd_match (tmp, command, min, false); + +XFREE (MTYPE_TMP, tmp); + +return ret; +} +else if (CMD_VARARG (str)) +return vararg_match; +else if (CMD_RANGE (str)) +{ +if (cmd_range_match (str, command)) +return range_match; +} +#ifdef HAVE_IPV6 +else if (CMD_IPV6 (str)) +{ +if (cmd_ipv6_match (command) >= min) +return ipv6_match; +} +else if (CMD_IPV6_PREFIX (str)) +{ +if (cmd_ipv6_prefix_match (command) >= min) +return ipv6_prefix_match; +} +#endif /* HAVE_IPV6 */ +else if (CMD_IPV4 (str)) +{ +if (cmd_ipv4_match (command) >= min) +return ipv4_match; +} +else if (CMD_IPV4_PREFIX (str)) +{ +if (cmd_ipv4_prefix_match (command) >= min) +return ipv4_prefix_match; +} +else if (CMD_VARIABLE (str)) +return extend_match; +else if (strncmp (command, str, strlen (command)) == 0) +{ +if (strcmp (command, str) == 0) +return exact_match; +else if (partly_match >= min) +return partly_match; +} + +return no_match; +} + +/* Filter vector at the specified index and by the given command string, to +* the desired matching level (thus allowing part matches), and return match +* type flag. +*/ static enum match_type -cmd_filter_by_completion (char *command, vector v, unsigned int index) +cmd_filter (char *command, vector v, unsigned int index, enum match_type level) { unsigned int i; - const char *str; struct cmd_element *cmd_element; enum match_type match_type; vector descvec; @@ -1160,112 +1250,42 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) for (j = 0; j < vector_active (descvec); j++) if ((desc = vector_slot (descvec, j))) - { - str = desc->cmd; - - if (CMD_VARARG (str)) - { - if (match_type < vararg_match) - match_type = vararg_match; - matched++; - } - else if (CMD_RANGE (str)) - { - if (cmd_range_match (str, command)) - { - if (match_type < range_match) - match_type = range_match; + { + enum match_type ret; - matched++; - } - } -#ifdef HAVE_IPV6 - else if (CMD_IPV6 (str)) - { - if (cmd_ipv6_match (command)) - { - if (match_type < ipv6_match) - match_type = ipv6_match; - - matched++; - } - } - else if (CMD_IPV6_PREFIX (str)) - { - if (cmd_ipv6_prefix_match (command)) - { - if (match_type < ipv6_prefix_match) - match_type = ipv6_prefix_match; - - matched++; - } - } -#endif /* HAVE_IPV6 */ - else if (CMD_IPV4 (str)) - { - if (cmd_ipv4_match (command)) - { - if (match_type < ipv4_match) - match_type = ipv4_match; + ret = cmd_match (desc->cmd, command, level, true); + + if (ret != no_match) + matched++; - matched++; - } - } - else if (CMD_IPV4_PREFIX (str)) - { - if (cmd_ipv4_prefix_match (command)) - { - if (match_type < ipv4_prefix_match) - match_type = ipv4_prefix_match; - matched++; - } - } - else - /* Check is this point's argument optional ? */ - if (CMD_OPTION (str) || CMD_VARIABLE (str)) - { - if (match_type < extend_match) - match_type = extend_match; - matched++; - } - else if (strncmp (command, str, strlen (command)) == 0) - { - if (strcmp (command, str) == 0) - match_type = exact_match; - else - { - if (match_type < partly_match) - match_type = partly_match; - } - matched++; - } + if (match_type < ret) + match_type = ret; } if (!matched) vector_slot (v, i) = NULL; } } - return match_type; -} -/* Filter vector by command character with index. */ -static enum match_type -cmd_filter_by_string (char *command, vector v, unsigned int index) -{ - unsigned int i; - const char *str; - struct cmd_element *cmd_element; - enum match_type match_type; - vector descvec; - struct desc *desc; - - match_type = no_match; - - /* If command and cmd_element string does not match set NULL to vector */ +if (match_type == no_match) +return no_match; + +/* 2nd pass: We now know the 'strongest' match type for the index, so we +* go again and filter out commands whose argument (at this index) is +* 'weaker'. E.g., if we have 2 commands: +* +* foo bar <1-255> +* foo bar BLAH +* +* and the command string is 'foo bar 10', then we will get here with with +* 'range_match' being the strongest match. However, if 'BLAH' came +* earlier, it won't have been filtered out (as a CMD_VARIABLE allows "10"). +* +* If we don't do a 2nd pass and filter it out, the higher-layers will +* consider this to be ambiguous. +*/ for (i = 0; i < vector_active (v); i++) if ((cmd_element = vector_slot (v, i)) != NULL) { - /* If given index is bigger than max string vector of command, - set NULL */ if (index >= vector_active (cmd_element->strvec)) vector_slot (v, i) = NULL; else @@ -1277,81 +1297,19 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) for (j = 0; j < vector_active (descvec); j++) if ((desc = vector_slot (descvec, j))) - { - str = desc->cmd; + { + enum match_type ret; - if (CMD_VARARG (str)) - { - if (match_type < vararg_match) - match_type = vararg_match; - matched++; - } - else if (CMD_RANGE (str)) - { - if (cmd_range_match (str, command)) - { - if (match_type < range_match) - match_type = range_match; - matched++; - } - } -#ifdef HAVE_IPV6 - else if (CMD_IPV6 (str)) - { - if (cmd_ipv6_match (command) == exact_match) - { - if (match_type < ipv6_match) - match_type = ipv6_match; - matched++; - } - } - else if (CMD_IPV6_PREFIX (str)) - { - if (cmd_ipv6_prefix_match (command) == exact_match) - { - if (match_type < ipv6_prefix_match) - match_type = ipv6_prefix_match; - matched++; - } - } -#endif /* HAVE_IPV6 */ - else if (CMD_IPV4 (str)) - { - if (cmd_ipv4_match (command) == exact_match) - { - if (match_type < ipv4_match) - match_type = ipv4_match; - matched++; - } - } - else if (CMD_IPV4_PREFIX (str)) - { - if (cmd_ipv4_prefix_match (command) == exact_match) - { - if (match_type < ipv4_prefix_match) - match_type = ipv4_prefix_match; - matched++; - } - } - else if (CMD_OPTION (str) || CMD_VARIABLE (str)) - { - if (match_type < extend_match) - match_type = extend_match; - matched++; - } - else - { - if (strcmp (command, str) == 0) - { - match_type = exact_match; - matched++; - } - } + ret = cmd_match (desc->cmd, command, any_match, true); + + if (ret >= match_type) + matched++; } if (!matched) vector_slot (v, i) = NULL; } } + return match_type; } @@ -1361,7 +1319,6 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) { unsigned int i; unsigned int j; - const char *str = NULL; struct cmd_element *cmd_element; const char *matched = NULL; vector descvec; @@ -1378,18 +1335,21 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) if ((desc = vector_slot (descvec, j))) { enum match_type ret; - - str = desc->cmd; + char *str = desc->cmd; + if (CMD_OPTION(str)) + if ((str = cmd_deopt (str)) == NULL) + continue; + switch (type) { case exact_match: - if (!(CMD_OPTION (str) || CMD_VARIABLE (str)) + if (!(CMD_VARIABLE (str)) && strcmp (command, str) == 0) match++; break; case partly_match: - if (!(CMD_OPTION (str) || CMD_VARIABLE (str)) + if (!(CMD_VARIABLE (str)) && strncmp (command, str, strlen (command)) == 0) { if (matched && strcmp (matched, str) != 0) @@ -1438,13 +1398,16 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) } break; case extend_match: - if (CMD_OPTION (str) || CMD_VARIABLE (str)) + if (CMD_VARIABLE (str)) match++; break; case no_match: default: break; } + +if (CMD_OPTION(desc->cmd)) +XFREE (MTYPE_TMP, str); } if (!match) vector_slot (v, i) = NULL; @@ -1614,7 +1577,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) for (i = 0; i < index; i++) if ((command = vector_slot (vline, i))) { - match = cmd_filter_by_completion (command, cmd_vector, i); + match = cmd_filter (command, cmd_vector, i, any_match); if (match == vararg_match) { @@ -1663,7 +1626,7 @@ cmd_describe_command_real (vector vline, struct vty *vty, int *status) /* Make sure that cmd_vector is filtered based on current word */ command = vector_slot (vline, index); if (command) - match = cmd_filter_by_completion (command, cmd_vector, index); +match = cmd_filter (command, cmd_vector, index, any_match); /* Make description vector. */ for (i = 0; i < vector_active (cmd_vector); i++) @@ -1817,7 +1780,7 @@ cmd_complete_command_real (vector vline, struct vty *vty, int *status) int ret; /* First try completion match, if there is exactly match return 1 */ - match = cmd_filter_by_completion (command, cmd_vector, i); + match = cmd_filter (command, cmd_vector, i, any_match); /* If there is exact match then filter ambiguous match else check ambiguousness. */ @@ -2026,7 +1989,7 @@ cmd_execute_command_real (vector vline, struct vty *vty, { int ret; - match = cmd_filter_by_completion (command, cmd_vector, index); + match = cmd_filter (command, cmd_vector, index, any_match); if (match == vararg_match) break; @@ -2205,8 +2168,8 @@ cmd_execute_command_strict (vector vline, struct vty *vty, { int ret; - match = cmd_filter_by_string (vector_slot (vline, index), - cmd_vector, index); + match = cmd_filter (vector_slot (vline, index), cmd_vector, + index, exact_match); /* If command meets '.VARARG' then finish matching. */ if (match == vararg_match) @@ -90,6 +90,7 @@ struct interface #define ZEBRA_INTERFACE_ACTIVE (1 << 0) #define ZEBRA_INTERFACE_SUB (1 << 1) #define ZEBRA_INTERFACE_LINKDETECTION (1 << 2) +#define ZEBRA_INTERFACE_UNNUMBERED (1 << 3) /* Interface flags. */ uint64_t flags; @@ -927,12 +927,18 @@ proto_redistnum(int afi, const char *s) return ZEBRA_ROUTE_STATIC; else if (strncmp (s, "r", 1) == 0) return ZEBRA_ROUTE_RIP; - else if (strncmp (s, "o", 1) == 0) + else if (strncmp (s, "os", 2) == 0) return ZEBRA_ROUTE_OSPF; else if (strncmp (s, "i", 1) == 0) return ZEBRA_ROUTE_ISIS; - else if (strncmp (s, "b", 1) == 0) + else if (strncmp (s, "bg", 2) == 0) return ZEBRA_ROUTE_BGP; + else if (strncmp (s, "ol", 2) == 0) + return ZEBRA_ROUTE_OLSR; + else if (strncmp (s, "ba", 2) == 0) + return ZEBRA_ROUTE_BATMAN; + else if (strncmp (s, "d", 1) == 0) + return ZEBRA_ROUTE_DHCP; } if (afi == AFI_IP6) { @@ -944,12 +950,16 @@ proto_redistnum(int afi, const char *s) return ZEBRA_ROUTE_STATIC; else if (strncmp (s, "r", 1) == 0) return ZEBRA_ROUTE_RIPNG; - else if (strncmp (s, "o", 1) == 0) + else if (strncmp (s, "os", 2) == 0) return ZEBRA_ROUTE_OSPF6; else if (strncmp (s, "i", 1) == 0) return ZEBRA_ROUTE_ISIS; - else if (strncmp (s, "b", 1) == 0) + else if (strncmp (s, "bg", 2) == 0) return ZEBRA_ROUTE_BGP; + else if (strncmp (s, "ol", 2) == 0) + return ZEBRA_ROUTE_OLSR; + else if (strncmp (s, "ba", 2) == 0) + return ZEBRA_ROUTE_BATMAN; } return -1; } @@ -298,3 +298,76 @@ static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt) ctxt->md5_stc += C; ctxt->md5_std += D; } + +/* From RFC 2104 */ +void +hmac_md5(text, text_len, key, key_len, digest) +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 */ + +{ + MD5_CTX context; + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + bzero( k_ipad, sizeof k_ipad); + bzero( k_opad, sizeof k_opad); + bcopy( key, k_ipad, key_len); + bcopy( key, k_opad, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + MD5Init(&context); /* init context for 1st + * pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, text, text_len); /* then text of datagram */ + MD5Final(digest, &context); /* finish up 1st pass */ + /* + * perform outer MD5 + */ + MD5Init(&context); /* init context for 2nd + * pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, digest, 16); /* then results of 1st + * hash */ + MD5Final(digest, &context); /* finish up 2nd pass */ +} @@ -82,4 +82,7 @@ do { \ md5_result((x), (y)); \ } while (0) +/* From RFC 2104 */ +void hmac_md5(unsigned char* text, int text_len, unsigned char* key, int key_len, caddr_t digest); + #endif /* ! _LIBZEBRA_MD5_H_*/ diff --git a/lib/prefix.c b/lib/prefix.c index c85e6594..f5de4bde 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -180,6 +180,46 @@ prefix_cmp (const struct prefix *p1, const struct prefix *p2) return 0; } +/* + * Count the number of common bits in 2 prefixes. The prefix length is + * ignored for this function; the whole prefix is compared. If the prefix + * address families don't match, return -1; otherwise the return value is + * in range 0 ... maximum prefix length for the address family. + */ +int +prefix_common_bits (const struct prefix *p1, const struct prefix *p2) +{ + int pos, bit; + int length = 0; + u_char xor; + + /* Set both prefix's head pointer. */ + const u_char *pp1 = (const u_char *)&p1->u.prefix; + const u_char *pp2 = (const u_char *)&p2->u.prefix; + + if (p1->family == AF_INET) + length = IPV4_MAX_BYTELEN; +#ifdef HAVE_IPV6 + if (p1->family == AF_INET6) + length = IPV6_MAX_BYTELEN; +#endif + if (p1->family != p2->family || !length) + return -1; + + for (pos = 0; pos < length; pos++) + if (pp1[pos] != pp2[pos]) + break; + if (pos == length) + return pos * 8; + + xor = pp1[pos] ^ pp2[pos]; + for (bit = 0; bit < 8; bit++) + if (xor & (1 << (7 - bit))) + break; + + return pos * 8 + bit; +} + /* Return prefix family type string. */ const char * prefix_family_str (const struct prefix *p) @@ -569,6 +609,20 @@ sockunion2hostprefix (const union sockunion *su) return NULL; } +void +prefix2sockunion (const struct prefix *p, union sockunion *su) +{ + memset (su, 0, sizeof (*su)); + + su->sa.sa_family = p->family; + if (p->family == AF_INET) + su->sin.sin_addr = p->u.prefix4; +#ifdef HAVE_IPV6 + if (p->family == AF_INET6) + memcpy (&su->sin6.sin6_addr, &p->u.prefix6, sizeof (struct in6_addr)); +#endif /* HAVE_IPV6 */ +} + int prefix_blen (const struct prefix *p) { diff --git a/lib/prefix.h b/lib/prefix.h index a7598b7e..f6259dee 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -156,12 +156,14 @@ extern int prefix2str (const struct prefix *, char *, int); extern int prefix_match (const struct prefix *, const struct prefix *); extern int prefix_same (const struct prefix *, const struct prefix *); extern int prefix_cmp (const struct prefix *, const struct prefix *); +extern int prefix_common_bits (const struct prefix *, const struct prefix *); extern void prefix_copy (struct prefix *dest, const struct prefix *src); extern void apply_mask (struct prefix *); extern struct prefix *sockunion2prefix (const union sockunion *dest, const union sockunion *mask); extern struct prefix *sockunion2hostprefix (const union sockunion *); +extern void prefix2sockunion (const struct prefix *, union sockunion *); extern struct prefix_ipv4 *prefix_ipv4_new (void); extern void prefix_ipv4_free (struct prefix_ipv4 *); diff --git a/lib/route_types.txt b/lib/route_types.txt index d2d4cb6c..dfa34d74 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -56,8 +56,10 @@ ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP" # This at least makes it trivial for users of these protocols # to 'switch on' redist support (direct numeric entry remaining # possible). -ZEBRA_ROUTE_HSLS, hsls, hslsd, 'H', 0, 0, "HSLS" -ZEBRA_ROUTE_OLSR, olsr, olsrd, 'o', 0, 0, "OLSR" +ZEBRA_ROUTE_HSLS, hsls, hslsd, 'h', 1, 1, "HSLS" +ZEBRA_ROUTE_OLSR, olsr, olsrd, 'o', 1, 1, "OLSR" +ZEBRA_ROUTE_BATMAN, batman, batman, 'b', 1, 1, "BATMAN" +ZEBRA_ROUTE_DHCP, dhcp, dhcpc, 'D', 1, 0, "DHCP" ZEBRA_ROUTE_PIM, pim, pimd, 'P', 0, 0, "PIM-SSM" ## help strings @@ -73,5 +75,7 @@ ZEBRA_ROUTE_ISIS, "Intermediate System to Intermediate System (IS-IS)" ZEBRA_ROUTE_BGP, "Border Gateway Protocol (BGP)" ZEBRA_ROUTE_HSLS, "Hazy-Sighted Link State Protocol (HSLS)" ZEBRA_ROUTE_OLSR, "Optimised Link State Routing (OLSR)" +ZEBRA_ROUTE_BATMAN, "Better Approach To Mobile Ad-hoc Networking (BATMAN)" +ZEBRA_ROUTE_DHCP, "Dynamic Host Configuration Protocol (DHCP)" ZEBRA_ROUTE_PIM, "Protocol Independent Multicast, Source Specific Mode (PIM-SSM)" diff --git a/lib/sockunion.c b/lib/sockunion.c index d1f6d80b..5de3bcfc 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -551,6 +551,16 @@ sockopt_v6only (int family, int sock) return 0; } +int +sockopt_cork (int sock, int onoff) +{ +#ifdef TCP_CORK + return setsockopt (sock, IPPROTO_TCP, TCP_CORK, &onoff, sizeof(onoff)); +#else + return 0; +#endif +} + /* If same family and same prefix return 1. */ int sockunion_same (union sockunion *su1, union sockunion *su2) diff --git a/lib/sockunion.h b/lib/sockunion.h index db145cf2..2e8ce2d0 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -103,6 +103,7 @@ extern int sockopt_v6only (int family, int sock); extern int sockunion_bind (int sock, union sockunion *, unsigned short, union sockunion *); extern int sockopt_ttl (int family, int sock, int ttl); +extern int sockopt_cork (int sock, int onoff); 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, diff --git a/lib/stream.c b/lib/stream.c index 983330ff..bff74d7b 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -711,32 +711,6 @@ stream_read (struct stream *s, int fd, size_t size) return nbytes; } -/* Read size from fd. */ -int -stream_read_unblock (struct stream *s, int fd, size_t size) -{ - int nbytes; - int val; - - STREAM_VERIFY_SANE(s); - - if (STREAM_WRITEABLE (s) < size) - { - STREAM_BOUND_WARN (s, "put"); - return 0; - } - - val = fcntl (fd, F_GETFL, 0); - fcntl (fd, F_SETFL, val|O_NONBLOCK); - nbytes = read (fd, s->data + s->endp, size); - fcntl (fd, F_SETFL, val); - - if (nbytes > 0) - s->endp += nbytes; - - return nbytes; -} - ssize_t stream_read_try(struct stream *s, int fd, size_t size) { diff --git a/lib/stream.h b/lib/stream.h index 3e4ba7b4..486a3f93 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -181,10 +181,6 @@ extern u_int32_t stream_get_ipv4 (struct stream *); Use stream_read_try instead. */ extern int stream_read (struct stream *, int, size_t); -/* Deprecated: all file descriptors should already be non-blocking. - Will be removed. Use stream_read_try instead. */ -extern int stream_read_unblock (struct stream *, int, size_t); - /* Read up to size bytes into the stream. Return code: >0: number of bytes read diff --git a/lib/thread.c b/lib/thread.c index e89af541..1e714417 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -20,8 +20,9 @@ */ /* #define DEBUG */ - +#include <errno.h> #include <zebra.h> +#include <sys/times.h> #include "thread.h" #include "memory.h" @@ -31,8 +32,7 @@ #include "sigevent.h" /* Recent absolute time of day */ -struct timeval recent_time; -static struct timeval last_recent_time; +static struct timeval recent_time; /* Relative time, since startup */ static struct timeval relative_time; static struct timeval relative_time_base; @@ -94,54 +94,98 @@ timeval_elapsed (struct timeval a, struct timeval b) } #ifndef HAVE_CLOCK_MONOTONIC +static unsigned long recent_clock_mark; /* Holds value of last call to times(2) */ +static unsigned long last_clock_mark; +static unsigned long clocks_per_sec, msec_scale, usec_scale; + +static unsigned long quagga_times(void) +{ +#if defined(GNU_LINUX) + unsigned long ret; + + errno = 0; + ret = times(NULL); /* Linux can handle NULL */ + /* Workaround broken syscall impl. + * A bugfix exists for the kernel, hopefully + * it will make it into 2.6.28 + */ + if (errno) + ret = (unsigned long) (-errno); + return ret; +#else + struct tms dummy; /* Only return value is used */ + + return times(&dummy); +#endif +} + static void quagga_gettimeofday_relative_adjust (void) { - struct timeval diff; - if (timeval_cmp (recent_time, last_recent_time) < 0) - { - relative_time.tv_sec++; - relative_time.tv_usec = 0; - } - else - { - diff = timeval_subtract (recent_time, last_recent_time); - relative_time.tv_sec += diff.tv_sec; - relative_time.tv_usec += diff.tv_usec; - relative_time = timeval_adjust (relative_time); - } - last_recent_time = recent_time; + unsigned long diff; + + diff = recent_clock_mark - last_clock_mark; + if (!diff) + return; + /* save mark for next calculation */ + last_clock_mark = recent_clock_mark; + + relative_time.tv_sec += diff / clocks_per_sec; /* convert to seconds */ + relative_time.tv_usec += (diff % clocks_per_sec) * usec_scale; /* convert to useconds */ + relative_time = timeval_adjust (relative_time); } #endif /* !HAVE_CLOCK_MONOTONIC */ +static int init_quagga_timers(void) +{ + int ret; + + ret = gettimeofday (&recent_time, NULL); + relative_time_base = recent_time; +#if !defined(HAVE_CLOCK_MONOTONIC) + clocks_per_sec = sysconf(_SC_CLK_TCK); + assert(clocks_per_sec != 0); + + /* Precondition: 1000 % clocks_per_sec == 0 */ + assert(1000 % clocks_per_sec == 0); + msec_scale = 1000 / clocks_per_sec; + + /* Precondition: TIMER_SECOND_MICRO % clocks_per_sec == 0 */ + assert(TIMER_SECOND_MICRO % clocks_per_sec == 0); + usec_scale = TIMER_SECOND_MICRO / clocks_per_sec; + recent_clock_mark = quagga_times(); + last_clock_mark = recent_clock_mark; +#endif + if (ret) + return ret; + timers_inited = 1; + return 0; +} + /* gettimeofday wrapper, to keep recent_time updated */ static int quagga_gettimeofday (struct timeval *tv) { int ret; - - assert (tv); - - if (!(ret = gettimeofday (&recent_time, NULL))) - { - /* init... */ - if (!timers_inited) - { - relative_time_base = last_recent_time = recent_time; - timers_inited = 1; - } - /* avoid copy if user passed recent_time pointer.. */ - if (tv != &recent_time) - *tv = recent_time; - return 0; - } - return ret; + + /* init... */ + if (!timers_inited) + ret = init_quagga_timers(); + else + ret = gettimeofday (&recent_time, NULL); + if (ret) + return ret; + + /* avoid copy if user passed recent_time pointer.. */ + if (tv != &recent_time) + *tv = recent_time; + return 0; } static int quagga_get_relative (struct timeval *tv) { - int ret; + int ret = 0; #ifdef HAVE_CLOCK_MONOTONIC { @@ -153,8 +197,12 @@ quagga_get_relative (struct timeval *tv) } } #else /* !HAVE_CLOCK_MONOTONIC */ - if (!(ret = quagga_gettimeofday (&recent_time))) - quagga_gettimeofday_relative_adjust(); + /* init... */ + if (!timers_inited) + ret = init_quagga_timers(); + + recent_clock_mark = quagga_times(); + quagga_gettimeofday_relative_adjust(); #endif /* HAVE_CLOCK_MONOTONIC */ if (tv) @@ -910,7 +958,6 @@ thread_fetch (struct thread_master *m, struct thread *fetch) struct thread *thread; fd_set readfd; fd_set writefd; - fd_set exceptfd; struct timeval timer_val; struct timeval timer_val_bg; struct timeval *timer_wait; @@ -936,7 +983,6 @@ thread_fetch (struct thread_master *m, struct thread *fetch) /* Structure copy. */ readfd = m->readfd; writefd = m->writefd; - exceptfd = m->exceptfd; /* Calculate select wait timer if nothing else to do */ quagga_get_relative (NULL); @@ -947,7 +993,7 @@ thread_fetch (struct thread_master *m, struct thread *fetch) (!timer_wait || (timeval_cmp (*timer_wait, *timer_wait_bg) > 0))) timer_wait = timer_wait_bg; - num = select (FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait); + num = select (FD_SETSIZE, &readfd, &writefd, NULL, timer_wait); /* Signals should get quick treatment */ if (num < 0) @@ -1028,14 +1074,6 @@ thread_getrusage (RUSAGE_T *r) getrusage(RUSAGE_SELF, &(r->cpu)); #endif r->real = relative_time; - -#ifdef HAVE_CLOCK_MONOTONIC - /* quagga_get_relative() only updates recent_time if gettimeofday - * based, not when using CLOCK_MONOTONIC. As we export recent_time - * and guarantee to update it before threads are run... - */ - quagga_gettimeofday(&recent_time); -#endif /* HAVE_CLOCK_MONOTONIC */ } /* We check thread consumed time. If the system has getrusage, we'll diff --git a/lib/thread.h b/lib/thread.h index f3769e25..c0198a36 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -54,7 +54,6 @@ struct thread_master struct thread_list background; fd_set readfd; fd_set writefd; - fd_set exceptfd; unsigned long alloc; }; @@ -216,10 +215,6 @@ extern time_t quagga_time (time_t *); extern unsigned long thread_consumed_time(RUSAGE_T *after, RUSAGE_T *before, unsigned long *cpu_time_elapsed); -/* Global variable containing a recent result from gettimeofday. This can - be used instead of calling gettimeofday if a recent value is sufficient. - This is guaranteed to be refreshed before a thread is called. */ -extern struct timeval recent_time; /* Similar to recent_time, but a monotonically increasing time value */ extern struct timeval recent_relative_time (void); #endif /* _ZEBRA_THREAD_H */ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 777bc7c9..cb347451 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1394,13 +1394,17 @@ DEFUN (ipv6_ospf6_advertise_prefix_list, oi->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, argv[0]); ospf6_interface_connected_route_update (oi->interface); - OSPF6_LINK_LSA_SCHEDULE (oi); - if (oi->state == OSPF6_INTERFACE_DR) + + if (oi->area) { - OSPF6_NETWORK_LSA_SCHEDULE (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); + OSPF6_LINK_LSA_SCHEDULE (oi); + if (oi->state == OSPF6_INTERFACE_DR) + { + OSPF6_NETWORK_LSA_SCHEDULE (oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); + } + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); } - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); return CMD_SUCCESS; } @@ -1433,13 +1437,17 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list, } ospf6_interface_connected_route_update (oi->interface); - OSPF6_LINK_LSA_SCHEDULE (oi); - if (oi->state == OSPF6_INTERFACE_DR) + + if (oi->area) { - OSPF6_NETWORK_LSA_SCHEDULE (oi); - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); + OSPF6_LINK_LSA_SCHEDULE (oi); + if (oi->state == OSPF6_INTERFACE_DR) + { + OSPF6_NETWORK_LSA_SCHEDULE (oi); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi); + } + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); } - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area); return CMD_SUCCESS; } diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 15fd2e5f..bd5c026c 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -2470,7 +2470,7 @@ ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr) ifaddr = nbr->oi->address->u.prefix4; } - nbraddr = nbr->address.u.prefix4; + nbraddr = nbr->src; msg = new_msg_nsm_change (0, ifaddr, nbraddr, nbr->router_id, nbr->state); if (!msg) diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index 5d0cae42..d3873561 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -130,18 +130,6 @@ ospf_find_asbr_route_through_area (struct route_table *rtrs, return NULL; } -static void -ospf_ase_complete_direct_routes (struct ospf_route *ro, struct in_addr nexthop) -{ - struct listnode *node; - struct ospf_path *op; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (ro->paths, node, op)) - if (op->nexthop.s_addr == 0) - op->nexthop.s_addr = nexthop.s_addr; -} - static int ospf_ase_forward_address_check (struct ospf *ospf, struct in_addr fwd_addr) { @@ -451,8 +439,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) /* if there is a Intra/Inter area route to the N do not install external route */ - if (rn = route_node_lookup (ospf->new_table, - (struct prefix *) &p)) + if ((rn = route_node_lookup (ospf->new_table, + (struct prefix *) &p))) { route_unlock_node(rn); if (rn->info == NULL) @@ -463,8 +451,8 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) } /* Find a route to the same dest */ /* If there is no route, create new one. */ - if (rn = route_node_lookup (ospf->new_external_route, - (struct prefix *) &p)) + if ((rn = route_node_lookup (ospf->new_external_route, + (struct prefix *) &p))) route_unlock_node(rn); if (!rn || (or = rn->info) == NULL) @@ -475,8 +463,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) ospf_route_add (ospf->new_external_route, &p, new, asbr_route); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); return 0; } else @@ -513,8 +499,7 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) if (IS_DEBUG_OSPF (lsa, LSA)) zlog_debug ("Route[External]: New route is better"); ospf_route_subst (rn, new, asbr_route); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (new, al->e[0].fwd_addr); + or = new; new = NULL; } @@ -531,8 +516,6 @@ ospf_ase_calculate_route (struct ospf *ospf, struct ospf_lsa * lsa) if (IS_DEBUG_OSPF (lsa, LSA)) zlog_debug ("Route[External]: Routes are equal"); ospf_route_copy_nexthops (or, asbr_route->paths); - if (al->e[0].fwd_addr.s_addr) - ospf_ase_complete_direct_routes (or, al->e[0].fwd_addr); } } /* Make sure setting newly calculated ASBR route.*/ diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index e65b2e33..4786a87c 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -215,9 +215,9 @@ ospf_nbr_state_message (struct ospf_neighbor *nbr, char *buf, size_t size) int state; struct ospf_interface *oi = nbr->oi; - if (IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4)) + if (IPV4_ADDR_SAME (&DR (oi), &nbr->src)) state = ISM_DR; - else if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) + else if (IPV4_ADDR_SAME (&BDR (oi), &nbr->src)) state = ISM_Backup; else state = ISM_DROther; diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 41661da2..5ebf4f2f 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -346,7 +346,7 @@ ospf_flood_through_interface (struct ospf_interface *oi, struct ospf_lsa *lsa) { struct ospf_neighbor *onbr; - struct route_node *rn; + struct listnode *node; int retx_flag; if (IS_DEBUG_OSPF_EVENT) @@ -364,14 +364,10 @@ ospf_flood_through_interface (struct ospf_interface *oi, /* Each of the neighbors attached to this interface are examined, to determine whether they must receive the new LSA. The following steps are executed for each neighbor: */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, onbr)) { struct ospf_lsa *ls_req; - - if (rn->info == NULL) - continue; - onbr = rn->info; if (IS_DEBUG_OSPF_EVENT) zlog_debug ("ospf_flood_through_interface(): considering nbr %s (%s)", inet_ntoa (onbr->router_id), @@ -543,13 +539,12 @@ ospf_flood_through_interface (struct ospf_interface *oi, addresses. */ if (oi->type == OSPF_IFTYPE_NBMA) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) - ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) + ospf_ls_upd_send_lsa (nbr, lsa, OSPF_SEND_PACKET_DIRECT); } else ospf_ls_upd_send_lsa (oi->nbr_self, lsa, OSPF_SEND_PACKET_INDIRECT); @@ -934,21 +929,20 @@ static void ospf_ls_retransmit_delete_nbr_if (struct ospf_interface *oi, struct ospf_lsa *lsa) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; struct ospf_lsa *lsr; if (ospf_if_is_enable (oi)) - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) /* If LSA find in LS-retransmit list, then remove it. */ - if ((nbr = rn->info) != NULL) - { - lsr = ospf_ls_retransmit_lookup (nbr, lsa); - - /* If LSA find in ls-retransmit list, remove it. */ - if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum) - ospf_ls_retransmit_delete (nbr, lsr); - } + { + lsr = ospf_ls_retransmit_lookup (nbr, lsa); + + /* If LSA find in ls-retransmit list, remove it. */ + if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum) + ospf_ls_retransmit_delete (nbr, lsr); + } } void diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index afe3acf1..33a83b4d 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -211,7 +211,9 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) } else return oi; - + + ospf_lsa_pos_set(-1,-1, oi); /* delete position in router LSA */ + /* Set zebra interface pointer. */ oi->ifp = ifp; oi->address = p; @@ -223,7 +225,7 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) oi->network_lsa_self = NULL; /* Initialize neighbor list. */ - oi->nbrs = route_table_init (); + oi->nbrs = list_new (); /* Initialize static neighbor list. */ oi->nbr_nbma = list_new (); @@ -258,7 +260,6 @@ ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p) void ospf_if_cleanup (struct ospf_interface *oi) { - struct route_node *rn; struct listnode *node, *nnode; struct ospf_neighbor *nbr; struct ospf_nbr_nbma *nbr_nbma; @@ -282,10 +283,9 @@ ospf_if_cleanup (struct ospf_interface *oi) } /* send Neighbor event KillNbr to all associated neighbors. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr != oi->nbr_self) - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr); + for (ALL_LIST_ELEMENTS (oi->nbrs, node, nnode, nbr)) + if (nbr != oi->nbr_self) + OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr); /* Cleanup Link State Acknowlegdment list. */ for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa)) @@ -321,7 +321,7 @@ ospf_if_free (struct ospf_interface *oi) /* Free Pseudo Neighbour */ ospf_nbr_delete (oi->nbr_self); - route_table_finish (oi->nbrs); + list_free (oi->nbrs); route_table_finish (oi->ls_upd_queue); /* Free any lists that should be freed */ @@ -397,6 +397,29 @@ ospf_if_exists (struct ospf_interface *oic) return NULL; } +/* Lookup OSPF interface by router LSA posistion */ +struct ospf_interface * +ospf_if_lookup_by_lsa_pos (struct ospf_area *area, int lsa_pos) +{ + struct listnode *node; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) + { + if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end) + return oi; + } + return NULL; +} + +/* Set OSPF interface position in router LSA */ +void +ospf_lsa_pos_set(int pos_beg, int pos_end, struct ospf_interface *oi) +{ + oi->lsa_pos_beg = pos_beg; + oi->lsa_pos_end = pos_end; +} + struct ospf_interface * ospf_if_lookup_by_local_addr (struct ospf *ospf, struct interface *ifp, struct in_addr address) @@ -479,6 +502,20 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src, return match; } + +struct ospf_interface * +ospf_if_lookup_by_ifindex(struct ospf_area *area, unsigned int ifindex) +{ + struct listnode *node; + struct ospf_interface *oi; + + for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) + { + if (oi->ifp->ifindex == ifindex) + return oi; + } + return NULL; +} void ospf_if_stream_set (struct ospf_interface *oi) @@ -803,6 +840,7 @@ ospf_if_down (struct ospf_interface *oi) return 0; OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); + ospf_lsa_pos_set(-1, -1, oi); /* delete position in router LSA */ /* Shutdown packet reception and sending */ ospf_if_stream_unset (oi); diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index ab0b7580..82bf31a5 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -47,6 +47,7 @@ struct ospf_if_params DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */ DECLARE_IF_PARAM (u_char, passive_interface); /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */ DECLARE_IF_PARAM (u_char, priority); /* OSPF Interface priority */ + DECLARE_IF_PARAM (struct in_addr, if_area); /* Enable OSPF on this interface with area if_area */ DECLARE_IF_PARAM (u_char, type); /* type of interface */ #define OSPF_IF_ACTIVE 0 #define OSPF_IF_PASSIVE 1 @@ -124,6 +125,10 @@ struct ospf_interface /* OSPF Area. */ struct ospf_area *area; +/* Position range in Router LSA */ + int lsa_pos_beg; /* inclusive, >= */ + int lsa_pos_end; /* exclusive, < */ + /* Interface data from zebra. */ struct interface *ifp; struct ospf_vl_data *vl_data; /* Data for Virtual Link */ @@ -171,7 +176,7 @@ struct ospf_interface u_int32_t output_cost; /* Acutual Interface Output Cost */ /* Neighbor information. */ - struct route_table *nbrs; /* OSPF Neighbor List */ + struct list *nbrs; /* OSPF Neighbor List */ struct ospf_neighbor *nbr_self; /* Neighbor Self */ #define DR(I) ((I)->nbr_self->d_router) #define BDR(I) ((I)->nbr_self->bd_router) @@ -242,6 +247,9 @@ extern int ospf_if_down (struct ospf_interface *); extern int ospf_if_is_up (struct ospf_interface *); extern struct ospf_interface *ospf_if_exists (struct ospf_interface *); +extern struct ospf_interface *ospf_if_lookup_by_lsa_pos (struct ospf_area *, + int); +extern void ospf_lsa_pos_set(int, int, struct ospf_interface *); extern struct ospf_interface *ospf_if_lookup_by_local_addr (struct ospf *, struct interface *, @@ -256,7 +264,8 @@ extern struct ospf_interface *ospf_if_lookup_recv_if (struct ospf *, struct interface *); extern struct ospf_interface *ospf_if_is_configured (struct ospf *, struct in_addr *); - +extern struct ospf_interface *ospf_if_lookup_by_ifindex(struct ospf_area *, + unsigned int); extern struct ospf_if_params *ospf_lookup_if_params (struct interface *, struct in_addr); extern struct ospf_if_params *ospf_get_if_params (struct interface *, diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index 18402836..2186e894 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -88,7 +88,7 @@ ospf_elect_dr (struct ospf_interface *oi, struct list *el_list) listnode_add (dr_list, nbr); /* Preserve neighbor BDR. */ - if (IPV4_ADDR_SAME (&BDR (oi), &nbr->address.u.prefix4)) + if (IPV4_ADDR_SAME (&BDR (oi), &nbr->src)) bdr = nbr; } @@ -100,7 +100,7 @@ ospf_elect_dr (struct ospf_interface *oi, struct list *el_list) /* Set DR to interface. */ if (dr) - DR (oi) = dr->address.u.prefix4; + DR (oi) = dr->src; else DR (oi).s_addr = 0; @@ -141,7 +141,7 @@ ospf_elect_bdr (struct ospf_interface *oi, struct list *el_list) /* Set BDR to interface. */ if (bdr) - BDR (oi) = bdr->address.u.prefix4; + BDR (oi) = bdr->src; else BDR (oi).s_addr = 0; @@ -163,38 +163,36 @@ ospf_ism_state (struct ospf_interface *oi) } static void -ospf_dr_eligible_routers (struct route_table *nbrs, struct list *el_list) +ospf_dr_eligible_routers (struct list *nbrs, struct list *el_list) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor eligible? */ - if (nbr->priority > 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - listnode_add (el_list, nbr); + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor eligible? */ + if (nbr->priority > 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + listnode_add (el_list, nbr); } /* Generate AdjOK? NSM event. */ static void -ospf_dr_change (struct ospf *ospf, struct route_table *nbrs) +ospf_dr_change (struct ospf *ospf, struct list *nbrs) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore 0.0.0.0 node*/ - if (nbr->router_id.s_addr != 0) - /* Is neighbor upper 2-Way? */ - if (nbr->state >= NSM_TwoWay) - /* Ignore myself. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id)) - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK); + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + /* Ignore 0.0.0.0 node*/ + if (nbr->router_id.s_addr != 0) + /* Is neighbor upper 2-Way? */ + if (nbr->state >= NSM_TwoWay) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf->router_id)) + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_AdjOK); } static int diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index e708d5e2..6dd1d341 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -436,17 +436,13 @@ struct ospf_neighbor * ospf_nbr_lookup_ptop (struct ospf_interface *oi) { struct ospf_neighbor *nbr = NULL; - struct route_node *rn; + struct listnode *node; /* Search neighbor, there must be one of two nbrs. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) - { - route_unlock_node (rn); - break; - } + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + break; /* PtoP link must have only 1 neighbor. */ if (ospf_nbr_count (oi, 0) > 1) @@ -531,9 +527,16 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) { /* For unnumbered point-to-point networks, the Link Data field should specify the interface's MIB-II ifIndex value. */ - links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, + if (CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + id.s_addr = htonl(oi->ifp->ifindex); + else + id = oi->address->u.prefix4; + + links += link_info_set (s, nbr->router_id, id, LSA_LINK_TYPE_POINTOPOINT, 0, cost); } + if (CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + return links; /* Regardless of the state of the neighboring router, we must add a Type 3 link (stub network). @@ -623,7 +626,7 @@ static int lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) { int links = 0; - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr = NULL; struct in_addr id, mask; u_int16_t cost = ospf_link_cost (oi); @@ -636,20 +639,18 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) zlog_debug ("PointToMultipoint: running ptomultip_set"); /* Search neighbor, */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - /* Ignore myself. */ - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + /* Ignore myself. */ + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + { + links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, + LSA_LINK_TYPE_POINTOPOINT, 0, cost); + if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) + zlog_debug ("PointToMultipoint: set link to %s", + inet_ntoa(oi->address->u.prefix4)); + } - { - links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, - LSA_LINK_TYPE_POINTOPOINT, 0, cost); - if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) - zlog_debug ("PointToMultipoint: set link to %s", - inet_ntoa(oi->address->u.prefix4)); - } - return links; } @@ -657,9 +658,11 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) static int router_lsa_link_set (struct stream *s, struct ospf_area *area) { + struct ospf_host_route *host; + struct in_addr host_mask = {~0}; /* All ones */ struct listnode *node; struct ospf_interface *oi; - int links = 0; + int links = 0, old_links; for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi)) { @@ -670,6 +673,7 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) { if (oi->state != ISM_Down) { + old_links = links; /* Describe each link. */ switch (oi->type) { @@ -691,10 +695,14 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) case OSPF_IFTYPE_LOOPBACK: links += lsa_link_loopback_set (s, oi); } + ospf_lsa_pos_set(old_links, links, oi); } } } - + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (host->area == NULL || host->area == area) + links += link_info_set (s, host->host_addr, host_mask, + LSA_LINK_TYPE_STUB, 0, host->cost); return links; } @@ -1025,7 +1033,7 @@ static void ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi) { struct in_addr mask; - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; masklen2ip (oi->address->prefixlen, &mask); @@ -1036,10 +1044,9 @@ ospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi) its OSPF Router ID. The Designated Router includes itself in this list. RFC2328, Section 12.4.2 */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr->state == NSM_Full || nbr == oi->nbr_self) - stream_put_ipv4 (s, nbr->router_id.s_addr); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr->state == NSM_Full || nbr == oi->nbr_self) + stream_put_ipv4 (s, nbr->router_id.s_addr); } static struct ospf_lsa * @@ -2839,19 +2846,14 @@ ospf_check_nbr_status (struct ospf *ospf) struct listnode *node, *nnode; struct ospf_interface *oi; - for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) + for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) { - struct route_node *rn; struct ospf_neighbor *nbr; if (ospf_if_is_enable (oi)) - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading) - { - route_unlock_node (rn); - return 0; - } + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + if (nbr->state == NSM_Exchange || nbr->state == NSM_Loading) + return 0; } return 1; diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index 967ca15d..e55a1903 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -43,26 +43,6 @@ #include "ospfd/ospf_flood.h" #include "ospfd/ospf_dump.h" -/* Fill in the the 'key' as appropriate to retrieve the entry for nbr - * from the ospf_interface's nbrs table. Indexed by interface address - * for all cases except Virtual-link interfaces, where neighbours are - * indexed by router-ID instead. - */ -static void -ospf_nbr_key (struct ospf_interface *oi, struct ospf_neighbor *nbr, - struct prefix *key) -{ - key->family = AF_INET; - key->prefixlen = IPV4_MAX_BITLEN; - - /* vlinks are indexed by router-id */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - key->u.prefix4 = nbr->router_id; - else - key->u.prefix4 = nbr->src; - return; -} - struct ospf_neighbor * ospf_nbr_new (struct ospf_interface *oi) { @@ -143,44 +123,43 @@ ospf_nbr_free (struct ospf_neighbor *nbr) XFREE (MTYPE_OSPF_NEIGHBOR, nbr); } +/* lookup nbr by address - use this only if you know you must + * otherwise use the ospf_nbr_lookup() wrapper, which deals + * with virtual link and PointToPoint neighbours + */ +struct ospf_neighbor * +ospf_nbr_lookup_by_addr (struct list *nbrs, + struct in_addr *addr) +{ + struct listnode *node; + struct ospf_neighbor *nbr; -/* Delete specified OSPF neighbor from interface. */ -void -ospf_nbr_delete (struct ospf_neighbor *nbr) + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + if (IPV4_ADDR_SAME (&nbr->src, addr)) + return nbr; + + return NULL; +} + +struct ospf_neighbor * +ospf_nbr_lookup_by_routerid (struct list *nbrs, + struct in_addr *id) { - struct ospf_interface *oi; - struct route_node *rn; - struct prefix p; + struct listnode *node; + struct ospf_neighbor *nbr; - oi = nbr->oi; - - /* get appropriate prefix 'key' */ - ospf_nbr_key (oi, nbr, &p); + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) + if (IPV4_ADDR_SAME (&nbr->router_id, id)) + return nbr; - rn = route_node_lookup (oi->nbrs, &p); - if (rn) - { - /* If lookup for a NBR succeeds, the leaf route_node could - * only exist because there is (or was) a nbr there. - * If the nbr was deleted, the leaf route_node should have - * lost its last refcount too, and be deleted. - * Therefore a looked-up leaf route_node in nbrs table - * should never have NULL info. - */ - assert (rn->info); - - if (rn->info) - { - rn->info = NULL; - route_unlock_node (rn); - } - else - zlog_info ("Can't find neighbor %s in the interface %s", - inet_ntoa (nbr->src), IF_NAME (oi)); - - route_unlock_node (rn); - } + return NULL; +} +/* Delete specified OSPF neighbor from interface. */ +void +ospf_nbr_delete (struct ospf_neighbor *nbr) +{ + listnode_delete(nbr->oi->nbrs, nbr); /* Free ospf_neighbor structure. */ ospf_nbr_free (nbr); } @@ -206,11 +185,9 @@ ospf_nbr_bidirectional (struct in_addr *router_id, void ospf_nbr_add_self (struct ospf_interface *oi) { - struct prefix p; - struct route_node *rn; + struct ospf_neighbor *nbr; /* Initial state */ - oi->nbr_self->address = *oi->address; oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority); oi->nbr_self->router_id = oi->ospf->router_id; oi->nbr_self->src = oi->address->u.prefix4; @@ -229,19 +206,23 @@ ospf_nbr_add_self (struct ospf_interface *oi) SET_FLAG (oi->nbr_self->options, OSPF_OPTION_NP); break; } - - /* Add nbr_self to nbrs table */ - ospf_nbr_key (oi, oi->nbr_self, &p); - - rn = route_node_get (oi->nbrs, &p); - if (rn->info) + + /* Sanity check, should not be needed */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK || + oi->type == OSPF_IFTYPE_POINTOPOINT) + nbr = ospf_nbr_lookup_by_routerid (oi->nbrs, &oi->nbr_self->router_id); + else + nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &oi->nbr_self->src); + if (nbr) { - /* There is already pseudo neighbor. */ - assert (oi->nbr_self == rn->info); - route_unlock_node (rn); + assert (oi->nbr_self == nbr); + zlog_info("Self neighbor already added for ospf I/F:%s", + oi->ifp->name); + return; } - else - rn->info = oi->nbr_self; + + /* Add nbr_self to nbrs table */ + listnode_add(oi->nbrs, oi->nbr_self); } /* Get neighbor count by status. @@ -250,14 +231,13 @@ int ospf_nbr_count (struct ospf_interface *oi, int state) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; int count = 0; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (state == 0 || nbr->state == state) - count++; + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (state == 0 || nbr->state == state) + count++; return count; } @@ -267,80 +247,24 @@ int ospf_nbr_count_opaque_capable (struct ospf_interface *oi) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; int count = 0; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) - if (nbr->state == NSM_Full) - if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) - count++; + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) + if (nbr->state == NSM_Full) + if (CHECK_FLAG (nbr->options, OSPF_OPTION_O)) + count++; return count; } #endif /* HAVE_OPAQUE_LSA */ -/* lookup nbr by address - use this only if you know you must - * otherwise use the ospf_nbr_lookup() wrapper, which deals - * with virtual link neighbours - */ -struct ospf_neighbor * -ospf_nbr_lookup_by_addr (struct route_table *nbrs, - struct in_addr *addr) -{ - struct prefix p; - struct route_node *rn; - struct ospf_neighbor *nbr; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = *addr; - - rn = route_node_lookup (nbrs, &p); - if (! rn) - return NULL; - - /* See comment in ospf_nbr_delete */ - assert (rn->info); - - if (rn->info == NULL) - { - route_unlock_node (rn); - return NULL; - } - - nbr = (struct ospf_neighbor *) rn->info; - route_unlock_node (rn); - - return nbr; -} - -struct ospf_neighbor * -ospf_nbr_lookup_by_routerid (struct route_table *nbrs, - struct in_addr *id) -{ - struct route_node *rn; - struct ospf_neighbor *nbr; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) - if (IPV4_ADDR_SAME (&nbr->router_id, id)) - { - route_unlock_node(rn); - return nbr; - } - - return NULL; -} - void ospf_renegotiate_optional_capabilities (struct ospf *top) { - struct listnode *node; + struct listnode *node, *nnode; struct ospf_interface *oi; - struct route_table *nbrs; - struct route_node *rn; struct ospf_neighbor *nbr; /* At first, flush self-originated LSAs from routing domain. */ @@ -349,12 +273,9 @@ ospf_renegotiate_optional_capabilities (struct ospf *top) /* Revert all neighbor status to ExStart. */ for (ALL_LIST_ELEMENTS_RO (top->oiflist, node, oi)) { - if ((nbrs = oi->nbrs) == NULL) - continue; - - for (rn = route_top (nbrs); rn; rn = route_next (rn)) - { - if ((nbr = rn->info) == NULL || nbr == oi->nbr_self) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + { + if (nbr == oi->nbr_self) continue; if (nbr->state < NSM_ExStart) @@ -375,22 +296,22 @@ struct ospf_neighbor * ospf_nbr_lookup (struct ospf_interface *oi, struct ip *iph, struct ospf_header *ospfh) { - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - return (ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id)); + if (oi->type == OSPF_IFTYPE_VIRTUALLINK || + oi->type == OSPF_IFTYPE_POINTOPOINT) + return ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id); else - return (ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src)); + return ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src); } static struct ospf_neighbor * ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh, - struct prefix *p) + struct ip *iph) { struct ospf_neighbor *nbr; nbr = ospf_nbr_new (oi); nbr->state = NSM_Down; - nbr->src = p->u.prefix4; - memcpy (&nbr->address, p, sizeof (struct prefix)); + nbr->src = iph->ip_src; nbr->nbr_nbma = NULL; if (oi->type == OSPF_IFTYPE_NBMA) @@ -420,43 +341,31 @@ ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh, if (IS_DEBUG_OSPF_EVENT) zlog_debug ("NSM[%s:%s]: start", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); - + + listnode_add(oi->nbrs, nbr); return nbr; } struct ospf_neighbor * ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh, - struct ip *iph, struct prefix *p) + struct ip *iph) { - struct route_node *rn; - struct prefix key; struct ospf_neighbor *nbr; - - key.family = AF_INET; - key.prefixlen = IPV4_MAX_BITLEN; - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - key.u.prefix4 = ospfh->router_id; /* index vlink nbrs by router-id */ - else - key.u.prefix4 = iph->ip_src; - - rn = route_node_get (oi->nbrs, &key); - if (rn->info) + nbr = ospf_nbr_lookup (oi, iph, ospfh); + if (nbr) { - route_unlock_node (rn); - nbr = rn->info; - if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) { nbr->src = iph->ip_src; - memcpy (&nbr->address, p, sizeof (struct prefix)); } } else { - rn->info = nbr = ospf_nbr_add (oi, ospfh, p); + nbr = ospf_nbr_add (oi, ospfh, iph); + listnode_add (oi->nbrs, nbr); } - + nbr->router_id = ospfh->router_id; return nbr; diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 25f13524..70cc7855 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -37,8 +37,6 @@ struct ospf_neighbor u_int32_t dd_seqnum; /* DD Sequence Number. */ /* Neighbor Information from Hello. */ - struct prefix address; /* Neighbor Interface Address. */ - struct in_addr src; /* Src address. */ struct in_addr router_id; /* Router ID. */ u_char options; /* Options. */ @@ -91,8 +89,8 @@ struct ospf_neighbor }; /* Macros. */ -#define NBR_IS_DR(n) IPV4_ADDR_SAME (&n->address.u.prefix4, &n->d_router) -#define NBR_IS_BDR(n) IPV4_ADDR_SAME (&n->address.u.prefix4, &n->bd_router) +#define NBR_IS_DR(n) IPV4_ADDR_SAME (&n->src, &n->d_router) +#define NBR_IS_BDR(n) IPV4_ADDR_SAME (&n->src, &n->bd_router) /* Prototypes. */ extern struct ospf_neighbor *ospf_nbr_new (struct ospf_interface *); @@ -106,14 +104,13 @@ extern int ospf_nbr_count_opaque_capable (struct ospf_interface *); #endif /* HAVE_OPAQUE_LSA */ extern struct ospf_neighbor *ospf_nbr_get (struct ospf_interface *, struct ospf_header *, - struct ip *, struct prefix *); + struct ip *); extern struct ospf_neighbor *ospf_nbr_lookup (struct ospf_interface *, struct ip *, struct ospf_header *); -extern struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct route_table *, +extern struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct list *, struct in_addr *); -extern struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct route_table - *, +extern struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct list *, struct in_addr *); extern void ospf_renegotiate_optional_capabilities (struct ospf *top); diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 15fff349..b15efbd6 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -153,8 +153,8 @@ nsm_should_adj (struct ospf_neighbor *nbr) || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) || IPV4_ADDR_SAME (&oi->address->u.prefix4, &BDR (oi)) /* Neighboring Router is the DRouter or the BDRouter. */ - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &DR (oi)) - || IPV4_ADDR_SAME (&nbr->address.u.prefix4, &BDR (oi))) + || IPV4_ADDR_SAME (&nbr->src, &DR (oi)) + || IPV4_ADDR_SAME (&nbr->src, &BDR (oi))) return 1; return 0; @@ -393,7 +393,7 @@ nsm_kill_nbr (struct ospf_neighbor *nbr) if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) zlog_debug ("NSM[%s:%s]: Down (PollIntervalTimer scheduled)", - IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); + IF_NAME (nbr->oi), inet_ntoa (nbr->src)); } return 0; diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 0b6ac4cb..826d149f 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -2118,11 +2118,12 @@ out: * 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); +static void ospf_opaque_exclude_lsa_from_lsreq (struct list *nbrs, + struct ospf_neighbor *inbr, struct ospf_lsa *lsa); 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); +static unsigned long ospf_opaque_nrxmt_self (struct list *nbrs, int lsa_type); void ospf_opaque_adjust_lsreq (struct ospf_neighbor *nbr, struct list *lsas) @@ -2199,18 +2200,16 @@ out: } static void -ospf_opaque_exclude_lsa_from_lsreq (struct route_table *nbrs, +ospf_opaque_exclude_lsa_from_lsreq (struct list *nbrs, struct ospf_neighbor *inbr, struct ospf_lsa *lsa) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *onbr; struct ospf_lsa *ls_req; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (nbrs, node, onbr)) { - if ((onbr = rn->info) == NULL) - continue; if (onbr == inbr) continue; if ((ls_req = ospf_ls_request_lookup (onbr, lsa)) == NULL) @@ -2412,17 +2411,15 @@ out: } static unsigned long -ospf_opaque_nrxmt_self (struct route_table *nbrs, int lsa_type) +ospf_opaque_nrxmt_self (struct list *nbrs, int lsa_type) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; struct ospf *top; unsigned long n = 0; - for (rn = route_top (nbrs); rn; rn = route_next (rn)) + for (ALL_LIST_ELEMENTS_RO (nbrs, node, nbr)) { - 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)) diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1066e64f..74e1d46f 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -324,7 +324,7 @@ static int ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) { struct ospf_header *ospfh; - unsigned char digest[OSPF_AUTH_MD5_SIZE]; + unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0}; MD5_CTX ctx; void *ibuf; u_int32_t t; @@ -351,7 +351,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op) /* Get MD5 Authentication key from auth_key list. */ if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt))) - auth_key = (const u_int8_t *) ""; + auth_key = (const u_int8_t *) digest; else { ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt))); @@ -745,7 +745,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, struct ospf_hello *hello; struct ospf_neighbor *nbr; int old_state; - struct prefix p; /* increment statistics. */ oi->hello_in++; @@ -765,20 +764,15 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, return; } - /* get neighbor prefix. */ - p.family = AF_INET; - p.prefixlen = ip_masklen (hello->network_mask); - p.u.prefix4 = iph->ip_src; - /* Compare network mask. */ /* Checking is ignored for Point-to-Point and Virtual link. */ if (oi->type != OSPF_IFTYPE_POINTOPOINT && oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (oi->address->prefixlen != p.prefixlen) + if (oi->address->prefixlen != ip_masklen (hello->network_mask)) { zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).", inet_ntoa(ospfh->router_id), IF_NAME(oi), - (int)oi->address->prefixlen, (int)p.prefixlen); + (int)oi->address->prefixlen, (int)ip_masklen (hello->network_mask)); return; } @@ -873,7 +867,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, } /* get neighbour struct */ - nbr = ospf_nbr_get (oi, ospfh, iph, &p); + nbr = ospf_nbr_get (oi, ospfh, iph); /* neighbour must be valid, ospf_nbr_get creates if none existed */ assert (nbr); @@ -902,10 +896,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, (old_state == NSM_Down || old_state == NSM_Attempt)) { OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); - nbr->priority = hello->priority; - nbr->d_router = hello->d_router; - nbr->bd_router = hello->bd_router; - return; + goto done; } if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors, @@ -917,42 +908,50 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, else { OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); - /* Set neighbor information. */ - nbr->priority = hello->priority; - nbr->d_router = hello->d_router; - nbr->bd_router = hello->bd_router; - return; + goto done; } + /* Neighbor priority check. */ + if (nbr->priority >= 0 && nbr->priority != hello->priority) + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + /* If neighbor itself declares DR and no BDR exists, cause event BackupSeen */ - if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router)) - if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting) + if (oi->state == ISM_Waiting && + IPV4_ADDR_SAME (&nbr->src, &hello->d_router) && + hello->bd_router.s_addr == 0) + { OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); + goto done; + } + /* had not previously. */ + if ((IPV4_ADDR_SAME (&nbr->src, &hello->d_router) && + IPV4_ADDR_CMP (&nbr->src, &nbr->d_router)) || + (IPV4_ADDR_CMP (&nbr->src, &hello->d_router) && + IPV4_ADDR_SAME (&nbr->src, &nbr->d_router))) + { + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + goto done; + } /* neighbor itself declares BDR. */ if (oi->state == ISM_Waiting && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router)) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); - - /* had not previously. */ - if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) && - IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) || - (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router))) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); - + IPV4_ADDR_SAME (&nbr->src, &hello->bd_router)) + { + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); + goto done; + } /* had not previously. */ - if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) && - IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) || - (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) && - IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router))) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); - - /* Neighbor priority check. */ - if (nbr->priority >= 0 && nbr->priority != hello->priority) - OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + if ((IPV4_ADDR_SAME (&nbr->src, &hello->bd_router) && + IPV4_ADDR_CMP (&nbr->src, &nbr->bd_router)) || + (IPV4_ADDR_CMP (&nbr->src, &hello->bd_router) && + IPV4_ADDR_SAME (&nbr->src, &nbr->bd_router))) + { + OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); + goto done; + } + done: /* Set neighbor information. */ nbr->priority = hello->priority; nbr->d_router = hello->d_router; @@ -1260,7 +1259,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT "); if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O) - && IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4)) + && IPV4_ADDR_SAME (&DR (oi), &nbr->src)) { zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; " "Opaque-LSAs cannot be reliably advertised " @@ -2620,7 +2619,7 @@ static int ospf_make_hello (struct ospf_interface *oi, struct stream *s) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; u_int16_t length = OSPF_HELLO_MIN_SIZE; struct in_addr mask; unsigned long p; @@ -2662,10 +2661,9 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s) stream_put_ipv4 (s, BDR (oi).s_addr); /* Add neighbor seen. */ - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */ - if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */ + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */ + if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */ if (nbr->state != NSM_Down) /* This is myself for DR election. */ if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) { @@ -3048,7 +3046,7 @@ ospf_hello_reply_timer (struct thread *thread) zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); - ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4); + ospf_hello_send_sub (nbr->oi, &nbr->src); return 0; } @@ -3081,45 +3079,43 @@ ospf_hello_send (struct ospf_interface *oi) if (oi->type == OSPF_IFTYPE_NBMA) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + { + /* RFC 2328 Section 9.5.1 + If the router is not eligible to become Designated Router, + it must periodically send Hello Packets to both the + Designated Router and the Backup Designated Router (if they + exist). */ + if (PRIORITY(oi) == 0 && + IPV4_ADDR_CMP(&DR(oi), &nbr->src) && + IPV4_ADDR_CMP(&BDR(oi), &nbr->src)) + continue; + + /* If the router is eligible to become Designated Router, it + must periodically send Hello Packets to all neighbors that + are also eligible. In addition, if the router is itself the + Designated Router or Backup Designated Router, it must also + send periodic Hello Packets to all other neighbors. */ + + if (nbr->priority == 0 && oi->state == ISM_DROther) + continue; + /* if oi->state == Waiting, send hello to all neighbors */ { - /* RFC 2328 Section 9.5.1 - If the router is not eligible to become Designated Router, - it must periodically send Hello Packets to both the - Designated Router and the Backup Designated Router (if they - exist). */ - if (PRIORITY(oi) == 0 && - IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) && - IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4)) - continue; - - /* If the router is eligible to become Designated Router, it - must periodically send Hello Packets to all neighbors that - are also eligible. In addition, if the router is itself the - Designated Router or Backup Designated Router, it must also - send periodic Hello Packets to all other neighbors. */ - - if (nbr->priority == 0 && oi->state == ISM_DROther) - continue; - /* if oi->state == Waiting, send hello to all neighbors */ - { - struct ospf_packet *op_dup; + struct ospf_packet *op_dup; - op_dup = ospf_packet_dup(op); - op_dup->dst = nbr->address.u.prefix4; + op_dup = ospf_packet_dup(op); + op_dup->dst = nbr->src; - /* Add packet to the interface output queue. */ - ospf_packet_add (oi, op_dup); - - OSPF_ISM_WRITE_ON (oi->ospf); - } + /* Add packet to the interface output queue. */ + ospf_packet_add (oi, op_dup); + OSPF_ISM_WRITE_ON (oi->ospf); } + } ospf_packet_free (op); } else @@ -3165,7 +3161,7 @@ ospf_db_desc_send (struct ospf_neighbor *nbr) if (oi->type == OSPF_IFTYPE_POINTOPOINT) op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); else - op->dst = nbr->address.u.prefix4; + op->dst = nbr->src; /* Add packet to the interface output queue. */ ospf_packet_add (oi, op); @@ -3227,7 +3223,7 @@ ospf_ls_req_send (struct ospf_neighbor *nbr) if (oi->type == OSPF_IFTYPE_POINTOPOINT) op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); else - op->dst = nbr->address.u.prefix4; + op->dst = nbr->src; /* Add packet to the interface output queue. */ ospf_packet_add (oi, op); @@ -3434,7 +3430,7 @@ ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag) else if (oi->type == OSPF_IFTYPE_POINTOPOINT) p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS); else if (flag == OSPF_SEND_PACKET_DIRECT) - p.prefix = nbr->address.u.prefix4; + p.prefix = nbr->src; else if (oi->state == ISM_DR || oi->state == ISM_Backup) p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS); else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) @@ -3514,7 +3510,7 @@ ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa) struct ospf_interface *oi = nbr->oi; if (listcount (oi->ls_ack_direct.ls_ack) == 0) - oi->ls_ack_direct.dst = nbr->address.u.prefix4; + oi->ls_ack_direct.dst = nbr->src; listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa)); @@ -3537,13 +3533,12 @@ ospf_ls_ack_send_delayed (struct ospf_interface *oi) if (oi->type == OSPF_IFTYPE_NBMA) { struct ospf_neighbor *nbr; - struct route_node *rn; + struct listnode *node; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL) + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange) while (listcount (oi->ls_ack)) - ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4); + ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->src); return; } if (oi->type == OSPF_IFTYPE_VIRTUALLINK) diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 267237b8..2a81e97a 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -810,12 +810,18 @@ ospf_route_copy_nexthops_from_vertex (struct ospf_route *to, { nexthop = vp->nexthop; - if (nexthop->oi != NULL) + if (nexthop->oi != NULL) { - if (! ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) + if (!ospf_path_exist (to->paths, nexthop->router, nexthop->oi)) { path = ospf_path_new (); - path->nexthop = nexthop->router; + + /* PtoP I/F's are always directly connected */ + if (if_is_pointopoint (nexthop->oi->ifp)) + path->nexthop.s_addr = INADDR_ANY; + else + path->nexthop = nexthop->router; + path->ifindex = nexthop->oi->ifp->ifindex; listnode_add (to->paths, path); } diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 17ab68e5..5483aaf5 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -121,6 +121,12 @@ struct ospf_route } u; }; +struct ospf_host_route { + struct in_addr host_addr; + u_int32_t cost; /* i.e. metric. */ + struct ospf_area *area; /* NULL == all areas */ +}; + extern struct ospf_path *ospf_path_new (void); extern void ospf_path_free (struct ospf_path *); extern struct ospf_path *ospf_path_lookup (struct list *, struct ospf_path *); diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index cc4974ce..84b169f4 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -2105,16 +2105,15 @@ static struct ospf_neighbor * ospf_snmp_nbr_lookup (struct ospf *ospf, struct in_addr *nbr_addr, unsigned int *ifindex) { - struct listnode *node, *nnode; + struct listnode *node, *nnode, *nbrnode; struct ospf_interface *oi; struct ospf_neighbor *nbr; struct route_node *rn; for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) { - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL - && nbr != oi->nbr_self + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nbrnode, nbr)) + if (nbr != oi->nbr_self /* If EXACT match is needed, provide ALL entry found && nbr->state != NSM_Down */ @@ -2134,10 +2133,9 @@ static struct ospf_neighbor * ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, int first) { - struct listnode *nn; + struct listnode *nn, *nbrnode; struct ospf_interface *oi; struct ospf_neighbor *nbr; - struct route_node *rn; struct ospf_neighbor *min = NULL; struct ospf *ospf = ospf; @@ -2145,9 +2143,8 @@ ospf_snmp_nbr_lookup_next (struct in_addr *nbr_addr, unsigned int *ifindex, for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, nn, oi)) { - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info) != NULL - && nbr != oi->nbr_self + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nbrnode, nbr)) + if (nbr != oi->nbr_self && nbr->state != NSM_Down && nbr->src.s_addr != 0) { @@ -2613,9 +2610,9 @@ ospfTrapNbrStateChange (struct ospf_neighbor *on) ospf_nbr_state_message(on, msgbuf, sizeof(msgbuf)); zlog (NULL, LOG_INFO, "ospfTrapNbrStateChange trap sent: %s now %s", - inet_ntoa(on->address.u.prefix4), msgbuf); + inet_ntoa(on->router_id), msgbuf); - oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE); + oid_copy_addr (index, &(on->router_id), IN_ADDR_SIZE); index[IN_ADDR_SIZE] = 0; smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid), @@ -2632,7 +2629,7 @@ ospfTrapVirtNbrStateChange (struct ospf_neighbor *on) zlog (NULL, LOG_INFO, "ospfTrapVirtNbrStateChange trap sent"); - oid_copy_addr (index, &(on->address.u.prefix4), IN_ADDR_SIZE); + oid_copy_addr (index, &(on->router_id), IN_ADDR_SIZE); index[IN_ADDR_SIZE] = 0; smux_trap (ospf_oid, sizeof ospf_oid / sizeof (oid), diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index ca200222..fb863681 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -480,13 +480,15 @@ ospf_spf_add_parent (struct vertex *v, struct vertex *w, static unsigned int ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, struct vertex *w, struct router_lsa_link *l, - unsigned int distance) + unsigned int distance, int lsa_pos) { struct listnode *node, *nnode; struct vertex_nexthop *nh; struct vertex_parent *vp; struct ospf_interface *oi = NULL; unsigned int added = 0; + char buf1[BUFSIZ]; + char buf2[BUFSIZ]; if (IS_DEBUG_OSPF_EVENT) { @@ -505,30 +507,38 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, the OSPF interface connecting to the destination network/router. */ + /* we *must* be supplied with the link data */ + assert (l != NULL); + oi = ospf_if_lookup_by_lsa_pos (area, lsa_pos); + if (!oi) + { + zlog_debug("%s: OI not found in LSA: lsa_pos:%d link_id:%s link_data:%s", + __func__, lsa_pos, + inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); + return 0; + } + + if (IS_DEBUG_OSPF_EVENT) + { + zlog_debug("%s: considering link:%s " + "type:%d link_id:%s link_data:%s", + __func__, oi->ifp->name, l->m[0].type, + inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), + inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); + } + if (w->type == OSPF_VERTEX_ROUTER) { /* l is a link from v to w * l2 will be link from w to v */ struct router_lsa_link *l2 = NULL; - - /* we *must* be supplied with the link data */ - assert (l != NULL); - - if (IS_DEBUG_OSPF_EVENT) - { - char buf1[BUFSIZ]; - char buf2[BUFSIZ]; - - zlog_debug("ospf_nexthop_calculation(): considering link " - "type %d link_id %s link_data %s", - l->m[0].type, - inet_ntop (AF_INET, &l->link_id, buf1, BUFSIZ), - inet_ntop (AF_INET, &l->link_data, buf2, BUFSIZ)); - } if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) { + struct in_addr nexthop; + /* If the destination is a router which connects to the calculating router via a Point-to-MultiPoint network, the destination's next hop IP address(es) @@ -539,68 +549,53 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, provides an IP address of the next hop router. At this point l is a link from V to W, and V is the - root ("us"). Find the local interface associated - with l (its address is in l->link_data). If it - is a point-to-multipoint interface, then look through - the links in the opposite direction (W to V). If - any of them have an address that lands within the + root ("us"). If it is a point-to-multipoint interface, + then look through the links in the opposite direction (W to V). + If any of them have an address that lands within the subnet declared by the PtMP link, then that link - is a constituent of the PtMP link, and its address is + is a constituent of the PtMP link, and its address is a nexthop address for V. */ - oi = ospf_if_is_configured (area->ospf, &l->link_data); - if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) - { - struct prefix_ipv4 la; - - la.family = AF_INET; - la.prefixlen = oi->address->prefixlen; - - /* V links to W on PtMP interface - - find the interface address on W */ - while ((l2 = ospf_get_next_link (w, v, l2))) - { - la.prefix = l2->link_data; - - if (prefix_cmp ((struct prefix *) &la, - oi->address) == 0) - /* link_data is on our PtMP network */ - break; - } - } /* end l is on point-to-multipoint link */ - else - { - /* l is a regular point-to-point link. - Look for a link from W to V. - */ - while ((l2 = ospf_get_next_link (w, v, l2))) - { - oi = ospf_if_is_configured (area->ospf, - &(l2->link_data)); - - if (oi == NULL) - continue; - - if (!IPV4_ADDR_SAME (&oi->address->u.prefix4, - &l->link_data)) - continue; - - break; - } - } - - if (oi && l2) + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + { + added = 1; + nexthop.s_addr = 0; /* Nexthop not required */ + } + else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + { + struct prefix_ipv4 la; + + la.family = AF_INET; + la.prefixlen = oi->address->prefixlen; + + /* V links to W on PtMP interface + - find the interface address on W */ + while ((l2 = ospf_get_next_link (w, v, l2))) + { + la.prefix = l2->link_data; + + if (prefix_cmp ((struct prefix *) &la, + oi->address) != 0) + continue; + /* link_data is on our PtMP network */ + added = 1; + nexthop = l2->link_data; + break; + } + } + + if (added) { /* found all necessary info to build nexthop */ nh = vertex_nexthop_new (); nh->oi = oi; - nh->router = l2->link_data; + nh->router = nexthop; ospf_spf_add_parent (v, w, nh, distance); return 1; } else - zlog_info("ospf_nexthop_calculation(): " - "could not determine nexthop for link"); + zlog_info("%s: could not determine nexthop for link %s", + __func__, oi->ifp->name); } /* end point-to-point link from V to W */ else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) { @@ -633,19 +628,13 @@ ospf_nexthop_calculation (struct ospf_area *area, struct vertex *v, else { assert(w->type == OSPF_VERTEX_NETWORK); - oi = ospf_if_is_configured (area->ospf, &(l->link_data)); - if (oi) - { - nh = vertex_nexthop_new (); - nh->oi = oi; - nh->router.s_addr = 0; - ospf_spf_add_parent (v, w, nh, distance); - return 1; - } + + nh = vertex_nexthop_new (); + nh->oi = oi; + nh->router.s_addr = 0; /* Nexthop not required */ + ospf_spf_add_parent (v, w, nh, distance); + return 1; } - zlog_info("ospf_nexthop_calculation(): " - "Unknown attached link"); - return 0; } /* end V is the root */ /* Check if W's parent is a network connected to root. */ else if (v->type == OSPF_VERTEX_NETWORK) @@ -726,7 +715,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, u_char *lim; struct router_lsa_link *l = NULL; struct in_addr *r; - int type = 0; + int type = 0, lsa_pos=-1, lsa_pos_next=0; /* If this is a router-LSA, and bit V of the router-LSA (see Section A.4.2:RFC2328) is set, set Area A's TransitCapability to TRUE. */ @@ -754,7 +743,8 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, if (v->lsa->type == OSPF_ROUTER_LSA) { l = (struct router_lsa_link *) p; - + lsa_pos = lsa_pos_next; /* LSA link position */ + lsa_pos_next++; p += (ROUTER_LSA_MIN_SIZE + (l->m[0].tos_count * ROUTER_LSA_TOS_SIZE)); @@ -876,7 +866,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, w = ospf_vertex_new (w_lsa); /* Calculate nexthop to W. */ - if (ospf_nexthop_calculation (area, v, w, l, distance)) + if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) pqueue_enqueue (w, candidate); else if (IS_DEBUG_OSPF_EVENT) zlog_debug ("Nexthop Calc failed"); @@ -896,7 +886,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, { /* Found an equal-cost path to W. * Calculate nexthop of to W from V. */ - ospf_nexthop_calculation (area, v, w, l, distance); + ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos); } /* less than. */ else @@ -906,7 +896,7 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, * valid nexthop it will call spf_add_parents, which * will flush the old parents */ - if (ospf_nexthop_calculation (area, v, w, l, distance)) + if (ospf_nexthop_calculation (area, v, w, l, distance, lsa_pos)) /* Decrease the key of the node in the heap. * trickle-sort it up towards root, just in case this * node should now be the new root due the cost change. diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index d024a2ac..236c10b1 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2839,6 +2839,9 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, vty_out (vty, " Internet Address %s/%d,", inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen); + vty_out(vty, " Unnumbered: %s,", + CHECK_FLAG(oi->ifp->status, ZEBRA_INTERFACE_UNNUMBERED) ? "YES" : "NO"); + if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK) { struct in_addr *dest; @@ -2888,7 +2891,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, vty_out (vty, " Designated Router (ID) %s,", inet_ntoa (nbr->router_id)); vty_out (vty, " Interface Address %s%s", - inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE); + inet_ntoa (nbr->src), VTY_NEWLINE); } } @@ -2907,7 +2910,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, vty_out (vty, " Backup Designated Router (ID) %s,", inet_ntoa (nbr->router_id)); vty_out (vty, " Interface Address %s%s", - inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE); + inet_ntoa (nbr->src), VTY_NEWLINE); } } @@ -3001,39 +3004,37 @@ show_ip_ospf_neighbour_header (struct vty *vty) static void show_ip_ospf_neighbor_sub (struct vty *vty, struct ospf_interface *oi) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; char msgbuf[16]; char timebuf[OSPF_TIME_DUMP_SIZE]; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - /* Do not show myself. */ - if (nbr != oi->nbr_self) - /* Down state is not shown. */ - if (nbr->state != NSM_Down) - { - ospf_nbr_state_message (nbr, msgbuf, 16); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + /* Do not show myself. */ + if (nbr != oi->nbr_self) + /* Down state is not shown. */ + if (nbr->state != NSM_Down) + { + ospf_nbr_state_message (nbr, msgbuf, 16); + if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) + vty_out (vty, "%-15s %3d %-15s ", + "-", nbr->priority, + msgbuf); + else + vty_out (vty, "%-15s %3d %-15s ", + inet_ntoa (nbr->router_id), nbr->priority, + msgbuf); - if (nbr->state == NSM_Attempt && nbr->router_id.s_addr == 0) - vty_out (vty, "%-15s %3d %-15s ", - "-", nbr->priority, - msgbuf); - else - vty_out (vty, "%-15s %3d %-15s ", - inet_ntoa (nbr->router_id), nbr->priority, - msgbuf); - - vty_out (vty, "%9s ", - ospf_timer_dump (nbr->t_inactivity, timebuf, + vty_out (vty, "%9s ", + ospf_timer_dump (nbr->t_inactivity, timebuf, sizeof(timebuf))); - - vty_out (vty, "%-15s ", inet_ntoa (nbr->src)); - vty_out (vty, "%-20s %5ld %5ld %5d%s", - IF_NAME (oi), ospf_ls_retransmit_count (nbr), - ospf_ls_request_count (nbr), ospf_db_summary_count (nbr), - VTY_NEWLINE); - } + + vty_out (vty, "%-15s ", inet_ntoa (nbr->src)); + vty_out (vty, "%-20s %5ld %5ld %5d%s", + IF_NAME (oi), ospf_ls_retransmit_count (nbr), + ospf_ls_request_count (nbr), ospf_db_summary_count (nbr), + VTY_NEWLINE); + } } DEFUN (show_ip_ospf_neighbor, @@ -3199,7 +3200,7 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, /* Show interface address. */ vty_out (vty, " interface address %s%s", - inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE); + inet_ntoa (nbr->src), VTY_NEWLINE); /* Show Area ID. */ vty_out (vty, " In the area %s via interface %s%s", ospf_area_desc_string (oi->area), oi->ifp->name, VTY_NEWLINE); @@ -3320,14 +3321,13 @@ DEFUN (show_ip_ospf_neighbor_detail, for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) { - struct route_node *rn; + struct listnode *nnode; struct ospf_neighbor *nbr; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); } return CMD_SUCCESS; @@ -3356,15 +3356,14 @@ DEFUN (show_ip_ospf_neighbor_detail_all, for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) { - struct route_node *rn; + struct listnode *nnode; struct ospf_neighbor *nbr; struct ospf_nbr_nbma *nbr_nbma; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - if (nbr != oi->nbr_self) - if (oi->type == OSPF_IFTYPE_NBMA && nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, rn->info); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, nnode, nbr)) + if (nbr != oi->nbr_self) + if (oi->type == OSPF_IFTYPE_NBMA && nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); if (oi->type == OSPF_IFTYPE_NBMA) { @@ -3393,8 +3392,9 @@ DEFUN (show_ip_ospf_neighbor_int_detail, struct ospf *ospf; struct ospf_interface *oi; struct interface *ifp; - struct route_node *rn, *nrn; + struct route_node *rn; struct ospf_neighbor *nbr; + struct listnode *node; ifp = if_lookup_by_name (argv[0]); if (!ifp) @@ -3413,11 +3413,10 @@ DEFUN (show_ip_ospf_neighbor_int_detail, for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) if ((oi = rn->info)) - for (nrn = route_top (oi->nbrs); nrn; nrn = route_next (nrn)) - if ((nbr = nrn->info)) - if (nbr != oi->nbr_self) - if (nbr->state != NSM_Down) - show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub (vty, oi, nbr); return CMD_SUCCESS; } @@ -4929,17 +4928,16 @@ ALIAS (no_ip_ospf_cost2, static void ospf_nbr_timer_update (struct ospf_interface *oi) { - struct route_node *rn; + struct listnode *node; struct ospf_neighbor *nbr; - for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) - if ((nbr = rn->info)) - { - nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait); - nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval); - nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval); - nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval); - } + for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr)) + { + nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait); + nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval); + nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval); + nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval); + } } static int @@ -5774,6 +5772,71 @@ ALIAS (no_ip_ospf_transmit_delay, "OSPF interface commands\n" "Link state transmit delay\n") +DEFUN (ip_ospf_area, + ip_ospf_area_cmd, + "ip ospf area (A.B.C.D|<0-4294967295>)", + "IP Information\n" + "OSPF interface commands\n" + "Enable OSPF on this interface\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n") +{ + struct interface *ifp = vty->index; + int format, ret; + struct in_addr area_id; + struct ospf *ospf; + struct ospf_if_params *params; + + ret = ospf_str2area_id (argv[0], &area_id, &format); + + if (ret < 0) + { + vty_out (vty, "Please specify area by A.B.C.D|<0-4294967295>%s", + VTY_NEWLINE); + return CMD_WARNING; + } + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + { + vty_out (vty, "There is already a interface statement.%s", VTY_NEWLINE); + return CMD_WARNING; + } + if (memcmp (ifp->name, "VLINK", 5) == 0) + { + vty_out (vty, "Cannot enable OSPF on a virtual link.%s", VTY_NEWLINE); + return CMD_WARNING; + } + + SET_IF_PARAM (params, if_area); + params->if_area = area_id; + ospf_interface_set (ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_area, + no_ip_ospf_area_cmd, + "no ip ospf area", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Disable OSPF on this interface\n") +{ + struct interface *ifp = vty->index; + struct ospf *ospf; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS (ifp); + if (!OSPF_IF_PARAM_CONFIGURED(params, if_area)) + return CMD_SUCCESS; + + UNSET_IF_PARAM (params, if_area); + + ospf_interface_unset (ifp); + return CMD_SUCCESS; +} + + DEFUN (ospf_redistribute_source_metric_type, ospf_redistribute_source_metric_type_routemap_cmd, @@ -7374,6 +7437,123 @@ DEFUN (show_ip_ospf_route, return CMD_SUCCESS; } +DEFUN (ip_ospf_host, + ip_ospf_host_cmd, + "ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all) cost <0-65535>", + "OSPF specific commands\n" + "Add a host route to OPSF\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + u_int32_t cost; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + cost = strtol (argv[2], NULL, 10); + /* cost range is <0-65535>. */ + if (cost < 0 || cost > 65535) + { + vty_out (vty, "cost is invalid%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); /* returns if error */ + area = ospf_area_get (ospf, area_id, format); + } + + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (!node) + { + host = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf_host_route)); + listnode_add (ospf->hostlist, host); + } + host->host_addr = host_addr; + host->cost = cost; + host->area = area; + + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_host, + no_ip_ospf_host_cmd, + "no ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all)", + NO_STR + "OSPF specific commands\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); + area = ospf_area_get (ospf, area_id, format); + } + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (node) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + } + return CMD_SUCCESS; +} + const char *ospf_abr_type_str[] = { @@ -7581,6 +7761,14 @@ config_write_interface (struct vty *vty) vty_out (vty, "%s", VTY_NEWLINE); } + /* Area print. */ + if (OSPF_IF_PARAM_CONFIGURED (params, if_area)) + { + vty_out (vty, " ip ospf area %s%s", + inet_ntoa (params->if_area), + VTY_NEWLINE); + } + /* MTU ignore print. */ if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) && params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) @@ -7955,6 +8143,7 @@ ospf_config_write (struct vty *vty) struct interface *ifp; struct ospf_interface *oi; struct listnode *node; + struct ospf_host_route *host; int write = 0; ospf = ospf_lookup (); @@ -8022,7 +8211,20 @@ ospf_config_write (struct vty *vty) /* passive-interface print. */ if (ospf->passive_interface_default == OSPF_IF_PASSIVE) vty_out (vty, " passive-interface default%s", VTY_NEWLINE); - + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + { + char buf[28]; + + if (host->area) + area_id2str(buf, sizeof(buf), host->area); + else + strcpy(buf, "all"); + vty_out (vty, " ip ospf host %s area %s cost %d%s", + inet_ntoa (host->host_addr), + buf, host->cost, VTY_NEWLINE); + } + for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface) && IF_DEF_PARAMS (ifp)->passive_interface != @@ -8222,6 +8424,10 @@ ospf_vty_if_init (void) install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_transmit_delay_cmd); + /* "ip ospf area" commands. */ + install_element (INTERFACE_NODE, &ip_ospf_area_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_area_cmd); + /* These commands are compatibitliy for previous version. */ install_element (INTERFACE_NODE, &ospf_authentication_key_cmd); install_element (INTERFACE_NODE, &no_ospf_authentication_key_cmd); @@ -8508,6 +8714,10 @@ ospf_vty_init (void) install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd); install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd); + /* "ip ospf host" commands. */ + install_element (OSPF_NODE, &ip_ospf_host_cmd); + install_element (OSPF_NODE, &no_ip_ospf_host_cmd); + /* Init interface related vty commands. */ ospf_vty_if_init (); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 6f0a71ff..ed35cc80 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -195,6 +195,17 @@ ospf_interface_state_up (int command, struct zclient *zclient, ospf_if_recalculate_output_cost (ifp); } + if (CHECK_FLAG(if_tmp.status ^ ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + { + if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) + zlog_debug ("Zebra: Interface[%s] Unnumbered state change %d -> %d.", + ifp->name, + if_tmp.status & ZEBRA_INTERFACE_UNNUMBERED, + ifp->status & ZEBRA_INTERFACE_UNNUMBERED); + + ospf_if_reset (ifp); + } + if (if_tmp.mtu != ifp->mtu) { if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index a7553e73..93611da9 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -231,7 +231,7 @@ ospf_new (void) } new->t_read = thread_add_read (master, ospf_read, new, new->fd); new->oi_write_q = list_new (); - + new->hostlist = list_new(); /* host route list */ return new; } @@ -401,6 +401,7 @@ ospf_finish_final (struct ospf *ospf) struct ospf_lsa *lsa; struct ospf_interface *oi; struct ospf_area *area; + struct ospf_host_route *host; struct ospf_vl_data *vl_data; struct listnode *node, *nnode; int i; @@ -471,6 +472,12 @@ ospf_finish_final (struct ospf *ospf) ospf_area_free (area); } + for (ALL_LIST_ELEMENTS (ospf->hostlist, node, nnode, host)) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + } + /* Cancel all timers. */ OSPF_TIMER_OFF (ospf->t_external_lsa); OSPF_TIMER_OFF (ospf->t_router_lsa_update); @@ -646,8 +653,32 @@ ospf_area_free (struct ospf_area *area) void ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) { + struct interface *ifp; + struct listnode *node; + struct ospf_if_params *params; + struct route_node *rn; + struct ospf_network *network; + struct ospf_host_route *host; struct ospf_area *area; + /* Check if any interface is a member of this area */ + for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) + { + params = IF_DEF_PARAMS (ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area) + && IPV4_ADDR_SAME (&area_id, ¶ms->if_area)) + return; + } + /* Check if any network is a member of this area */ + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) + { + network = rn->info; + if (network && IPV4_ADDR_SAME (&area_id, &network->area_id)) + { + route_unlock_node (rn); + return; + } + } area = ospf_area_lookup_by_area_id (ospf, area_id); if (area && listcount (area->oiflist) == 0 && @@ -660,6 +691,9 @@ ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) IMPORT_NAME (area) == NULL && area->auth_type == OSPF_AUTH_NULL) { + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (!host->area || host->area == area) + return; listnode_delete (ospf->areas, area); ospf_area_free (area); } @@ -701,6 +735,67 @@ ospf_area_add_if (struct ospf_area *area, struct ospf_interface *oi) listnode_add (area->oiflist, oi); } +void add_ospf_interface(struct interface *ifp, struct ospf_area *area, + struct connected *co) +{ + struct ospf_interface *oi; + + oi = ospf_if_new (area->ospf, ifp, co->address); + oi->connected = co; + + oi->area = area; + + oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); + oi->output_cost = ospf_if_get_output_cost (oi); + + /* Add pseudo neighbor. */ + ospf_nbr_add_self (oi); + + /* Relate ospf interface to ospf instance. */ + oi->ospf = area->ospf; + + /* update network type as interface flag */ + /* If network type is specified previously, + skip network type setting. */ + oi->type = IF_DEF_PARAMS (ifp)->type; + + ospf_area_add_if (oi->area, oi); + + /* if router_id is not configured, dont bring up + * interfaces. + * ospf_router_id_update() will call ospf_if_update + * whenever r-id is configured instead. + */ + if ((area->ospf->router_id.s_addr != 0) + && if_is_operative (ifp)) + ospf_if_up (oi); +} + +void update_redistributed(struct ospf *ospf, int add_to_ospf) +{ + struct route_node *rn; + struct external_info *ei; + + if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) + if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) + for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); + rn; rn = route_next (rn)) + if ((ei = rn->info) != NULL) + if (add_to_ospf) + { + if (ospf_external_info_find_lsa (ospf, &ei->p)) + if (!ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_flush (ospf, ei->type, &ei->p, + ei->ifindex /*, ei->nexthop */); + } + else + { + if (!ospf_external_info_find_lsa (ospf, &ei->p)) + if (ospf_distribute_check_connected (ospf, ei)) + ospf_external_lsa_originate (ospf, ei); + } +} + void ospf_area_del_if (struct ospf_area *area, struct ospf_interface *oi) { @@ -754,16 +849,7 @@ ospf_network_set (struct ospf *ospf, struct prefix_ipv4 *p, ospf_network_run ((struct prefix *)p, area); /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (ospf_external_info_find_lsa (ospf, &ei->p)) - if (!ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_flush (ospf, ei->type, &ei->p, - ei->ifindex /*, ei->nexthop */); - + update_redistributed(ospf, 1); /* interfaces possibly added */ ospf_area_check_free (ospf, area_id); return 1; @@ -795,12 +881,17 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, /* Find interfaces that not configured already. */ for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) { + struct ospf_if_params *params; int found = 0; struct connected *co = oi->connected; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - continue; - + continue; + + params = IF_DEF_PARAMS (oi->ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) + continue; + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) { if (rn->info == NULL) @@ -819,18 +910,103 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p, } /* Update connected redistribute. */ - if (ospf_is_type_redistributed (ZEBRA_ROUTE_CONNECT)) - if (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)) - for (rn = route_top (EXTERNAL_INFO (ZEBRA_ROUTE_CONNECT)); - rn; rn = route_next (rn)) - if ((ei = rn->info) != NULL) - if (!ospf_external_info_find_lsa (ospf, &ei->p)) - if (ospf_distribute_check_connected (ospf, ei)) - ospf_external_lsa_originate (ospf, ei); + update_redistributed(ospf, 0); /* interfaces possibly removed */ + return 1; +} + +int +ospf_interface_set (struct interface *ifp) +{ + struct ospf_area *area; + struct route_node *rn; + struct external_info *ei; + struct listnode *cnode; + struct connected *co; + struct ospf *ospf; + struct ospf_if_params *params; + struct in_addr area_id; + int ret = OSPF_AREA_ID_FORMAT_ADDRESS; + + if ((ospf = ospf_lookup ()) == NULL) + return 1; /* Ospf not ready yet */ + + params = IF_DEF_PARAMS (ifp); + area_id = params->if_area; + + area = ospf_area_get (ospf, area_id, ret); + + for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, co)) + { + struct ospf_interface *oi; + + if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY)) + continue; + + oi = ospf_if_table_lookup(ifp, co->address); + if (oi) + { /* Just adjust area for existing interface */ + ospf_area_del_if (oi->area, oi); + oi->area = area; + ospf_area_add_if (oi->area, oi); + } + else + { + add_ospf_interface(ifp, area, co); + } + } + + /* Update connected redistribute. */ + update_redistributed(ospf, 1); /* interface possibly added */ + ospf_area_check_free (ospf, area_id); return 1; } +int +ospf_interface_unset (struct interface *ifp) +{ + struct route_node *rn_oi, *rn; + struct ospf *ospf; + + if ((ospf = ospf_lookup ()) == NULL) + return 1; /* Ospf not ready yet */ + + /* Find interfaces that may need to be removed. */ + for (rn_oi = route_top (IF_OIFS (ifp)); rn_oi; rn_oi = route_next (rn_oi)) + { + struct ospf_interface *oi; + struct connected *co; + int found = 0; + + if ( (oi = rn_oi->info) == NULL) + continue; + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + continue; + co = oi->connected; + + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) + { + if (rn->info == NULL) + continue; + + if (ospf_network_match_iface(co,&rn->p)) + { + found = 1; + route_unlock_node (rn); + break; + } + } + + if (found == 0) + ospf_if_free (oi); + } + + /* Update connected redistribute. */ + update_redistributed(ospf, 0); /* interfaces possibly removed */ + return 1; +} + + /* Check whether interface matches given network * returns: 1, true. 0, false */ @@ -862,39 +1038,9 @@ ospf_network_run_interface (struct prefix *p, struct ospf_area *area, if (p->family == co->address->family && ! ospf_if_table_lookup(ifp, co->address) && ospf_network_match_iface(co,p)) - { - struct ospf_interface *oi; - - oi = ospf_if_new (area->ospf, ifp, co->address); - oi->connected = co; - - oi->area = area; - - oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4); - oi->output_cost = ospf_if_get_output_cost (oi); - - /* Add pseudo neighbor. */ - ospf_nbr_add_self (oi); - - /* Relate ospf interface to ospf instance. */ - oi->ospf = area->ospf; - - /* update network type as interface flag */ - /* If network type is specified previously, - skip network type setting. */ - oi->type = IF_DEF_PARAMS (ifp)->type; - - ospf_area_add_if (oi->area, oi); - - /* if router_id is not configured, dont bring up - * interfaces. - * ospf_router_id_update() will call ospf_if_update - * whenever r-id is configured instead. - */ - if ((area->ospf->router_id.s_addr != 0) - && if_is_operative (ifp)) - ospf_if_up (oi); - } + { + add_ospf_interface(ifp, area, co); + } } } @@ -953,15 +1099,22 @@ ospf_if_update (struct ospf *ospf, struct interface *ifp) /* OSPF must be on and Router-ID must be configured. */ if (!ospf || ospf->router_id.s_addr == 0) return; - - /* Run each netowrk for this interface. */ - for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) - if (rn->info != NULL) - { - network = (struct ospf_network *) rn->info; - area = ospf_area_get (ospf, network->area_id, network->format); - ospf_network_run_interface (&rn->p, area, ifp); - } + + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS (ifp), if_area)) + { + ospf_interface_set (ifp); + } + else + { + /* Run each netowrk for this interface. */ + for (rn = route_top (ospf->networks); rn; rn = route_next (rn)) + if (rn->info != NULL) + { + network = (struct ospf_network *) rn->info; + area = ospf_area_get (ospf, network->area_id, network->format); + ospf_network_run_interface (&rn->p, area, ifp); + } + } } void @@ -1397,8 +1550,6 @@ ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma, struct ospf_interface *oi) { struct ospf_neighbor *nbr; - struct route_node *rn; - struct prefix p; if (oi->type != OSPF_IFTYPE_NBMA) return; @@ -1406,37 +1557,27 @@ ospf_nbr_nbma_add (struct ospf_nbr_nbma *nbr_nbma, if (nbr_nbma->nbr != NULL) return; - if (IPV4_ADDR_SAME (&oi->nbr_self->address.u.prefix4, &nbr_nbma->addr)) + if (IPV4_ADDR_SAME (&oi->nbr_self->src, &nbr_nbma->addr)) return; nbr_nbma->oi = oi; listnode_add (oi->nbr_nbma, nbr_nbma); /* Get neighbor information from table. */ - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.u.prefix4 = nbr_nbma->addr; - - rn = route_node_get (oi->nbrs, (struct prefix *)&p); - if (rn->info) + nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &nbr_nbma->addr); + if (nbr) { - nbr = rn->info; nbr->nbr_nbma = nbr_nbma; nbr_nbma->nbr = nbr; - - route_unlock_node (rn); } else { - nbr = rn->info = ospf_nbr_new (oi); + nbr = ospf_nbr_new (oi); nbr->state = NSM_Down; nbr->src = nbr_nbma->addr; nbr->nbr_nbma = nbr_nbma; nbr->priority = nbr_nbma->priority; - nbr->address = p; - nbr_nbma->nbr = nbr; - OSPF_NSM_EVENT_EXECUTE (nbr, NSM_Start); } } diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 64e91cef..3fc86256 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -329,6 +329,9 @@ struct ospf u_int32_t rx_lsa_count; struct route_table *distance_table; + + /* Host route list */ + struct list *hostlist; }; /* OSPF area structure. */ @@ -609,6 +612,9 @@ extern struct ospf_area *ospf_area_lookup_by_area_id (struct ospf *, extern void ospf_area_add_if (struct ospf_area *, struct ospf_interface *); extern void ospf_area_del_if (struct ospf_area *, struct ospf_interface *); +extern int ospf_interface_set (struct interface *ifp); +extern int ospf_interface_unset (struct interface *ifp); + extern void ospf_route_map_init (void); extern void ospf_snmp_init (void); diff --git a/zebra/interface.c b/zebra/interface.c index e09ca41f..e19648d7 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -83,6 +83,10 @@ if_zebra_new_hook (struct interface *ifp) rtadv->DefaultPreference = RTADV_PREF_MEDIUM; rtadv->AdvPrefixList = list_new (); + + rtadv->AdvRDNSSFlag = 0; + rtadv->AdvRDNSSLifetime = RTADV_RDNSS_DEFAULT_LIFETIME; + rtadv->AdvRDNSSList = list_new (); } #endif /* RTADV */ @@ -655,6 +659,9 @@ nd_dump_vty (struct vty *vty, struct interface *ifp) vty_out (vty, " ND router advertisements with " "Home Agent flag bit set.%s", VTY_NEWLINE); + if (rtadv->AdvRDNSSFlag) + vty_out (vty, " ND router advertisements with " + "RDNSS information.%s", VTY_NEWLINE); if (rtadv->AdvIntervalOption) vty_out (vty, " ND router advertisements with Adv. Interval option.%s", VTY_NEWLINE); @@ -1016,6 +1023,53 @@ DEFUN (no_multicast, return CMD_SUCCESS; } +DEFUN (unnumbered, + unnumbered_cmd, + "unnumbered", + "Set interface to IP Unnumbered mode\n") +{ + int ret; + struct interface *ifp; + struct zebra_if *if_data; + + ifp = (struct interface *) vty->index; + + zlog_debug("VTY: interface %s, Setting ifp->status |= ZEBRA_INTERFACE_UNNUMBERED", + ifp->name); + + SET_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED); + + /* force protocols to recalculate routes due to IP change */ + if (if_is_operative (ifp)) + zebra_interface_up_update (ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_unnumbered, + no_unnumbered_cmd, + "no unnumbered", + NO_STR + "Set interface to IP Numbered mode\n") +{ + int ret; + struct interface *ifp; + struct zebra_if *if_data; + + ifp = (struct interface *) vty->index; + + zlog_debug("VTY: interface %s, Setting ifp->status &= ~ZEBRA_INTERFACE_UNNUMBERED;", + ifp->name); + + UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED); + + /* force protocols to recalculate routes due to IP change */ + if (if_is_operative (ifp)) + zebra_interface_up_update (ifp); + + return CMD_SUCCESS; +} + DEFUN (linkdetect, linkdetect_cmd, "link-detect", @@ -1711,6 +1765,9 @@ if_config_write (struct vty *vty) if (ifp->bandwidth != 0) vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE); + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_UNNUMBERED)) + vty_out (vty, " unnumbered%s", VTY_NEWLINE); + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) vty_out(vty, " link-detect%s", VTY_NEWLINE); @@ -1791,6 +1848,8 @@ zebra_if_init (void) install_element (INTERFACE_NODE, &no_interface_desc_cmd); install_element (INTERFACE_NODE, &multicast_cmd); install_element (INTERFACE_NODE, &no_multicast_cmd); + install_element (INTERFACE_NODE, &unnumbered_cmd); + install_element (INTERFACE_NODE, &no_unnumbered_cmd); install_element (INTERFACE_NODE, &linkdetect_cmd); install_element (INTERFACE_NODE, &no_linkdetect_cmd); install_element (INTERFACE_NODE, &shutdown_if_cmd); diff --git a/zebra/interface.h b/zebra/interface.h index 0cf66403..305abaac 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -178,6 +178,20 @@ struct rtadvconf Default: 0 (medium) */ int DefaultPreference; #define RTADV_PREF_MEDIUM 0x0 /* Per RFC4191. */ + + /* A list of Recursive DNS server addresses specified in + RFC 5006 */ + int AdvRDNSSFlag; + struct list *AdvRDNSSList; + + /* the maximum lifetime in seconds over which the RDNSS entry + * may be used. After this time a host may send a router solicitation + * message to refresh the RDNSS information. + * + * Default is infinity lifetime (0xffffffff) */ + uint32_t AdvRDNSSLifetime; +#define RTADV_RDNSS_INFINITY_LIFETIME (0xffffffff) +#define RTADV_RDNSS_DEFAULT_LIFETIME RTADV_RDNSS_INFINITY_LIFETIME }; #endif /* RTADV */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index aa962a35..639617a5 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -338,6 +338,7 @@ int ifm_read (struct if_msghdr *ifm) { struct interface *ifp = NULL; + struct sockaddr_dl *sdl; char ifname[IFNAMSIZ]; short ifnlen = 0; caddr_t *cp; @@ -375,6 +376,7 @@ ifm_read (struct if_msghdr *ifm) RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp); RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp); RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp); + sdl = (struct sockaddr_dl *)cp; RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen); RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp); RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp); @@ -473,6 +475,16 @@ ifm_read (struct if_msghdr *ifm) #endif /* __bsdi__ */ if_get_metric (ifp); + /* + * XXX sockaddr_dl contents can be larger than the structure + * definition, so the user of the stored structure must be + * careful not to read off the end. + * + * a nonzero ifnlen from RTA_NAME_GET() means sdl is valid + */ + if (ifnlen) + memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl)); + if_add_update (ifp); } else diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 8cc3c4cb..7d9c0f6c 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -233,6 +233,32 @@ rtadv_send_packet (int sock, struct interface *ifp) len += sizeof(struct nd_opt_homeagent_info); } + if (zif->rtadv.AdvRDNSSFlag) + { + char *addr_ptr; + struct nd_opt_rdnss *ndopt_rdnss; + struct prefix *rdnss_prefix; + unsigned int rdnss_entries = 1; + + ndopt_rdnss = (struct nd_opt_rdnss *) (buf + len); + ndopt_rdnss->nd_opt_type = ND_OPT_RDNSS; + ndopt_rdnss->nd_opt_reserved = 0; + ndopt_rdnss->nd_opt_lifetime = htonl(zif->rtadv.AdvRDNSSLifetime); + + len += sizeof(struct nd_opt_rdnss); + + /* Fill in all RDNS server entries */ + for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvRDNSSList, node, rdnss_prefix)) + { + addr_ptr = (char *)(buf + len); + memcpy(addr_ptr, &rdnss_prefix->u.prefix6, sizeof (struct in6_addr)); + len += sizeof (struct in6_addr); + rdnss_entries += 2; + } + + ndopt_rdnss->nd_opt_len = rdnss_entries; + } + if (zif->rtadv.AdvIntervalOption) { struct nd_opt_adv_interval *ndopt_adv = @@ -1430,6 +1456,115 @@ DEFUN (no_ipv6_nd_router_preference, return CMD_SUCCESS; } +static struct prefix * +rtadv_rdnss_lookup (struct list *list, struct prefix *p) +{ + struct listnode *node; + struct prefix *prefix; + + for (ALL_LIST_ELEMENTS_RO (list, node, prefix)) + if (prefix_same (prefix, p)) + return prefix; + return NULL; +} + +static void +rtadv_rdnss_set (struct zebra_if *zif, struct prefix *p) +{ + struct prefix *prefix; + struct list *rdnsslist = zif->rtadv.AdvRDNSSList; + + prefix = rtadv_rdnss_lookup (rdnsslist, p); + if (prefix) + return; + + prefix = prefix_new (); + memcpy (prefix, p, sizeof (struct prefix)); + listnode_add (rdnsslist, prefix); + + return; +} + +static int +rtadv_rdnss_reset (struct zebra_if *zif, struct prefix *rp) +{ + struct prefix *prefix; + + prefix = rtadv_rdnss_lookup(zif->rtadv.AdvRDNSSList, rp); + if (prefix != NULL) + { + listnode_delete (zif->rtadv.AdvRDNSSList, (void *) prefix); + prefix_free (prefix); + return 1; + } + else + return 0; +} + +DEFUN (ipv6_nd_rdnss, + ipv6_nd_rdnss_cmd, + "ipv6 nd rdnss X:X::X:X (<0-4294967295>|infinite)", + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "RDNSS Option\n" + "IPv6 address of recursive DNS server\n") +{ + int ret; + char *pnt; + struct interface *ifp; + struct zebra_if *zif; + struct prefix rp; + + ifp = (struct interface *) vty->index; + zif = ifp->info; + + /* make sure no slash exists in the argument */ + pnt = strchr (argv[0], '/'); + if (pnt != NULL) + { + vty_out (vty, "Malformed IPv6 RDNS address - no prefix notation allowed%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* now we can abuse str2prefix_ipv6 for a sanity check + * because IPv6 addresses with missing prefix + * slashes '/' are treated as host routes */ + ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp); + if (!ret) + { + vty_out (vty, "Malformed IPv6 RDNS address%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rtadv_rdnss_set(zif, &rp); + zif->rtadv.AdvRDNSSFlag = 1; + + if (argc > 1) + { + if ( strncmp (argv[1], "i", 1) == 0) + { + zif->rtadv.AdvRDNSSLifetime = RTADV_RDNSS_INFINITY_LIFETIME; + } + else + { + zif->rtadv.AdvRDNSSLifetime = + (u_int32_t) strtoll (argv[1], (char **)NULL, 10); + } + } + + return CMD_SUCCESS; +} + +ALIAS (ipv6_nd_rdnss, + ipv6_nd_rdnss_nolife_cmd, + "ipv6 nd rdnss X:X::X:X", + "Interface IPv6 config commands\n" + "Neighbor discovery\n" + "RDNSS Option\n" + "IPv6 address of recursive DNS server\n") + + /* Write configuration about router advertisement. */ void rtadv_config_write (struct vty *vty, struct interface *ifp) @@ -1605,6 +1740,8 @@ rtadv_init (void) install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd); install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd); install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd); + install_element (INTERFACE_NODE, &ipv6_nd_rdnss_cmd); + install_element (INTERFACE_NODE, &ipv6_nd_rdnss_nolife_cmd); } static int diff --git a/zebra/rtadv.h b/zebra/rtadv.h index d8d263d0..0893ba53 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -66,6 +66,9 @@ extern void rtadv_init (void); #ifndef ND_OPT_HA_INFORMATION #define ND_OPT_HA_INFORMATION 8 /* HA Information Option */ #endif +#ifndef ND_OPT_RDNSS +#define ND_OPT_RDNSS 25 /* RDNSS option (RFC 5006) */ +#endif #ifndef HAVE_STRUCT_ND_OPT_ADV_INTERVAL struct nd_opt_adv_interval { /* Advertisement interval option */ @@ -94,6 +97,15 @@ struct nd_opt_homeagent_info { /* Home Agent info */ } __attribute__((__packed__)); #endif +/* see RFC 5006, section 5.1 */ +struct nd_opt_rdnss { + uint8_t nd_opt_type; + uint8_t nd_opt_len; + uint16_t nd_opt_reserved; + uint32_t nd_opt_lifetime; + /* followed by n (16 byte) entries */ +} __attribute__((__packed__)); + extern const char *rtadv_pref_strs[]; #endif /* _ZEBRA_RTADV_H */ |