diff options
Diffstat (limited to 'ripd')
| -rw-r--r-- | ripd/rip_debug.c | 237 | ||||
| -rw-r--r-- | ripd/rip_debug.h | 4 | ||||
| -rw-r--r-- | ripd/rip_interface.c | 2409 | ||||
| -rw-r--r-- | ripd/rip_interface.h | 20 | ||||
| -rw-r--r-- | ripd/rip_main.c | 197 | ||||
| -rw-r--r-- | ripd/rip_memory.c | 10 | ||||
| -rw-r--r-- | ripd/rip_offset.c | 545 | ||||
| -rw-r--r-- | ripd/rip_peer.c | 230 | ||||
| -rw-r--r-- | ripd/rip_routemap.c | 784 | ||||
| -rw-r--r-- | ripd/rip_snmp.c | 865 | ||||
| -rw-r--r-- | ripd/rip_zebra.c | 943 | ||||
| -rw-r--r-- | ripd/ripd.c | 6755 | ||||
| -rw-r--r-- | ripd/ripd.h | 481 |
13 files changed, 6581 insertions, 6899 deletions
diff --git a/ripd/rip_debug.c b/ripd/rip_debug.c index 04252a85fb..b2c80817dd 100644 --- a/ripd/rip_debug.c +++ b/ripd/rip_debug.c @@ -34,30 +34,28 @@ DEFUN (show_debugging_rip, DEBUG_STR RIP_STR) { - vty_out (vty, "RIP debugging status:\n"); - - if (IS_RIP_DEBUG_EVENT) - vty_out (vty, " RIP event debugging is on\n"); - - if (IS_RIP_DEBUG_PACKET) - { - if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) - { - vty_out (vty," RIP packet debugging is on\n"); - } - else - { - if (IS_RIP_DEBUG_SEND) - vty_out (vty," RIP packet send debugging is on\n"); - else - vty_out (vty," RIP packet receive debugging is on\n"); + vty_out(vty, "RIP debugging status:\n"); + + if (IS_RIP_DEBUG_EVENT) + vty_out(vty, " RIP event debugging is on\n"); + + if (IS_RIP_DEBUG_PACKET) { + if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) { + vty_out(vty, " RIP packet debugging is on\n"); + } else { + if (IS_RIP_DEBUG_SEND) + vty_out(vty, + " RIP packet send debugging is on\n"); + else + vty_out(vty, + " RIP packet receive debugging is on\n"); + } } - } - if (IS_RIP_DEBUG_ZEBRA) - vty_out (vty, " RIP zebra debugging is on\n"); + if (IS_RIP_DEBUG_ZEBRA) + vty_out(vty, " RIP zebra debugging is on\n"); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (debug_rip_events, @@ -67,8 +65,8 @@ DEFUN (debug_rip_events, RIP_STR "RIP events\n") { - rip_debug_event = RIP_DEBUG_EVENT; - return CMD_WARNING_CONFIG_FAILED; + rip_debug_event = RIP_DEBUG_EVENT; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (debug_rip_packet, @@ -78,10 +76,10 @@ DEFUN (debug_rip_packet, RIP_STR "RIP packet\n") { - rip_debug_packet = RIP_DEBUG_PACKET; - rip_debug_packet |= RIP_DEBUG_SEND; - rip_debug_packet |= RIP_DEBUG_RECV; - return CMD_SUCCESS; + rip_debug_packet = RIP_DEBUG_PACKET; + rip_debug_packet |= RIP_DEBUG_SEND; + rip_debug_packet |= RIP_DEBUG_RECV; + return CMD_SUCCESS; } DEFUN (debug_rip_packet_direct, @@ -93,13 +91,17 @@ DEFUN (debug_rip_packet_direct, "RIP receive packet\n" "RIP send packet\n") { - int idx_recv_send = 3; - rip_debug_packet |= RIP_DEBUG_PACKET; - if (strncmp ("send", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - rip_debug_packet |= RIP_DEBUG_SEND; - if (strncmp ("recv", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - rip_debug_packet |= RIP_DEBUG_RECV; - return CMD_SUCCESS; + int idx_recv_send = 3; + rip_debug_packet |= RIP_DEBUG_PACKET; + if (strncmp("send", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) + rip_debug_packet |= RIP_DEBUG_SEND; + if (strncmp("recv", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) + rip_debug_packet |= RIP_DEBUG_RECV; + return CMD_SUCCESS; } DEFUN (debug_rip_zebra, @@ -109,8 +111,8 @@ DEFUN (debug_rip_zebra, RIP_STR "RIP and ZEBRA communication\n") { - rip_debug_zebra = RIP_DEBUG_ZEBRA; - return CMD_WARNING_CONFIG_FAILED; + rip_debug_zebra = RIP_DEBUG_ZEBRA; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_debug_rip_events, @@ -121,8 +123,8 @@ DEFUN (no_debug_rip_events, RIP_STR "RIP events\n") { - rip_debug_event = 0; - return CMD_SUCCESS; + rip_debug_event = 0; + return CMD_SUCCESS; } DEFUN (no_debug_rip_packet, @@ -133,8 +135,8 @@ DEFUN (no_debug_rip_packet, RIP_STR "RIP packet\n") { - rip_debug_packet = 0; - return CMD_SUCCESS; + rip_debug_packet = 0; + return CMD_SUCCESS; } DEFUN (no_debug_rip_packet_direct, @@ -147,22 +149,23 @@ DEFUN (no_debug_rip_packet_direct, "RIP option set for receive packet\n" "RIP option set for send packet\n") { - int idx_recv_send = 4; - if (strncmp ("send", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - { - if (IS_RIP_DEBUG_RECV) - rip_debug_packet &= ~RIP_DEBUG_SEND; - else - rip_debug_packet = 0; - } - else if (strncmp ("recv", argv[idx_recv_send]->arg, strlen (argv[idx_recv_send]->arg)) == 0) - { - if (IS_RIP_DEBUG_SEND) - rip_debug_packet &= ~RIP_DEBUG_RECV; - else - rip_debug_packet = 0; - } - return CMD_SUCCESS; + int idx_recv_send = 4; + if (strncmp("send", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) { + if (IS_RIP_DEBUG_RECV) + rip_debug_packet &= ~RIP_DEBUG_SEND; + else + rip_debug_packet = 0; + } else if (strncmp("recv", argv[idx_recv_send]->arg, + strlen(argv[idx_recv_send]->arg)) + == 0) { + if (IS_RIP_DEBUG_SEND) + rip_debug_packet &= ~RIP_DEBUG_RECV; + else + rip_debug_packet = 0; + } + return CMD_SUCCESS; } DEFUN (no_debug_rip_zebra, @@ -173,85 +176,73 @@ DEFUN (no_debug_rip_zebra, RIP_STR "RIP and ZEBRA communication\n") { - rip_debug_zebra = 0; - return CMD_WARNING_CONFIG_FAILED; + rip_debug_zebra = 0; + return CMD_WARNING_CONFIG_FAILED; } /* Debug node. */ -static struct cmd_node debug_node = -{ - DEBUG_NODE, - "", /* Debug node has no interface. */ - 1 -}; +static struct cmd_node debug_node = {DEBUG_NODE, + "", /* Debug node has no interface. */ + 1}; -static int -config_write_debug (struct vty *vty) +static int config_write_debug(struct vty *vty) { - int write = 0; + int write = 0; - if (IS_RIP_DEBUG_EVENT) - { - vty_out (vty, "debug rip events\n"); - write++; - } - if (IS_RIP_DEBUG_PACKET) - { - if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) - { - vty_out (vty,"debug rip packet\n"); - write++; + if (IS_RIP_DEBUG_EVENT) { + vty_out(vty, "debug rip events\n"); + write++; } - else - { - if (IS_RIP_DEBUG_SEND) - vty_out (vty,"debug rip packet send\n"); - else - vty_out (vty,"debug rip packet recv\n"); - write++; + if (IS_RIP_DEBUG_PACKET) { + if (IS_RIP_DEBUG_SEND && IS_RIP_DEBUG_RECV) { + vty_out(vty, "debug rip packet\n"); + write++; + } else { + if (IS_RIP_DEBUG_SEND) + vty_out(vty, "debug rip packet send\n"); + else + vty_out(vty, "debug rip packet recv\n"); + write++; + } } - } - if (IS_RIP_DEBUG_ZEBRA) - { - vty_out (vty, "debug rip zebra\n"); - write++; - } - return write; + if (IS_RIP_DEBUG_ZEBRA) { + vty_out(vty, "debug rip zebra\n"); + write++; + } + return write; } -void -rip_debug_reset (void) +void rip_debug_reset(void) { - rip_debug_event = 0; - rip_debug_packet = 0; - rip_debug_zebra = 0; + rip_debug_event = 0; + rip_debug_packet = 0; + rip_debug_zebra = 0; } -void -rip_debug_init (void) +void rip_debug_init(void) { - rip_debug_event = 0; - rip_debug_packet = 0; - rip_debug_zebra = 0; - - install_node (&debug_node, config_write_debug); - - install_element (ENABLE_NODE, &show_debugging_rip_cmd); - install_element (ENABLE_NODE, &debug_rip_events_cmd); - install_element (ENABLE_NODE, &debug_rip_packet_cmd); - install_element (ENABLE_NODE, &debug_rip_packet_direct_cmd); - install_element (ENABLE_NODE, &debug_rip_zebra_cmd); - install_element (ENABLE_NODE, &no_debug_rip_events_cmd); - install_element (ENABLE_NODE, &no_debug_rip_packet_cmd); - install_element (ENABLE_NODE, &no_debug_rip_packet_direct_cmd); - install_element (ENABLE_NODE, &no_debug_rip_zebra_cmd); - - install_element (CONFIG_NODE, &debug_rip_events_cmd); - install_element (CONFIG_NODE, &debug_rip_packet_cmd); - install_element (CONFIG_NODE, &debug_rip_packet_direct_cmd); - install_element (CONFIG_NODE, &debug_rip_zebra_cmd); - install_element (CONFIG_NODE, &no_debug_rip_events_cmd); - install_element (CONFIG_NODE, &no_debug_rip_packet_cmd); - install_element (CONFIG_NODE, &no_debug_rip_packet_direct_cmd); - install_element (CONFIG_NODE, &no_debug_rip_zebra_cmd); + rip_debug_event = 0; + rip_debug_packet = 0; + rip_debug_zebra = 0; + + install_node(&debug_node, config_write_debug); + + install_element(ENABLE_NODE, &show_debugging_rip_cmd); + install_element(ENABLE_NODE, &debug_rip_events_cmd); + install_element(ENABLE_NODE, &debug_rip_packet_cmd); + install_element(ENABLE_NODE, &debug_rip_packet_direct_cmd); + install_element(ENABLE_NODE, &debug_rip_zebra_cmd); + install_element(ENABLE_NODE, &no_debug_rip_events_cmd); + install_element(ENABLE_NODE, &no_debug_rip_packet_cmd); + install_element(ENABLE_NODE, &no_debug_rip_packet_direct_cmd); + install_element(ENABLE_NODE, &no_debug_rip_zebra_cmd); + + install_element(CONFIG_NODE, &debug_rip_events_cmd); + install_element(CONFIG_NODE, &debug_rip_packet_cmd); + install_element(CONFIG_NODE, &debug_rip_packet_direct_cmd); + install_element(CONFIG_NODE, &debug_rip_zebra_cmd); + install_element(CONFIG_NODE, &no_debug_rip_events_cmd); + install_element(CONFIG_NODE, &no_debug_rip_packet_cmd); + install_element(CONFIG_NODE, &no_debug_rip_packet_direct_cmd); + install_element(CONFIG_NODE, &no_debug_rip_zebra_cmd); } diff --git a/ripd/rip_debug.h b/ripd/rip_debug.h index e1dcd2fa7a..c3b15d2e15 100644 --- a/ripd/rip_debug.h +++ b/ripd/rip_debug.h @@ -46,7 +46,7 @@ extern unsigned long rip_debug_event; extern unsigned long rip_debug_packet; extern unsigned long rip_debug_zebra; -extern void rip_debug_init (void); -extern void rip_debug_reset (void); +extern void rip_debug_init(void); +extern void rip_debug_reset(void); #endif /* _ZEBRA_RIP_DEBUG_H */ diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 357856e1e8..a170471123 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -41,25 +41,22 @@ #include "ripd/rip_debug.h" #include "ripd/rip_interface.h" -DEFINE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) -DEFINE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) +DEFINE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) +DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) /* static prototypes */ -static void rip_enable_apply (struct interface *); -static void rip_passive_interface_apply (struct interface *); +static void rip_enable_apply(struct interface *); +static void rip_passive_interface_apply(struct interface *); static int rip_if_down(struct interface *ifp); -static int rip_enable_if_lookup (const char *ifname); -static int rip_enable_network_lookup2 (struct connected *connected); -static void rip_enable_apply_all (void); +static int rip_enable_if_lookup(const char *ifname); +static int rip_enable_network_lookup2(struct connected *connected); +static void rip_enable_apply_all(void); -const struct message ri_version_msg[] = -{ - {RI_RIP_VERSION_1, "1"}, - {RI_RIP_VERSION_2, "2"}, - {RI_RIP_VERSION_1_AND_2, "1 2"}, - {RI_RIP_VERSION_NONE, "none"}, - { 0 } -}; +const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"}, + {RI_RIP_VERSION_2, "2"}, + {RI_RIP_VERSION_1_AND_2, "1 2"}, + {RI_RIP_VERSION_NONE, "none"}, + {0}}; extern struct zebra_privs_t ripd_privs; @@ -70,167 +67,158 @@ vector rip_enable_interface; struct route_table *rip_enable_network; /* Vector to store passive-interface name. */ -static int passive_default; /* are we in passive-interface default mode? */ +static int passive_default; /* are we in passive-interface default mode? */ vector Vrip_passive_nondefault; /* Join to the RIP version 2 multicast group. */ -static int -ipv4_multicast_join (int sock, - struct in_addr group, - struct in_addr ifa, - ifindex_t ifindex) +static int ipv4_multicast_join(int sock, struct in_addr group, + struct in_addr ifa, ifindex_t ifindex) { - int ret; + int ret; - ret = setsockopt_ipv4_multicast (sock, - IP_ADD_MEMBERSHIP, - ifa, - group.s_addr, - ifindex); + ret = setsockopt_ipv4_multicast(sock, IP_ADD_MEMBERSHIP, ifa, + group.s_addr, ifindex); - if (ret < 0) - zlog_info("can't setsockopt IP_ADD_MEMBERSHIP %s", safe_strerror(errno)); + if (ret < 0) + zlog_info("can't setsockopt IP_ADD_MEMBERSHIP %s", + safe_strerror(errno)); - return ret; + return ret; } /* Leave from the RIP version 2 multicast group. */ -static int -ipv4_multicast_leave (int sock, - struct in_addr group, - struct in_addr ifa, - ifindex_t ifindex) +static int ipv4_multicast_leave(int sock, struct in_addr group, + struct in_addr ifa, ifindex_t ifindex) { - int ret; + int ret; - ret = setsockopt_ipv4_multicast (sock, - IP_DROP_MEMBERSHIP, - ifa, - group.s_addr, - ifindex); + ret = setsockopt_ipv4_multicast(sock, IP_DROP_MEMBERSHIP, ifa, + group.s_addr, ifindex); - if (ret < 0) - zlog_info("can't setsockopt IP_DROP_MEMBERSHIP"); + if (ret < 0) + zlog_info("can't setsockopt IP_DROP_MEMBERSHIP"); - return ret; + return ret; } -static void rip_interface_reset (struct rip_interface *); +static void rip_interface_reset(struct rip_interface *); /* Allocate new RIP's interface configuration. */ -static struct rip_interface * -rip_interface_new (void) +static struct rip_interface *rip_interface_new(void) { - struct rip_interface *ri; + struct rip_interface *ri; - ri = XCALLOC (MTYPE_RIP_INTERFACE, sizeof (struct rip_interface)); + ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface)); - rip_interface_reset (ri); + rip_interface_reset(ri); - return ri; + return ri; } -void -rip_interface_multicast_set (int sock, struct connected *connected) +void rip_interface_multicast_set(int sock, struct connected *connected) { - struct in_addr addr; + struct in_addr addr; - assert (connected != NULL); + assert(connected != NULL); - addr = CONNECTED_ID(connected)->u.prefix4; + addr = CONNECTED_ID(connected)->u.prefix4; + + if (setsockopt_ipv4_multicast_if(sock, addr, connected->ifp->ifindex) + < 0) { + zlog_warn( + "Can't setsockopt IP_MULTICAST_IF on fd %d to " + "ifindex %d for interface %s", + sock, connected->ifp->ifindex, connected->ifp->name); + } - if (setsockopt_ipv4_multicast_if (sock, addr, connected->ifp->ifindex) < 0) - { - zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to " - "ifindex %d for interface %s", - sock, connected->ifp->ifindex, - connected->ifp->name); - } - - return; + return; } /* Send RIP request packet to specified interface. */ -static void -rip_request_interface_send (struct interface *ifp, u_char version) +static void rip_request_interface_send(struct interface *ifp, u_char version) { - struct sockaddr_in to; + struct sockaddr_in to; - /* RIPv2 support multicast. */ - if (version == RIPv2 && if_is_multicast (ifp)) - { - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast request on %s", ifp->name); + /* RIPv2 support multicast. */ + if (version == RIPv2 && if_is_multicast(ifp)) { - rip_request_send (NULL, ifp, version, NULL); - return; - } + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast request on %s", ifp->name); - /* RIPv1 and non multicast interface. */ - if (if_is_pointopoint (ifp) || if_is_broadcast (ifp)) - { - struct listnode *cnode, *cnnode; - struct connected *connected; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("broadcast request to %s", ifp->name); + rip_request_send(NULL, ifp, version, NULL); + return; + } - for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, connected)) - { - if (connected->address->family == AF_INET) - { - memset (&to, 0, sizeof (struct sockaddr_in)); - to.sin_port = htons (RIP_PORT_DEFAULT); - if (connected->destination) - /* use specified broadcast or peer destination addr */ - to.sin_addr = connected->destination->u.prefix4; - else if (connected->address->prefixlen < IPV4_MAX_PREFIXLEN) - /* calculate the appropriate broadcast address */ - to.sin_addr.s_addr = - ipv4_broadcast_addr(connected->address->u.prefix4.s_addr, - connected->address->prefixlen); - else - /* do not know where to send the packet */ - continue; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr)); - - rip_request_send (&to, ifp, version, connected); - } + /* RIPv1 and non multicast interface. */ + if (if_is_pointopoint(ifp) || if_is_broadcast(ifp)) { + struct listnode *cnode, *cnnode; + struct connected *connected; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("broadcast request to %s", ifp->name); + + for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode, + connected)) { + if (connected->address->family == AF_INET) { + memset(&to, 0, sizeof(struct sockaddr_in)); + to.sin_port = htons(RIP_PORT_DEFAULT); + if (connected->destination) + /* use specified broadcast or peer + * destination addr */ + to.sin_addr = connected->destination->u + .prefix4; + else if (connected->address->prefixlen + < IPV4_MAX_PREFIXLEN) + /* calculate the appropriate broadcast + * address */ + to.sin_addr + .s_addr = ipv4_broadcast_addr( + connected->address->u.prefix4 + .s_addr, + connected->address->prefixlen); + else + /* do not know where to send the packet + */ + continue; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("SEND request to %s", + inet_ntoa(to.sin_addr)); + + rip_request_send(&to, ifp, version, connected); + } + } } - } } /* This will be executed when interface goes up. */ -static void -rip_request_interface (struct interface *ifp) +static void rip_request_interface(struct interface *ifp) { - struct rip_interface *ri; + struct rip_interface *ri; - /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */ - if (if_is_loopback (ifp)) - return; + /* In default ripd doesn't send RIP_REQUEST to the loopback interface. + */ + if (if_is_loopback(ifp)) + return; - /* If interface is down, don't send RIP packet. */ - if (! if_is_operative (ifp)) - return; + /* If interface is down, don't send RIP packet. */ + if (!if_is_operative(ifp)) + return; - /* Fetch RIP interface information. */ - ri = ifp->info; + /* Fetch RIP interface information. */ + ri = ifp->info; - /* If there is no version configuration in the interface, - use rip's version setting. */ - { - int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? - rip->version_send : ri->ri_send); - if (vsend & RIPv1) - rip_request_interface_send (ifp, RIPv1); - if (vsend & RIPv2) - rip_request_interface_send (ifp, RIPv2); - } + /* If there is no version configuration in the interface, + use rip's version setting. */ + { + int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? rip->version_send + : ri->ri_send); + if (vsend & RIPv1) + rip_request_interface_send(ifp, RIPv1); + if (vsend & RIPv2) + rip_request_interface_send(ifp, RIPv2); + } } #if 0 @@ -267,949 +255,892 @@ rip_request_neighbor_all (void) #endif /* Multicast packet receive socket. */ -static int -rip_multicast_join (struct interface *ifp, int sock) +static int rip_multicast_join(struct interface *ifp, int sock) { - struct listnode *cnode; - struct connected *ifc; + struct listnode *cnode; + struct connected *ifc; - if (if_is_operative (ifp) && if_is_multicast (ifp)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast join at %s", ifp->name); + if (if_is_operative(ifp) && if_is_multicast(ifp)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast join at %s", ifp->name); - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc)) - { - struct prefix_ipv4 *p; - struct in_addr group; - - p = (struct prefix_ipv4 *) ifc->address; - - if (p->family != AF_INET) - continue; - - group.s_addr = htonl (INADDR_RIP_GROUP); - if (ipv4_multicast_join (sock, group, p->prefix, ifp->ifindex) < 0) - return -1; - else - return 0; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { + struct prefix_ipv4 *p; + struct in_addr group; + + p = (struct prefix_ipv4 *)ifc->address; + + if (p->family != AF_INET) + continue; + + group.s_addr = htonl(INADDR_RIP_GROUP); + if (ipv4_multicast_join(sock, group, p->prefix, + ifp->ifindex) + < 0) + return -1; + else + return 0; + } } - } - return 0; + return 0; } /* Leave from multicast group. */ -static void -rip_multicast_leave (struct interface *ifp, int sock) +static void rip_multicast_leave(struct interface *ifp, int sock) { - struct listnode *cnode; - struct connected *connected; + struct listnode *cnode; + struct connected *connected; - if (if_is_up (ifp) && if_is_multicast (ifp)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast leave from %s", ifp->name); + if (if_is_up(ifp) && if_is_multicast(ifp)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast leave from %s", ifp->name); - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - struct prefix_ipv4 *p; - struct in_addr group; - - p = (struct prefix_ipv4 *) connected->address; - - if (p->family != AF_INET) - continue; - - group.s_addr = htonl (INADDR_RIP_GROUP); - if (ipv4_multicast_leave (sock, group, p->prefix, ifp->ifindex) == 0) - return; - } - } + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + struct prefix_ipv4 *p; + struct in_addr group; + + p = (struct prefix_ipv4 *)connected->address; + + if (p->family != AF_INET) + continue; + + group.s_addr = htonl(INADDR_RIP_GROUP); + if (ipv4_multicast_leave(sock, group, p->prefix, + ifp->ifindex) + == 0) + return; + } + } } /* Is there and address on interface that I could use ? */ -static int -rip_if_ipv4_address_check (struct interface *ifp) +static int rip_if_ipv4_address_check(struct interface *ifp) { - struct listnode *nn; - struct connected *connected; - int count = 0; + struct listnode *nn; + struct connected *connected; + int count = 0; - for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected)) - { - struct prefix *p; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, connected)) { + struct prefix *p; - p = connected->address; + p = connected->address; + + if (p->family == AF_INET) + count++; + } - if (p->family == AF_INET) - count++; - } - - return count; + return count; } - - - + /* Does this address belongs to me ? */ -int -if_check_address (struct in_addr addr) -{ - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct listnode *cnode; - struct connected *connected; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected)) - { - struct prefix_ipv4 *p; +int if_check_address(struct in_addr addr) +{ + struct listnode *node; + struct interface *ifp; - p = (struct prefix_ipv4 *) connected->address; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct listnode *cnode; + struct connected *connected; - if (p->family != AF_INET) - continue; + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) { + struct prefix_ipv4 *p; - if (IPV4_ADDR_CMP (&p->prefix, &addr) == 0) - return 1; + p = (struct prefix_ipv4 *)connected->address; + + if (p->family != AF_INET) + continue; + + if (IPV4_ADDR_CMP(&p->prefix, &addr) == 0) + return 1; + } } - } - return 0; + return 0; } /* Inteface link down message processing. */ -int -rip_interface_down (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int rip_interface_down(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; + struct interface *ifp; + struct stream *s; - s = zclient->ibuf; + s = zclient->ibuf; - /* zebra_interface_state_read() updates interface structure in - iflist. */ - ifp = zebra_interface_state_read (s, vrf_id); + /* zebra_interface_state_read() updates interface structure in + iflist. */ + ifp = zebra_interface_state_read(s, vrf_id); - if (ifp == NULL) - return 0; + if (ifp == NULL) + return 0; - rip_if_down(ifp); - - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface %s index %d flags %llx metric %d mtu %d is down", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu); + rip_if_down(ifp); - return 0; + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug( + "interface %s index %d flags %llx metric %d mtu %d is down", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); + + return 0; } /* Inteface link up message processing */ -int -rip_interface_up (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int rip_interface_up(int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; + + /* zebra_interface_state_read () updates interface structure in + iflist. */ + ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); - /* zebra_interface_state_read () updates interface structure in - iflist. */ - ifp = zebra_interface_state_read (zclient->ibuf, vrf_id); + if (ifp == NULL) + return 0; - if (ifp == NULL) - return 0; + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug( + "interface %s index %d flags %#llx metric %d mtu %d is up", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface %s index %d flags %#llx metric %d mtu %d is up", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu); + /* Check if this interface is RIP enabled or not.*/ + rip_enable_apply(ifp); - /* Check if this interface is RIP enabled or not.*/ - rip_enable_apply (ifp); - - /* Check for a passive interface */ - rip_passive_interface_apply (ifp); + /* Check for a passive interface */ + rip_passive_interface_apply(ifp); - /* Apply distribute list to the all interface. */ - rip_distribute_update_interface (ifp); + /* Apply distribute list to the all interface. */ + rip_distribute_update_interface(ifp); - return 0; + return 0; } /* Inteface addition message from zebra. */ -int -rip_interface_add (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +int rip_interface_add(int command, struct zclient *zclient, zebra_size_t length, + vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp; - ifp = zebra_interface_add_read (zclient->ibuf, vrf_id); + ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface add %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu); + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug( + "interface add %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); - /* Check if this interface is RIP enabled or not.*/ - rip_enable_apply (ifp); - - /* Check for a passive interface */ - rip_passive_interface_apply (ifp); + /* Check if this interface is RIP enabled or not.*/ + rip_enable_apply(ifp); - /* Apply distribute list to the all interface. */ - rip_distribute_update_interface (ifp); + /* Check for a passive interface */ + rip_passive_interface_apply(ifp); - /* rip_request_neighbor_all (); */ + /* Apply distribute list to the all interface. */ + rip_distribute_update_interface(ifp); - /* Check interface routemap. */ - rip_if_rmap_update_interface (ifp); + /* rip_request_neighbor_all (); */ - return 0; + /* Check interface routemap. */ + rip_if_rmap_update_interface(ifp); + + return 0; } -int -rip_interface_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int rip_interface_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; - struct stream *s; + struct interface *ifp; + struct stream *s; + + s = zclient->ibuf; + /* zebra_interface_state_read() updates interface structure in iflist */ + ifp = zebra_interface_state_read(s, vrf_id); - s = zclient->ibuf; - /* zebra_interface_state_read() updates interface structure in iflist */ - ifp = zebra_interface_state_read (s, vrf_id); + if (ifp == NULL) + return 0; + + if (if_is_up(ifp)) { + rip_if_down(ifp); + } - if (ifp == NULL) - return 0; + zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", + ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, + ifp->metric, ifp->mtu); - if (if_is_up (ifp)) { - rip_if_down(ifp); - } - - zlog_info("interface delete %s index %d flags %#llx metric %d mtu %d", - ifp->name, ifp->ifindex, (unsigned long long) ifp->flags, - ifp->metric, ifp->mtu); - - /* To support pseudo interface do not free interface structure. */ - /* if_delete(ifp); */ - ifp->ifindex = IFINDEX_DELETED; + /* To support pseudo interface do not free interface structure. */ + /* if_delete(ifp); */ + ifp->ifindex = IFINDEX_DELETED; - return 0; + return 0; } -static void -rip_interface_clean (struct rip_interface *ri) +static void rip_interface_clean(struct rip_interface *ri) { - ri->enable_network = 0; - ri->enable_interface = 0; - ri->running = 0; + ri->enable_network = 0; + ri->enable_interface = 0; + ri->running = 0; - if (ri->t_wakeup) - { - thread_cancel (ri->t_wakeup); - ri->t_wakeup = NULL; - } + if (ri->t_wakeup) { + thread_cancel(ri->t_wakeup); + ri->t_wakeup = NULL; + } } -void -rip_interfaces_clean (void) +void rip_interfaces_clean(void) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - rip_interface_clean (ifp->info); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + rip_interface_clean(ifp->info); } -static void -rip_interface_reset (struct rip_interface *ri) +static void rip_interface_reset(struct rip_interface *ri) { - /* Default authentication type is simple password for Cisco - compatibility. */ - ri->auth_type = RIP_NO_AUTH; - ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; + /* Default authentication type is simple password for Cisco + compatibility. */ + ri->auth_type = RIP_NO_AUTH; + ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; - /* Set default split-horizon behavior. If the interface is Frame - Relay or SMDS is enabled, the default value for split-horizon is - off. But currently Zebra does detect Frame Relay or SMDS - interface. So all interface is set to split horizon. */ - ri->split_horizon_default = RIP_SPLIT_HORIZON; - ri->split_horizon = ri->split_horizon_default; + /* Set default split-horizon behavior. If the interface is Frame + Relay or SMDS is enabled, the default value for split-horizon is + off. But currently Zebra does detect Frame Relay or SMDS + interface. So all interface is set to split horizon. */ + ri->split_horizon_default = RIP_SPLIT_HORIZON; + ri->split_horizon = ri->split_horizon_default; - ri->ri_send = RI_RIP_UNSPEC; - ri->ri_receive = RI_RIP_UNSPEC; + ri->ri_send = RI_RIP_UNSPEC; + ri->ri_receive = RI_RIP_UNSPEC; - ri->v2_broadcast = 0; + ri->v2_broadcast = 0; - if (ri->auth_str) - { - free (ri->auth_str); - ri->auth_str = NULL; - } - if (ri->key_chain) - { - free (ri->key_chain); - ri->key_chain = NULL; - } + if (ri->auth_str) { + free(ri->auth_str); + ri->auth_str = NULL; + } + if (ri->key_chain) { + free(ri->key_chain); + ri->key_chain = NULL; + } + + ri->list[RIP_FILTER_IN] = NULL; + ri->list[RIP_FILTER_OUT] = NULL; - ri->list[RIP_FILTER_IN] = NULL; - ri->list[RIP_FILTER_OUT] = NULL; + ri->prefix[RIP_FILTER_IN] = NULL; + ri->prefix[RIP_FILTER_OUT] = NULL; - ri->prefix[RIP_FILTER_IN] = NULL; - ri->prefix[RIP_FILTER_OUT] = NULL; + ri->recv_badpackets = 0; + ri->recv_badroutes = 0; + ri->sent_updates = 0; - ri->recv_badpackets = 0; - ri->recv_badroutes = 0; - ri->sent_updates = 0; + ri->passive = 0; - ri->passive = 0; - - rip_interface_clean (ri); + rip_interface_clean(ri); } -void -rip_interfaces_reset (void) +void rip_interfaces_reset(void) { - struct listnode *node; - struct interface *ifp; + struct listnode *node; + struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - rip_interface_reset (ifp->info); + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) + rip_interface_reset(ifp->info); } -int -rip_if_down(struct interface *ifp) +int rip_if_down(struct interface *ifp) { - struct route_node *rp; - struct rip_info *rinfo; - struct rip_interface *ri = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL, *nextnode = NULL; - if (rip) - { - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS (list, listnode, nextnode, rinfo)) - if (rinfo->ifindex == ifp->ifindex) - rip_ecmp_delete (rinfo); - - ri = ifp->info; - - if (ri->running) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("turn off %s", ifp->name); - - /* Leave from multicast group. */ - rip_multicast_leave (ifp, rip->sock); - - ri->running = 0; - } - } - - return 0; + struct route_node *rp; + struct rip_info *rinfo; + struct rip_interface *ri = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL, *nextnode = NULL; + if (rip) { + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS(list, listnode, nextnode, + rinfo)) + if (rinfo->ifindex == ifp->ifindex) + rip_ecmp_delete(rinfo); + + ri = ifp->info; + + if (ri->running) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("turn off %s", ifp->name); + + /* Leave from multicast group. */ + rip_multicast_leave(ifp, rip->sock); + + ri->running = 0; + } + } + + return 0; } /* Needed for stop RIP process. */ -void -rip_if_down_all () +void rip_if_down_all() { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_if_down (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_if_down(ifp); } -static void -rip_apply_address_add (struct connected *ifc) +static void rip_apply_address_add(struct connected *ifc) { - struct prefix_ipv4 address; - struct prefix *p; + struct prefix_ipv4 address; + struct prefix *p; - if (!rip) - return; - - if (! if_is_up(ifc->ifp)) - return; + if (!rip) + return; - p = ifc->address; + if (!if_is_up(ifc->ifp)) + return; - memset (&address, 0, sizeof (address)); - address.family = p->family; - address.prefix = p->u.prefix4; - address.prefixlen = p->prefixlen; - apply_mask_ipv4(&address); + p = ifc->address; - /* Check if this interface is RIP enabled or not - or Check if this address's prefix is RIP enabled */ - if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) || - (rip_enable_network_lookup2(ifc) >= 0)) - rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex, NULL, 0, 0, 0); + memset(&address, 0, sizeof(address)); + address.family = p->family; + address.prefix = p->u.prefix4; + address.prefixlen = p->prefixlen; + apply_mask_ipv4(&address); + /* Check if this interface is RIP enabled or not + or Check if this address's prefix is RIP enabled */ + if ((rip_enable_if_lookup(ifc->ifp->name) >= 0) + || (rip_enable_network_lookup2(ifc) >= 0)) + rip_redistribute_add(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, + &address, ifc->ifp->ifindex, NULL, 0, 0, + 0); } -int -rip_interface_address_add (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int rip_interface_address_add(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - struct prefix *p; + struct connected *ifc; + struct prefix *p; - ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD, - zclient->ibuf, vrf_id); + ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, + zclient->ibuf, vrf_id); - if (ifc == NULL) - return 0; + if (ifc == NULL) + return 0; - p = ifc->address; + p = ifc->address; - if (p->family == AF_INET) - { - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("connected address %s/%d is added", - inet_ntoa (p->u.prefix4), p->prefixlen); + if (p->family == AF_INET) { + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug("connected address %s/%d is added", + inet_ntoa(p->u.prefix4), p->prefixlen); - rip_enable_apply(ifc->ifp); - /* Check if this prefix needs to be redistributed */ - rip_apply_address_add(ifc); + rip_enable_apply(ifc->ifp); + /* Check if this prefix needs to be redistributed */ + rip_apply_address_add(ifc); - hook_call(rip_ifaddr_add, ifc); - } + hook_call(rip_ifaddr_add, ifc); + } - return 0; + return 0; } -static void -rip_apply_address_del (struct connected *ifc) { - struct prefix_ipv4 address; - struct prefix *p; +static void rip_apply_address_del(struct connected *ifc) +{ + struct prefix_ipv4 address; + struct prefix *p; - if (!rip) - return; + if (!rip) + return; - if (! if_is_up(ifc->ifp)) - return; + if (!if_is_up(ifc->ifp)) + return; - p = ifc->address; + p = ifc->address; - memset (&address, 0, sizeof (address)); - address.family = p->family; - address.prefix = p->u.prefix4; - address.prefixlen = p->prefixlen; - apply_mask_ipv4(&address); + memset(&address, 0, sizeof(address)); + address.family = p->family; + address.prefix = p->u.prefix4; + address.prefixlen = p->prefixlen; + apply_mask_ipv4(&address); - rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, ifc->ifp->ifindex); + rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, + &address, ifc->ifp->ifindex); } -int -rip_interface_address_delete (int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +int rip_interface_address_delete(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct connected *ifc; - struct prefix *p; - - ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE, - zclient->ibuf, vrf_id); - - if (ifc) - { - p = ifc->address; - if (p->family == AF_INET) - { - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("connected address %s/%d is deleted", - inet_ntoa (p->u.prefix4), p->prefixlen); + struct connected *ifc; + struct prefix *p; - hook_call(rip_ifaddr_del, ifc); + ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, + zclient->ibuf, vrf_id); - /* Chech wether this prefix needs to be removed */ - rip_apply_address_del(ifc); + if (ifc) { + p = ifc->address; + if (p->family == AF_INET) { + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug("connected address %s/%d is deleted", + inet_ntoa(p->u.prefix4), + p->prefixlen); - } + hook_call(rip_ifaddr_del, ifc); - connected_free (ifc); + /* Chech wether this prefix needs to be removed */ + rip_apply_address_del(ifc); + } - } + connected_free(ifc); + } - return 0; + return 0; } /* Check interface is enabled by network statement. */ /* Check wether the interface has at least a connected prefix that * is within the ripng_enable_network table. */ -static int -rip_enable_network_lookup_if (struct interface *ifp) -{ - struct listnode *node, *nnode; - struct connected *connected; - struct prefix_ipv4 address; - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) - { - struct prefix *p; - struct route_node *node; - - p = connected->address; - - if (p->family == AF_INET) - { - address.family = AF_INET; - address.prefix = p->u.prefix4; - address.prefixlen = IPV4_MAX_BITLEN; - - node = route_node_match (rip_enable_network, - (struct prefix *)&address); - if (node) - { - route_unlock_node (node); - return 1; - } - } - } - return -1; +static int rip_enable_network_lookup_if(struct interface *ifp) +{ + struct listnode *node, *nnode; + struct connected *connected; + struct prefix_ipv4 address; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { + struct prefix *p; + struct route_node *node; + + p = connected->address; + + if (p->family == AF_INET) { + address.family = AF_INET; + address.prefix = p->u.prefix4; + address.prefixlen = IPV4_MAX_BITLEN; + + node = route_node_match(rip_enable_network, + (struct prefix *)&address); + if (node) { + route_unlock_node(node); + return 1; + } + } + } + return -1; } /* Check wether connected is within the ripng_enable_network table. */ -int -rip_enable_network_lookup2 (struct connected *connected) +int rip_enable_network_lookup2(struct connected *connected) { - struct prefix_ipv4 address; - struct prefix *p; + struct prefix_ipv4 address; + struct prefix *p; - p = connected->address; + p = connected->address; - if (p->family == AF_INET) { - struct route_node *node; + if (p->family == AF_INET) { + struct route_node *node; - address.family = p->family; - address.prefix = p->u.prefix4; - address.prefixlen = IPV4_MAX_BITLEN; + address.family = p->family; + address.prefix = p->u.prefix4; + address.prefixlen = IPV4_MAX_BITLEN; - /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within rip_enable_network */ - node = route_node_match (rip_enable_network, - (struct prefix *)&address); + /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within + * rip_enable_network */ + node = route_node_match(rip_enable_network, + (struct prefix *)&address); - if (node) { - route_unlock_node (node); - return 1; - } - } + if (node) { + route_unlock_node(node); + return 1; + } + } - return -1; + return -1; } /* Add RIP enable network. */ -static int -rip_enable_network_add (struct prefix *p) +static int rip_enable_network_add(struct prefix *p) { - struct route_node *node; + struct route_node *node; - node = route_node_get (rip_enable_network, p); + node = route_node_get(rip_enable_network, p); - if (node->info) - { - route_unlock_node (node); - return -1; - } - else - node->info = (void *)1; + if (node->info) { + route_unlock_node(node); + return -1; + } else + node->info = (void *)1; - /* XXX: One should find a better solution than a generic one */ - rip_enable_apply_all(); + /* XXX: One should find a better solution than a generic one */ + rip_enable_apply_all(); - return 1; + return 1; } /* Delete RIP enable network. */ -static int -rip_enable_network_delete (struct prefix *p) +static int rip_enable_network_delete(struct prefix *p) { - struct route_node *node; + struct route_node *node; - node = route_node_lookup (rip_enable_network, p); - if (node) - { - node->info = NULL; + node = route_node_lookup(rip_enable_network, p); + if (node) { + node->info = NULL; - /* Unlock info lock. */ - route_unlock_node (node); + /* Unlock info lock. */ + route_unlock_node(node); - /* Unlock lookup lock. */ - route_unlock_node (node); + /* Unlock lookup lock. */ + route_unlock_node(node); - /* XXX: One should find a better solution than a generic one */ - rip_enable_apply_all (); + /* XXX: One should find a better solution than a generic one */ + rip_enable_apply_all(); - return 1; - } - return -1; + return 1; + } + return -1; } /* Check interface is enabled by ifname statement. */ -static int -rip_enable_if_lookup (const char *ifname) +static int rip_enable_if_lookup(const char *ifname) { - unsigned int i; - char *str; + unsigned int i; + char *str; - for (i = 0; i < vector_active (rip_enable_interface); i++) - if ((str = vector_slot (rip_enable_interface, i)) != NULL) - if (strcmp (str, ifname) == 0) - return i; - return -1; + for (i = 0; i < vector_active(rip_enable_interface); i++) + if ((str = vector_slot(rip_enable_interface, i)) != NULL) + if (strcmp(str, ifname) == 0) + return i; + return -1; } /* Add interface to rip_enable_if. */ -static int -rip_enable_if_add (const char *ifname) +static int rip_enable_if_add(const char *ifname) { - int ret; + int ret; - ret = rip_enable_if_lookup (ifname); - if (ret >= 0) - return -1; + ret = rip_enable_if_lookup(ifname); + if (ret >= 0) + return -1; - vector_set (rip_enable_interface, strdup (ifname)); + vector_set(rip_enable_interface, strdup(ifname)); - rip_enable_apply_all(); /* TODOVJ */ + rip_enable_apply_all(); /* TODOVJ */ - return 1; + return 1; } /* Delete interface from rip_enable_if. */ -static int -rip_enable_if_delete (const char *ifname) +static int rip_enable_if_delete(const char *ifname) { - int index; - char *str; + int index; + char *str; - index = rip_enable_if_lookup (ifname); - if (index < 0) - return -1; + index = rip_enable_if_lookup(ifname); + if (index < 0) + return -1; - str = vector_slot (rip_enable_interface, index); - free (str); - vector_unset (rip_enable_interface, index); + str = vector_slot(rip_enable_interface, index); + free(str); + vector_unset(rip_enable_interface, index); - rip_enable_apply_all(); /* TODOVJ */ + rip_enable_apply_all(); /* TODOVJ */ - return 1; + return 1; } /* Join to multicast group and send request to the interface. */ -static int -rip_interface_wakeup (struct thread *t) +static int rip_interface_wakeup(struct thread *t) { - struct interface *ifp; - struct rip_interface *ri; - - /* Get interface. */ - ifp = THREAD_ARG (t); - - ri = ifp->info; - ri->t_wakeup = NULL; + struct interface *ifp; + struct rip_interface *ri; - /* Join to multicast group. */ - if (rip_multicast_join (ifp, rip->sock) < 0) - { - zlog_err ("multicast join failed, interface %s not running", ifp->name); - return 0; - } + /* Get interface. */ + ifp = THREAD_ARG(t); - /* Set running flag. */ - ri->running = 1; + ri = ifp->info; + ri->t_wakeup = NULL; - /* Send RIP request to the interface. */ - rip_request_interface (ifp); - - return 0; -} + /* Join to multicast group. */ + if (rip_multicast_join(ifp, rip->sock) < 0) { + zlog_err("multicast join failed, interface %s not running", + ifp->name); + return 0; + } -static void -rip_connect_set (struct interface *ifp, int set) -{ - struct listnode *node, *nnode; - struct connected *connected; - struct prefix_ipv4 address; - - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) - { - struct prefix *p; - p = connected->address; - - if (p->family != AF_INET) - continue; - - address.family = AF_INET; - address.prefix = p->u.prefix4; - address.prefixlen = p->prefixlen; - apply_mask_ipv4 (&address); - - if (set) { - /* Check once more wether this prefix is within a "network IF_OR_PREF" one */ - if ((rip_enable_if_lookup(connected->ifp->name) >= 0) || - (rip_enable_network_lookup2(connected) >= 0)) - rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, connected->ifp->ifindex, - NULL, 0, 0, 0); - } else - { - rip_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE, - &address, connected->ifp->ifindex); - if (rip_redistribute_check (ZEBRA_ROUTE_CONNECT)) - rip_redistribute_add (ZEBRA_ROUTE_CONNECT, RIP_ROUTE_REDISTRIBUTE, - &address, connected->ifp->ifindex, - NULL, 0, 0, 0); - } - } + /* Set running flag. */ + ri->running = 1; + + /* Send RIP request to the interface. */ + rip_request_interface(ifp); + + return 0; +} + +static void rip_connect_set(struct interface *ifp, int set) +{ + struct listnode *node, *nnode; + struct connected *connected; + struct prefix_ipv4 address; + + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { + struct prefix *p; + p = connected->address; + + if (p->family != AF_INET) + continue; + + address.family = AF_INET; + address.prefix = p->u.prefix4; + address.prefixlen = p->prefixlen; + apply_mask_ipv4(&address); + + if (set) { + /* Check once more wether this prefix is within a + * "network IF_OR_PREF" one */ + if ((rip_enable_if_lookup(connected->ifp->name) >= 0) + || (rip_enable_network_lookup2(connected) >= 0)) + rip_redistribute_add( + ZEBRA_ROUTE_CONNECT, + RIP_ROUTE_INTERFACE, &address, + connected->ifp->ifindex, NULL, 0, 0, 0); + } else { + rip_redistribute_delete(ZEBRA_ROUTE_CONNECT, + RIP_ROUTE_INTERFACE, &address, + connected->ifp->ifindex); + if (rip_redistribute_check(ZEBRA_ROUTE_CONNECT)) + rip_redistribute_add( + ZEBRA_ROUTE_CONNECT, + RIP_ROUTE_REDISTRIBUTE, &address, + connected->ifp->ifindex, NULL, 0, 0, 0); + } + } } /* Update interface status. */ -void -rip_enable_apply (struct interface *ifp) +void rip_enable_apply(struct interface *ifp) { - int ret; - struct rip_interface *ri = NULL; + int ret; + struct rip_interface *ri = NULL; - /* Check interface. */ - if (! if_is_operative (ifp)) - return; + /* Check interface. */ + if (!if_is_operative(ifp)) + return; - ri = ifp->info; - - /* Check network configuration. */ - ret = rip_enable_network_lookup_if (ifp); - - /* If the interface is matched. */ - if (ret > 0) - ri->enable_network = 1; - else - ri->enable_network = 0; - - /* Check interface name configuration. */ - ret = rip_enable_if_lookup (ifp->name); - if (ret >= 0) - ri->enable_interface = 1; - else - ri->enable_interface = 0; - - /* any interface MUST have an IPv4 address */ - if ( ! rip_if_ipv4_address_check (ifp) ) - { - ri->enable_network = 0; - ri->enable_interface = 0; - } - - /* Update running status of the interface. */ - if (ri->enable_network || ri->enable_interface) - { - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("turn on %s", ifp->name); + ri = ifp->info; + + /* Check network configuration. */ + ret = rip_enable_network_lookup_if(ifp); + + /* If the interface is matched. */ + if (ret > 0) + ri->enable_network = 1; + else + ri->enable_network = 0; + + /* Check interface name configuration. */ + ret = rip_enable_if_lookup(ifp->name); + if (ret >= 0) + ri->enable_interface = 1; + else + ri->enable_interface = 0; - /* Add interface wake up thread. */ - thread_add_timer(master, rip_interface_wakeup, ifp, 1, - &ri->t_wakeup); - rip_connect_set (ifp, 1); + /* any interface MUST have an IPv4 address */ + if (!rip_if_ipv4_address_check(ifp)) { + ri->enable_network = 0; + ri->enable_interface = 0; } - } - else - { - if (ri->running) - { - /* Might as well clean up the route table as well - * rip_if_down sets to 0 ri->running, and displays "turn off %s" - **/ - rip_if_down(ifp); - rip_connect_set (ifp, 0); + /* Update running status of the interface. */ + if (ri->enable_network || ri->enable_interface) { + { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("turn on %s", ifp->name); + + /* Add interface wake up thread. */ + thread_add_timer(master, rip_interface_wakeup, ifp, 1, + &ri->t_wakeup); + rip_connect_set(ifp, 1); + } + } else { + if (ri->running) { + /* Might as well clean up the route table as well + * rip_if_down sets to 0 ri->running, and displays "turn + *off %s" + **/ + rip_if_down(ifp); + + rip_connect_set(ifp, 0); + } } - } } /* Apply network configuration to all interface. */ -void -rip_enable_apply_all () +void rip_enable_apply_all() { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - /* Check each interface. */ - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_enable_apply (ifp); + /* Check each interface. */ + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_enable_apply(ifp); } -int -rip_neighbor_lookup (struct sockaddr_in *from) +int rip_neighbor_lookup(struct sockaddr_in *from) { - struct prefix_ipv4 p; - struct route_node *node; + struct prefix_ipv4 p; + struct route_node *node; - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = from->sin_addr; - p.prefixlen = IPV4_MAX_BITLEN; + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = from->sin_addr; + p.prefixlen = IPV4_MAX_BITLEN; - node = route_node_lookup (rip->neighbor, (struct prefix *) &p); - if (node) - { - route_unlock_node (node); - return 1; - } - return 0; + node = route_node_lookup(rip->neighbor, (struct prefix *)&p); + if (node) { + route_unlock_node(node); + return 1; + } + return 0; } /* Add new RIP neighbor to the neighbor tree. */ -static int -rip_neighbor_add (struct prefix_ipv4 *p) +static int rip_neighbor_add(struct prefix_ipv4 *p) { - struct route_node *node; + struct route_node *node; - node = route_node_get (rip->neighbor, (struct prefix *) p); + node = route_node_get(rip->neighbor, (struct prefix *)p); - if (node->info) - return -1; + if (node->info) + return -1; - node->info = rip->neighbor; + node->info = rip->neighbor; - return 0; + return 0; } /* Delete RIP neighbor from the neighbor tree. */ -static int -rip_neighbor_delete (struct prefix_ipv4 *p) +static int rip_neighbor_delete(struct prefix_ipv4 *p) { - struct route_node *node; + struct route_node *node; - /* Lock for look up. */ - node = route_node_lookup (rip->neighbor, (struct prefix *) p); - if (! node) - return -1; - - node->info = NULL; + /* Lock for look up. */ + node = route_node_lookup(rip->neighbor, (struct prefix *)p); + if (!node) + return -1; - /* Unlock lookup lock. */ - route_unlock_node (node); + node->info = NULL; - /* Unlock real neighbor information lock. */ - route_unlock_node (node); + /* Unlock lookup lock. */ + route_unlock_node(node); - return 0; + /* Unlock real neighbor information lock. */ + route_unlock_node(node); + + return 0; } /* Clear all network and neighbor configuration. */ -void -rip_clean_network () -{ - unsigned int i; - char *str; - struct route_node *rn; - - /* rip_enable_network. */ - for (rn = route_top (rip_enable_network); rn; rn = route_next (rn)) - if (rn->info) - { - rn->info = NULL; - route_unlock_node (rn); - } - - /* rip_enable_interface. */ - for (i = 0; i < vector_active (rip_enable_interface); i++) - if ((str = vector_slot (rip_enable_interface, i)) != NULL) - { - free (str); - vector_slot (rip_enable_interface, i) = NULL; - } +void rip_clean_network() +{ + unsigned int i; + char *str; + struct route_node *rn; + + /* rip_enable_network. */ + for (rn = route_top(rip_enable_network); rn; rn = route_next(rn)) + if (rn->info) { + rn->info = NULL; + route_unlock_node(rn); + } + + /* rip_enable_interface. */ + for (i = 0; i < vector_active(rip_enable_interface); i++) + if ((str = vector_slot(rip_enable_interface, i)) != NULL) { + free(str); + vector_slot(rip_enable_interface, i) = NULL; + } } /* Utility function for looking up passive interface settings. */ -static int -rip_passive_nondefault_lookup (const char *ifname) +static int rip_passive_nondefault_lookup(const char *ifname) { - unsigned int i; - char *str; + unsigned int i; + char *str; - for (i = 0; i < vector_active (Vrip_passive_nondefault); i++) - if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL) - if (strcmp (str, ifname) == 0) - return i; - return -1; + for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) + if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) + if (strcmp(str, ifname) == 0) + return i; + return -1; } -void -rip_passive_interface_apply (struct interface *ifp) +void rip_passive_interface_apply(struct interface *ifp) { - struct rip_interface *ri; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->passive = ((rip_passive_nondefault_lookup (ifp->name) < 0) ? - passive_default : !passive_default); + ri->passive = ((rip_passive_nondefault_lookup(ifp->name) < 0) + ? passive_default + : !passive_default); - if (IS_RIP_DEBUG_ZEBRA) - zlog_debug ("interface %s: passive = %d",ifp->name,ri->passive); + if (IS_RIP_DEBUG_ZEBRA) + zlog_debug("interface %s: passive = %d", ifp->name, + ri->passive); } -static void -rip_passive_interface_apply_all (void) +static void rip_passive_interface_apply_all(void) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_passive_interface_apply (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_passive_interface_apply(ifp); } /* Passive interface. */ -static int -rip_passive_nondefault_set (struct vty *vty, const char *ifname) +static int rip_passive_nondefault_set(struct vty *vty, const char *ifname) { - if (rip_passive_nondefault_lookup (ifname) >= 0) - return CMD_WARNING_CONFIG_FAILED; + if (rip_passive_nondefault_lookup(ifname) >= 0) + return CMD_WARNING_CONFIG_FAILED; - vector_set (Vrip_passive_nondefault, strdup (ifname)); + vector_set(Vrip_passive_nondefault, strdup(ifname)); - rip_passive_interface_apply_all (); + rip_passive_interface_apply_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } -static int -rip_passive_nondefault_unset (struct vty *vty, const char *ifname) +static int rip_passive_nondefault_unset(struct vty *vty, const char *ifname) { - int i; - char *str; + int i; + char *str; - i = rip_passive_nondefault_lookup (ifname); - if (i < 0) - return CMD_WARNING_CONFIG_FAILED; + i = rip_passive_nondefault_lookup(ifname); + if (i < 0) + return CMD_WARNING_CONFIG_FAILED; - str = vector_slot (Vrip_passive_nondefault, i); - free (str); - vector_unset (Vrip_passive_nondefault, i); + str = vector_slot(Vrip_passive_nondefault, i); + free(str); + vector_unset(Vrip_passive_nondefault, i); - rip_passive_interface_apply_all (); + rip_passive_interface_apply_all(); - return CMD_SUCCESS; + return CMD_SUCCESS; } /* Free all configured RIP passive-interface settings. */ -void -rip_passive_nondefault_clean (void) +void rip_passive_nondefault_clean(void) { - unsigned int i; - char *str; + unsigned int i; + char *str; - for (i = 0; i < vector_active (Vrip_passive_nondefault); i++) - if ((str = vector_slot (Vrip_passive_nondefault, i)) != NULL) - { - free (str); - vector_slot (Vrip_passive_nondefault, i) = NULL; - } - rip_passive_interface_apply_all (); + for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) + if ((str = vector_slot(Vrip_passive_nondefault, i)) != NULL) { + free(str); + vector_slot(Vrip_passive_nondefault, i) = NULL; + } + rip_passive_interface_apply_all(); } /* RIP enable network or interface configuration. */ @@ -1220,25 +1151,24 @@ DEFUN (rip_network, "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" "Interface name\n") { - int idx_ipv4_word = 1; - int ret; - struct prefix_ipv4 p; + int idx_ipv4_word = 1; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4_word]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4_word]->arg, &p); - if (ret) - ret = rip_enable_network_add ((struct prefix *) &p); - else - ret = rip_enable_if_add (argv[idx_ipv4_word]->arg); + if (ret) + ret = rip_enable_network_add((struct prefix *)&p); + else + ret = rip_enable_if_add(argv[idx_ipv4_word]->arg); - if (ret < 0) - { - vty_out (vty, "There is a same network configuration %s\n", - argv[idx_ipv4_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + vty_out(vty, "There is a same network configuration %s\n", + argv[idx_ipv4_word]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP enable network or interface configuration. */ @@ -1250,25 +1180,24 @@ DEFUN (no_rip_network, "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n" "Interface name\n") { - int idx_ipv4_word = 2; - int ret; - struct prefix_ipv4 p; + int idx_ipv4_word = 2; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4_word]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4_word]->arg, &p); - if (ret) - ret = rip_enable_network_delete ((struct prefix *) &p); - else - ret = rip_enable_if_delete (argv[idx_ipv4_word]->arg); + if (ret) + ret = rip_enable_network_delete((struct prefix *)&p); + else + ret = rip_enable_if_delete(argv[idx_ipv4_word]->arg); - if (ret < 0) - { - vty_out (vty, "Can't find network configuration %s\n", - argv[idx_ipv4_word]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret < 0) { + vty_out(vty, "Can't find network configuration %s\n", + argv[idx_ipv4_word]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP neighbor configuration set. */ @@ -1278,21 +1207,20 @@ DEFUN (rip_neighbor, "Specify a neighbor router\n" "Neighbor address\n") { - int idx_ipv4 = 1; - int ret; - struct prefix_ipv4 p; + int idx_ipv4 = 1; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p); + + if (ret <= 0) { + vty_out(vty, "Please specify address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ret <= 0) - { - vty_out (vty, "Please specify address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + rip_neighbor_add(&p); - rip_neighbor_add (&p); - - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP neighbor configuration unset. */ @@ -1303,21 +1231,20 @@ DEFUN (no_rip_neighbor, "Specify a neighbor router\n" "Neighbor address\n") { - int idx_ipv4 = 2; - int ret; - struct prefix_ipv4 p; + int idx_ipv4 = 2; + int ret; + struct prefix_ipv4 p; - ret = str2prefix_ipv4 (argv[idx_ipv4]->arg, &p); + ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p); - if (ret <= 0) - { - vty_out (vty, "Please specify address by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ret <= 0) { + vty_out(vty, "Please specify address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rip_neighbor_delete(&p); - rip_neighbor_delete (&p); - - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_rip_receive_version, @@ -1330,28 +1257,27 @@ DEFUN (ip_rip_receive_version, "RIP version\n" "None\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_type = 4; - struct rip_interface *ri; - - ri = ifp->info; - - switch (argv[idx_type]->arg[0]) - { - case '1': - ri->ri_receive = RI_RIP_VERSION_1; - return CMD_SUCCESS; - case '2': - ri->ri_receive = RI_RIP_VERSION_2; - return CMD_SUCCESS; - case 'n': - ri->ri_receive = RI_RIP_VERSION_NONE; - return CMD_SUCCESS; - default: - break; - } + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_type = 4; + struct rip_interface *ri; + + ri = ifp->info; + + switch (argv[idx_type]->arg[0]) { + case '1': + ri->ri_receive = RI_RIP_VERSION_1; + return CMD_SUCCESS; + case '2': + ri->ri_receive = RI_RIP_VERSION_2; + return CMD_SUCCESS; + case 'n': + ri->ri_receive = RI_RIP_VERSION_NONE; + return CMD_SUCCESS; + default: + break; + } - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (ip_rip_receive_version_1, @@ -1366,14 +1292,14 @@ DEFUN (ip_rip_receive_version_1, "RIP version 2\n" "RIP version 1\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - /* Version 1 and 2. */ - ri->ri_receive = RI_RIP_VERSION_1_AND_2; - return CMD_SUCCESS; + /* Version 1 and 2. */ + ri->ri_receive = RI_RIP_VERSION_1_AND_2; + return CMD_SUCCESS; } DEFUN (no_ip_rip_receive_version, @@ -1386,13 +1312,13 @@ DEFUN (no_ip_rip_receive_version, "Version control\n" "RIP version\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->ri_receive = RI_RIP_UNSPEC; - return CMD_SUCCESS; + ri->ri_receive = RI_RIP_UNSPEC; + return CMD_SUCCESS; } @@ -1405,24 +1331,22 @@ DEFUN (ip_rip_send_version, "Version control\n" "RIP version\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_type = 4; - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_type = 4; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - /* Version 1. */ - if (atoi (argv[idx_type]->arg) == 1) - { - ri->ri_send = RI_RIP_VERSION_1; - return CMD_SUCCESS; - } - if (atoi (argv[idx_type]->arg) == 2) - { - ri->ri_send = RI_RIP_VERSION_2; - return CMD_SUCCESS; - } - return CMD_WARNING_CONFIG_FAILED; + /* Version 1. */ + if (atoi(argv[idx_type]->arg) == 1) { + ri->ri_send = RI_RIP_VERSION_1; + return CMD_SUCCESS; + } + if (atoi(argv[idx_type]->arg) == 2) { + ri->ri_send = RI_RIP_VERSION_2; + return CMD_SUCCESS; + } + return CMD_WARNING_CONFIG_FAILED; } DEFUN (ip_rip_send_version_1, @@ -1437,14 +1361,14 @@ DEFUN (ip_rip_send_version_1, "RIP version 2\n" "RIP version 1\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - /* Version 1 and 2. */ - ri->ri_send = RI_RIP_VERSION_1_AND_2; - return CMD_SUCCESS; + /* Version 1 and 2. */ + ri->ri_send = RI_RIP_VERSION_1_AND_2; + return CMD_SUCCESS; } DEFUN (no_ip_rip_send_version, @@ -1457,13 +1381,13 @@ DEFUN (no_ip_rip_send_version, "Version control\n" "RIP version\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->ri_send = RI_RIP_UNSPEC; - return CMD_SUCCESS; + ri->ri_send = RI_RIP_UNSPEC; + return CMD_SUCCESS; } @@ -1474,13 +1398,13 @@ DEFUN (ip_rip_v2_broadcast, "Routing Information Protocol\n" "Send ip broadcast v2 update\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->v2_broadcast = 1; - return CMD_SUCCESS; + ri->v2_broadcast = 1; + return CMD_SUCCESS; } DEFUN (no_ip_rip_v2_broadcast, @@ -1491,13 +1415,13 @@ DEFUN (no_ip_rip_v2_broadcast, "Routing Information Protocol\n" "Send ip broadcast v2 update\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->v2_broadcast = 0; - return CMD_SUCCESS; + ri->v2_broadcast = 0; + return CMD_SUCCESS; } DEFUN (ip_rip_authentication_mode, @@ -1513,40 +1437,38 @@ DEFUN (ip_rip_authentication_mode, "RFC compatible\n" "Old ripd compatible\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - char *cryptmode = argv[4]->text; - char *authlen = (argc > 5) ? argv[6]->text : NULL; - struct rip_interface *ri; - int auth_type; - - ri = ifp->info; - - if (strmatch ("md5", cryptmode)) - auth_type = RIP_AUTH_MD5; - else { - assert (strmatch ("text", cryptmode)); - auth_type = RIP_AUTH_SIMPLE_PASSWORD; - } - - ri->auth_type = auth_type; - - if (argc > 5) - { - if (auth_type != RIP_AUTH_MD5) - { - vty_out (vty, "auth length argument only valid for md5\n"); - return CMD_WARNING_CONFIG_FAILED; - } - if (strmatch ("rfc", authlen)) - ri->md5_auth_len = RIP_AUTH_MD5_SIZE; - else - { - assert (strmatch ("old-ripd", authlen)); - ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; - } - } - - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(interface, ifp); + char *cryptmode = argv[4]->text; + char *authlen = (argc > 5) ? argv[6]->text : NULL; + struct rip_interface *ri; + int auth_type; + + ri = ifp->info; + + if (strmatch("md5", cryptmode)) + auth_type = RIP_AUTH_MD5; + else { + assert(strmatch("text", cryptmode)); + auth_type = RIP_AUTH_SIMPLE_PASSWORD; + } + + ri->auth_type = auth_type; + + if (argc > 5) { + if (auth_type != RIP_AUTH_MD5) { + vty_out(vty, + "auth length argument only valid for md5\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (strmatch("rfc", authlen)) + ri->md5_auth_len = RIP_AUTH_MD5_SIZE; + else { + assert(strmatch("old-ripd", authlen)); + ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; + } + } + + return CMD_SUCCESS; } DEFUN (no_ip_rip_authentication_mode, @@ -1563,15 +1485,15 @@ DEFUN (no_ip_rip_authentication_mode, "RFC compatible\n" "Old ripd compatible\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->auth_type = RIP_NO_AUTH; - ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; + ri->auth_type = RIP_NO_AUTH; + ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (ip_rip_authentication_string, @@ -1583,31 +1505,29 @@ DEFUN (ip_rip_authentication_string, "Authentication string\n" "Authentication string\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_line = 4; - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_line = 4; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (strlen (argv[idx_line]->arg) > 16) - { - vty_out (vty, - "%% RIPv2 authentication string must be shorter than 16\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (strlen(argv[idx_line]->arg) > 16) { + vty_out(vty, + "%% RIPv2 authentication string must be shorter than 16\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ri->key_chain) - { - vty_out (vty, "%% key-chain configuration exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ri->key_chain) { + vty_out(vty, "%% key-chain configuration exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ri->auth_str) - free (ri->auth_str); + if (ri->auth_str) + free(ri->auth_str); - ri->auth_str = strdup (argv[idx_line]->arg); + ri->auth_str = strdup(argv[idx_line]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_rip_authentication_string, @@ -1620,17 +1540,17 @@ DEFUN (no_ip_rip_authentication_string, "Authentication string\n" "Authentication string\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (ri->auth_str) - free (ri->auth_str); + if (ri->auth_str) + free(ri->auth_str); - ri->auth_str = NULL; + ri->auth_str = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1643,24 +1563,23 @@ DEFUN (ip_rip_authentication_key_chain, "Authentication key-chain\n" "name of key-chain\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - int idx_line = 4; - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_line = 4; + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (ri->auth_str) - { - vty_out (vty,"%% authentication string configuration exists\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (ri->auth_str) { + vty_out(vty, "%% authentication string configuration exists\n"); + return CMD_WARNING_CONFIG_FAILED; + } - if (ri->key_chain) - free (ri->key_chain); + if (ri->key_chain) + free(ri->key_chain); - ri->key_chain = strdup (argv[idx_line]->arg); + ri->key_chain = strdup(argv[idx_line]->arg); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_ip_rip_authentication_key_chain, @@ -1673,17 +1592,17 @@ DEFUN (no_ip_rip_authentication_key_chain, "Authentication key-chain\n" "name of key-chain\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - if (ri->key_chain) - free (ri->key_chain); + if (ri->key_chain) + free(ri->key_chain); - ri->key_chain = NULL; + ri->key_chain = NULL; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -1698,13 +1617,13 @@ DEFUN (ip_rip_split_horizon, "Routing Information Protocol\n" "Perform split horizon\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIP_SPLIT_HORIZON; - return CMD_SUCCESS; + ri->split_horizon = RIP_SPLIT_HORIZON; + return CMD_SUCCESS; } DEFUN (ip_rip_split_horizon_poisoned_reverse, @@ -1715,13 +1634,13 @@ DEFUN (ip_rip_split_horizon_poisoned_reverse, "Perform split horizon\n" "With poisoned-reverse\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE; - return CMD_SUCCESS; + ri->split_horizon = RIP_SPLIT_HORIZON_POISONED_REVERSE; + return CMD_SUCCESS; } /* CHANGED: no ip rip split-horizon @@ -1736,13 +1655,13 @@ DEFUN (no_ip_rip_split_horizon, "Routing Information Protocol\n" "Perform split horizon\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - ri->split_horizon = RIP_NO_SPLIT_HORIZON; - return CMD_SUCCESS; + ri->split_horizon = RIP_NO_SPLIT_HORIZON; + return CMD_SUCCESS; } DEFUN (no_ip_rip_split_horizon_poisoned_reverse, @@ -1754,20 +1673,19 @@ DEFUN (no_ip_rip_split_horizon_poisoned_reverse, "Perform split horizon\n" "With poisoned-reverse\n") { - VTY_DECLVAR_CONTEXT(interface, ifp); - struct rip_interface *ri; + VTY_DECLVAR_CONTEXT(interface, ifp); + struct rip_interface *ri; - ri = ifp->info; + ri = ifp->info; - switch( ri->split_horizon ) - { - case RIP_SPLIT_HORIZON_POISONED_REVERSE: - ri->split_horizon = RIP_SPLIT_HORIZON; - default: - break; - } + switch (ri->split_horizon) { + case RIP_SPLIT_HORIZON_POISONED_REVERSE: + ri->split_horizon = RIP_SPLIT_HORIZON; + default: + break; + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (rip_passive_interface, @@ -1777,15 +1695,15 @@ DEFUN (rip_passive_interface, "Interface name\n" "default for all interfaces\n") { - if (argv[1]->type == WORD_TKN) { // user passed 'default' - passive_default = 1; - rip_passive_nondefault_clean(); - return CMD_SUCCESS; - } - if (passive_default) - return rip_passive_nondefault_unset (vty, argv[1]->arg); - else - return rip_passive_nondefault_set (vty, argv[1]->arg); + if (argv[1]->type == WORD_TKN) { // user passed 'default' + passive_default = 1; + rip_passive_nondefault_clean(); + return CMD_SUCCESS; + } + if (passive_default) + return rip_passive_nondefault_unset(vty, argv[1]->arg); + else + return rip_passive_nondefault_set(vty, argv[1]->arg); } DEFUN (no_rip_passive_interface, @@ -1796,224 +1714,217 @@ DEFUN (no_rip_passive_interface, "Interface name\n" "default for all interfaces\n") { - if (argv[2]->type == WORD_TKN) { - passive_default = 0; - rip_passive_nondefault_clean(); - return CMD_SUCCESS; - } - if (passive_default) - return rip_passive_nondefault_set (vty, argv[2]->arg); - else - return rip_passive_nondefault_unset (vty, argv[2]->arg); + if (argv[2]->type == WORD_TKN) { + passive_default = 0; + rip_passive_nondefault_clean(); + return CMD_SUCCESS; + } + if (passive_default) + return rip_passive_nondefault_set(vty, argv[2]->arg); + else + return rip_passive_nondefault_unset(vty, argv[2]->arg); } /* Write rip configuration of each interface. */ -static int -rip_interface_config_write (struct vty *vty) -{ - struct listnode *node; - struct interface *ifp; - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - struct rip_interface *ri; - - if (ifp->ifindex == IFINDEX_DELETED) - continue; - - ri = ifp->info; - - /* Do not display the interface if there is no - * configuration about it. - **/ - if ((!ifp->desc) && - (ri->split_horizon == ri->split_horizon_default) && - (ri->ri_send == RI_RIP_UNSPEC) && - (ri->ri_receive == RI_RIP_UNSPEC) && - (ri->auth_type != RIP_AUTH_MD5) && - (!ri->v2_broadcast) && - (ri->md5_auth_len != RIP_AUTH_MD5_SIZE) && - (!ri->auth_str) && - (!ri->key_chain) ) - continue; - - vty_out (vty, "interface %s\n",ifp->name); - - if (ifp->desc) - vty_out (vty, " description %s\n",ifp->desc); - - /* Split horizon. */ - if (ri->split_horizon != ri->split_horizon_default) - { - switch (ri->split_horizon) { - case RIP_SPLIT_HORIZON: - vty_out (vty, " ip rip split-horizon\n"); - break; - case RIP_SPLIT_HORIZON_POISONED_REVERSE: - vty_out (vty," ip rip split-horizon poisoned-reverse\n"); - break; - case RIP_NO_SPLIT_HORIZON: - default: - vty_out (vty, " no ip rip split-horizon\n"); - break; - } +static int rip_interface_config_write(struct vty *vty) +{ + struct listnode *node; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + struct rip_interface *ri; + + if (ifp->ifindex == IFINDEX_DELETED) + continue; + + ri = ifp->info; + + /* Do not display the interface if there is no + * configuration about it. + **/ + if ((!ifp->desc) + && (ri->split_horizon == ri->split_horizon_default) + && (ri->ri_send == RI_RIP_UNSPEC) + && (ri->ri_receive == RI_RIP_UNSPEC) + && (ri->auth_type != RIP_AUTH_MD5) && (!ri->v2_broadcast) + && (ri->md5_auth_len != RIP_AUTH_MD5_SIZE) + && (!ri->auth_str) && (!ri->key_chain)) + continue; + + vty_out(vty, "interface %s\n", ifp->name); + + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); + + /* Split horizon. */ + if (ri->split_horizon != ri->split_horizon_default) { + switch (ri->split_horizon) { + case RIP_SPLIT_HORIZON: + vty_out(vty, " ip rip split-horizon\n"); + break; + case RIP_SPLIT_HORIZON_POISONED_REVERSE: + vty_out(vty, + " ip rip split-horizon poisoned-reverse\n"); + break; + case RIP_NO_SPLIT_HORIZON: + default: + vty_out(vty, " no ip rip split-horizon\n"); + break; + } + } + + /* RIP version setting. */ + if (ri->ri_send != RI_RIP_UNSPEC) + vty_out(vty, " ip rip send version %s\n", + lookup_msg(ri_version_msg, ri->ri_send, NULL)); + + if (ri->ri_receive != RI_RIP_UNSPEC) + vty_out(vty, " ip rip receive version %s \n", + lookup_msg(ri_version_msg, ri->ri_receive, + NULL)); + + if (ri->v2_broadcast) + vty_out(vty, " ip rip v2-broadcast\n"); + + /* RIP authentication. */ + if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) + vty_out(vty, " ip rip authentication mode text\n"); + + if (ri->auth_type == RIP_AUTH_MD5) { + vty_out(vty, " ip rip authentication mode md5"); + if (ri->md5_auth_len == RIP_AUTH_MD5_COMPAT_SIZE) + vty_out(vty, " auth-length old-ripd"); + else + vty_out(vty, " auth-length rfc"); + vty_out(vty, "\n"); + } + + if (ri->auth_str) + vty_out(vty, " ip rip authentication string %s\n", + ri->auth_str); + + if (ri->key_chain) + vty_out(vty, " ip rip authentication key-chain %s\n", + ri->key_chain); + + vty_out(vty, "!\n"); + } + return 0; +} + +int config_write_rip_network(struct vty *vty, int config_mode) +{ + unsigned int i; + char *ifname; + struct route_node *node; + + /* Network type RIP enable interface statement. */ + for (node = route_top(rip_enable_network); node; + node = route_next(node)) + if (node->info) + vty_out(vty, "%s%s/%d\n", + config_mode ? " network " : " ", + inet_ntoa(node->p.u.prefix4), + node->p.prefixlen); + + /* Interface name RIP enable statement. */ + for (i = 0; i < vector_active(rip_enable_interface); i++) + if ((ifname = vector_slot(rip_enable_interface, i)) != NULL) + vty_out(vty, "%s%s\n", + config_mode ? " network " : " ", ifname); + + /* RIP neighbors listing. */ + for (node = route_top(rip->neighbor); node; node = route_next(node)) + if (node->info) + vty_out(vty, "%s%s\n", + config_mode ? " neighbor " : " ", + inet_ntoa(node->p.u.prefix4)); + + /* RIP passive interface listing. */ + if (config_mode) { + if (passive_default) + vty_out(vty, " passive-interface default\n"); + for (i = 0; i < vector_active(Vrip_passive_nondefault); i++) + if ((ifname = vector_slot(Vrip_passive_nondefault, i)) + != NULL) + vty_out(vty, " %spassive-interface %s\n", + (passive_default ? "no " : ""), ifname); } - /* RIP version setting. */ - if (ri->ri_send != RI_RIP_UNSPEC) - vty_out (vty, " ip rip send version %s\n", - lookup_msg(ri_version_msg, ri->ri_send, NULL)); - - if (ri->ri_receive != RI_RIP_UNSPEC) - vty_out (vty, " ip rip receive version %s \n", - lookup_msg(ri_version_msg, ri->ri_receive, NULL)); - - if (ri->v2_broadcast) - vty_out (vty, " ip rip v2-broadcast\n"); - - /* RIP authentication. */ - if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) - vty_out (vty, " ip rip authentication mode text\n"); - - if (ri->auth_type == RIP_AUTH_MD5) - { - vty_out (vty, " ip rip authentication mode md5"); - if (ri->md5_auth_len == RIP_AUTH_MD5_COMPAT_SIZE) - vty_out (vty, " auth-length old-ripd"); - else - vty_out (vty, " auth-length rfc"); - vty_out (vty, "\n"); - } - - if (ri->auth_str) - vty_out (vty, " ip rip authentication string %s\n", - ri->auth_str); - - if (ri->key_chain) - vty_out (vty, " ip rip authentication key-chain %s\n", - ri->key_chain); - - vty_out (vty, "!\n"); - } - return 0; -} - -int -config_write_rip_network (struct vty *vty, int config_mode) -{ - unsigned int i; - char *ifname; - struct route_node *node; - - /* Network type RIP enable interface statement. */ - for (node = route_top (rip_enable_network); node; node = route_next (node)) - if (node->info) - vty_out (vty, "%s%s/%d\n", - config_mode ? " network " : " ", - inet_ntoa (node->p.u.prefix4), - node->p.prefixlen); - - /* Interface name RIP enable statement. */ - for (i = 0; i < vector_active (rip_enable_interface); i++) - if ((ifname = vector_slot (rip_enable_interface, i)) != NULL) - vty_out (vty, "%s%s\n", - config_mode ? " network " : " ", - ifname); - - /* RIP neighbors listing. */ - for (node = route_top (rip->neighbor); node; node = route_next (node)) - if (node->info) - vty_out (vty, "%s%s\n", - config_mode ? " neighbor " : " ", - inet_ntoa(node->p.u.prefix4)); - - /* RIP passive interface listing. */ - if (config_mode) { - if (passive_default) - vty_out (vty, " passive-interface default\n"); - for (i = 0; i < vector_active (Vrip_passive_nondefault); i++) - if ((ifname = vector_slot (Vrip_passive_nondefault, i)) != NULL) - vty_out (vty, " %spassive-interface %s\n", - (passive_default ? "no " : ""), ifname); - } - - return 0; -} - -static struct cmd_node interface_node = -{ - INTERFACE_NODE, - "%s(config-if)# ", - 1, + return 0; +} + +static struct cmd_node interface_node = { + INTERFACE_NODE, "%s(config-if)# ", 1, }; /* Called when interface structure allocated. */ -static int -rip_interface_new_hook (struct interface *ifp) +static int rip_interface_new_hook(struct interface *ifp) { - ifp->info = rip_interface_new (); - return 0; + ifp->info = rip_interface_new(); + return 0; } /* Called when interface structure deleted. */ -static int -rip_interface_delete_hook (struct interface *ifp) +static int rip_interface_delete_hook(struct interface *ifp) { - XFREE (MTYPE_RIP_INTERFACE, ifp->info); - ifp->info = NULL; - return 0; + XFREE(MTYPE_RIP_INTERFACE, ifp->info); + ifp->info = NULL; + return 0; } /* Allocate and initialize interface vector. */ -void -rip_if_init (void) +void rip_if_init(void) { - /* Default initial size of interface vector. */ - if_add_hook (IF_NEW_HOOK, rip_interface_new_hook); - if_add_hook (IF_DELETE_HOOK, rip_interface_delete_hook); - - /* RIP network init. */ - rip_enable_interface = vector_init (1); - rip_enable_network = route_table_init (); + /* Default initial size of interface vector. */ + if_add_hook(IF_NEW_HOOK, rip_interface_new_hook); + if_add_hook(IF_DELETE_HOOK, rip_interface_delete_hook); + + /* RIP network init. */ + rip_enable_interface = vector_init(1); + rip_enable_network = route_table_init(); - /* RIP passive interface. */ - Vrip_passive_nondefault = vector_init (1); + /* RIP passive interface. */ + Vrip_passive_nondefault = vector_init(1); - /* Install interface node. */ - install_node (&interface_node, rip_interface_config_write); - if_cmd_init (); + /* Install interface node. */ + install_node(&interface_node, rip_interface_config_write); + if_cmd_init(); - /* Install commands. */ - install_element (RIP_NODE, &rip_network_cmd); - install_element (RIP_NODE, &no_rip_network_cmd); - install_element (RIP_NODE, &rip_neighbor_cmd); - install_element (RIP_NODE, &no_rip_neighbor_cmd); + /* Install commands. */ + install_element(RIP_NODE, &rip_network_cmd); + install_element(RIP_NODE, &no_rip_network_cmd); + install_element(RIP_NODE, &rip_neighbor_cmd); + install_element(RIP_NODE, &no_rip_neighbor_cmd); - install_element (RIP_NODE, &rip_passive_interface_cmd); - install_element (RIP_NODE, &no_rip_passive_interface_cmd); + install_element(RIP_NODE, &rip_passive_interface_cmd); + install_element(RIP_NODE, &no_rip_passive_interface_cmd); - install_element (INTERFACE_NODE, &ip_rip_send_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_send_version_1_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_send_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_send_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_send_version_1_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_send_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_receive_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_receive_version_1_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_receive_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_receive_version_cmd); + install_element(INTERFACE_NODE, &ip_rip_receive_version_1_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_receive_version_cmd); - install_element (INTERFACE_NODE, &ip_rip_v2_broadcast_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_v2_broadcast_cmd); + install_element(INTERFACE_NODE, &ip_rip_v2_broadcast_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_v2_broadcast_cmd); - install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_mode_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd); - install_element (INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd); + install_element(INTERFACE_NODE, + &no_ip_rip_authentication_key_chain_cmd); - install_element (INTERFACE_NODE, &ip_rip_authentication_string_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_authentication_string_cmd); + install_element(INTERFACE_NODE, &ip_rip_authentication_string_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_authentication_string_cmd); - install_element (INTERFACE_NODE, &ip_rip_split_horizon_cmd); - install_element (INTERFACE_NODE, &ip_rip_split_horizon_poisoned_reverse_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_cmd); - install_element (INTERFACE_NODE, &no_ip_rip_split_horizon_poisoned_reverse_cmd); + install_element(INTERFACE_NODE, &ip_rip_split_horizon_cmd); + install_element(INTERFACE_NODE, + &ip_rip_split_horizon_poisoned_reverse_cmd); + install_element(INTERFACE_NODE, &no_ip_rip_split_horizon_cmd); + install_element(INTERFACE_NODE, + &no_ip_rip_split_horizon_poisoned_reverse_cmd); } diff --git a/ripd/rip_interface.h b/ripd/rip_interface.h index 9513bafc22..8723388e75 100644 --- a/ripd/rip_interface.h +++ b/ripd/rip_interface.h @@ -20,17 +20,13 @@ #ifndef _QUAGGA_RIP_INTERFACE_H #define _QUAGGA_RIP_INTERFACE_H -extern int rip_interface_down (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_up (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_add (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_delete (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_address_add (int , struct zclient *, zebra_size_t, - vrf_id_t); -extern int rip_interface_address_delete (int , struct zclient *, zebra_size_t, - vrf_id_t); +extern int rip_interface_down(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_up(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_delete(int, struct zclient *, zebra_size_t, vrf_id_t); +extern int rip_interface_address_add(int, struct zclient *, zebra_size_t, + vrf_id_t); +extern int rip_interface_address_delete(int, struct zclient *, zebra_size_t, + vrf_id_t); #endif /* _QUAGGA_RIP_INTERFACE_H */ diff --git a/ripd/rip_main.c b/ripd/rip_main.c index 1a7d03bca1..91b623beb4 100644 --- a/ripd/rip_main.c +++ b/ripd/rip_main.c @@ -39,34 +39,24 @@ #include "ripd/ripd.h" /* ripd options. */ -static struct option longopts[] = -{ - { "retain", no_argument, NULL, 'r'}, - { 0 } -}; +static struct option longopts[] = {{"retain", no_argument, NULL, 'r'}, {0}}; /* ripd privileges */ -zebra_capabilities_t _caps_p [] = -{ - ZCAP_NET_RAW, - ZCAP_BIND -}; +zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND}; -struct zebra_privs_t ripd_privs = -{ +struct zebra_privs_t ripd_privs = { #if defined(FRR_USER) - .user = FRR_USER, + .user = FRR_USER, #endif #if defined FRR_GROUP - .group = FRR_GROUP, + .group = FRR_GROUP, #endif #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif - .caps_p = _caps_p, - .cap_num_p = 2, - .cap_num_i = 0 -}; + .caps_p = _caps_p, + .cap_num_p = 2, + .cap_num_i = 0}; /* Route retain mode flag. */ int retain_mode = 0; @@ -77,119 +67,110 @@ struct thread_master *master; static struct frr_daemon_info ripd_di; /* SIGHUP handler. */ -static void -sighup (void) +static void sighup(void) { - zlog_info ("SIGHUP received"); - rip_clean (); - rip_reset (); - zlog_info ("ripd restarting!"); + zlog_info("SIGHUP received"); + rip_clean(); + rip_reset(); + zlog_info("ripd restarting!"); - /* Reload config file. */ - vty_read_config (ripd_di.config_file, config_default); + /* Reload config file. */ + vty_read_config(ripd_di.config_file, config_default); - /* Try to return to normal operation. */ + /* Try to return to normal operation. */ } /* SIGINT handler. */ -static void -sigint (void) +static void sigint(void) { - zlog_notice ("Terminating on signal"); + zlog_notice("Terminating on signal"); - if (! retain_mode) - rip_clean (); + if (!retain_mode) + rip_clean(); - rip_zclient_stop (); + rip_zclient_stop(); - exit (0); + exit(0); } /* SIGUSR1 handler. */ -static void -sigusr1 (void) +static void sigusr1(void) { - zlog_rotate(); + zlog_rotate(); } -static struct quagga_signal_t ripd_signals[] = -{ - { - .signal = SIGHUP, - .handler = &sighup, - }, - { - .signal = SIGUSR1, - .handler = &sigusr1, - }, - { - .signal = SIGINT, - .handler = &sigint, - }, - { - .signal = SIGTERM, - .handler = &sigint, - }, -}; - -FRR_DAEMON_INFO(ripd, RIP, - .vty_port = RIP_VTY_PORT, - - .proghelp = "Implementation of the RIP routing protocol.", - - .signals = ripd_signals, - .n_signals = array_size(ripd_signals), - - .privs = &ripd_privs, -) +static struct quagga_signal_t ripd_signals[] = { + { + .signal = SIGHUP, + .handler = &sighup, + }, + { + .signal = SIGUSR1, + .handler = &sigusr1, + }, + { + .signal = SIGINT, + .handler = &sigint, + }, + { + .signal = SIGTERM, + .handler = &sigint, + }, +}; -/* Main routine of ripd. */ -int -main (int argc, char **argv) -{ - frr_preinit (&ripd_di, argc, argv); - frr_opt_add ("r", longopts, - " -r, --retain When program terminates, retain added route by ripd.\n"); +FRR_DAEMON_INFO(ripd, RIP, .vty_port = RIP_VTY_PORT, - /* Command line option parse. */ - while (1) - { - int opt; + .proghelp = "Implementation of the RIP routing protocol.", - opt = frr_getopt (argc, argv, NULL); - - if (opt == EOF) - break; + .signals = ripd_signals, .n_signals = array_size(ripd_signals), - switch (opt) - { - case 0: - break; - case 'r': - retain_mode = 1; - break; - default: - frr_help_exit (1); - break; + .privs = &ripd_privs, ) + +/* Main routine of ripd. */ +int main(int argc, char **argv) +{ + frr_preinit(&ripd_di, argc, argv); + frr_opt_add( + "r", longopts, + " -r, --retain When program terminates, retain added route by ripd.\n"); + + /* Command line option parse. */ + while (1) { + int opt; + + opt = frr_getopt(argc, argv, NULL); + + if (opt == EOF) + break; + + switch (opt) { + case 0: + break; + case 'r': + retain_mode = 1; + break; + default: + frr_help_exit(1); + break; + } } - } - /* Prepare master thread. */ - master = frr_init (); + /* Prepare master thread. */ + master = frr_init(); - /* Library initialization. */ - keychain_init (); - vrf_init (NULL, NULL, NULL, NULL); + /* Library initialization. */ + keychain_init(); + vrf_init(NULL, NULL, NULL, NULL); - /* RIP related initialization. */ - rip_init (); - rip_if_init (); - rip_zclient_init(master); - rip_peer_init (); + /* RIP related initialization. */ + rip_init(); + rip_if_init(); + rip_zclient_init(master); + rip_peer_init(); - frr_config_fork (); - frr_run (master); + frr_config_fork(); + frr_run(master); - /* Not reached. */ - return (0); + /* Not reached. */ + return (0); } diff --git a/ripd/rip_memory.c b/ripd/rip_memory.c index 662a6ccedd..4cdd3df048 100644 --- a/ripd/rip_memory.c +++ b/ripd/rip_memory.c @@ -26,9 +26,9 @@ #include "rip_memory.h" DEFINE_MGROUP(RIPD, "ripd") -DEFINE_MTYPE(RIPD, RIP, "RIP structure") -DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info") -DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface") -DEFINE_MTYPE(RIPD, RIP_PEER, "RIP peer") +DEFINE_MTYPE(RIPD, RIP, "RIP structure") +DEFINE_MTYPE(RIPD, RIP_INFO, "RIP route info") +DEFINE_MTYPE(RIPD, RIP_INTERFACE, "RIP interface") +DEFINE_MTYPE(RIPD, RIP_PEER, "RIP peer") DEFINE_MTYPE(RIPD, RIP_OFFSET_LIST, "RIP offset list") -DEFINE_MTYPE(RIPD, RIP_DISTANCE, "RIP distance") +DEFINE_MTYPE(RIPD, RIP_DISTANCE, "RIP distance") diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c index 63f93d1391..6b539046f5 100644 --- a/ripd/rip_offset.c +++ b/ripd/rip_offset.c @@ -33,165 +33,148 @@ #define RIP_OFFSET_LIST_OUT 1 #define RIP_OFFSET_LIST_MAX 2 -struct rip_offset_list -{ - char *ifname; - - struct - { - char *alist_name; - /* struct access_list *alist; */ - int metric; - } direct[RIP_OFFSET_LIST_MAX]; +struct rip_offset_list { + char *ifname; + + struct { + char *alist_name; + /* struct access_list *alist; */ + int metric; + } direct[RIP_OFFSET_LIST_MAX]; }; static struct list *rip_offset_list_master; -static int -strcmp_safe (const char *s1, const char *s2) +static int strcmp_safe(const char *s1, const char *s2) { - if (s1 == NULL && s2 == NULL) - return 0; - if (s1 == NULL) - return -1; - if (s2 == NULL) - return 1; - return strcmp (s1, s2); + if (s1 == NULL && s2 == NULL) + return 0; + if (s1 == NULL) + return -1; + if (s2 == NULL) + return 1; + return strcmp(s1, s2); } -static struct rip_offset_list * -rip_offset_list_new (void) +static struct rip_offset_list *rip_offset_list_new(void) { - return XCALLOC (MTYPE_RIP_OFFSET_LIST, sizeof (struct rip_offset_list)); + return XCALLOC(MTYPE_RIP_OFFSET_LIST, sizeof(struct rip_offset_list)); } -static void -rip_offset_list_free (struct rip_offset_list *offset) +static void rip_offset_list_free(struct rip_offset_list *offset) { - XFREE (MTYPE_RIP_OFFSET_LIST, offset); + XFREE(MTYPE_RIP_OFFSET_LIST, offset); } -static struct rip_offset_list * -rip_offset_list_lookup (const char *ifname) +static struct rip_offset_list *rip_offset_list_lookup(const char *ifname) { - struct rip_offset_list *offset; - struct listnode *node, *nnode; + struct rip_offset_list *offset; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (rip_offset_list_master, node, nnode, offset)) - { - if (strcmp_safe (offset->ifname, ifname) == 0) - return offset; - } - return NULL; + for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { + if (strcmp_safe(offset->ifname, ifname) == 0) + return offset; + } + return NULL; } -static struct rip_offset_list * -rip_offset_list_get (const char *ifname) +static struct rip_offset_list *rip_offset_list_get(const char *ifname) { - struct rip_offset_list *offset; - - offset = rip_offset_list_lookup (ifname); - if (offset) - return offset; - - offset = rip_offset_list_new (); - if (ifname) - offset->ifname = strdup (ifname); - listnode_add_sort (rip_offset_list_master, offset); - - return offset; + struct rip_offset_list *offset; + + offset = rip_offset_list_lookup(ifname); + if (offset) + return offset; + + offset = rip_offset_list_new(); + if (ifname) + offset->ifname = strdup(ifname); + listnode_add_sort(rip_offset_list_master, offset); + + return offset; } -static int -rip_offset_list_set (struct vty *vty, const char *alist, const char *direct_str, - const char *metric_str, const char *ifname) +static int rip_offset_list_set(struct vty *vty, const char *alist, + const char *direct_str, const char *metric_str, + const char *ifname) { - int direct; - int metric; - struct rip_offset_list *offset; - - /* Check direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = RIP_OFFSET_LIST_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RIP_OFFSET_LIST_OUT; - else - { - vty_out (vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi (metric_str); - if (metric < 0 || metric > 16) - { - vty_out (vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = rip_offset_list_get (ifname); - - if (offset->direct[direct].alist_name) - free (offset->direct[direct].alist_name); - offset->direct[direct].alist_name = strdup (alist); - offset->direct[direct].metric = metric; - - return CMD_SUCCESS; + int direct; + int metric; + struct rip_offset_list *offset; + + /* Check direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = RIP_OFFSET_LIST_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RIP_OFFSET_LIST_OUT; + else { + vty_out(vty, "Invalid direction: %s\n", direct_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check metric. */ + metric = atoi(metric_str); + if (metric < 0 || metric > 16) { + vty_out(vty, "Invalid metric: %s\n", metric_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get offset-list structure with interface name. */ + offset = rip_offset_list_get(ifname); + + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = strdup(alist); + offset->direct[direct].metric = metric; + + return CMD_SUCCESS; } -static int -rip_offset_list_unset (struct vty *vty, const char *alist, - const char *direct_str, const char *metric_str, - const char *ifname) +static int rip_offset_list_unset(struct vty *vty, const char *alist, + const char *direct_str, const char *metric_str, + const char *ifname) { - int direct; - int metric; - struct rip_offset_list *offset; - - /* Check direction. */ - if (strncmp (direct_str, "i", 1) == 0) - direct = RIP_OFFSET_LIST_IN; - else if (strncmp (direct_str, "o", 1) == 0) - direct = RIP_OFFSET_LIST_OUT; - else - { - vty_out (vty, "Invalid direction: %s\n", direct_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Check metric. */ - metric = atoi (metric_str); - if (metric < 0 || metric > 16) - { - vty_out (vty, "Invalid metric: %s\n", metric_str); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Get offset-list structure with interface name. */ - offset = rip_offset_list_lookup (ifname); - - if (offset) - { - if (offset->direct[direct].alist_name) - free (offset->direct[direct].alist_name); - offset->direct[direct].alist_name = NULL; - - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL && - offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) - { - listnode_delete (rip_offset_list_master, offset); - if (offset->ifname) - free (offset->ifname); - rip_offset_list_free (offset); + int direct; + int metric; + struct rip_offset_list *offset; + + /* Check direction. */ + if (strncmp(direct_str, "i", 1) == 0) + direct = RIP_OFFSET_LIST_IN; + else if (strncmp(direct_str, "o", 1) == 0) + direct = RIP_OFFSET_LIST_OUT; + else { + vty_out(vty, "Invalid direction: %s\n", direct_str); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Check metric. */ + metric = atoi(metric_str); + if (metric < 0 || metric > 16) { + vty_out(vty, "Invalid metric: %s\n", metric_str); + return CMD_WARNING_CONFIG_FAILED; } - } - else - { - vty_out (vty, "Can't find offset-list\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + + /* Get offset-list structure with interface name. */ + offset = rip_offset_list_lookup(ifname); + + if (offset) { + if (offset->direct[direct].alist_name) + free(offset->direct[direct].alist_name); + offset->direct[direct].alist_name = NULL; + + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name == NULL + && offset->direct[RIP_OFFSET_LIST_OUT].alist_name == NULL) { + listnode_delete(rip_offset_list_master, offset); + if (offset->ifname) + free(offset->ifname); + rip_offset_list_free(offset); + } + } else { + vty_out(vty, "Can't find offset-list\n"); + return CMD_WARNING_CONFIG_FAILED; + } + return CMD_SUCCESS; } #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIP_OFFSET_LIST_IN].alist_name) @@ -201,82 +184,78 @@ rip_offset_list_unset (struct vty *vty, const char *alist, #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIP_OFFSET_LIST_OUT].metric) /* If metric is modifed return 1. */ -int -rip_offset_list_apply_in (struct prefix_ipv4 *p, struct interface *ifp, - u_int32_t *metric) +int rip_offset_list_apply_in(struct prefix_ipv4 *p, struct interface *ifp, + u_int32_t *metric) { - struct rip_offset_list *offset; - struct access_list *alist; - - /* Look up offset-list with interface name. */ - offset = rip_offset_list_lookup (ifp->name); - if (offset && OFFSET_LIST_IN_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_IN_METRIC (offset); - return 1; + struct rip_offset_list *offset; + struct access_list *alist; + + /* Look up offset-list with interface name. */ + offset = rip_offset_list_lookup(ifp->name); + if (offset && OFFSET_LIST_IN_NAME(offset)) { + alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_IN_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup (NULL); - if (offset && OFFSET_LIST_IN_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_IN_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_IN_METRIC (offset); - return 1; + /* Look up offset-list without interface name. */ + offset = rip_offset_list_lookup(NULL); + if (offset && OFFSET_LIST_IN_NAME(offset)) { + alist = access_list_lookup(AFI_IP, OFFSET_LIST_IN_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_IN_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - return 0; + return 0; } /* If metric is modifed return 1. */ -int -rip_offset_list_apply_out (struct prefix_ipv4 *p, struct interface *ifp, - u_int32_t *metric) +int rip_offset_list_apply_out(struct prefix_ipv4 *p, struct interface *ifp, + u_int32_t *metric) { - struct rip_offset_list *offset; - struct access_list *alist; - - /* Look up offset-list with interface name. */ - offset = rip_offset_list_lookup (ifp->name); - if (offset && OFFSET_LIST_OUT_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_OUT_METRIC (offset); - return 1; + struct rip_offset_list *offset; + struct access_list *alist; + + /* Look up offset-list with interface name. */ + offset = rip_offset_list_lookup(ifp->name); + if (offset && OFFSET_LIST_OUT_NAME(offset)) { + alist = access_list_lookup(AFI_IP, + OFFSET_LIST_OUT_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_OUT_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - - /* Look up offset-list without interface name. */ - offset = rip_offset_list_lookup (NULL); - if (offset && OFFSET_LIST_OUT_NAME (offset)) - { - alist = access_list_lookup (AFI_IP, OFFSET_LIST_OUT_NAME (offset)); - - if (alist - && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT) - { - *metric += OFFSET_LIST_OUT_METRIC (offset); - return 1; + + /* Look up offset-list without interface name. */ + offset = rip_offset_list_lookup(NULL); + if (offset && OFFSET_LIST_OUT_NAME(offset)) { + alist = access_list_lookup(AFI_IP, + OFFSET_LIST_OUT_NAME(offset)); + + if (alist + && access_list_apply(alist, (struct prefix *)p) + == FILTER_PERMIT) { + *metric += OFFSET_LIST_OUT_METRIC(offset); + return 1; + } + return 0; } - return 0; - } - return 0; + return 0; } DEFUN (rip_offset_list, @@ -288,10 +267,12 @@ DEFUN (rip_offset_list, "For outgoing updates\n" "Metric value\n") { - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - return rip_offset_list_set (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, NULL); + int idx_word = 1; + int idx_in_out = 2; + int idx_number = 3; + return rip_offset_list_set(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, argv[idx_number]->arg, + NULL); } DEFUN (rip_offset_list_ifname, @@ -304,11 +285,13 @@ DEFUN (rip_offset_list_ifname, "Metric value\n" "Interface to match\n") { - int idx_word = 1; - int idx_in_out = 2; - int idx_number = 3; - int idx_ifname = 4; - return rip_offset_list_set (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, argv[idx_ifname]->arg); + int idx_word = 1; + int idx_in_out = 2; + int idx_number = 3; + int idx_ifname = 4; + return rip_offset_list_set(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, argv[idx_number]->arg, + argv[idx_ifname]->arg); } DEFUN (no_rip_offset_list, @@ -321,10 +304,12 @@ DEFUN (no_rip_offset_list, "For outgoing updates\n" "Metric value\n") { - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - return rip_offset_list_unset (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, NULL); + int idx_word = 2; + int idx_in_out = 3; + int idx_number = 4; + return rip_offset_list_unset(vty, argv[idx_word]->arg, + argv[idx_in_out]->arg, + argv[idx_number]->arg, NULL); } DEFUN (no_rip_offset_list_ifname, @@ -338,87 +323,89 @@ DEFUN (no_rip_offset_list_ifname, "Metric value\n" "Interface to match\n") { - int idx_word = 2; - int idx_in_out = 3; - int idx_number = 4; - int idx_ifname = 5; - return rip_offset_list_unset (vty, argv[idx_word]->arg, argv[idx_in_out]->arg, argv[idx_number]->arg, argv[idx_ifname]->arg); + int idx_word = 2; + int idx_in_out = 3; + int idx_number = 4; + int idx_ifname = 5; + return rip_offset_list_unset( + vty, argv[idx_word]->arg, argv[idx_in_out]->arg, + argv[idx_number]->arg, argv[idx_ifname]->arg); } -static int -offset_list_cmp (struct rip_offset_list *o1, struct rip_offset_list *o2) +static int offset_list_cmp(struct rip_offset_list *o1, + struct rip_offset_list *o2) { - return strcmp_safe (o1->ifname, o2->ifname); + return strcmp_safe(o1->ifname, o2->ifname); } -static void -offset_list_del (struct rip_offset_list *offset) +static void offset_list_del(struct rip_offset_list *offset) { - if (OFFSET_LIST_IN_NAME (offset)) - free (OFFSET_LIST_IN_NAME (offset)); - if (OFFSET_LIST_OUT_NAME (offset)) - free (OFFSET_LIST_OUT_NAME (offset)); - if (offset->ifname) - free (offset->ifname); - rip_offset_list_free (offset); + if (OFFSET_LIST_IN_NAME(offset)) + free(OFFSET_LIST_IN_NAME(offset)); + if (OFFSET_LIST_OUT_NAME(offset)) + free(OFFSET_LIST_OUT_NAME(offset)); + if (offset->ifname) + free(offset->ifname); + rip_offset_list_free(offset); } -void -rip_offset_init () +void rip_offset_init() { - rip_offset_list_master = list_new (); - rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp; - rip_offset_list_master->del = (void (*)(void *)) offset_list_del; - - install_element (RIP_NODE, &rip_offset_list_cmd); - install_element (RIP_NODE, &rip_offset_list_ifname_cmd); - install_element (RIP_NODE, &no_rip_offset_list_cmd); - install_element (RIP_NODE, &no_rip_offset_list_ifname_cmd); + rip_offset_list_master = list_new(); + rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; + rip_offset_list_master->del = (void (*)(void *))offset_list_del; + + install_element(RIP_NODE, &rip_offset_list_cmd); + install_element(RIP_NODE, &rip_offset_list_ifname_cmd); + install_element(RIP_NODE, &no_rip_offset_list_cmd); + install_element(RIP_NODE, &no_rip_offset_list_ifname_cmd); } -void -rip_offset_clean () +void rip_offset_clean() { - list_delete (rip_offset_list_master); + list_delete(rip_offset_list_master); - rip_offset_list_master = list_new (); - rip_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp; - rip_offset_list_master->del = (void (*)(void *)) offset_list_del; + rip_offset_list_master = list_new(); + rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; + rip_offset_list_master->del = (void (*)(void *))offset_list_del; } -int -config_write_rip_offset_list (struct vty *vty) +int config_write_rip_offset_list(struct vty *vty) { - struct listnode *node, *nnode; - struct rip_offset_list *offset; - - for (ALL_LIST_ELEMENTS (rip_offset_list_master, node, nnode, offset)) - { - if (! offset->ifname) - { - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) - vty_out (vty, " offset-list %s in %d\n", - offset->direct[RIP_OFFSET_LIST_IN].alist_name, - offset->direct[RIP_OFFSET_LIST_IN].metric); - if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) - vty_out (vty, " offset-list %s out %d\n", - offset->direct[RIP_OFFSET_LIST_OUT].alist_name, - offset->direct[RIP_OFFSET_LIST_OUT].metric); - } - else - { - if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) - vty_out (vty, " offset-list %s in %d %s\n", - offset->direct[RIP_OFFSET_LIST_IN].alist_name, - offset->direct[RIP_OFFSET_LIST_IN].metric, - offset->ifname); - if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) - vty_out (vty, " offset-list %s out %d %s\n", - offset->direct[RIP_OFFSET_LIST_OUT].alist_name, - offset->direct[RIP_OFFSET_LIST_OUT].metric, - offset->ifname); + struct listnode *node, *nnode; + struct rip_offset_list *offset; + + for (ALL_LIST_ELEMENTS(rip_offset_list_master, node, nnode, offset)) { + if (!offset->ifname) { + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) + vty_out(vty, " offset-list %s in %d\n", + offset->direct[RIP_OFFSET_LIST_IN] + .alist_name, + offset->direct[RIP_OFFSET_LIST_IN] + .metric); + if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) + vty_out(vty, " offset-list %s out %d\n", + offset->direct[RIP_OFFSET_LIST_OUT] + .alist_name, + offset->direct[RIP_OFFSET_LIST_OUT] + .metric); + } else { + if (offset->direct[RIP_OFFSET_LIST_IN].alist_name) + vty_out(vty, " offset-list %s in %d %s\n", + offset->direct[RIP_OFFSET_LIST_IN] + .alist_name, + offset->direct[RIP_OFFSET_LIST_IN] + .metric, + offset->ifname); + if (offset->direct[RIP_OFFSET_LIST_OUT].alist_name) + vty_out(vty, " offset-list %s out %d %s\n", + offset->direct[RIP_OFFSET_LIST_OUT] + .alist_name, + offset->direct[RIP_OFFSET_LIST_OUT] + .metric, + offset->ifname); + } } - } - return 0; + return 0; } diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index 7f494a0981..763bfc142c 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -32,175 +32,155 @@ /* Linked list of RIP peer. */ struct list *peer_list; -static struct rip_peer * -rip_peer_new (void) +static struct rip_peer *rip_peer_new(void) { - return XCALLOC (MTYPE_RIP_PEER, sizeof (struct rip_peer)); + return XCALLOC(MTYPE_RIP_PEER, sizeof(struct rip_peer)); } -static void -rip_peer_free (struct rip_peer *peer) +static void rip_peer_free(struct rip_peer *peer) { - XFREE (MTYPE_RIP_PEER, peer); + XFREE(MTYPE_RIP_PEER, peer); } -struct rip_peer * -rip_peer_lookup (struct in_addr *addr) +struct rip_peer *rip_peer_lookup(struct in_addr *addr) { - struct rip_peer *peer; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - if (IPV4_ADDR_SAME (&peer->addr, addr)) - return peer; - } - return NULL; + struct rip_peer *peer; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + if (IPV4_ADDR_SAME(&peer->addr, addr)) + return peer; + } + return NULL; } -struct rip_peer * -rip_peer_lookup_next (struct in_addr *addr) +struct rip_peer *rip_peer_lookup_next(struct in_addr *addr) { - struct rip_peer *peer; - struct listnode *node, *nnode; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - if (htonl (peer->addr.s_addr) > htonl (addr->s_addr)) - return peer; - } - return NULL; + struct rip_peer *peer; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + if (htonl(peer->addr.s_addr) > htonl(addr->s_addr)) + return peer; + } + return NULL; } /* RIP peer is timeout. */ -static int -rip_peer_timeout (struct thread *t) +static int rip_peer_timeout(struct thread *t) { - struct rip_peer *peer; + struct rip_peer *peer; - peer = THREAD_ARG (t); - listnode_delete (peer_list, peer); - rip_peer_free (peer); + peer = THREAD_ARG(t); + listnode_delete(peer_list, peer); + rip_peer_free(peer); - return 0; + return 0; } /* Get RIP peer. At the same time update timeout thread. */ -static struct rip_peer * -rip_peer_get (struct in_addr *addr) +static struct rip_peer *rip_peer_get(struct in_addr *addr) { - struct rip_peer *peer; - - peer = rip_peer_lookup (addr); - - if (peer) - { - if (peer->t_timeout) - thread_cancel (peer->t_timeout); - } - else - { - peer = rip_peer_new (); - peer->addr = *addr; - listnode_add_sort (peer_list, peer); - } - - /* Update timeout thread. */ - peer->t_timeout = NULL; - thread_add_timer(master, rip_peer_timeout, peer, RIP_PEER_TIMER_DEFAULT, - &peer->t_timeout); - - /* Last update time set. */ - time (&peer->uptime); - - return peer; + struct rip_peer *peer; + + peer = rip_peer_lookup(addr); + + if (peer) { + if (peer->t_timeout) + thread_cancel(peer->t_timeout); + } else { + peer = rip_peer_new(); + peer->addr = *addr; + listnode_add_sort(peer_list, peer); + } + + /* Update timeout thread. */ + peer->t_timeout = NULL; + thread_add_timer(master, rip_peer_timeout, peer, RIP_PEER_TIMER_DEFAULT, + &peer->t_timeout); + + /* Last update time set. */ + time(&peer->uptime); + + return peer; } -void -rip_peer_update (struct sockaddr_in *from, u_char version) +void rip_peer_update(struct sockaddr_in *from, u_char version) { - struct rip_peer *peer; - peer = rip_peer_get (&from->sin_addr); - peer->version = version; + struct rip_peer *peer; + peer = rip_peer_get(&from->sin_addr); + peer->version = version; } -void -rip_peer_bad_route (struct sockaddr_in *from) +void rip_peer_bad_route(struct sockaddr_in *from) { - struct rip_peer *peer; - peer = rip_peer_get (&from->sin_addr); - peer->recv_badroutes++; + struct rip_peer *peer; + peer = rip_peer_get(&from->sin_addr); + peer->recv_badroutes++; } -void -rip_peer_bad_packet (struct sockaddr_in *from) +void rip_peer_bad_packet(struct sockaddr_in *from) { - struct rip_peer *peer; - peer = rip_peer_get (&from->sin_addr); - peer->recv_badpackets++; + struct rip_peer *peer; + peer = rip_peer_get(&from->sin_addr); + peer->recv_badpackets++; } /* Display peer uptime. */ -static char * -rip_peer_uptime (struct rip_peer *peer, char *buf, size_t len) +static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len) { - time_t uptime; - struct tm *tm; - - /* If there is no connection has been done before print `never'. */ - if (peer->uptime == 0) - { - snprintf (buf, len, "never "); - return buf; - } - - /* Get current time. */ - uptime = time (NULL); - uptime -= peer->uptime; - tm = gmtime (&uptime); - - /* Making formatted timer strings. */ + time_t uptime; + struct tm *tm; + + /* If there is no connection has been done before print `never'. */ + if (peer->uptime == 0) { + snprintf(buf, len, "never "); + return buf; + } + + /* Get current time. */ + uptime = time(NULL); + uptime -= peer->uptime; + tm = gmtime(&uptime); + +/* Making formatted timer strings. */ #define ONE_DAY_SECOND 60*60*24 #define ONE_WEEK_SECOND 60*60*24*7 - if (uptime < ONE_DAY_SECOND) - snprintf (buf, len, "%02d:%02d:%02d", - tm->tm_hour, tm->tm_min, tm->tm_sec); - else if (uptime < ONE_WEEK_SECOND) - snprintf (buf, len, "%dd%02dh%02dm", - tm->tm_yday, tm->tm_hour, tm->tm_min); - else - snprintf (buf, len, "%02dw%dd%02dh", - tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour); - return buf; + if (uptime < ONE_DAY_SECOND) + snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + else if (uptime < ONE_WEEK_SECOND) + snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour, + tm->tm_min); + else + snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7, + tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour); + return buf; } -void -rip_peer_display (struct vty *vty) +void rip_peer_display(struct vty *vty) { - struct rip_peer *peer; - struct listnode *node, *nnode; + struct rip_peer *peer; + struct listnode *node, *nnode; #define RIP_UPTIME_LEN 25 - char timebuf[RIP_UPTIME_LEN]; - - for (ALL_LIST_ELEMENTS (peer_list, node, nnode, peer)) - { - vty_out (vty, " %-16s %9d %9d %9d %s\n", inet_ntoa (peer->addr), - peer->recv_badpackets, peer->recv_badroutes, - ZEBRA_RIP_DISTANCE_DEFAULT, - rip_peer_uptime(peer, timebuf, RIP_UPTIME_LEN)); - } + char timebuf[RIP_UPTIME_LEN]; + + for (ALL_LIST_ELEMENTS(peer_list, node, nnode, peer)) { + vty_out(vty, " %-16s %9d %9d %9d %s\n", + inet_ntoa(peer->addr), peer->recv_badpackets, + peer->recv_badroutes, ZEBRA_RIP_DISTANCE_DEFAULT, + rip_peer_uptime(peer, timebuf, RIP_UPTIME_LEN)); + } } -static int -rip_peer_list_cmp (struct rip_peer *p1, struct rip_peer *p2) +static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2) { - return htonl (p1->addr.s_addr) > htonl (p2->addr.s_addr); + return htonl(p1->addr.s_addr) > htonl(p2->addr.s_addr); } -void -rip_peer_init (void) +void rip_peer_init(void) { - peer_list = list_new (); - peer_list->cmp = (int (*)(void *, void *)) rip_peer_list_cmp; + peer_list = list_new(); + peer_list->cmp = (int (*)(void *, void *))rip_peer_list_cmp; } diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 3f1495c0f0..7255df5e67 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -28,620 +28,552 @@ #include "command.h" #include "filter.h" #include "log.h" -#include "sockunion.h" /* for inet_aton () */ +#include "sockunion.h" /* for inet_aton () */ #include "plist.h" #include "vrf.h" #include "ripd/ripd.h" -struct rip_metric_modifier -{ - enum - { - metric_increment, - metric_decrement, - metric_absolute - } type; - - u_char metric; +struct rip_metric_modifier { + enum { metric_increment, metric_decrement, metric_absolute } type; + + u_char metric; }; /* Hook function for updating route_map assignment. */ /* ARGSUSED */ -static void -rip_route_map_update (const char *notused) +static void rip_route_map_update(const char *notused) { - int i; - - if (rip) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (rip->route_map[i].name) - rip->route_map[i].map = - route_map_lookup_by_name (rip->route_map[i].name); + int i; + + if (rip) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rip->route_map[i].name) + rip->route_map[i].map = + route_map_lookup_by_name( + rip->route_map[i].name); + } } - } } /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - u_int32_t *metric; - u_int32_t check; - struct rip_info *rinfo; - - if (type == RMAP_RIP) - { - metric = rule; - rinfo = object; - - /* If external metric is available, the route-map should - work on this one (for redistribute purpose) */ - check = (rinfo->external_metric) ? rinfo->external_metric : - rinfo->metric; - if (check == *metric) - return RMAP_MATCH; - else +static route_map_result_t route_match_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) +{ + u_int32_t *metric; + u_int32_t check; + struct rip_info *rinfo; + + if (type == RMAP_RIP) { + metric = rule; + rinfo = object; + + /* If external metric is available, the route-map should + work on this one (for redistribute purpose) */ + check = (rinfo->external_metric) ? rinfo->external_metric + : rinfo->metric; + if (check == *metric) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map `match metric' match statement. `arg' is METRIC value */ -static void * -route_match_metric_compile (const char *arg) +static void *route_match_metric_compile(const char *arg) { - u_int32_t *metric; + u_int32_t *metric; - metric = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); - *metric = atoi (arg); + metric = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_int32_t)); + *metric = atoi(arg); - if(*metric > 0) - return metric; + if (*metric > 0) + return metric; - XFREE (MTYPE_ROUTE_MAP_COMPILED, metric); - return NULL; + XFREE(MTYPE_ROUTE_MAP_COMPILED, metric); + return NULL; } /* Free route map's compiled `match metric' value. */ -static void -route_match_metric_free (void *rule) +static void route_match_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for metric matching. */ -struct route_map_rule_cmd route_match_metric_cmd = -{ - "metric", - route_match_metric, - route_match_metric_compile, - route_match_metric_free -}; +struct route_map_rule_cmd route_match_metric_cmd = { + "metric", route_match_metric, route_match_metric_compile, + route_match_metric_free}; /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_interface (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_interface(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct rip_info *rinfo; - struct interface *ifp; - char *ifname; + struct rip_info *rinfo; + struct interface *ifp; + char *ifname; - if (type == RMAP_RIP) - { - ifname = rule; - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); + if (type == RMAP_RIP) { + ifname = rule; + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (!ifp) - return RMAP_NOMATCH; + if (!ifp) + return RMAP_NOMATCH; - rinfo = object; + rinfo = object; - if (rinfo->ifindex_out == ifp->ifindex || rinfo->ifindex == ifp->ifindex) - return RMAP_MATCH; - else + if (rinfo->ifindex_out == ifp->ifindex + || rinfo->ifindex == ifp->ifindex) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map `match interface' match statement. `arg' is IFNAME value */ /* XXX I don`t know if I need to check does interface exist? */ -static void * -route_match_interface_compile (const char *arg) +static void *route_match_interface_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `match interface' value. */ -static void -route_match_interface_free (void *rule) +static void route_match_interface_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for interface matching. */ -struct route_map_rule_cmd route_match_interface_cmd = -{ - "interface", - route_match_interface, - route_match_interface_compile, - route_match_interface_free -}; +struct route_map_rule_cmd route_match_interface_cmd = { + "interface", route_match_interface, route_match_interface_compile, + route_match_interface_free}; /* `match ip next-hop IP_ACCESS_LIST' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_next_hop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - struct access_list *alist; - struct rip_info *rinfo; - struct prefix_ipv4 p; - - if (type == RMAP_RIP) - { - rinfo = object; - p.family = AF_INET; - p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; - - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) +static route_map_result_t route_match_ip_next_hop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) +{ + struct access_list *alist; + struct rip_info *rinfo; + struct prefix_ipv4 p; + + if (type == RMAP_RIP) { + rinfo = object; + p.family = AF_INET; + p.prefix = + (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; + + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, &p) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip next-hop' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_next_hop_compile (const char *arg) +static void *route_match_ip_next_hop_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `. */ -static void -route_match_ip_next_hop_free (void *rule) +static void route_match_ip_next_hop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip next-hop matching. */ -static struct route_map_rule_cmd route_match_ip_next_hop_cmd = -{ - "ip next-hop", - route_match_ip_next_hop, - route_match_ip_next_hop_compile, - route_match_ip_next_hop_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_cmd = { + "ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile, + route_match_ip_next_hop_free}; /* `match ip next-hop prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_next_hop_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; - struct rip_info *rinfo; - struct prefix_ipv4 p; - - if (type == RMAP_RIP) - { - rinfo = object; - p.family = AF_INET; - p.prefix = (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; - - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) - return RMAP_NOMATCH; - - return (prefix_list_apply (plist, &p) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; + struct prefix_list *plist; + struct rip_info *rinfo; + struct prefix_ipv4 p; + + if (type == RMAP_RIP) { + rinfo = object; + p.family = AF_INET; + p.prefix = + (rinfo->nexthop.s_addr) ? rinfo->nexthop : rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; + + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, &p) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } + return RMAP_NOMATCH; } -static void * -route_match_ip_next_hop_prefix_list_compile (const char *arg) +static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_next_hop_prefix_list_free (void *rule) +static void route_match_ip_next_hop_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = -{ - "ip next-hop prefix-list", - route_match_ip_next_hop_prefix_list, - route_match_ip_next_hop_prefix_list_compile, - route_match_ip_next_hop_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = { + "ip next-hop prefix-list", route_match_ip_next_hop_prefix_list, + route_match_ip_next_hop_prefix_list_compile, + route_match_ip_next_hop_prefix_list_free}; /* `match ip address IP_ACCESS_LIST' */ /* Match function should return 1 if match is success else return zero. */ -static route_map_result_t -route_match_ip_address (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_match_ip_address(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct access_list *alist; + struct access_list *alist; - if (type == RMAP_RIP) - { - alist = access_list_lookup (AFI_IP, (char *) rule); - if (alist == NULL) + if (type == RMAP_RIP) { + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, prefix) == FILTER_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (access_list_apply (alist, prefix) == FILTER_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } /* Route map `ip address' match statement. `arg' should be access-list name. */ -static void * -route_match_ip_address_compile (const char *arg) +static void *route_match_ip_address_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } /* Free route map's compiled `ip address' value. */ -static void -route_match_ip_address_free (void *rule) +static void route_match_ip_address_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip address matching. */ -static struct route_map_rule_cmd route_match_ip_address_cmd = -{ - "ip address", - route_match_ip_address, - route_match_ip_address_compile, - route_match_ip_address_free -}; +static struct route_map_rule_cmd route_match_ip_address_cmd = { + "ip address", route_match_ip_address, route_match_ip_address_compile, + route_match_ip_address_free}; /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address_prefix_list(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - struct prefix_list *plist; + struct prefix_list *plist; - if (type == RMAP_RIP) - { - plist = prefix_list_lookup (AFI_IP, (char *) rule); - if (plist == NULL) + if (type == RMAP_RIP) { + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, prefix) == PREFIX_DENY + ? RMAP_NOMATCH + : RMAP_MATCH); + } return RMAP_NOMATCH; - - return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? - RMAP_NOMATCH : RMAP_MATCH); - } - return RMAP_NOMATCH; } -static void * -route_match_ip_address_prefix_list_compile (const char *arg) +static void *route_match_ip_address_prefix_list_compile(const char *arg) { - return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); + return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void -route_match_ip_address_prefix_list_free (void *rule) +static void route_match_ip_address_prefix_list_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } -static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = -{ - "ip address prefix-list", - route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free -}; +static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { + "ip address prefix-list", route_match_ip_address_prefix_list, + route_match_ip_address_prefix_list_compile, + route_match_ip_address_prefix_list_free}; /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ -static route_map_result_t -route_match_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - route_tag_t *tag; - struct rip_info *rinfo; - route_tag_t rinfo_tag; - - if (type == RMAP_RIP) - { - tag = rule; - rinfo = object; - - /* The information stored by rinfo is host ordered. */ - rinfo_tag = rinfo->tag; - if (rinfo_tag == *tag) - return RMAP_MATCH; - else +static route_map_result_t route_match_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + route_tag_t *tag; + struct rip_info *rinfo; + route_tag_t rinfo_tag; + + if (type == RMAP_RIP) { + tag = rule; + rinfo = object; + + /* The information stored by rinfo is host ordered. */ + rinfo_tag = rinfo->tag; + if (rinfo_tag == *tag) + return RMAP_MATCH; + else + return RMAP_NOMATCH; + } return RMAP_NOMATCH; - } - return RMAP_NOMATCH; } /* Route map commands for tag matching. */ -static struct route_map_rule_cmd route_match_tag_cmd = -{ - "tag", - route_match_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free, +static struct route_map_rule_cmd route_match_tag_cmd = { + "tag", route_match_tag, route_map_rule_tag_compile, + route_map_rule_tag_free, }; /* `set metric METRIC' */ /* Set metric to attribute. */ -static route_map_result_t -route_set_metric (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) -{ - if (type == RMAP_RIP) - { - struct rip_metric_modifier *mod; - struct rip_info *rinfo; - - mod = rule; - rinfo = object; - - if (mod->type == metric_increment) - rinfo->metric_out += mod->metric; - else if (mod->type == metric_decrement) - rinfo->metric_out -= mod->metric; - else if (mod->type == metric_absolute) - rinfo->metric_out = mod->metric; - - if ((signed int)rinfo->metric_out < 1) - rinfo->metric_out = 1; - if (rinfo->metric_out > RIP_METRIC_INFINITY) - rinfo->metric_out = RIP_METRIC_INFINITY; - - rinfo->metric_set = 1; - } - return RMAP_OKAY; +static route_map_result_t route_set_metric(void *rule, struct prefix *prefix, + route_map_object_t type, + void *object) +{ + if (type == RMAP_RIP) { + struct rip_metric_modifier *mod; + struct rip_info *rinfo; + + mod = rule; + rinfo = object; + + if (mod->type == metric_increment) + rinfo->metric_out += mod->metric; + else if (mod->type == metric_decrement) + rinfo->metric_out -= mod->metric; + else if (mod->type == metric_absolute) + rinfo->metric_out = mod->metric; + + if ((signed int)rinfo->metric_out < 1) + rinfo->metric_out = 1; + if (rinfo->metric_out > RIP_METRIC_INFINITY) + rinfo->metric_out = RIP_METRIC_INFINITY; + + rinfo->metric_set = 1; + } + return RMAP_OKAY; } /* set metric compilation. */ -static void * -route_set_metric_compile (const char *arg) -{ - int len; - const char *pnt; - int type; - long metric; - char *endptr = NULL; - struct rip_metric_modifier *mod; - - len = strlen (arg); - pnt = arg; - - if (len == 0) - return NULL; - - /* Examine first character. */ - if (arg[0] == '+') - { - type = metric_increment; - pnt++; - } - else if (arg[0] == '-') - { - type = metric_decrement; - pnt++; - } - else - type = metric_absolute; - - /* Check beginning with digit string. */ - if (*pnt < '0' || *pnt > '9') - return NULL; - - /* Convert string to integer. */ - metric = strtol (pnt, &endptr, 10); - - if (metric == LONG_MAX || *endptr != '\0') - return NULL; - if (metric < 0 || metric > RIP_METRIC_INFINITY) - return NULL; - - mod = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, - sizeof (struct rip_metric_modifier)); - mod->type = type; - mod->metric = metric; - - return mod; +static void *route_set_metric_compile(const char *arg) +{ + int len; + const char *pnt; + int type; + long metric; + char *endptr = NULL; + struct rip_metric_modifier *mod; + + len = strlen(arg); + pnt = arg; + + if (len == 0) + return NULL; + + /* Examine first character. */ + if (arg[0] == '+') { + type = metric_increment; + pnt++; + } else if (arg[0] == '-') { + type = metric_decrement; + pnt++; + } else + type = metric_absolute; + + /* Check beginning with digit string. */ + if (*pnt < '0' || *pnt > '9') + return NULL; + + /* Convert string to integer. */ + metric = strtol(pnt, &endptr, 10); + + if (metric == LONG_MAX || *endptr != '\0') + return NULL; + if (metric < 0 || metric > RIP_METRIC_INFINITY) + return NULL; + + mod = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, + sizeof(struct rip_metric_modifier)); + mod->type = type; + mod->metric = metric; + + return mod; } /* Free route map's compiled `set metric' value. */ -static void -route_set_metric_free (void *rule) +static void route_set_metric_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Set metric rule structure. */ -static struct route_map_rule_cmd route_set_metric_cmd = -{ - "metric", - route_set_metric, - route_set_metric_compile, - route_set_metric_free, +static struct route_map_rule_cmd route_set_metric_cmd = { + "metric", route_set_metric, route_set_metric_compile, + route_set_metric_free, }; /* `set ip next-hop IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_ip_nexthop (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_ip_nexthop(void *rule, + struct prefix *prefix, + route_map_object_t type, + void *object) { - struct in_addr *address; - struct rip_info *rinfo; - - if(type == RMAP_RIP) - { - /* Fetch routemap's rule information. */ - address = rule; - rinfo = object; - - /* Set next hop value. */ - rinfo->nexthop_out = *address; - } - - return RMAP_OKAY; + struct in_addr *address; + struct rip_info *rinfo; + + if (type == RMAP_RIP) { + /* Fetch routemap's rule information. */ + address = rule; + rinfo = object; + + /* Set next hop value. */ + rinfo->nexthop_out = *address; + } + + return RMAP_OKAY; } /* Route map `ip nexthop' compile function. Given string is converted to struct in_addr structure. */ -static void * -route_set_ip_nexthop_compile (const char *arg) +static void *route_set_ip_nexthop_compile(const char *arg) { - int ret; - struct in_addr *address; + int ret; + struct in_addr *address; - address = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (struct in_addr)); + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr)); - ret = inet_aton (arg, address); + ret = inet_aton(arg, address); - if (ret == 0) - { - XFREE (MTYPE_ROUTE_MAP_COMPILED, address); - return NULL; - } + if (ret == 0) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } - return address; + return address; } /* Free route map's compiled `ip nexthop' value. */ -static void -route_set_ip_nexthop_free (void *rule) +static void route_set_ip_nexthop_free(void *rule) { - XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } /* Route map commands for ip nexthop set. */ -static struct route_map_rule_cmd route_set_ip_nexthop_cmd = -{ - "ip next-hop", - route_set_ip_nexthop, - route_set_ip_nexthop_compile, - route_set_ip_nexthop_free -}; +static struct route_map_rule_cmd route_set_ip_nexthop_cmd = { + "ip next-hop", route_set_ip_nexthop, route_set_ip_nexthop_compile, + route_set_ip_nexthop_free}; /* `set tag TAG' */ /* Set tag to object. ojbect must be pointer to struct attr. */ -static route_map_result_t -route_set_tag (void *rule, struct prefix *prefix, - route_map_object_t type, void *object) +static route_map_result_t route_set_tag(void *rule, struct prefix *prefix, + route_map_object_t type, void *object) { - route_tag_t *tag; - struct rip_info *rinfo; - - if(type == RMAP_RIP) - { - /* Fetch routemap's rule information. */ - tag = rule; - rinfo = object; - - /* Set next hop value. */ - rinfo->tag_out = *tag; - } - - return RMAP_OKAY; + route_tag_t *tag; + struct rip_info *rinfo; + + if (type == RMAP_RIP) { + /* Fetch routemap's rule information. */ + tag = rule; + rinfo = object; + + /* Set next hop value. */ + rinfo->tag_out = *tag; + } + + return RMAP_OKAY; } /* Route map commands for tag set. */ -static struct route_map_rule_cmd route_set_tag_cmd = -{ - "tag", - route_set_tag, - route_map_rule_tag_compile, - route_map_rule_tag_free -}; +static struct route_map_rule_cmd route_set_tag_cmd = { + "tag", route_set_tag, route_map_rule_tag_compile, + route_map_rule_tag_free}; #define MATCH_STR "Match values from routing table\n" #define SET_STR "Set values in destination routing protocol\n" -void -rip_route_map_reset () +void rip_route_map_reset() { - ; + ; } /* Route-map init */ -void -rip_route_map_init () +void rip_route_map_init() { - route_map_init (); + route_map_init(); - route_map_add_hook (rip_route_map_update); - route_map_delete_hook (rip_route_map_update); + route_map_add_hook(rip_route_map_update); + route_map_delete_hook(rip_route_map_update); - route_map_match_interface_hook (generic_match_add); - route_map_no_match_interface_hook (generic_match_delete); + route_map_match_interface_hook(generic_match_add); + route_map_no_match_interface_hook(generic_match_delete); - route_map_match_ip_address_hook (generic_match_add); - route_map_no_match_ip_address_hook (generic_match_delete); + route_map_match_ip_address_hook(generic_match_add); + route_map_no_match_ip_address_hook(generic_match_delete); - route_map_match_ip_address_prefix_list_hook (generic_match_add); - route_map_no_match_ip_address_prefix_list_hook (generic_match_delete); + route_map_match_ip_address_prefix_list_hook(generic_match_add); + route_map_no_match_ip_address_prefix_list_hook(generic_match_delete); - route_map_match_ip_next_hop_hook (generic_match_add); - route_map_no_match_ip_next_hop_hook (generic_match_delete); + route_map_match_ip_next_hop_hook(generic_match_add); + route_map_no_match_ip_next_hop_hook(generic_match_delete); - route_map_match_ip_next_hop_prefix_list_hook (generic_match_add); - route_map_no_match_ip_next_hop_prefix_list_hook (generic_match_delete); + route_map_match_ip_next_hop_prefix_list_hook(generic_match_add); + route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete); - route_map_match_metric_hook (generic_match_add); - route_map_no_match_metric_hook (generic_match_delete); + route_map_match_metric_hook(generic_match_add); + route_map_no_match_metric_hook(generic_match_delete); - route_map_match_tag_hook (generic_match_add); - route_map_no_match_tag_hook (generic_match_delete); + route_map_match_tag_hook(generic_match_add); + route_map_no_match_tag_hook(generic_match_delete); - route_map_set_ip_nexthop_hook (generic_set_add); - route_map_no_set_ip_nexthop_hook (generic_set_delete); + route_map_set_ip_nexthop_hook(generic_set_add); + route_map_no_set_ip_nexthop_hook(generic_set_delete); - route_map_set_metric_hook (generic_set_add); - route_map_no_set_metric_hook (generic_set_delete); + route_map_set_metric_hook(generic_set_add); + route_map_no_set_metric_hook(generic_set_delete); - route_map_set_tag_hook (generic_set_add); - route_map_no_set_tag_hook (generic_set_delete); + route_map_set_tag_hook(generic_set_add); + route_map_no_set_tag_hook(generic_set_delete); - route_map_install_match (&route_match_metric_cmd); - route_map_install_match (&route_match_interface_cmd); - route_map_install_match (&route_match_ip_next_hop_cmd); - route_map_install_match (&route_match_ip_next_hop_prefix_list_cmd); - route_map_install_match (&route_match_ip_address_cmd); - route_map_install_match (&route_match_ip_address_prefix_list_cmd); - route_map_install_match (&route_match_tag_cmd); + route_map_install_match(&route_match_metric_cmd); + route_map_install_match(&route_match_interface_cmd); + route_map_install_match(&route_match_ip_next_hop_cmd); + route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); + route_map_install_match(&route_match_ip_address_cmd); + route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_tag_cmd); - route_map_install_set (&route_set_metric_cmd); - route_map_install_set (&route_set_ip_nexthop_cmd); - route_map_install_set (&route_set_tag_cmd); + route_map_install_set(&route_set_metric_cmd); + route_map_install_set(&route_set_ip_nexthop_cmd); + route_map_install_set(&route_set_tag_cmd); } diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index 6a4ae11ae1..45bb2e377a 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -82,319 +82,311 @@ SNMP_LOCAL_VARIABLES /* RIP-MIB instances. */ -static oid rip_oid [] = { RIPV2MIB }; +static oid rip_oid[] = {RIPV2MIB}; /* Interface cache table sorted by interface's address. */ static struct route_table *rip_ifaddr_table; /* Hook functions. */ -static u_char *rip2Globals (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); -static u_char *rip2PeerTable (struct variable *, oid [], size_t *, - int, size_t *, WriteMethod **); - -static struct variable rip_variables[] = -{ - /* RIP Global Counters. */ - {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals, - 2, {1, 1}}, - {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals, - 2, {1, 2}}, - /* RIP Interface Tables. */ - {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry, - 3, {2, 1, 1}}, - {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry, - 3, {2, 1, 2}}, - {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry, - 3, {2, 1, 3}}, - {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry, - 3, {2, 1, 4}}, - {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry, - 3, {2, 1, 5}}, - {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress, - /* RIP Interface Configuration Table. */ - 3, {3, 1, 1}}, - {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress, - 3, {3, 1, 2}}, - {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 3}}, - {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress, - 3, {3, 1, 4}}, - {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 5}}, - {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 6}}, - {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 7}}, - {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress, - 3, {3, 1, 8}}, - {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress, - 3, {3, 1, 9}}, - {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable, - /* RIP Peer Table. */ - 3, {4, 1, 1}}, - {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable, - 3, {4, 1, 2}}, - {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable, - 3, {4, 1, 3}}, - {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable, - 3, {4, 1, 4}}, - {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable, - 3, {4, 1, 5}}, - {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable, - 3, {4, 1, 6}} -}; +static u_char *rip2Globals(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); +static u_char *rip2IfStatEntry(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); +static u_char *rip2IfConfAddress(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); +static u_char *rip2PeerTable(struct variable *, oid[], size_t *, int, size_t *, + WriteMethod **); + +static struct variable rip_variables[] = { + /* RIP Global Counters. */ + {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals, 2, {1, 1}}, + {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals, 2, {1, 2}}, + /* RIP Interface Tables. */ + {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry, 3, {2, 1, 1}}, + {RIP2IFSTATRCVBADPACKETS, + COUNTER, + RONLY, + rip2IfStatEntry, + 3, + {2, 1, 2}}, + {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry, 3, {2, 1, 3}}, + {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry, 3, {2, 1, 4}}, + {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry, 3, {2, 1, 5}}, + {RIP2IFCONFADDRESS, + IPADDRESS, + RONLY, + rip2IfConfAddress, + /* RIP Interface Configuration Table. */ + 3, + {3, 1, 1}}, + {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress, 3, {3, 1, 2}}, + {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 3}}, + {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress, 3, {3, 1, 4}}, + {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 5}}, + {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 6}}, + {RIP2IFCONFDEFAULTMETRIC, + COUNTER, + RONLY, + rip2IfConfAddress, + 3, + {3, 1, 7}}, + {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 8}}, + {RIP2IFCONFSRCADDRESS, + IPADDRESS, + RONLY, + rip2IfConfAddress, + 3, + {3, 1, 9}}, + {RIP2PEERADDRESS, + IPADDRESS, + RONLY, + rip2PeerTable, + /* RIP Peer Table. */ + 3, + {4, 1, 1}}, + {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable, 3, {4, 1, 2}}, + {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable, 3, {4, 1, 3}}, + {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable, 3, {4, 1, 4}}, + {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable, 3, {4, 1, 5}}, + {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable, 3, {4, 1, 6}}}; extern struct thread_master *master; -static u_char * -rip2Globals (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *rip2Globals(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Retrun global counter. */ - switch (v->magic) - { - case RIP2GLOBALROUTECHANGES: - return SNMP_INTEGER (rip_global_route_changes); - break; - case RIP2GLOBALQUERIES: - return SNMP_INTEGER (rip_global_queries); - break; - default: - return NULL; - break; - } - return NULL; + if (smux_header_generic(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + /* Retrun global counter. */ + switch (v->magic) { + case RIP2GLOBALROUTECHANGES: + return SNMP_INTEGER(rip_global_route_changes); + break; + case RIP2GLOBALQUERIES: + return SNMP_INTEGER(rip_global_queries); + break; + default: + return NULL; + break; + } + return NULL; } -static int -rip_snmp_ifaddr_add (struct connected *ifc) +static int rip_snmp_ifaddr_add(struct connected *ifc) { - struct interface *ifp = ifc->ifp; - struct prefix *p; - struct route_node *rn; + struct interface *ifp = ifc->ifp; + struct prefix *p; + struct route_node *rn; - p = ifc->address; + p = ifc->address; - if (p->family != AF_INET) - return 0; + if (p->family != AF_INET) + return 0; - rn = route_node_get (rip_ifaddr_table, p); - rn->info = ifp; - return 0; + rn = route_node_get(rip_ifaddr_table, p); + rn->info = ifp; + return 0; } -static int -rip_snmp_ifaddr_del (struct connected *ifc) +static int rip_snmp_ifaddr_del(struct connected *ifc) { - struct interface *ifp = ifc->ifp; - struct prefix *p; - struct route_node *rn; - struct interface *i; - - p = ifc->address; - - if (p->family != AF_INET) - return 0; - - rn = route_node_lookup (rip_ifaddr_table, p); - if (! rn) - return 0; - i = rn->info; - if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ)) - { - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - } - return 0; + struct interface *ifp = ifc->ifp; + struct prefix *p; + struct route_node *rn; + struct interface *i; + + p = ifc->address; + + if (p->family != AF_INET) + return 0; + + rn = route_node_lookup(rip_ifaddr_table, p); + if (!rn) + return 0; + i = rn->info; + if (rn && !strncmp(i->name, ifp->name, INTERFACE_NAMSIZ)) { + rn->info = NULL; + route_unlock_node(rn); + route_unlock_node(rn); + } + return 0; } -static struct interface * -rip_ifaddr_lookup_next (struct in_addr *addr) +static struct interface *rip_ifaddr_lookup_next(struct in_addr *addr) { - struct prefix_ipv4 p; - struct route_node *rn; - struct interface *ifp; - - p.family = AF_INET; - p.prefixlen = IPV4_MAX_BITLEN; - p.prefix = *addr; - - rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p); - - for (rn = route_next (rn); rn; rn = route_next (rn)) - if (rn->info) - break; - - if (rn && rn->info) - { - ifp = rn->info; - *addr = rn->p.u.prefix4; - route_unlock_node (rn); - return ifp; - } - return NULL; + struct prefix_ipv4 p; + struct route_node *rn; + struct interface *ifp; + + p.family = AF_INET; + p.prefixlen = IPV4_MAX_BITLEN; + p.prefix = *addr; + + rn = route_node_get(rip_ifaddr_table, (struct prefix *)&p); + + for (rn = route_next(rn); rn; rn = route_next(rn)) + if (rn->info) + break; + + if (rn && rn->info) { + ifp = rn->info; + *addr = rn->p.u.prefix4; + route_unlock_node(rn); + return ifp; + } + return NULL; } -static struct interface * -rip2IfLookup (struct variable *v, oid name[], size_t *length, - struct in_addr *addr, int exact) +static struct interface *rip2IfLookup(struct variable *v, oid name[], + size_t *length, struct in_addr *addr, + int exact) { - int len; - struct interface *ifp; - - if (exact) - { - /* Check the length. */ - if (*length - v->namelen != sizeof (struct in_addr)) - return NULL; + int len; + struct interface *ifp; - oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr); + if (exact) { + /* Check the length. */ + if (*length - v->namelen != sizeof(struct in_addr)) + return NULL; - return if_lookup_exact_address ((void *)addr, AF_INET, VRF_DEFAULT); - } - else - { - len = *length - v->namelen; - if (len > 4) len = 4; + oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr); - oid2in_addr (name + v->namelen, len, addr); + return if_lookup_exact_address((void *)addr, AF_INET, + VRF_DEFAULT); + } else { + len = *length - v->namelen; + if (len > 4) + len = 4; - ifp = rip_ifaddr_lookup_next (addr); + oid2in_addr(name + v->namelen, len, addr); - if (ifp == NULL) - return NULL; + ifp = rip_ifaddr_lookup_next(addr); - oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr)); + if (ifp == NULL) + return NULL; - *length = v->namelen + sizeof (struct in_addr); + oid_copy_addr(name + v->namelen, addr, sizeof(struct in_addr)); - return ifp; - } - return NULL; -} + *length = v->namelen + sizeof(struct in_addr); -static struct rip_peer * -rip2PeerLookup (struct variable *v, oid name[], size_t *length, - struct in_addr *addr, int exact) -{ - int len; - struct rip_peer *peer; - - if (exact) - { - /* Check the length. */ - if (*length - v->namelen != sizeof (struct in_addr) + 1) + return ifp; + } return NULL; +} - oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr); - - peer = rip_peer_lookup (addr); - - if (peer->domain == (int)name[v->namelen + sizeof (struct in_addr)]) - return peer; - - return NULL; - } - else - { - len = *length - v->namelen; - if (len > 4) len = 4; - - oid2in_addr (name + v->namelen, len, addr); - - len = *length - v->namelen; - peer = rip_peer_lookup (addr); - if (peer) - { - if ((len < (int)sizeof (struct in_addr) + 1) || - (peer->domain > (int)name[v->namelen + sizeof (struct in_addr)])) - { - oid_copy_addr (name + v->namelen, &peer->addr, - sizeof (struct in_addr)); - name[v->namelen + sizeof (struct in_addr)] = peer->domain; - *length = sizeof (struct in_addr) + v->namelen + 1; - return peer; - } - } - peer = rip_peer_lookup_next (addr); - - if (! peer) +static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[], + size_t *length, struct in_addr *addr, + int exact) +{ + int len; + struct rip_peer *peer; + + if (exact) { + /* Check the length. */ + if (*length - v->namelen != sizeof(struct in_addr) + 1) + return NULL; + + oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr); + + peer = rip_peer_lookup(addr); + + if (peer->domain + == (int)name[v->namelen + sizeof(struct in_addr)]) + return peer; + + return NULL; + } else { + len = *length - v->namelen; + if (len > 4) + len = 4; + + oid2in_addr(name + v->namelen, len, addr); + + len = *length - v->namelen; + peer = rip_peer_lookup(addr); + if (peer) { + if ((len < (int)sizeof(struct in_addr) + 1) + || (peer->domain + > (int)name[v->namelen + + sizeof(struct in_addr)])) { + oid_copy_addr(name + v->namelen, &peer->addr, + sizeof(struct in_addr)); + name[v->namelen + sizeof(struct in_addr)] = + peer->domain; + *length = + sizeof(struct in_addr) + v->namelen + 1; + return peer; + } + } + peer = rip_peer_lookup_next(addr); + + if (!peer) + return NULL; + + oid_copy_addr(name + v->namelen, &peer->addr, + sizeof(struct in_addr)); + name[v->namelen + sizeof(struct in_addr)] = peer->domain; + *length = sizeof(struct in_addr) + v->namelen + 1; + + return peer; + } return NULL; - - oid_copy_addr (name + v->namelen, &peer->addr, - sizeof (struct in_addr)); - name[v->namelen + sizeof (struct in_addr)] = peer->domain; - *length = sizeof (struct in_addr) + v->namelen + 1; - - return peer; - } - return NULL; } -static u_char * -rip2IfStatEntry (struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, WriteMethod **write_method) +static u_char *rip2IfStatEntry(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) { - struct interface *ifp; - struct rip_interface *ri; - static struct in_addr addr; - static long valid = SNMP_VALID; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - /* Lookup interface. */ - ifp = rip2IfLookup (v, name, length, &addr, exact); - if (! ifp) - return NULL; - - /* Fetch rip_interface information. */ - ri = ifp->info; - - switch (v->magic) - { - case RIP2IFSTATADDRESS: - return SNMP_IPADDRESS (addr); - break; - case RIP2IFSTATRCVBADPACKETS: - *var_len = sizeof (long); - return (u_char *) &ri->recv_badpackets; - - case RIP2IFSTATRCVBADROUTES: - *var_len = sizeof (long); - return (u_char *) &ri->recv_badroutes; - - case RIP2IFSTATSENTUPDATES: - *var_len = sizeof (long); - return (u_char *) &ri->sent_updates; - - case RIP2IFSTATSTATUS: - *var_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &valid; - - default: - return NULL; - - } - return NULL; + struct interface *ifp; + struct rip_interface *ri; + static struct in_addr addr; + static long valid = SNMP_VALID; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + /* Lookup interface. */ + ifp = rip2IfLookup(v, name, length, &addr, exact); + if (!ifp) + return NULL; + + /* Fetch rip_interface information. */ + ri = ifp->info; + + switch (v->magic) { + case RIP2IFSTATADDRESS: + return SNMP_IPADDRESS(addr); + break; + case RIP2IFSTATRCVBADPACKETS: + *var_len = sizeof(long); + return (u_char *)&ri->recv_badpackets; + + case RIP2IFSTATRCVBADROUTES: + *var_len = sizeof(long); + return (u_char *)&ri->recv_badroutes; + + case RIP2IFSTATSENTUPDATES: + *var_len = sizeof(long); + return (u_char *)&ri->sent_updates; + + case RIP2IFSTATSTATUS: + *var_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&valid; + + default: + return NULL; + } + return NULL; } -static long -rip2IfConfSend (struct rip_interface *ri) +static long rip2IfConfSend(struct rip_interface *ri) { #define doNotSend 1 #define ripVersion1 2 @@ -403,156 +395,151 @@ rip2IfConfSend (struct rip_interface *ri) #define ripV1Demand 5 #define ripV2Demand 6 - if (! ri->running) - return doNotSend; - - if (ri->ri_send & RIPv2) - return ripVersion2; - else if (ri->ri_send & RIPv1) - return ripVersion1; - else if (rip) - { - if (rip->version_send == RIPv2) - return ripVersion2; - else if (rip->version_send == RIPv1) - return ripVersion1; - } - return doNotSend; + if (!ri->running) + return doNotSend; + + if (ri->ri_send & RIPv2) + return ripVersion2; + else if (ri->ri_send & RIPv1) + return ripVersion1; + else if (rip) { + if (rip->version_send == RIPv2) + return ripVersion2; + else if (rip->version_send == RIPv1) + return ripVersion1; + } + return doNotSend; } -static long -rip2IfConfReceive (struct rip_interface *ri) +static long rip2IfConfReceive(struct rip_interface *ri) { #define rip1 1 #define rip2 2 #define rip1OrRip2 3 #define doNotReceive 4 - int recvv; - - if (! ri->running) - return doNotReceive; - - recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv : - ri->ri_receive; - if (recvv == RI_RIP_VERSION_1_AND_2) - return rip1OrRip2; - else if (recvv & RIPv2) - return rip2; - else if (recvv & RIPv1) - return rip1; - else - return doNotReceive; + int recvv; + + if (!ri->running) + return doNotReceive; + + recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv + : ri->ri_receive; + if (recvv == RI_RIP_VERSION_1_AND_2) + return rip1OrRip2; + else if (recvv & RIPv2) + return rip2; + else if (recvv & RIPv1) + return rip1; + else + return doNotReceive; } -static u_char * -rip2IfConfAddress (struct variable *v, oid name[], size_t *length, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *rip2IfConfAddress(struct variable *v, oid name[], size_t *length, + int exact, size_t *val_len, + WriteMethod **write_method) { - static struct in_addr addr; - static long valid = SNMP_INVALID; - static long domain = 0; - static long config = 0; - static u_int auth = 0; - struct interface *ifp; - struct rip_interface *ri; - - if (smux_header_table(v, name, length, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - /* Lookup interface. */ - ifp = rip2IfLookup (v, name, length, &addr, exact); - if (! ifp) - return NULL; - - /* Fetch rip_interface information. */ - ri = ifp->info; - - switch (v->magic) - { - case RIP2IFCONFADDRESS: - *val_len = sizeof (struct in_addr); - return (u_char *) &addr; - - case RIP2IFCONFDOMAIN: - *val_len = 2; - return (u_char *) &domain; - - case RIP2IFCONFAUTHTYPE: - auth = ri->auth_type; - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *)&auth; - - case RIP2IFCONFAUTHKEY: - *val_len = 0; - return (u_char *) &domain; - case RIP2IFCONFSEND: - config = rip2IfConfSend (ri); - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &config; - case RIP2IFCONFRECEIVE: - config = rip2IfConfReceive (ri); - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &config; - - case RIP2IFCONFDEFAULTMETRIC: - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &ifp->metric; - case RIP2IFCONFSTATUS: - *val_len = sizeof (long); - v->type = ASN_INTEGER; - return (u_char *) &valid; - case RIP2IFCONFSRCADDRESS: - *val_len = sizeof (struct in_addr); - return (u_char *) &addr; - - default: - return NULL; - - } - return NULL; + static struct in_addr addr; + static long valid = SNMP_INVALID; + static long domain = 0; + static long config = 0; + static u_int auth = 0; + struct interface *ifp; + struct rip_interface *ri; + + if (smux_header_table(v, name, length, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + /* Lookup interface. */ + ifp = rip2IfLookup(v, name, length, &addr, exact); + if (!ifp) + return NULL; + + /* Fetch rip_interface information. */ + ri = ifp->info; + + switch (v->magic) { + case RIP2IFCONFADDRESS: + *val_len = sizeof(struct in_addr); + return (u_char *)&addr; + + case RIP2IFCONFDOMAIN: + *val_len = 2; + return (u_char *)&domain; + + case RIP2IFCONFAUTHTYPE: + auth = ri->auth_type; + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&auth; + + case RIP2IFCONFAUTHKEY: + *val_len = 0; + return (u_char *)&domain; + case RIP2IFCONFSEND: + config = rip2IfConfSend(ri); + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&config; + case RIP2IFCONFRECEIVE: + config = rip2IfConfReceive(ri); + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&config; + + case RIP2IFCONFDEFAULTMETRIC: + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&ifp->metric; + case RIP2IFCONFSTATUS: + *val_len = sizeof(long); + v->type = ASN_INTEGER; + return (u_char *)&valid; + case RIP2IFCONFSRCADDRESS: + *val_len = sizeof(struct in_addr); + return (u_char *)&addr; + + default: + return NULL; + } + return NULL; } -static u_char * -rip2PeerTable (struct variable *v, oid name[], size_t *length, - int exact, size_t *val_len, WriteMethod **write_method) +static u_char *rip2PeerTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *val_len, + WriteMethod **write_method) { - static struct in_addr addr; - static int domain = 0; - static int version; - /* static time_t uptime; */ - - struct rip_peer *peer; - - if (smux_header_table(v, name, length, exact, val_len, write_method) - == MATCH_FAILED) - return NULL; - - memset (&addr, 0, sizeof (struct in_addr)); - - /* Lookup interface. */ - peer = rip2PeerLookup (v, name, length, &addr, exact); - if (! peer) - return NULL; - - switch (v->magic) - { - case RIP2PEERADDRESS: - *val_len = sizeof (struct in_addr); - return (u_char *) &peer->addr; - - case RIP2PEERDOMAIN: - *val_len = 2; - return (u_char *) &domain; - - case RIP2PEERLASTUPDATE: + static struct in_addr addr; + static int domain = 0; + static int version; + /* static time_t uptime; */ + + struct rip_peer *peer; + + if (smux_header_table(v, name, length, exact, val_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(&addr, 0, sizeof(struct in_addr)); + + /* Lookup interface. */ + peer = rip2PeerLookup(v, name, length, &addr, exact); + if (!peer) + return NULL; + + switch (v->magic) { + case RIP2PEERADDRESS: + *val_len = sizeof(struct in_addr); + return (u_char *)&peer->addr; + + case RIP2PEERDOMAIN: + *val_len = 2; + return (u_char *)&domain; + + case RIP2PEERLASTUPDATE: #if 0 /* We don't know the SNMP agent startup time. We have two choices here: * - assume ripd startup time equals SNMP agent startup time @@ -563,53 +550,47 @@ rip2PeerTable (struct variable *v, oid name[], size_t *length, uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */ return (u_char *) &uptime; #else - return (u_char *) NULL; + return (u_char *)NULL; #endif - case RIP2PEERVERSION: - *val_len = sizeof (int); - version = peer->version; - return (u_char *) &version; + case RIP2PEERVERSION: + *val_len = sizeof(int); + version = peer->version; + return (u_char *)&version; - case RIP2PEERRCVBADPACKETS: - *val_len = sizeof (int); - return (u_char *) &peer->recv_badpackets; + case RIP2PEERRCVBADPACKETS: + *val_len = sizeof(int); + return (u_char *)&peer->recv_badpackets; - case RIP2PEERRCVBADROUTES: - *val_len = sizeof (int); - return (u_char *) &peer->recv_badroutes; + case RIP2PEERRCVBADROUTES: + *val_len = sizeof(int); + return (u_char *)&peer->recv_badroutes; - default: - return NULL; - - } - return NULL; + default: + return NULL; + } + return NULL; } /* Register RIPv2-MIB. */ -static int -rip_snmp_init (struct thread_master *master) +static int rip_snmp_init(struct thread_master *master) { - rip_ifaddr_table = route_table_init (); + rip_ifaddr_table = route_table_init(); - smux_init (master); - REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid); - return 0; + smux_init(master); + REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid); + return 0; } -static int -rip_snmp_module_init (void) +static int rip_snmp_module_init(void) { - hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); - hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); + hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add); + hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del); - hook_register(frr_late_init, rip_snmp_init); - return 0; + hook_register(frr_late_init, rip_snmp_init); + return 0; } -FRR_MODULE_SETUP( - .name = "ripd_snmp", - .version = FRR_VERSION, - .description = "ripd AgentX SNMP module", - .init = rip_snmp_module_init, -) +FRR_MODULE_SETUP(.name = "ripd_snmp", .version = FRR_VERSION, + .description = "ripd AgentX SNMP module", + .init = rip_snmp_module_init, ) diff --git a/ripd/rip_zebra.c b/ripd/rip_zebra.c index dffa9db7cf..961a846db2 100644 --- a/ripd/rip_zebra.c +++ b/ripd/rip_zebra.c @@ -37,274 +37,265 @@ struct zclient *zclient = NULL; /* Send ECMP routes to zebra. */ -static void -rip_zebra_ipv4_send (struct route_node *rp, u_char cmd) +static void rip_zebra_ipv4_send(struct route_node *rp, u_char cmd) { - static struct in_addr **nexthops = NULL; - static unsigned int nexthops_len = 0; - - struct list *list = (struct list *)rp->info; - struct zapi_ipv4 api; - struct listnode *listnode = NULL; - struct rip_info *rinfo = NULL; - int count = 0; - - if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT)) - { - api.vrf_id = VRF_DEFAULT; - api.type = ZEBRA_ROUTE_RIP; - api.instance = 0; - api.flags = 0; - api.message = 0; - api.safi = SAFI_UNICAST; - - if (nexthops_len < listcount (list)) - { - nexthops_len = listcount (list); - nexthops = XREALLOC (MTYPE_TMP, nexthops, - nexthops_len * sizeof (struct in_addr *)); - } - - SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - nexthops[count++] = &rinfo->nexthop; - if (cmd == ZEBRA_IPV4_ROUTE_ADD) - SET_FLAG (rinfo->flags, RIP_RTF_FIB); - else - UNSET_FLAG (rinfo->flags, RIP_RTF_FIB); - } - - api.nexthop = nexthops; - api.nexthop_num = count; - api.ifindex_num = 0; - - rinfo = listgetdata (listhead (list)); - - SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); - api.metric = rinfo->metric; - - if (rinfo->distance && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) - { - SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = rinfo->distance; - } - - if (rinfo->tag) - { - SET_FLAG (api.message, ZAPI_MESSAGE_TAG); - api.tag = rinfo->tag; - } - - zapi_ipv4_route (cmd, zclient, - (struct prefix_ipv4 *)&rp->p, &api); - - if (IS_RIP_DEBUG_ZEBRA) - { - if (rip->ecmp) - zlog_debug ("%s: %s/%d nexthops %d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) ? \ - "Install into zebra" : "Delete from zebra", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen, count); - else - zlog_debug ("%s: %s/%d", - (cmd == ZEBRA_IPV4_ROUTE_ADD) ? \ - "Install into zebra" : "Delete from zebra", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen); - } - - rip_global_route_changes++; - } + static struct in_addr **nexthops = NULL; + static unsigned int nexthops_len = 0; + + struct list *list = (struct list *)rp->info; + struct zapi_ipv4 api; + struct listnode *listnode = NULL; + struct rip_info *rinfo = NULL; + int count = 0; + + if (vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], + VRF_DEFAULT)) { + api.vrf_id = VRF_DEFAULT; + api.type = ZEBRA_ROUTE_RIP; + api.instance = 0; + api.flags = 0; + api.message = 0; + api.safi = SAFI_UNICAST; + + if (nexthops_len < listcount(list)) { + nexthops_len = listcount(list); + nexthops = XREALLOC(MTYPE_TMP, nexthops, + nexthops_len + * sizeof(struct in_addr *)); + } + + SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + nexthops[count++] = &rinfo->nexthop; + if (cmd == ZEBRA_IPV4_ROUTE_ADD) + SET_FLAG(rinfo->flags, RIP_RTF_FIB); + else + UNSET_FLAG(rinfo->flags, RIP_RTF_FIB); + } + + api.nexthop = nexthops; + api.nexthop_num = count; + api.ifindex_num = 0; + + rinfo = listgetdata(listhead(list)); + + SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); + api.metric = rinfo->metric; + + if (rinfo->distance + && rinfo->distance != ZEBRA_RIP_DISTANCE_DEFAULT) { + SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = rinfo->distance; + } + + if (rinfo->tag) { + SET_FLAG(api.message, ZAPI_MESSAGE_TAG); + api.tag = rinfo->tag; + } + + zapi_ipv4_route(cmd, zclient, (struct prefix_ipv4 *)&rp->p, + &api); + + if (IS_RIP_DEBUG_ZEBRA) { + if (rip->ecmp) + zlog_debug("%s: %s/%d nexthops %d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen, count); + else + zlog_debug("%s: %s/%d", + (cmd == ZEBRA_IPV4_ROUTE_ADD) + ? "Install into zebra" + : "Delete from zebra", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen); + } + + rip_global_route_changes++; + } } /* Add/update ECMP routes to zebra. */ -void -rip_zebra_ipv4_add (struct route_node *rp) +void rip_zebra_ipv4_add(struct route_node *rp) { - rip_zebra_ipv4_send (rp, ZEBRA_IPV4_ROUTE_ADD); + rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_ADD); } /* Delete ECMP routes from zebra. */ -void -rip_zebra_ipv4_delete (struct route_node *rp) +void rip_zebra_ipv4_delete(struct route_node *rp) { - rip_zebra_ipv4_send (rp, ZEBRA_IPV4_ROUTE_DELETE); + rip_zebra_ipv4_send(rp, ZEBRA_IPV4_ROUTE_DELETE); } /* Zebra route add and delete treatment. */ -static int -rip_zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length, - vrf_id_t vrf_id) +static int rip_zebra_read_ipv4(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - unsigned long ifindex; - struct in_addr nexthop; - struct prefix_ipv4 p; - - if (!rip) - return 0; - - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc (s); - api.instance = stream_getw (s); - api.flags = stream_getl (s); - api.message = stream_getc (s); - - /* IPv4 prefix. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc (s)); - stream_get (&p.prefix, s, PSIZE (p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) - { - api.nexthop_num = stream_getc (s); - nexthop.s_addr = stream_get_ipv4 (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) - { - api.ifindex_num = stream_getc (s); - ifindex = stream_getl (s); - } - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) - api.distance = stream_getc (s); - else - api.distance = 255; - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) - api.metric = stream_getl (s); - else - api.metric = 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - /* Then fetch IPv4 prefixes. */ - if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) - rip_redistribute_add (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex, - &nexthop, api.metric, api.distance, api.tag); - else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) - rip_redistribute_delete (api.type, RIP_ROUTE_REDISTRIBUTE, &p, ifindex); - - return 0; + struct stream *s; + struct zapi_ipv4 api; + unsigned long ifindex; + struct in_addr nexthop; + struct prefix_ipv4 p; + + if (!rip) + return 0; + + s = zclient->ibuf; + ifindex = 0; + nexthop.s_addr = 0; + + /* Type, flags, message. */ + api.type = stream_getc(s); + api.instance = stream_getw(s); + api.flags = stream_getl(s); + api.message = stream_getc(s); + + /* IPv4 prefix. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = MIN(IPV4_MAX_PREFIXLEN, stream_getc(s)); + stream_get(&p.prefix, s, PSIZE(p.prefixlen)); + + /* Nexthop, ifindex, distance, metric. */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { + api.nexthop_num = stream_getc(s); + nexthop.s_addr = stream_get_ipv4(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { + api.ifindex_num = stream_getc(s); + ifindex = stream_getl(s); + } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) + api.distance = stream_getc(s); + else + api.distance = 255; + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC)) + api.metric = stream_getl(s); + else + api.metric = 0; + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getl(s); + else + api.tag = 0; + + /* Then fetch IPv4 prefixes. */ + if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD) + rip_redistribute_add(api.type, RIP_ROUTE_REDISTRIBUTE, &p, + ifindex, &nexthop, api.metric, + api.distance, api.tag); + else if (command == ZEBRA_REDISTRIBUTE_IPV4_DEL) + rip_redistribute_delete(api.type, RIP_ROUTE_REDISTRIBUTE, &p, + ifindex); + + return 0; } -void -rip_zclient_reset (void) +void rip_zclient_reset(void) { - zclient_reset (zclient); + zclient_reset(zclient); } /* RIP route-map set for redistribution */ -static void -rip_routemap_set (int type, const char *name) +static void rip_routemap_set(int type, const char *name) { - if (rip->route_map[type].name) - free(rip->route_map[type].name); + if (rip->route_map[type].name) + free(rip->route_map[type].name); - rip->route_map[type].name = strdup (name); - rip->route_map[type].map = route_map_lookup_by_name (name); + rip->route_map[type].name = strdup(name); + rip->route_map[type].map = route_map_lookup_by_name(name); } -static void -rip_redistribute_metric_set (int type, unsigned int metric) +static void rip_redistribute_metric_set(int type, unsigned int metric) { - rip->route_map[type].metric_config = 1; - rip->route_map[type].metric = metric; + rip->route_map[type].metric_config = 1; + rip->route_map[type].metric = metric; } -static int -rip_metric_unset (int type, unsigned int metric) +static int rip_metric_unset(int type, unsigned int metric) { #define DONT_CARE_METRIC_RIP 17 - if (metric != DONT_CARE_METRIC_RIP && - rip->route_map[type].metric != metric) - return 1; - rip->route_map[type].metric_config = 0; - rip->route_map[type].metric = 0; - return 0; + if (metric != DONT_CARE_METRIC_RIP + && rip->route_map[type].metric != metric) + return 1; + rip->route_map[type].metric_config = 0; + rip->route_map[type].metric = 0; + return 0; } /* RIP route-map unset for redistribution */ -static int -rip_routemap_unset (int type, const char *name) +static int rip_routemap_unset(int type, const char *name) { - if (! rip->route_map[type].name || - (name != NULL && strcmp(rip->route_map[type].name,name))) - return 1; + if (!rip->route_map[type].name + || (name != NULL && strcmp(rip->route_map[type].name, name))) + return 1; - free (rip->route_map[type].name); - rip->route_map[type].name = NULL; - rip->route_map[type].map = NULL; + free(rip->route_map[type].name); + rip->route_map[type].name = NULL; + rip->route_map[type].map = NULL; - return 0; + return 0; } /* Redistribution types */ static struct { - int type; - int str_min_len; - const char *str; -} redist_type[] = { - {ZEBRA_ROUTE_KERNEL, 1, "kernel"}, - {ZEBRA_ROUTE_CONNECT, 1, "connected"}, - {ZEBRA_ROUTE_STATIC, 1, "static"}, - {ZEBRA_ROUTE_OSPF, 1, "ospf"}, - {ZEBRA_ROUTE_BGP, 2, "bgp"}, - {ZEBRA_ROUTE_VNC, 1, "vnc"}, - {0, 0, NULL} -}; - -static int -rip_redistribute_unset (int type) + int type; + int str_min_len; + const char *str; +} redist_type[] = {{ZEBRA_ROUTE_KERNEL, 1, "kernel"}, + {ZEBRA_ROUTE_CONNECT, 1, "connected"}, + {ZEBRA_ROUTE_STATIC, 1, "static"}, + {ZEBRA_ROUTE_OSPF, 1, "ospf"}, + {ZEBRA_ROUTE_BGP, 2, "bgp"}, + {ZEBRA_ROUTE_VNC, 1, "vnc"}, + {0, 0, NULL}}; + +static int rip_redistribute_unset(int type) { - if (! vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT)) - return CMD_SUCCESS; + if (!vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT)) + return CMD_SUCCESS; - vrf_bitmap_unset (zclient->redist[AFI_IP][type], VRF_DEFAULT); + vrf_bitmap_unset(zclient->redist[AFI_IP][type], VRF_DEFAULT); - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, 0, VRF_DEFAULT); + if (zclient->sock > 0) + zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP, type, 0, VRF_DEFAULT); - /* Remove the routes from RIP table. */ - rip_redistribute_withdraw (type); + /* Remove the routes from RIP table. */ + rip_redistribute_withdraw(type); - return CMD_SUCCESS; + return CMD_SUCCESS; } -int -rip_redistribute_check (int type) +int rip_redistribute_check(int type) { - return vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT); + return vrf_bitmap_check(zclient->redist[AFI_IP][type], VRF_DEFAULT); } -void -rip_redistribute_clean (void) +void rip_redistribute_clean(void) { - int i; - - for (i = 0; redist_type[i].str; i++) - { - if (vrf_bitmap_check (zclient->redist[AFI_IP][redist_type[i].type], VRF_DEFAULT)) - { - if (zclient->sock > 0) - zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, - zclient, AFI_IP, redist_type[i].type, 0, - VRF_DEFAULT); - - vrf_bitmap_unset (zclient->redist[AFI_IP][redist_type[i].type], VRF_DEFAULT); - - /* Remove the routes from RIP table. */ - rip_redistribute_withdraw (redist_type[i].type); + int i; + + for (i = 0; redist_type[i].str; i++) { + if (vrf_bitmap_check( + zclient->redist[AFI_IP][redist_type[i].type], + VRF_DEFAULT)) { + if (zclient->sock > 0) + zebra_redistribute_send( + ZEBRA_REDISTRIBUTE_DELETE, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + + vrf_bitmap_unset( + zclient->redist[AFI_IP][redist_type[i].type], + VRF_DEFAULT); + + /* Remove the routes from RIP table. */ + rip_redistribute_withdraw(redist_type[i].type); + } } - } } DEFUN (rip_redistribute_rip, @@ -313,8 +304,8 @@ DEFUN (rip_redistribute_rip, "Redistribute information from another routing protocol\n" "Routing Information Protocol (RIP)\n") { - vrf_bitmap_set (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; + vrf_bitmap_set(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (no_rip_redistribute_rip, @@ -324,8 +315,8 @@ DEFUN (no_rip_redistribute_rip, "Redistribute information from another routing protocol\n" "Routing Information Protocol (RIP)\n") { - vrf_bitmap_unset (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); - return CMD_SUCCESS; + vrf_bitmap_unset(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT); + return CMD_SUCCESS; } DEFUN (rip_redistribute_type, @@ -334,22 +325,22 @@ DEFUN (rip_redistribute_type, REDIST_STR FRR_REDIST_HELP_STR_RIPD) { - int i; - - for(i = 0; redist_type[i].str; i++) - { - if (strncmp (redist_type[i].str, argv[1]->arg, - redist_type[i].str_min_len) == 0) - { - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, - AFI_IP, redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strncmp(redist_type[i].str, argv[1]->arg, + redist_type[i].str_min_len) + == 0) { + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } } - } - vty_out (vty, "Invalid type %s\n",argv[1]->arg); + vty_out(vty, "Invalid type %s\n", argv[1]->arg); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_rip_redistribute_type, @@ -359,23 +350,23 @@ DEFUN (no_rip_redistribute_type, REDIST_STR FRR_REDIST_HELP_STR_RIPD) { - int i; - - for (i = 0; redist_type[i].str; i++) - { - if (strncmp(redist_type[i].str, argv[2]->arg, - redist_type[i].str_min_len) == 0) - { - rip_metric_unset (redist_type[i].type, DONT_CARE_METRIC_RIP); - rip_routemap_unset (redist_type[i].type,NULL); - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n",argv[2]->arg); - - return CMD_WARNING_CONFIG_FAILED; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strncmp(redist_type[i].str, argv[2]->arg, + redist_type[i].str_min_len) + == 0) { + rip_metric_unset(redist_type[i].type, + DONT_CARE_METRIC_RIP); + rip_routemap_unset(redist_type[i].type, NULL); + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[2]->arg); + + return CMD_WARNING_CONFIG_FAILED; } DEFUN (rip_redistribute_type_routemap, @@ -386,23 +377,24 @@ DEFUN (rip_redistribute_type_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 1; - int idx_word = 3; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - rip_routemap_set (redist_type[i].type, argv[idx_word]->arg); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, - redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; - } - } + int idx_protocol = 1; + int idx_word = 3; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + rip_routemap_set(redist_type[i].type, + argv[idx_word]->arg); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } + } - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_rip_redistribute_type_routemap, @@ -414,23 +406,23 @@ DEFUN (no_rip_redistribute_type_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 2; - int idx_word = 4; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - if (rip_routemap_unset (redist_type[i].type,argv[idx_word]->arg)) - return CMD_WARNING_CONFIG_FAILED; - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - - return CMD_WARNING_CONFIG_FAILED; + int idx_protocol = 2; + int idx_word = 4; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + if (rip_routemap_unset(redist_type[i].type, + argv[idx_word]->arg)) + return CMD_WARNING_CONFIG_FAILED; + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + + return CMD_WARNING_CONFIG_FAILED; } DEFUN (rip_redistribute_type_metric, @@ -441,26 +433,27 @@ DEFUN (rip_redistribute_type_metric, "Metric\n" "Metric value\n") { - int idx_protocol = 1; - int idx_number = 3; - int i; - int metric; - - metric = atoi (argv[idx_number]->arg); - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - rip_redistribute_metric_set (redist_type[i].type, metric); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, - redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; - } - } + int idx_protocol = 1; + int idx_number = 3; + int i; + int metric; + + metric = atoi(argv[idx_number]->arg); + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + rip_redistribute_metric_set(redist_type[i].type, + metric); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } + } - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } DEFUN (no_rip_redistribute_type_metric, @@ -472,23 +465,23 @@ DEFUN (no_rip_redistribute_type_metric, "Metric\n" "Metric value\n") { - int idx_protocol = 2; - int idx_number = 4; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - if (rip_metric_unset (redist_type[i].type, atoi(argv[idx_number]->arg))) - return CMD_WARNING_CONFIG_FAILED; - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - - return CMD_WARNING_CONFIG_FAILED; + int idx_protocol = 2; + int idx_number = 4; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + if (rip_metric_unset(redist_type[i].type, + atoi(argv[idx_number]->arg))) + return CMD_WARNING_CONFIG_FAILED; + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + + return CMD_WARNING_CONFIG_FAILED; } DEFUN (rip_redistribute_type_metric_routemap, @@ -501,28 +494,30 @@ DEFUN (rip_redistribute_type_metric_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 1; - int idx_number = 3; - int idx_word = 5; - int i; - int metric; - - metric = atoi (argv[idx_number]->arg); - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - rip_redistribute_metric_set (redist_type[i].type, metric); - rip_routemap_set (redist_type[i].type, argv[idx_word]->arg); - zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, - redist_type[i].type, 0, VRF_DEFAULT); - return CMD_SUCCESS; - } - } + int idx_protocol = 1; + int idx_number = 3; + int idx_word = 5; + int i; + int metric; + + metric = atoi(argv[idx_number]->arg); + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + rip_redistribute_metric_set(redist_type[i].type, + metric); + rip_routemap_set(redist_type[i].type, + argv[idx_word]->arg); + zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, + AFI_IP, redist_type[i].type, 0, + VRF_DEFAULT); + return CMD_SUCCESS; + } + } - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); - return CMD_WARNING_CONFIG_FAILED; + return CMD_WARNING_CONFIG_FAILED; } @@ -537,29 +532,31 @@ DEFUN (no_rip_redistribute_type_metric_routemap, "Route map reference\n" "Pointer to route-map entries\n") { - int idx_protocol = 2; - int idx_number = 4; - int idx_word = 6; - int i; - - for (i = 0; redist_type[i].str; i++) { - if (strmatch (redist_type[i].str, argv[idx_protocol]->text)) - { - if (rip_metric_unset (redist_type[i].type, atoi(argv[idx_number]->arg))) - return CMD_WARNING_CONFIG_FAILED; - if (rip_routemap_unset (redist_type[i].type, argv[idx_word]->arg)) - { - rip_redistribute_metric_set(redist_type[i].type, atoi(argv[idx_number]->arg)); - return CMD_WARNING_CONFIG_FAILED; - } - rip_redistribute_unset (redist_type[i].type); - return CMD_SUCCESS; - } - } - - vty_out (vty, "Invalid type %s\n", argv[idx_protocol]->text); - - return CMD_WARNING_CONFIG_FAILED; + int idx_protocol = 2; + int idx_number = 4; + int idx_word = 6; + int i; + + for (i = 0; redist_type[i].str; i++) { + if (strmatch(redist_type[i].str, argv[idx_protocol]->text)) { + if (rip_metric_unset(redist_type[i].type, + atoi(argv[idx_number]->arg))) + return CMD_WARNING_CONFIG_FAILED; + if (rip_routemap_unset(redist_type[i].type, + argv[idx_word]->arg)) { + rip_redistribute_metric_set( + redist_type[i].type, + atoi(argv[idx_number]->arg)); + return CMD_WARNING_CONFIG_FAILED; + } + rip_redistribute_unset(redist_type[i].type); + return CMD_SUCCESS; + } + } + + vty_out(vty, "Invalid type %s\n", argv[idx_protocol]->text); + + return CMD_WARNING_CONFIG_FAILED; } /* Default information originate. */ @@ -570,20 +567,19 @@ DEFUN (rip_default_information_originate, "Control distribution of default route\n" "Distribute a default route\n") { - struct prefix_ipv4 p; + struct prefix_ipv4 p; + + if (!rip->default_information) { + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; - if (! rip->default_information) - { - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; + rip->default_information = 1; - rip->default_information = 1; - - rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, - NULL, 0, 0, 0); - } + rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0, + NULL, 0, 0, 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rip_default_information_originate, @@ -593,128 +589,125 @@ DEFUN (no_rip_default_information_originate, "Control distribution of default route\n" "Distribute a default route\n") { - struct prefix_ipv4 p; + struct prefix_ipv4 p; + + if (rip->default_information) { + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; - if (rip->default_information) - { - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; + rip->default_information = 0; - rip->default_information = 0; - - rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, 0); - } + rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_DEFAULT, &p, + 0); + } - return CMD_SUCCESS; + return CMD_SUCCESS; } /* RIP configuration write function. */ -static int -config_write_zebra (struct vty *vty) +static int config_write_zebra(struct vty *vty) { - if (! zclient->enable) - { - vty_out (vty, "no router zebra\n"); - return 1; - } - else if (! vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], VRF_DEFAULT)) - { - vty_out (vty, "router zebra\n"); - vty_out (vty, " no redistribute rip\n"); - return 1; - } - return 0; + if (!zclient->enable) { + vty_out(vty, "no router zebra\n"); + return 1; + } else if (!vrf_bitmap_check(zclient->redist[AFI_IP][ZEBRA_ROUTE_RIP], + VRF_DEFAULT)) { + vty_out(vty, "router zebra\n"); + vty_out(vty, " no redistribute rip\n"); + return 1; + } + return 0; } -int -config_write_rip_redistribute (struct vty *vty, int config_mode) +int config_write_rip_redistribute(struct vty *vty, int config_mode) { - int i; - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != zclient->redist_default && - vrf_bitmap_check (zclient->redist[AFI_IP][i], VRF_DEFAULT)) - { - if (config_mode) - { - if (rip->route_map[i].metric_config) - { - if (rip->route_map[i].name) - vty_out (vty, " redistribute %s metric %d route-map %s\n", - zebra_route_string(i), rip->route_map[i].metric, - rip->route_map[i].name); - else - vty_out (vty, " redistribute %s metric %d\n", - zebra_route_string(i),rip->route_map[i].metric); - } - else - { - if (rip->route_map[i].name) - vty_out (vty, " redistribute %s route-map %s\n", - zebra_route_string(i),rip->route_map[i].name); - else - vty_out (vty, " redistribute %s\n",zebra_route_string(i)); - } - } - else - vty_out (vty, " %s", zebra_route_string(i)); - } - return 0; + int i; + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (i != zclient->redist_default + && vrf_bitmap_check(zclient->redist[AFI_IP][i], + VRF_DEFAULT)) { + if (config_mode) { + if (rip->route_map[i].metric_config) { + if (rip->route_map[i].name) + vty_out(vty, + " redistribute %s metric %d route-map %s\n", + zebra_route_string(i), + rip->route_map[i] + .metric, + rip->route_map[i].name); + else + vty_out(vty, + " redistribute %s metric %d\n", + zebra_route_string(i), + rip->route_map[i] + .metric); + } else { + if (rip->route_map[i].name) + vty_out(vty, + " redistribute %s route-map %s\n", + zebra_route_string(i), + rip->route_map[i].name); + else + vty_out(vty, + " redistribute %s\n", + zebra_route_string(i)); + } + } else + vty_out(vty, " %s", zebra_route_string(i)); + } + return 0; } /* Zebra node structure. */ -static struct cmd_node zebra_node = -{ - ZEBRA_NODE, - "%s(config-router)# ", +static struct cmd_node zebra_node = { + ZEBRA_NODE, "%s(config-router)# ", }; -static void -rip_zebra_connected (struct zclient *zclient) +static void rip_zebra_connected(struct zclient *zclient) { - zclient_send_reg_requests (zclient, VRF_DEFAULT); + zclient_send_reg_requests(zclient, VRF_DEFAULT); } -void -rip_zclient_init (struct thread_master *master) +void rip_zclient_init(struct thread_master *master) { - /* Set default value to the zebra client structure. */ - zclient = zclient_new(master); - zclient_init (zclient, ZEBRA_ROUTE_RIP, 0); - zclient->zebra_connected = rip_zebra_connected; - zclient->interface_add = rip_interface_add; - zclient->interface_delete = rip_interface_delete; - zclient->interface_address_add = rip_interface_address_add; - zclient->interface_address_delete = rip_interface_address_delete; - zclient->interface_up = rip_interface_up; - zclient->interface_down = rip_interface_down; - zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; - zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; - - /* Install zebra node. */ - install_node (&zebra_node, config_write_zebra); - - /* Install command elements to zebra node. */ - install_default (ZEBRA_NODE); - install_element (ZEBRA_NODE, &rip_redistribute_rip_cmd); - install_element (ZEBRA_NODE, &no_rip_redistribute_rip_cmd); - - /* Install command elements to rip node. */ - install_element (RIP_NODE, &rip_redistribute_type_cmd); - install_element (RIP_NODE, &rip_redistribute_type_routemap_cmd); - install_element (RIP_NODE, &rip_redistribute_type_metric_cmd); - install_element (RIP_NODE, &rip_redistribute_type_metric_routemap_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_routemap_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_metric_cmd); - install_element (RIP_NODE, &no_rip_redistribute_type_metric_routemap_cmd); - install_element (RIP_NODE, &rip_default_information_originate_cmd); - install_element (RIP_NODE, &no_rip_default_information_originate_cmd); + /* Set default value to the zebra client structure. */ + zclient = zclient_new(master); + zclient_init(zclient, ZEBRA_ROUTE_RIP, 0); + zclient->zebra_connected = rip_zebra_connected; + zclient->interface_add = rip_interface_add; + zclient->interface_delete = rip_interface_delete; + zclient->interface_address_add = rip_interface_address_add; + zclient->interface_address_delete = rip_interface_address_delete; + zclient->interface_up = rip_interface_up; + zclient->interface_down = rip_interface_down; + zclient->redistribute_route_ipv4_add = rip_zebra_read_ipv4; + zclient->redistribute_route_ipv4_del = rip_zebra_read_ipv4; + + /* Install zebra node. */ + install_node(&zebra_node, config_write_zebra); + + /* Install command elements to zebra node. */ + install_default(ZEBRA_NODE); + install_element(ZEBRA_NODE, &rip_redistribute_rip_cmd); + install_element(ZEBRA_NODE, &no_rip_redistribute_rip_cmd); + + /* Install command elements to rip node. */ + install_element(RIP_NODE, &rip_redistribute_type_cmd); + install_element(RIP_NODE, &rip_redistribute_type_routemap_cmd); + install_element(RIP_NODE, &rip_redistribute_type_metric_cmd); + install_element(RIP_NODE, &rip_redistribute_type_metric_routemap_cmd); + install_element(RIP_NODE, &no_rip_redistribute_type_cmd); + install_element(RIP_NODE, &no_rip_redistribute_type_routemap_cmd); + install_element(RIP_NODE, &no_rip_redistribute_type_metric_cmd); + install_element(RIP_NODE, + &no_rip_redistribute_type_metric_routemap_cmd); + install_element(RIP_NODE, &rip_default_information_originate_cmd); + install_element(RIP_NODE, &no_rip_default_information_originate_cmd); } -void -rip_zclient_stop (void) +void rip_zclient_stop(void) { - zclient_stop (zclient); - zclient_free (zclient); + zclient_stop(zclient); + zclient_free(zclient); } diff --git a/ripd/ripd.c b/ripd/ripd.c index 8578dc3d21..d9b38bba89 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -65,187 +65,171 @@ long rip_global_route_changes = 0; long rip_global_queries = 0; /* Prototypes. */ -static void rip_event (enum rip_event, int); -static void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char); -static int rip_triggered_update (struct thread *); -static int rip_update_jitter (unsigned long); +static void rip_event(enum rip_event, int); +static void rip_output_process(struct connected *, struct sockaddr_in *, int, + u_char); +static int rip_triggered_update(struct thread *); +static int rip_update_jitter(unsigned long); /* RIP output routes type. */ -enum -{ - rip_all_route, - rip_changed_route -}; +enum { rip_all_route, rip_changed_route }; /* RIP command strings. */ -static const struct message rip_msg[] = -{ - {RIP_REQUEST, "REQUEST"}, - {RIP_RESPONSE, "RESPONSE"}, - {RIP_TRACEON, "TRACEON"}, - {RIP_TRACEOFF, "TRACEOFF"}, - {RIP_POLL, "POLL"}, - {RIP_POLL_ENTRY, "POLL ENTRY"}, - { 0 } -}; +static const struct message rip_msg[] = {{RIP_REQUEST, "REQUEST"}, + {RIP_RESPONSE, "RESPONSE"}, + {RIP_TRACEON, "TRACEON"}, + {RIP_TRACEOFF, "TRACEOFF"}, + {RIP_POLL, "POLL"}, + {RIP_POLL_ENTRY, "POLL ENTRY"}, + {0}}; /* Utility function to set boradcast option to the socket. */ -static int -sockopt_broadcast (int sock) +static int sockopt_broadcast(int sock) { - int ret; - int on = 1; + int ret; + int on = 1; - ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on); - if (ret < 0) - { - zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock); - return -1; - } - return 0; + ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, + sizeof on); + if (ret < 0) { + zlog_warn("can't set sockopt SO_BROADCAST to socket %d", sock); + return -1; + } + return 0; } -static int -rip_route_rte (struct rip_info *rinfo) +static int rip_route_rte(struct rip_info *rinfo) { - return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE); + return (rinfo->type == ZEBRA_ROUTE_RIP + && rinfo->sub_type == RIP_ROUTE_RTE); } -static struct rip_info * -rip_info_new (void) +static struct rip_info *rip_info_new(void) { - return XCALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info)); + return XCALLOC(MTYPE_RIP_INFO, sizeof(struct rip_info)); } -void -rip_info_free (struct rip_info *rinfo) +void rip_info_free(struct rip_info *rinfo) { - XFREE (MTYPE_RIP_INFO, rinfo); + XFREE(MTYPE_RIP_INFO, rinfo); } /* RIP route garbage collect timer. */ -static int -rip_garbage_collect (struct thread *t) +static int rip_garbage_collect(struct thread *t) { - struct rip_info *rinfo; - struct route_node *rp; + struct rip_info *rinfo; + struct route_node *rp; + + rinfo = THREAD_ARG(t); + rinfo->t_garbage_collect = NULL; - rinfo = THREAD_ARG (t); - rinfo->t_garbage_collect = NULL; + /* Off timeout timer. */ + RIP_TIMER_OFF(rinfo->t_timeout); - /* Off timeout timer. */ - RIP_TIMER_OFF (rinfo->t_timeout); - - /* Get route_node pointer. */ - rp = rinfo->rp; + /* Get route_node pointer. */ + rp = rinfo->rp; - /* Unlock route_node. */ - listnode_delete (rp->info, rinfo); - if (list_isempty ((struct list *)rp->info)) - { - list_free (rp->info); - rp->info = NULL; - route_unlock_node (rp); - } + /* Unlock route_node. */ + listnode_delete(rp->info, rinfo); + if (list_isempty((struct list *)rp->info)) { + list_free(rp->info); + rp->info = NULL; + route_unlock_node(rp); + } - /* Free RIP routing information. */ - rip_info_free (rinfo); + /* Free RIP routing information. */ + rip_info_free(rinfo); - return 0; + return 0; } -static void rip_timeout_update (struct rip_info *rinfo); +static void rip_timeout_update(struct rip_info *rinfo); /* Add new route to the ECMP list. * RETURN: the new entry added in the list, or NULL if it is not the first * entry and ECMP is not allowed. */ -struct rip_info * -rip_ecmp_add (struct rip_info *rinfo_new) +struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new) { - struct route_node *rp = rinfo_new->rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; + struct route_node *rp = rinfo_new->rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; - if (rp->info == NULL) - rp->info = list_new (); - list = (struct list *)rp->info; + if (rp->info == NULL) + rp->info = list_new(); + list = (struct list *)rp->info; - /* If ECMP is not allowed and some entry already exists in the list, - * do nothing. */ - if (listcount (list) && !rip->ecmp) - return NULL; + /* If ECMP is not allowed and some entry already exists in the list, + * do nothing. */ + if (listcount(list) && !rip->ecmp) + return NULL; - rinfo = rip_info_new (); - memcpy (rinfo, rinfo_new, sizeof (struct rip_info)); - listnode_add (list, rinfo); + rinfo = rip_info_new(); + memcpy(rinfo, rinfo_new, sizeof(struct rip_info)); + listnode_add(list, rinfo); - if (rip_route_rte (rinfo)) - { - rip_timeout_update (rinfo); - rip_zebra_ipv4_add (rp); - } + if (rip_route_rte(rinfo)) { + rip_timeout_update(rinfo); + rip_zebra_ipv4_add(rp); + } - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - /* Signal the output process to trigger an update (see section 2.5). */ - rip_event (RIP_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update (see section 2.5). */ + rip_event(RIP_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Replace the ECMP list with the new route. * RETURN: the new entry added in the list */ -struct rip_info * -rip_ecmp_replace (struct rip_info *rinfo_new) -{ - struct route_node *rp = rinfo_new->rp; - struct list *list = (struct list *)rp->info; - struct rip_info *rinfo = NULL, *tmp_rinfo = NULL; - struct listnode *node = NULL, *nextnode = NULL; - - if (list == NULL || listcount (list) == 0) - return rip_ecmp_add (rinfo_new); - - /* Get the first entry */ - rinfo = listgetdata (listhead (list)); - - /* Learnt route replaced by a local one. Delete it from zebra. */ - if (rip_route_rte (rinfo) && !rip_route_rte (rinfo_new)) - if (CHECK_FLAG (rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete (rp); - - /* Re-use the first entry, and delete the others. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIP_TIMER_OFF (tmp_rinfo->t_timeout); - RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - rip_info_free (tmp_rinfo); - } +struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new) +{ + struct route_node *rp = rinfo_new->rp; + struct list *list = (struct list *)rp->info; + struct rip_info *rinfo = NULL, *tmp_rinfo = NULL; + struct listnode *node = NULL, *nextnode = NULL; + + if (list == NULL || listcount(list) == 0) + return rip_ecmp_add(rinfo_new); + + /* Get the first entry */ + rinfo = listgetdata(listhead(list)); + + /* Learnt route replaced by a local one. Delete it from zebra. */ + if (rip_route_rte(rinfo) && !rip_route_rte(rinfo_new)) + if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) + rip_zebra_ipv4_delete(rp); + + /* Re-use the first entry, and delete the others. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIP_TIMER_OFF(tmp_rinfo->t_timeout); + RIP_TIMER_OFF(tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + rip_info_free(tmp_rinfo); + } - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_OFF (rinfo->t_garbage_collect); - memcpy (rinfo, rinfo_new, sizeof (struct rip_info)); + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + memcpy(rinfo, rinfo_new, sizeof(struct rip_info)); - if (rip_route_rte (rinfo)) - { - rip_timeout_update (rinfo); - /* The ADD message implies an update. */ - rip_zebra_ipv4_add (rp); - } + if (rip_route_rte(rinfo)) { + rip_timeout_update(rinfo); + /* The ADD message implies an update. */ + rip_zebra_ipv4_add(rp); + } - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - /* Signal the output process to trigger an update (see section 2.5). */ - rip_event (RIP_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update (see section 2.5). */ + rip_event(RIP_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Delete one route from the ECMP list. @@ -254,692 +238,694 @@ rip_ecmp_replace (struct rip_info *rinfo_new) * the entry - the entry is the last one in the list; its metric is set * to INFINITY, and the garbage collector is started for it */ -struct rip_info * -rip_ecmp_delete (struct rip_info *rinfo) -{ - struct route_node *rp = rinfo->rp; - struct list *list = (struct list *)rp->info; - - RIP_TIMER_OFF (rinfo->t_timeout); - - if (listcount (list) > 1) - { - /* Some other ECMP entries still exist. Just delete this entry. */ - RIP_TIMER_OFF (rinfo->t_garbage_collect); - listnode_delete (list, rinfo); - if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB)) - /* The ADD message implies the update. */ - rip_zebra_ipv4_add (rp); - rip_info_free (rinfo); - rinfo = NULL; - } - else - { - assert (rinfo == listgetdata (listhead (list))); - - /* This is the only entry left in the list. We must keep it in - * the list for garbage collection time, with INFINITY metric. */ - - rinfo->metric = RIP_METRIC_INFINITY; - RIP_TIMER_ON (rinfo->t_garbage_collect, - rip_garbage_collect, rip->garbage_time); - - if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB)) - rip_zebra_ipv4_delete (rp); - } +struct rip_info *rip_ecmp_delete(struct rip_info *rinfo) +{ + struct route_node *rp = rinfo->rp; + struct list *list = (struct list *)rp->info; + + RIP_TIMER_OFF(rinfo->t_timeout); + + if (listcount(list) > 1) { + /* Some other ECMP entries still exist. Just delete this entry. + */ + RIP_TIMER_OFF(rinfo->t_garbage_collect); + listnode_delete(list, rinfo); + if (rip_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) + /* The ADD message implies the update. */ + rip_zebra_ipv4_add(rp); + rip_info_free(rinfo); + rinfo = NULL; + } else { + assert(rinfo == listgetdata(listhead(list))); + + /* This is the only entry left in the list. We must keep it in + * the list for garbage collection time, with INFINITY metric. + */ + + rinfo->metric = RIP_METRIC_INFINITY; + RIP_TIMER_ON(rinfo->t_garbage_collect, rip_garbage_collect, + rip->garbage_time); + + if (rip_route_rte(rinfo) + && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB)) + rip_zebra_ipv4_delete(rp); + } - /* Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); + /* Set the route change flag on the first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); - /* Signal the output process to trigger an update (see section 2.5). */ - rip_event (RIP_TRIGGERED_UPDATE, 0); + /* Signal the output process to trigger an update (see section 2.5). */ + rip_event(RIP_TRIGGERED_UPDATE, 0); - return rinfo; + return rinfo; } /* Timeout RIP routes. */ -static int -rip_timeout (struct thread *t) +static int rip_timeout(struct thread *t) { - rip_ecmp_delete ((struct rip_info *)THREAD_ARG (t)); - return 0; + rip_ecmp_delete((struct rip_info *)THREAD_ARG(t)); + return 0; } -static void -rip_timeout_update (struct rip_info *rinfo) -{ - if (rinfo->metric != RIP_METRIC_INFINITY) - { - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time); - } -} - -static int -rip_filter (int rip_distribute, struct prefix_ipv4 *p, struct rip_interface *ri) -{ - struct distribute *dist; - struct access_list *alist; - struct prefix_list *plist; - int distribute = rip_distribute == RIP_FILTER_OUT ? - DISTRIBUTE_V4_OUT : DISTRIBUTE_V4_IN; - const char *inout = rip_distribute == RIP_FILTER_OUT ? "out" : "in"; - - /* Input distribute-list filtering. */ - if (ri->list[rip_distribute]) - { - if (access_list_apply (ri->list[rip_distribute], - (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; - } - } - if (ri->prefix[rip_distribute]) +static void rip_timeout_update(struct rip_info *rinfo) { - if (prefix_list_apply (ri->prefix[rip_distribute], - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; - } - } - - /* All interface filter check. */ - dist = distribute_lookup (NULL); - if (dist) - { - if (dist->list[distribute]) - { - alist = access_list_lookup (AFI_IP, dist->list[distribute]); - - if (alist) - { - if (access_list_apply (alist, (struct prefix *) p) == FILTER_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by distribute %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; + if (rinfo->metric != RIP_METRIC_INFINITY) { + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_ON(rinfo->t_timeout, rip_timeout, rip->timeout_time); + } +} + +static int rip_filter(int rip_distribute, struct prefix_ipv4 *p, + struct rip_interface *ri) +{ + struct distribute *dist; + struct access_list *alist; + struct prefix_list *plist; + int distribute = rip_distribute == RIP_FILTER_OUT ? DISTRIBUTE_V4_OUT + : DISTRIBUTE_V4_IN; + const char *inout = rip_distribute == RIP_FILTER_OUT ? "out" : "in"; + + /* Input distribute-list filtering. */ + if (ri->list[rip_distribute]) { + if (access_list_apply(ri->list[rip_distribute], + (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("%s/%d filtered by distribute %s", + inet_ntoa(p->prefix), p->prefixlen, + inout); + return -1; } - } } - if (dist->prefix[distribute]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[distribute]); - - if (plist) - { - if (prefix_list_apply (plist, - (struct prefix *) p) == PREFIX_DENY) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d filtered by prefix-list %s", - inet_ntoa (p->prefix), p->prefixlen, inout); - return -1; + if (ri->prefix[rip_distribute]) { + if (prefix_list_apply(ri->prefix[rip_distribute], + (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("%s/%d filtered by prefix-list %s", + inet_ntoa(p->prefix), p->prefixlen, + inout); + return -1; } - } } - } - return 0; + + /* All interface filter check. */ + dist = distribute_lookup(NULL); + if (dist) { + if (dist->list[distribute]) { + alist = access_list_lookup(AFI_IP, + dist->list[distribute]); + + if (alist) { + if (access_list_apply(alist, (struct prefix *)p) + == FILTER_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by distribute %s", + inet_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } + } + if (dist->prefix[distribute]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[distribute]); + + if (plist) { + if (prefix_list_apply(plist, (struct prefix *)p) + == PREFIX_DENY) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "%s/%d filtered by prefix-list %s", + inet_ntoa(p->prefix), + p->prefixlen, inout); + return -1; + } + } + } + } + return 0; } /* Check nexthop address validity. */ -static int -rip_nexthop_check (struct in_addr *addr) +static int rip_nexthop_check(struct in_addr *addr) { - struct listnode *node; - struct listnode *cnode; - struct interface *ifp; - struct connected *ifc; - struct prefix *p; + struct listnode *node; + struct listnode *cnode; + struct interface *ifp; + struct connected *ifc; + struct prefix *p; - /* If nexthop address matches local configured address then it is - invalid nexthop. */ + /* If nexthop address matches local configured address then it is + invalid nexthop. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc)) - { - p = ifc->address; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { + p = ifc->address; - if (p->family == AF_INET - && IPV4_ADDR_SAME (&p->u.prefix4, addr)) - return -1; + if (p->family == AF_INET + && IPV4_ADDR_SAME(&p->u.prefix4, addr)) + return -1; + } } - } - return 0; + return 0; } /* RIP add route to routing table. */ -static void -rip_rte_process (struct rte *rte, struct sockaddr_in *from, - struct interface *ifp) -{ - int ret; - struct prefix_ipv4 p; - struct route_node *rp; - struct rip_info *rinfo = NULL, newinfo; - struct rip_interface *ri; - struct in_addr *nexthop; - int same = 0; - unsigned char old_dist, new_dist; - struct list *list = NULL; - struct listnode *node = NULL; - - /* Make prefix structure. */ - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = rte->prefix; - p.prefixlen = ip_masklen (rte->mask); - - /* Make sure mask is applied. */ - apply_mask_ipv4 (&p); - - /* Apply input filters. */ - ri = ifp->info; - - ret = rip_filter (RIP_FILTER_IN, &p, ri); - if (ret < 0) - return; - - memset (&newinfo, 0, sizeof (newinfo)); - newinfo.type = ZEBRA_ROUTE_RIP; - newinfo.sub_type = RIP_ROUTE_RTE; - newinfo.nexthop = rte->nexthop; - newinfo.from = from->sin_addr; - newinfo.ifindex = ifp->ifindex; - newinfo.metric = rte->metric; - newinfo.metric_out = rte->metric; /* XXX */ - newinfo.tag = ntohs (rte->tag); /* XXX */ - - /* Modify entry according to the interface routemap. */ - if (ri->routemap[RIP_FILTER_IN]) - { - int ret; - - /* The object should be of the type of rip_info */ - ret = route_map_apply (ri->routemap[RIP_FILTER_IN], - (struct prefix *) &p, RMAP_RIP, &newinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIP %s/%d is filtered by route-map in", - inet_ntoa (p.prefix), p.prefixlen); - return; - } - - /* Get back the object */ - rte->nexthop = newinfo.nexthop_out; - rte->tag = htons (newinfo.tag_out); /* XXX */ - rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */ - } - - /* Once the entry has been validated, update the metric by - adding the cost of the network on wich the message - arrived. If the result is greater than infinity, use infinity - (RFC2453 Sec. 3.9.2) */ - /* Zebra ripd can handle offset-list in. */ - ret = rip_offset_list_apply_in (&p, ifp, &rte->metric); - - /* If offset-list does not modify the metric use interface's - metric. */ - if (!ret) - rte->metric += ifp->metric ? ifp->metric : 1; - - if (rte->metric > RIP_METRIC_INFINITY) - rte->metric = RIP_METRIC_INFINITY; - - /* Set nexthop pointer. */ - if (rte->nexthop.s_addr == 0) - nexthop = &from->sin_addr; - else - nexthop = &rte->nexthop; - - /* Check if nexthop address is myself, then do nothing. */ - if (rip_nexthop_check (nexthop) < 0) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop)); - return; - } - - /* Get index for the prefix. */ - rp = route_node_get (rip->table, (struct prefix *) &p); - - newinfo.rp = rp; - newinfo.nexthop = *nexthop; - newinfo.metric = rte->metric; - newinfo.tag = ntohs (rte->tag); - newinfo.distance = rip_distance_apply (&newinfo); - - new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIP_DISTANCE_DEFAULT; - - /* Check to see whether there is already RIP route on the table. */ - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, node, rinfo)) - { - /* Need to compare with redistributed entry or local entry */ - if (!rip_route_rte (rinfo)) - break; - - if (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) && - IPV4_ADDR_SAME (&rinfo->nexthop, nexthop)) - break; - - if (!listnextnode (node)) - { - /* Not found in the list */ - - if (rte->metric > rinfo->metric) - { - /* New route has a greater metric. Discard it. */ - route_unlock_node (rp); - return; - } - - if (rte->metric < rinfo->metric) - /* New route has a smaller metric. Replace the ECMP list - * with the new one in below. */ - break; - - /* Metrics are same. We compare the distances. */ - old_dist = rinfo->distance ? \ - rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT; - - if (new_dist > old_dist) - { - /* New route has a greater distance. Discard it. */ - route_unlock_node (rp); - return; - } - - if (new_dist < old_dist) - /* New route has a smaller distance. Replace the ECMP list - * with the new one in below. */ - break; - - /* Metrics and distances are both same. Keep "rinfo" null and - * the new route is added in the ECMP list in below. */ - } - } - - if (rinfo) - { - /* Local static route. */ - if (rinfo->type == ZEBRA_ROUTE_RIP - && ((rinfo->sub_type == RIP_ROUTE_STATIC) || - (rinfo->sub_type == RIP_ROUTE_DEFAULT)) - && rinfo->metric != RIP_METRIC_INFINITY) - { - route_unlock_node (rp); - return; - } - - /* Redistributed route check. */ - if (rinfo->type != ZEBRA_ROUTE_RIP - && rinfo->metric != RIP_METRIC_INFINITY) - { - old_dist = rinfo->distance; - /* Only routes directly connected to an interface (nexthop == 0) - * may have a valid NULL distance */ - if (rinfo->nexthop.s_addr != 0) - old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT; - /* If imported route does not have STRICT precedence, - mark it as a ghost */ - if (new_dist <= old_dist && rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_replace (&newinfo); - - route_unlock_node (rp); - return; - } - } - - if (!rinfo) - { - if (rp->info) - route_unlock_node (rp); - - /* Now, check to see whether there is already an explicit route - for the destination prefix. If there is no such route, add - this route to the routing table, unless the metric is - infinity (there is no point in adding a route which - unusable). */ - if (rte->metric != RIP_METRIC_INFINITY) - rip_ecmp_add (&newinfo); - } - else - { - /* Route is there but we are not sure the route is RIP or not. */ - - /* If there is an existing route, compare the next hop address - to the address of the router from which the datagram came. - If this datagram is from the same router as the existing - route, reinitialize the timeout. */ - same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) - && (rinfo->ifindex == ifp->ifindex)); - - old_dist = rinfo->distance ? \ - rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT; - - /* Next, compare the metrics. If the datagram is from the same - router as the existing route, and the new metric is different - than the old one; or, if the new metric is lower than the old - one, or if the tag has been changed; or if there is a route - with a lower administrave distance; or an update of the - distance on the actual route; do the following actions: */ - if ((same && rinfo->metric != rte->metric) - || (rte->metric < rinfo->metric) - || ((same) - && (rinfo->metric == rte->metric) - && (newinfo.tag != rinfo->tag)) - || (old_dist > new_dist) - || ((old_dist != new_dist) && same)) - { - if (listcount (list) == 1) - { - if (newinfo.metric != RIP_METRIC_INFINITY) - rip_ecmp_replace (&newinfo); - else - rip_ecmp_delete (rinfo); - } - else - { - if (newinfo.metric < rinfo->metric) - rip_ecmp_replace (&newinfo); - else if (newinfo.metric > rinfo->metric) - rip_ecmp_delete (rinfo); - else if (new_dist < old_dist) - rip_ecmp_replace (&newinfo); - else if (new_dist > old_dist) - rip_ecmp_delete (rinfo); - else - { - int update = CHECK_FLAG (rinfo->flags, RIP_RTF_FIB) ? 1 : 0; - - assert (newinfo.metric != RIP_METRIC_INFINITY); - - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_OFF (rinfo->t_garbage_collect); - memcpy (rinfo, &newinfo, sizeof (struct rip_info)); - rip_timeout_update (rinfo); - - if (update) - rip_zebra_ipv4_add (rp); - - /* - Set the route change flag on the first entry. */ - rinfo = listgetdata (listhead (list)); - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); - rip_event (RIP_TRIGGERED_UPDATE, 0); - } - } - } - else /* same & no change */ - rip_timeout_update (rinfo); - - /* Unlock tempolary lock of the route. */ - route_unlock_node (rp); - } -} +static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, + struct interface *ifp) +{ + int ret; + struct prefix_ipv4 p; + struct route_node *rp; + struct rip_info *rinfo = NULL, newinfo; + struct rip_interface *ri; + struct in_addr *nexthop; + int same = 0; + unsigned char old_dist, new_dist; + struct list *list = NULL; + struct listnode *node = NULL; + + /* Make prefix structure. */ + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = rte->prefix; + p.prefixlen = ip_masklen(rte->mask); + + /* Make sure mask is applied. */ + apply_mask_ipv4(&p); + + /* Apply input filters. */ + ri = ifp->info; -/* Dump RIP packet */ -static void -rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv) -{ - caddr_t lim; - struct rte *rte; - const char *command_str; - char pbuf[BUFSIZ], nbuf[BUFSIZ]; - u_char netmask = 0; - u_char *p; - - /* Set command string. */ - if (packet->command > 0 && packet->command < RIP_COMMAND_MAX) - command_str = lookup_msg (rip_msg, packet->command, NULL); - else - command_str = "unknown"; - - /* Dump packet header. */ - zlog_debug ("%s %s version %d packet size %d", - sndrcv, command_str, packet->version, size); - - /* Dump each routing table entry. */ - rte = packet->rte; - - for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) - { - if (packet->version == RIPv2) - { - netmask = ip_masklen (rte->mask); + ret = rip_filter(RIP_FILTER_IN, &p, ri); + if (ret < 0) + return; + + memset(&newinfo, 0, sizeof(newinfo)); + newinfo.type = ZEBRA_ROUTE_RIP; + newinfo.sub_type = RIP_ROUTE_RTE; + newinfo.nexthop = rte->nexthop; + newinfo.from = from->sin_addr; + newinfo.ifindex = ifp->ifindex; + newinfo.metric = rte->metric; + newinfo.metric_out = rte->metric; /* XXX */ + newinfo.tag = ntohs(rte->tag); /* XXX */ + + /* Modify entry according to the interface routemap. */ + if (ri->routemap[RIP_FILTER_IN]) { + int ret; + + /* The object should be of the type of rip_info */ + ret = route_map_apply(ri->routemap[RIP_FILTER_IN], + (struct prefix *)&p, RMAP_RIP, &newinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIP %s/%d is filtered by route-map in", + inet_ntoa(p.prefix), p.prefixlen); + return; + } + + /* Get back the object */ + rte->nexthop = newinfo.nexthop_out; + rte->tag = htons(newinfo.tag_out); /* XXX */ + rte->metric = + newinfo.metric_out; /* XXX: the routemap uses the + metric_out field */ + } + + /* Once the entry has been validated, update the metric by + adding the cost of the network on wich the message + arrived. If the result is greater than infinity, use infinity + (RFC2453 Sec. 3.9.2) */ + /* Zebra ripd can handle offset-list in. */ + ret = rip_offset_list_apply_in(&p, ifp, &rte->metric); - if (rte->family == htons (RIP_FAMILY_AUTH)) - { - if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD)) - { - p = (u_char *)&rte->prefix; + /* If offset-list does not modify the metric use interface's + metric. */ + if (!ret) + rte->metric += ifp->metric ? ifp->metric : 1; - zlog_debug (" family 0x%X type %d auth string: %s", - ntohs (rte->family), ntohs (rte->tag), p); + if (rte->metric > RIP_METRIC_INFINITY) + rte->metric = RIP_METRIC_INFINITY; + + /* Set nexthop pointer. */ + if (rte->nexthop.s_addr == 0) + nexthop = &from->sin_addr; + else + nexthop = &rte->nexthop; + + /* Check if nexthop address is myself, then do nothing. */ + if (rip_nexthop_check(nexthop) < 0) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("Nexthop address %s is myself", + inet_ntoa(*nexthop)); + return; + } + + /* Get index for the prefix. */ + rp = route_node_get(rip->table, (struct prefix *)&p); + + newinfo.rp = rp; + newinfo.nexthop = *nexthop; + newinfo.metric = rte->metric; + newinfo.tag = ntohs(rte->tag); + newinfo.distance = rip_distance_apply(&newinfo); + + new_dist = newinfo.distance ? newinfo.distance + : ZEBRA_RIP_DISTANCE_DEFAULT; + + /* Check to see whether there is already RIP route on the table. */ + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) { + /* Need to compare with redistributed entry or local + * entry */ + if (!rip_route_rte(rinfo)) + break; + + if (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) + && IPV4_ADDR_SAME(&rinfo->nexthop, nexthop)) + break; + + if (!listnextnode(node)) { + /* Not found in the list */ + + if (rte->metric > rinfo->metric) { + /* New route has a greater metric. + * Discard it. */ + route_unlock_node(rp); + return; + } + + if (rte->metric < rinfo->metric) + /* New route has a smaller metric. + * Replace the ECMP list + * with the new one in below. */ + break; + + /* Metrics are same. We compare the distances. + */ + old_dist = rinfo->distance + ? rinfo->distance + : ZEBRA_RIP_DISTANCE_DEFAULT; + + if (new_dist > old_dist) { + /* New route has a greater distance. + * Discard it. */ + route_unlock_node(rp); + return; + } + + if (new_dist < old_dist) + /* New route has a smaller distance. + * Replace the ECMP list + * with the new one in below. */ + break; + + /* Metrics and distances are both same. Keep + * "rinfo" null and + * the new route is added in the ECMP list in + * below. */ + } } - else if (rte->tag == htons (RIP_AUTH_MD5)) - { - struct rip_md5_info *md5; - - md5 = (struct rip_md5_info *) &packet->rte; - - zlog_debug (" family 0x%X type %d (MD5 authentication)", - ntohs (md5->family), ntohs (md5->type)); - zlog_debug (" RIP-2 packet len %d Key ID %d" - " Auth Data len %d", - ntohs (md5->packet_len), md5->keyid, - md5->auth_len); - zlog_debug (" Sequence Number %ld", - (u_long) ntohl (md5->sequence)); + + if (rinfo) { + /* Local static route. */ + if (rinfo->type == ZEBRA_ROUTE_RIP + && ((rinfo->sub_type == RIP_ROUTE_STATIC) + || (rinfo->sub_type == RIP_ROUTE_DEFAULT)) + && rinfo->metric != RIP_METRIC_INFINITY) { + route_unlock_node(rp); + return; } - else if (rte->tag == htons (RIP_AUTH_DATA)) - { - p = (u_char *)&rte->prefix; - - zlog_debug (" family 0x%X type %d (MD5 data)", - ntohs (rte->family), ntohs (rte->tag)); - zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X" - "%02X%02X%02X%02X%02X%02X%02X%02X", - p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8], p[9], p[10], p[11], p[12], p[13], - p[14], p[15]); + + /* Redistributed route check. */ + if (rinfo->type != ZEBRA_ROUTE_RIP + && rinfo->metric != RIP_METRIC_INFINITY) { + old_dist = rinfo->distance; + /* Only routes directly connected to an interface + * (nexthop == 0) + * may have a valid NULL distance */ + if (rinfo->nexthop.s_addr != 0) + old_dist = old_dist + ? old_dist + : ZEBRA_RIP_DISTANCE_DEFAULT; + /* If imported route does not have STRICT precedence, + mark it as a ghost */ + if (new_dist <= old_dist + && rte->metric != RIP_METRIC_INFINITY) + rip_ecmp_replace(&newinfo); + + route_unlock_node(rp); + return; } - else - { - zlog_debug (" family 0x%X type %d (Unknown auth type)", - ntohs (rte->family), ntohs (rte->tag)); + } + + if (!rinfo) { + if (rp->info) + route_unlock_node(rp); + + /* Now, check to see whether there is already an explicit route + for the destination prefix. If there is no such route, add + this route to the routing table, unless the metric is + infinity (there is no point in adding a route which + unusable). */ + if (rte->metric != RIP_METRIC_INFINITY) + rip_ecmp_add(&newinfo); + } else { + /* Route is there but we are not sure the route is RIP or not. + */ + + /* If there is an existing route, compare the next hop address + to the address of the router from which the datagram came. + If this datagram is from the same router as the existing + route, reinitialize the timeout. */ + same = (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr) + && (rinfo->ifindex == ifp->ifindex)); + + old_dist = rinfo->distance ? rinfo->distance + : ZEBRA_RIP_DISTANCE_DEFAULT; + + /* Next, compare the metrics. If the datagram is from the same + router as the existing route, and the new metric is different + than the old one; or, if the new metric is lower than the old + one, or if the tag has been changed; or if there is a route + with a lower administrave distance; or an update of the + distance on the actual route; do the following actions: */ + if ((same && rinfo->metric != rte->metric) + || (rte->metric < rinfo->metric) + || ((same) && (rinfo->metric == rte->metric) + && (newinfo.tag != rinfo->tag)) + || (old_dist > new_dist) + || ((old_dist != new_dist) && same)) { + if (listcount(list) == 1) { + if (newinfo.metric != RIP_METRIC_INFINITY) + rip_ecmp_replace(&newinfo); + else + rip_ecmp_delete(rinfo); + } else { + if (newinfo.metric < rinfo->metric) + rip_ecmp_replace(&newinfo); + else if (newinfo.metric > rinfo->metric) + rip_ecmp_delete(rinfo); + else if (new_dist < old_dist) + rip_ecmp_replace(&newinfo); + else if (new_dist > old_dist) + rip_ecmp_delete(rinfo); + else { + int update = CHECK_FLAG(rinfo->flags, + RIP_RTF_FIB) + ? 1 + : 0; + + assert(newinfo.metric + != RIP_METRIC_INFINITY); + + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + memcpy(rinfo, &newinfo, + sizeof(struct rip_info)); + rip_timeout_update(rinfo); + + if (update) + rip_zebra_ipv4_add(rp); + + /* - Set the route change flag on the + * first entry. */ + rinfo = listgetdata(listhead(list)); + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); + rip_event(RIP_TRIGGERED_UPDATE, 0); + } + } + } else /* same & no change */ + rip_timeout_update(rinfo); + + /* Unlock tempolary lock of the route. */ + route_unlock_node(rp); + } +} + +/* Dump RIP packet */ +static void rip_packet_dump(struct rip_packet *packet, int size, + const char *sndrcv) +{ + caddr_t lim; + struct rte *rte; + const char *command_str; + char pbuf[BUFSIZ], nbuf[BUFSIZ]; + u_char netmask = 0; + u_char *p; + + /* Set command string. */ + if (packet->command > 0 && packet->command < RIP_COMMAND_MAX) + command_str = lookup_msg(rip_msg, packet->command, NULL); + else + command_str = "unknown"; + + /* Dump packet header. */ + zlog_debug("%s %s version %d packet size %d", sndrcv, command_str, + packet->version, size); + + /* Dump each routing table entry. */ + rte = packet->rte; + + for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) { + if (packet->version == RIPv2) { + netmask = ip_masklen(rte->mask); + + if (rte->family == htons(RIP_FAMILY_AUTH)) { + if (rte->tag + == htons(RIP_AUTH_SIMPLE_PASSWORD)) { + p = (u_char *)&rte->prefix; + + zlog_debug( + " family 0x%X type %d auth string: %s", + ntohs(rte->family), + ntohs(rte->tag), p); + } else if (rte->tag == htons(RIP_AUTH_MD5)) { + struct rip_md5_info *md5; + + md5 = (struct rip_md5_info *)&packet + ->rte; + + zlog_debug( + " family 0x%X type %d (MD5 authentication)", + ntohs(md5->family), + ntohs(md5->type)); + zlog_debug( + " RIP-2 packet len %d Key ID %d" + " Auth Data len %d", + ntohs(md5->packet_len), + md5->keyid, md5->auth_len); + zlog_debug( + " Sequence Number %ld", + (u_long)ntohl(md5->sequence)); + } else if (rte->tag == htons(RIP_AUTH_DATA)) { + p = (u_char *)&rte->prefix; + + zlog_debug( + " family 0x%X type %d (MD5 data)", + ntohs(rte->family), + ntohs(rte->tag)); + zlog_debug( + " MD5: %02X%02X%02X%02X%02X%02X%02X%02X" + "%02X%02X%02X%02X%02X%02X%02X%02X", + p[0], p[1], p[2], p[3], p[4], + p[5], p[6], p[7], p[8], p[9], + p[10], p[11], p[12], p[13], + p[14], p[15]); + } else { + zlog_debug( + " family 0x%X type %d (Unknown auth type)", + ntohs(rte->family), + ntohs(rte->tag)); + } + } else + zlog_debug( + " %s/%d -> %s family %d tag %" ROUTE_TAG_PRI + " metric %ld", + inet_ntop(AF_INET, &rte->prefix, pbuf, + BUFSIZ), + netmask, + inet_ntop(AF_INET, &rte->nexthop, nbuf, + BUFSIZ), + ntohs(rte->family), + (route_tag_t)ntohs(rte->tag), + (u_long)ntohl(rte->metric)); + } else { + zlog_debug( + " %s family %d tag %" ROUTE_TAG_PRI + " metric %ld", + inet_ntop(AF_INET, &rte->prefix, pbuf, BUFSIZ), + ntohs(rte->family), + (route_tag_t)ntohs(rte->tag), + (u_long)ntohl(rte->metric)); } - } - else - zlog_debug (" %s/%d -> %s family %d tag %"ROUTE_TAG_PRI" metric %ld", - inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ), - netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf, - BUFSIZ), ntohs (rte->family), - (route_tag_t)ntohs (rte->tag), - (u_long) ntohl (rte->metric)); - } - else - { - zlog_debug (" %s family %d tag %"ROUTE_TAG_PRI" metric %ld", - inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ), - ntohs (rte->family), (route_tag_t)ntohs (rte->tag), - (u_long)ntohl (rte->metric)); } - } } /* Check if the destination address is valid (unicast; not net 0 or 127) (RFC2453 Section 3.9.2 - Page 26). But we don't check net 0 because we accept default route. */ -static int -rip_destination_check (struct in_addr addr) +static int rip_destination_check(struct in_addr addr) { - u_int32_t destination; + u_int32_t destination; - /* Convert to host byte order. */ - destination = ntohl (addr.s_addr); + /* Convert to host byte order. */ + destination = ntohl(addr.s_addr); - if (IPV4_NET127 (destination)) - return 0; + if (IPV4_NET127(destination)) + return 0; - /* Net 0 may match to the default route. */ - if (IPV4_NET0 (destination) && destination != 0) - return 0; + /* Net 0 may match to the default route. */ + if (IPV4_NET0(destination) && destination != 0) + return 0; - /* Unicast address must belong to class A, B, C. */ - if (IN_CLASSA (destination)) - return 1; - if (IN_CLASSB (destination)) - return 1; - if (IN_CLASSC (destination)) - return 1; + /* Unicast address must belong to class A, B, C. */ + if (IN_CLASSA(destination)) + return 1; + if (IN_CLASSB(destination)) + return 1; + if (IN_CLASSC(destination)) + return 1; - return 0; + return 0; } /* RIP version 2 authentication. */ -static int -rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from, - struct interface *ifp) -{ - struct rip_interface *ri; - char *auth_str = (char *) &rte->prefix; - int i; - - /* reject passwords with zeros in the middle of the string */ - for (i = strlen (auth_str); i < 16; i++) - { - if (auth_str[i] != '\0') - return 0; - } - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 simple password authentication from %s", - inet_ntoa (from->sin_addr)); - - ri = ifp->info; - - if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD - || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD)) - return 0; - - /* Simple password authentication. */ - if (ri->auth_str) - { - if (strncmp (auth_str, ri->auth_str, 16) == 0) - return 1; - } - if (ri->key_chain) - { - struct keychain *keychain; - struct key *key; - - keychain = keychain_lookup (ri->key_chain); - if (keychain == NULL) - return 0; +static int rip_auth_simple_password(struct rte *rte, struct sockaddr_in *from, + struct interface *ifp) +{ + struct rip_interface *ri; + char *auth_str = (char *)&rte->prefix; + int i; + + /* reject passwords with zeros in the middle of the string */ + for (i = strlen(auth_str); i < 16; i++) { + if (auth_str[i] != '\0') + return 0; + } + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RIPv2 simple password authentication from %s", + inet_ntoa(from->sin_addr)); + + ri = ifp->info; + + if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD + || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD)) + return 0; - key = key_match_for_accept (keychain, auth_str); - if (key) - return 1; - } - return 0; + /* Simple password authentication. */ + if (ri->auth_str) { + if (strncmp(auth_str, ri->auth_str, 16) == 0) + return 1; + } + if (ri->key_chain) { + struct keychain *keychain; + struct key *key; + + keychain = keychain_lookup(ri->key_chain); + if (keychain == NULL) + return 0; + + key = key_match_for_accept(keychain, auth_str); + if (key) + return 1; + } + return 0; } /* RIP version 2 authentication with MD5. */ -static int -rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from, - int length, struct interface *ifp) -{ - struct rip_interface *ri; - struct rip_md5_info *md5; - struct rip_md5_data *md5data; - struct keychain *keychain; - struct key *key; - MD5_CTX ctx; - u_char digest[RIP_AUTH_MD5_SIZE]; - u_int16_t packet_len; - char auth_str[RIP_AUTH_MD5_SIZE]; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication from %s", - inet_ntoa (from->sin_addr)); - - ri = ifp->info; - md5 = (struct rip_md5_info *) &packet->rte; - - /* Check auth type. */ - if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5)) - return 0; - - /* If the authentication length is less than 16, then it must be wrong for - * any interpretation of rfc2082. Some implementations also interpret - * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE. - */ - if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE) - || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE))) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication, strange authentication " - "length field %d", md5->auth_len); - return 0; - } - - /* grab and verify check packet length */ - packet_len = ntohs (md5->packet_len); - - if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication, packet length field %d " - "greater than received length %d!", - md5->packet_len, length); - return 0; - } - - /* retrieve authentication data */ - md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len); - - memset (auth_str, 0, RIP_AUTH_MD5_SIZE); - - if (ri->key_chain) - { - keychain = keychain_lookup (ri->key_chain); - if (keychain == NULL) - return 0; +static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from, + int length, struct interface *ifp) +{ + struct rip_interface *ri; + struct rip_md5_info *md5; + struct rip_md5_data *md5data; + struct keychain *keychain; + struct key *key; + MD5_CTX ctx; + u_char digest[RIP_AUTH_MD5_SIZE]; + u_int16_t packet_len; + char auth_str[RIP_AUTH_MD5_SIZE]; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RIPv2 MD5 authentication from %s", + inet_ntoa(from->sin_addr)); - key = key_lookup_for_accept (keychain, md5->keyid); - if (key == NULL) - return 0; + ri = ifp->info; + md5 = (struct rip_md5_info *)&packet->rte; + + /* Check auth type. */ + if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5)) + return 0; + + /* If the authentication length is less than 16, then it must be wrong + * for + * any interpretation of rfc2082. Some implementations also interpret + * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka + * RIP_AUTH_MD5_COMPAT_SIZE. + */ + if (!((md5->auth_len == RIP_AUTH_MD5_SIZE) + || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE))) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "RIPv2 MD5 authentication, strange authentication " + "length field %d", + md5->auth_len); + return 0; + } + + /* grab and verify check packet length */ + packet_len = ntohs(md5->packet_len); - strncpy (auth_str, key->string, RIP_AUTH_MD5_SIZE); - } - else if (ri->auth_str) - strncpy (auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE); - - if (auth_str[0] == 0) - return 0; - - /* MD5 digest authentication. */ - memset (&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE); - MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); - - if (memcmp (md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0) - return packet_len; - else - return 0; + if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "RIPv2 MD5 authentication, packet length field %d " + "greater than received length %d!", + md5->packet_len, length); + return 0; + } + + /* retrieve authentication data */ + md5data = (struct rip_md5_data *)(((u_char *)packet) + packet_len); + + memset(auth_str, 0, RIP_AUTH_MD5_SIZE); + + if (ri->key_chain) { + keychain = keychain_lookup(ri->key_chain); + if (keychain == NULL) + return 0; + + key = key_lookup_for_accept(keychain, md5->keyid); + if (key == NULL) + return 0; + + strncpy(auth_str, key->string, RIP_AUTH_MD5_SIZE); + } else if (ri->auth_str) + strncpy(auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE); + + if (auth_str[0] == 0) + return 0; + + /* MD5 digest authentication. */ + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE); + MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); + MD5Final(digest, &ctx); + + if (memcmp(md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0) + return packet_len; + else + return 0; } /* Pick correct auth string for sends, prepare auth_str buffer for use. @@ -950,39 +936,37 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from, * zero padded. * */ -static void -rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key, - char *auth_str, int len) +static void rip_auth_prepare_str_send(struct rip_interface *ri, struct key *key, + char *auth_str, int len) { - assert (ri || key); + assert(ri || key); - memset (auth_str, 0, len); - if (key && key->string) - strncpy (auth_str, key->string, len); - else if (ri->auth_str) - strncpy (auth_str, ri->auth_str, len); + memset(auth_str, 0, len); + if (key && key->string) + strncpy(auth_str, key->string, len); + else if (ri->auth_str) + strncpy(auth_str, ri->auth_str, len); - return; + return; } /* Write RIPv2 simple password authentication information * - * auth_str is presumed to be 2 bytes and correctly prepared + * auth_str is presumed to be 2 bytes and correctly prepared * (left justified and zero padded). */ -static void -rip_auth_simple_write (struct stream *s, char *auth_str, int len) +static void rip_auth_simple_write(struct stream *s, char *auth_str, int len) { - assert (s && len == RIP_AUTH_SIMPLE_SIZE); - - stream_putw (s, RIP_FAMILY_AUTH); - stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD); - stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE); - - return; + assert(s && len == RIP_AUTH_SIMPLE_SIZE); + + stream_putw(s, RIP_FAMILY_AUTH); + stream_putw(s, RIP_AUTH_SIMPLE_PASSWORD); + stream_put(s, auth_str, RIP_AUTH_SIMPLE_SIZE); + + return; } -/* write RIPv2 MD5 "authentication header" +/* write RIPv2 MD5 "authentication header" * (uses the auth key data field) * * Digest offset field is set to 0. @@ -990,1814 +974,1818 @@ rip_auth_simple_write (struct stream *s, char *auth_str, int len) * returns: offset of the digest offset field, which must be set when * length to the auth-data MD5 digest is known. */ -static size_t -rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri, - struct key *key) -{ - size_t doff = 0; - - assert (s && ri && ri->auth_type == RIP_AUTH_MD5); - - /* MD5 authentication. */ - stream_putw (s, RIP_FAMILY_AUTH); - stream_putw (s, RIP_AUTH_MD5); - - /* MD5 AH digest offset field. - * - * Set to placeholder value here, to true value when RIP-2 Packet length - * is known. Actual value is set in .....(). - */ - doff = stream_get_endp(s); - stream_putw (s, 0); - - /* Key ID. */ - if (key) - stream_putc (s, key->index % 256); - else - stream_putc (s, 1); - - /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds - * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this - * to be configurable. - */ - stream_putc (s, ri->md5_auth_len); - - /* Sequence Number (non-decreasing). */ - /* RFC2080: The value used in the sequence number is - arbitrary, but two suggestions are the time of the - message's creation or a simple message counter. */ - stream_putl (s, time (NULL)); - - /* Reserved field must be zero. */ - stream_putl (s, 0); - stream_putl (s, 0); - - return doff; +static size_t rip_auth_md5_ah_write(struct stream *s, struct rip_interface *ri, + struct key *key) +{ + size_t doff = 0; + + assert(s && ri && ri->auth_type == RIP_AUTH_MD5); + + /* MD5 authentication. */ + stream_putw(s, RIP_FAMILY_AUTH); + stream_putw(s, RIP_AUTH_MD5); + + /* MD5 AH digest offset field. + * + * Set to placeholder value here, to true value when RIP-2 Packet length + * is known. Actual value is set in .....(). + */ + doff = stream_get_endp(s); + stream_putw(s, 0); + + /* Key ID. */ + if (key) + stream_putc(s, key->index % 256); + else + stream_putc(s, 1); + + /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds + * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for + * this + * to be configurable. + */ + stream_putc(s, ri->md5_auth_len); + + /* Sequence Number (non-decreasing). */ + /* RFC2080: The value used in the sequence number is + arbitrary, but two suggestions are the time of the + message's creation or a simple message counter. */ + stream_putl(s, time(NULL)); + + /* Reserved field must be zero. */ + stream_putl(s, 0); + stream_putl(s, 0); + + return doff; } /* If authentication is in used, write the appropriate header * returns stream offset to which length must later be written * or 0 if this is not required */ -static size_t -rip_auth_header_write (struct stream *s, struct rip_interface *ri, - struct key *key, char *auth_str, int len) -{ - assert (ri->auth_type != RIP_NO_AUTH); - - switch (ri->auth_type) - { - case RIP_AUTH_SIMPLE_PASSWORD: - rip_auth_prepare_str_send (ri, key, auth_str, len); - rip_auth_simple_write (s, auth_str, len); - return 0; - case RIP_AUTH_MD5: - return rip_auth_md5_ah_write (s, ri, key); - } - assert (1); - return 0; +static size_t rip_auth_header_write(struct stream *s, struct rip_interface *ri, + struct key *key, char *auth_str, int len) +{ + assert(ri->auth_type != RIP_NO_AUTH); + + switch (ri->auth_type) { + case RIP_AUTH_SIMPLE_PASSWORD: + rip_auth_prepare_str_send(ri, key, auth_str, len); + rip_auth_simple_write(s, auth_str, len); + return 0; + case RIP_AUTH_MD5: + return rip_auth_md5_ah_write(s, ri, key); + } + assert(1); + return 0; } /* Write RIPv2 MD5 authentication data trailer */ -static void -rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff, - char *auth_str, int authlen) -{ - unsigned long len; - MD5_CTX ctx; - unsigned char digest[RIP_AUTH_MD5_SIZE]; - - /* Make it sure this interface is configured as MD5 - authentication. */ - assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE)); - assert (doff > 0); - - /* Get packet length. */ - len = stream_get_endp(s); - - /* Check packet length. */ - if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) - { - zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len); - return; - } - - /* Set the digest offset length in the header */ - stream_putw_at (s, doff, len); - - /* Set authentication data. */ - stream_putw (s, RIP_FAMILY_AUTH); - stream_putw (s, RIP_AUTH_DATA); - - /* Generate a digest for the RIP packet. */ - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - MD5Update(&ctx, STREAM_DATA (s), stream_get_endp (s)); - MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); - MD5Final(digest, &ctx); - - /* Copy the digest to the packet. */ - stream_write (s, digest, RIP_AUTH_MD5_SIZE); +static void rip_auth_md5_set(struct stream *s, struct rip_interface *ri, + size_t doff, char *auth_str, int authlen) +{ + unsigned long len; + MD5_CTX ctx; + unsigned char digest[RIP_AUTH_MD5_SIZE]; + + /* Make it sure this interface is configured as MD5 + authentication. */ + assert((ri->auth_type == RIP_AUTH_MD5) + && (authlen == RIP_AUTH_MD5_SIZE)); + assert(doff > 0); + + /* Get packet length. */ + len = stream_get_endp(s); + + /* Check packet length. */ + if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) { + zlog_err( + "rip_auth_md5_set(): packet length %ld is less than minimum length.", + len); + return; + } + + /* Set the digest offset length in the header */ + stream_putw_at(s, doff, len); + + /* Set authentication data. */ + stream_putw(s, RIP_FAMILY_AUTH); + stream_putw(s, RIP_AUTH_DATA); + + /* Generate a digest for the RIP packet. */ + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + MD5Update(&ctx, STREAM_DATA(s), stream_get_endp(s)); + MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE); + MD5Final(digest, &ctx); + + /* Copy the digest to the packet. */ + stream_write(s, digest, RIP_AUTH_MD5_SIZE); } /* RIP routing information. */ -static void -rip_response_process (struct rip_packet *packet, int size, - struct sockaddr_in *from, struct connected *ifc) -{ - caddr_t lim; - struct rte *rte; - struct prefix_ipv4 ifaddr; - struct prefix_ipv4 ifaddrclass; - int subnetted; - - memset(&ifaddr, 0, sizeof(ifaddr)); - /* We don't know yet. */ - subnetted = -1; - - /* The Response must be ignored if it is not from the RIP - port. (RFC2453 - Sec. 3.9.2)*/ - if (from->sin_port != htons(RIP_PORT_DEFAULT)) - { - zlog_info ("response doesn't come from RIP port: %d", - from->sin_port); - rip_peer_bad_packet (from); - return; - } - - /* The datagram's IPv4 source address should be checked to see - whether the datagram is from a valid neighbor; the source of the - datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */ - if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) == NULL) - { - zlog_info ("This datagram doesn't came from a valid neighbor: %s", - inet_ntoa (from->sin_addr)); - rip_peer_bad_packet (from); - return; - } - - /* It is also worth checking to see whether the response is from one - of the router's own addresses. */ - - ; /* Alredy done in rip_read () */ - - /* Update RIP peer. */ - rip_peer_update (from, packet->version); - - /* Set RTE pointer. */ - rte = packet->rte; - - for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++) - { - /* RIPv2 authentication check. */ - /* If the Address Family Identifier of the first (and only the - first) entry in the message is 0xFFFF, then the remainder of - the entry contains the authentication. */ - /* If the packet gets here it means authentication enabled */ - /* Check is done in rip_read(). So, just skipping it */ - if (packet->version == RIPv2 && - rte == packet->rte && - rte->family == htons(RIP_FAMILY_AUTH)) - continue; - - if (rte->family != htons(AF_INET)) - { - /* Address family check. RIP only supports AF_INET. */ - zlog_info ("Unsupported family %d from %s.", - ntohs (rte->family), inet_ntoa (from->sin_addr)); - continue; - } - - /* - is the destination address valid (e.g., unicast; not net 0 - or 127) */ - if (! rip_destination_check (rte->prefix)) - { - zlog_info ("Network is net 0 or net 127 or it is not unicast network"); - rip_peer_bad_route (from); - continue; - } - - /* Convert metric value to host byte order. */ - rte->metric = ntohl (rte->metric); - - /* - is the metric valid (i.e., between 1 and 16, inclusive) */ - if (! (rte->metric >= 1 && rte->metric <= 16)) - { - zlog_info ("Route's metric is not in the 1-16 range."); - rip_peer_bad_route (from); - continue; +static void rip_response_process(struct rip_packet *packet, int size, + struct sockaddr_in *from, + struct connected *ifc) +{ + caddr_t lim; + struct rte *rte; + struct prefix_ipv4 ifaddr; + struct prefix_ipv4 ifaddrclass; + int subnetted; + + memset(&ifaddr, 0, sizeof(ifaddr)); + /* We don't know yet. */ + subnetted = -1; + + /* The Response must be ignored if it is not from the RIP + port. (RFC2453 - Sec. 3.9.2)*/ + if (from->sin_port != htons(RIP_PORT_DEFAULT)) { + zlog_info("response doesn't come from RIP port: %d", + from->sin_port); + rip_peer_bad_packet(from); + return; } - /* RIPv1 does not have nexthop value. */ - if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) - { - zlog_info ("RIPv1 packet with nexthop value %s", - inet_ntoa (rte->nexthop)); - rip_peer_bad_route (from); - continue; + /* The datagram's IPv4 source address should be checked to see + whether the datagram is from a valid neighbor; the source of the + datagram must be on a directly connected network (RFC2453 - Sec. + 3.9.2) */ + if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) + == NULL) { + zlog_info( + "This datagram doesn't came from a valid neighbor: %s", + inet_ntoa(from->sin_addr)); + rip_peer_bad_packet(from); + return; } - /* That is, if the provided information is ignored, a possibly - sub-optimal, but absolutely valid, route may be taken. If - the received Next Hop is not directly reachable, it should be - treated as 0.0.0.0. */ - if (packet->version == RIPv2 && rte->nexthop.s_addr != 0) - { - u_int32_t addrval; - - /* Multicast address check. */ - addrval = ntohl (rte->nexthop.s_addr); - if (IN_CLASSD (addrval)) - { - zlog_info ("Nexthop %s is multicast address, skip this rte", - inet_ntoa (rte->nexthop)); - continue; - } - - if (! if_lookup_address ((void *)&rte->nexthop, AF_INET, VRF_DEFAULT)) - { - struct route_node *rn; - struct rip_info *rinfo; - - rn = route_node_match_ipv4 (rip->table, &rte->nexthop); - - if (rn) - { - rinfo = rn->info; - - if (rinfo->type == ZEBRA_ROUTE_RIP - && rinfo->sub_type == RIP_ROUTE_RTE) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Next hop %s is on RIP network. Set nexthop to the packet's originator", inet_ntoa (rte->nexthop)); - rte->nexthop = rinfo->from; - } - else - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop)); - rte->nexthop.s_addr = 0; - } - - route_unlock_node (rn); + /* It is also worth checking to see whether the response is from one + of the router's own addresses. */ + + ; /* Alredy done in rip_read () */ + + /* Update RIP peer. */ + rip_peer_update(from, packet->version); + + /* Set RTE pointer. */ + rte = packet->rte; + + for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) { + /* RIPv2 authentication check. */ + /* If the Address Family Identifier of the first (and only the + first) entry in the message is 0xFFFF, then the remainder of + the entry contains the authentication. */ + /* If the packet gets here it means authentication enabled */ + /* Check is done in rip_read(). So, just skipping it */ + if (packet->version == RIPv2 && rte == packet->rte + && rte->family == htons(RIP_FAMILY_AUTH)) + continue; + + if (rte->family != htons(AF_INET)) { + /* Address family check. RIP only supports AF_INET. */ + zlog_info("Unsupported family %d from %s.", + ntohs(rte->family), + inet_ntoa(from->sin_addr)); + continue; } - else - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop)); - rte->nexthop.s_addr = 0; + + /* - is the destination address valid (e.g., unicast; not net 0 + or 127) */ + if (!rip_destination_check(rte->prefix)) { + zlog_info( + "Network is net 0 or net 127 or it is not unicast network"); + rip_peer_bad_route(from); + continue; } - } - } + /* Convert metric value to host byte order. */ + rte->metric = ntohl(rte->metric); - /* For RIPv1, there won't be a valid netmask. + /* - is the metric valid (i.e., between 1 and 16, inclusive) */ + if (!(rte->metric >= 1 && rte->metric <= 16)) { + zlog_info("Route's metric is not in the 1-16 range."); + rip_peer_bad_route(from); + continue; + } - This is a best guess at the masks. If everyone was using old - Ciscos before the 'ip subnet zero' option, it would be almost - right too :-) - - Cisco summarize ripv1 advertisments to the classful boundary - (/16 for class B's) except when the RIP packet does to inside - the classful network in question. */ + /* RIPv1 does not have nexthop value. */ + if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) { + zlog_info("RIPv1 packet with nexthop value %s", + inet_ntoa(rte->nexthop)); + rip_peer_bad_route(from); + continue; + } - if ((packet->version == RIPv1 && rte->prefix.s_addr != 0) - || (packet->version == RIPv2 - && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0))) - { - u_int32_t destination; - - if (subnetted == -1) - { - memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4)); - memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4)); - apply_classful_mask_ipv4 (&ifaddrclass); - subnetted = 0; - if (ifaddr.prefixlen > ifaddrclass.prefixlen) - subnetted = 1; - } - - destination = ntohl (rte->prefix.s_addr); - - if (IN_CLASSA (destination)) - masklen2ip (8, &rte->mask); - else if (IN_CLASSB (destination)) - masklen2ip (16, &rte->mask); - else if (IN_CLASSC (destination)) - masklen2ip (24, &rte->mask); - - if (subnetted == 1) - masklen2ip (ifaddrclass.prefixlen, - (struct in_addr *) &destination); - if ((subnetted == 1) && ((rte->prefix.s_addr & destination) == - ifaddrclass.prefix.s_addr)) - { - masklen2ip (ifaddr.prefixlen, &rte->mask); - if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr) - masklen2ip (32, &rte->mask); - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix)); - } - else - { - if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr) - continue; - } - - if (IS_RIP_DEBUG_EVENT) - { - zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix)); - zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask)); - } - } - - /* In case of RIPv2, if prefix in RTE is not netmask applied one - ignore the entry. */ - if ((packet->version == RIPv2) - && (rte->mask.s_addr != 0) - && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)) - { - zlog_warn ("RIPv2 address %s is not mask /%d applied one", - inet_ntoa (rte->prefix), ip_masklen (rte->mask)); - rip_peer_bad_route (from); - continue; - } + /* That is, if the provided information is ignored, a possibly + sub-optimal, but absolutely valid, route may be taken. If + the received Next Hop is not directly reachable, it should be + treated as 0.0.0.0. */ + if (packet->version == RIPv2 && rte->nexthop.s_addr != 0) { + u_int32_t addrval; + + /* Multicast address check. */ + addrval = ntohl(rte->nexthop.s_addr); + if (IN_CLASSD(addrval)) { + zlog_info( + "Nexthop %s is multicast address, skip this rte", + inet_ntoa(rte->nexthop)); + continue; + } + + if (!if_lookup_address((void *)&rte->nexthop, AF_INET, + VRF_DEFAULT)) { + struct route_node *rn; + struct rip_info *rinfo; + + rn = route_node_match_ipv4(rip->table, + &rte->nexthop); + + if (rn) { + rinfo = rn->info; + + if (rinfo->type == ZEBRA_ROUTE_RIP + && rinfo->sub_type + == RIP_ROUTE_RTE) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Next hop %s is on RIP network. Set nexthop to the packet's originator", + inet_ntoa( + rte->nexthop)); + rte->nexthop = rinfo->from; + } else { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Next hop %s is not directly reachable. Treat it as 0.0.0.0", + inet_ntoa( + rte->nexthop)); + rte->nexthop.s_addr = 0; + } + + route_unlock_node(rn); + } else { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Next hop %s is not directly reachable. Treat it as 0.0.0.0", + inet_ntoa( + rte->nexthop)); + rte->nexthop.s_addr = 0; + } + } + } - /* Default route's netmask is ignored. */ - if (packet->version == RIPv2 - && (rte->prefix.s_addr == 0) - && (rte->mask.s_addr != 0)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Default route with non-zero netmask. Set zero to netmask"); - rte->mask.s_addr = 0; + /* For RIPv1, there won't be a valid netmask. + + This is a best guess at the masks. If everyone was using old + Ciscos before the 'ip subnet zero' option, it would be almost + right too :-) + + Cisco summarize ripv1 advertisments to the classful boundary + (/16 for class B's) except when the RIP packet does to inside + the classful network in question. */ + + if ((packet->version == RIPv1 && rte->prefix.s_addr != 0) + || (packet->version == RIPv2 + && (rte->prefix.s_addr != 0 + && rte->mask.s_addr == 0))) { + u_int32_t destination; + + if (subnetted == -1) { + memcpy(&ifaddr, ifc->address, + sizeof(struct prefix_ipv4)); + memcpy(&ifaddrclass, &ifaddr, + sizeof(struct prefix_ipv4)); + apply_classful_mask_ipv4(&ifaddrclass); + subnetted = 0; + if (ifaddr.prefixlen > ifaddrclass.prefixlen) + subnetted = 1; + } + + destination = ntohl(rte->prefix.s_addr); + + if (IN_CLASSA(destination)) + masklen2ip(8, &rte->mask); + else if (IN_CLASSB(destination)) + masklen2ip(16, &rte->mask); + else if (IN_CLASSC(destination)) + masklen2ip(24, &rte->mask); + + if (subnetted == 1) + masklen2ip(ifaddrclass.prefixlen, + (struct in_addr *)&destination); + if ((subnetted == 1) + && ((rte->prefix.s_addr & destination) + == ifaddrclass.prefix.s_addr)) { + masklen2ip(ifaddr.prefixlen, &rte->mask); + if ((rte->prefix.s_addr & rte->mask.s_addr) + != rte->prefix.s_addr) + masklen2ip(32, &rte->mask); + if (IS_RIP_DEBUG_EVENT) + zlog_debug("Subnetted route %s", + inet_ntoa(rte->prefix)); + } else { + if ((rte->prefix.s_addr & rte->mask.s_addr) + != rte->prefix.s_addr) + continue; + } + + if (IS_RIP_DEBUG_EVENT) { + zlog_debug("Resultant route %s", + inet_ntoa(rte->prefix)); + zlog_debug("Resultant mask %s", + inet_ntoa(rte->mask)); + } + } + + /* In case of RIPv2, if prefix in RTE is not netmask applied one + ignore the entry. */ + if ((packet->version == RIPv2) && (rte->mask.s_addr != 0) + && ((rte->prefix.s_addr & rte->mask.s_addr) + != rte->prefix.s_addr)) { + zlog_warn( + "RIPv2 address %s is not mask /%d applied one", + inet_ntoa(rte->prefix), ip_masklen(rte->mask)); + rip_peer_bad_route(from); + continue; + } + + /* Default route's netmask is ignored. */ + if (packet->version == RIPv2 && (rte->prefix.s_addr == 0) + && (rte->mask.s_addr != 0)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Default route with non-zero netmask. Set zero to netmask"); + rte->mask.s_addr = 0; + } + + /* Routing table updates. */ + rip_rte_process(rte, from, ifc->ifp); } - - /* Routing table updates. */ - rip_rte_process (rte, from, ifc->ifp); - } } /* Make socket for RIP protocol. */ -static int -rip_create_socket (void) -{ - int ret; - int sock; - struct sockaddr_in addr; - - memset (&addr, 0, sizeof (struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; +static int rip_create_socket(void) +{ + int ret; + int sock; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof (struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* sending port must always be the RIP port */ - addr.sin_port = htons (RIP_PORT_DEFAULT); - - /* Make datagram socket. */ - sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) - { - zlog_err("Cannot create UDP socket: %s", safe_strerror(errno)); - exit (1); - } - - sockopt_broadcast (sock); - sockopt_reuseaddr (sock); - sockopt_reuseport (sock); - setsockopt_ipv4_multicast_loop (sock, 0); + /* sending port must always be the RIP port */ + addr.sin_port = htons(RIP_PORT_DEFAULT); + + /* Make datagram socket. */ + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) { + zlog_err("Cannot create UDP socket: %s", safe_strerror(errno)); + exit(1); + } + + sockopt_broadcast(sock); + sockopt_reuseaddr(sock); + sockopt_reuseport(sock); + setsockopt_ipv4_multicast_loop(sock, 0); #ifdef RIP_RECVMSG - setsockopt_pktinfo (sock); + setsockopt_pktinfo(sock); #endif /* RIP_RECVMSG */ #ifdef IPTOS_PREC_INTERNETCONTROL - setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL); + setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL); #endif - if (ripd_privs.change (ZPRIVS_RAISE)) - zlog_err ("rip_create_socket: could not raise privs"); - setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF); - if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0) - - { - int save_errno = errno; - if (ripd_privs.change (ZPRIVS_LOWER)) - zlog_err ("rip_create_socket: could not lower privs"); - - zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__, - sock, inet_ntoa(addr.sin_addr), - (int) ntohs(addr.sin_port), - safe_strerror(save_errno)); - - close (sock); - return ret; - } - - if (ripd_privs.change (ZPRIVS_LOWER)) - zlog_err ("rip_create_socket: could not lower privs"); - - return sock; + if (ripd_privs.change(ZPRIVS_RAISE)) + zlog_err("rip_create_socket: could not raise privs"); + setsockopt_so_recvbuf(sock, RIP_UDP_RCV_BUF); + if ((ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) + + { + int save_errno = errno; + if (ripd_privs.change(ZPRIVS_LOWER)) + zlog_err("rip_create_socket: could not lower privs"); + + zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__, + sock, inet_ntoa(addr.sin_addr), + (int)ntohs(addr.sin_port), safe_strerror(save_errno)); + + close(sock); + return ret; + } + + if (ripd_privs.change(ZPRIVS_LOWER)) + zlog_err("rip_create_socket: could not lower privs"); + + return sock; } /* RIP packet send to destination address, on interface denoted by * by connected argument. NULL to argument denotes destination should be * should be RIP multicast group */ -static int -rip_send_packet (u_char * buf, int size, struct sockaddr_in *to, - struct connected *ifc) -{ - int ret; - struct sockaddr_in sin; - - assert (ifc != NULL); - - if (IS_RIP_DEBUG_PACKET) - { +static int rip_send_packet(u_char *buf, int size, struct sockaddr_in *to, + struct connected *ifc) +{ + int ret; + struct sockaddr_in sin; + + assert(ifc != NULL); + + if (IS_RIP_DEBUG_PACKET) { #define ADDRESS_SIZE 20 - char dst[ADDRESS_SIZE]; - dst[ADDRESS_SIZE - 1] = '\0'; - - if (to) - { - strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1); - } - else - { - sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); - strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1); - } + char dst[ADDRESS_SIZE]; + dst[ADDRESS_SIZE - 1] = '\0'; + + if (to) { + strncpy(dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1); + } else { + sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); + strncpy(dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1); + } #undef ADDRESS_SIZE - zlog_debug("rip_send_packet %s > %s (%s)", - inet_ntoa(ifc->address->u.prefix4), - dst, ifc->ifp->name); - } - - if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) ) - { - /* - * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured - * with multiple addresses on the same subnet: the first address - * on the subnet is configured "primary", and all subsequent addresses - * on that subnet are treated as "secondary" addresses. - * In order to avoid routing-table bloat on other rip listeners, - * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs. - * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY - * flag is set, we would end up sending a packet for a "secondary" - * source address on non-linux systems. - */ - if (IS_RIP_DEBUG_PACKET) - zlog_debug("duplicate dropped"); - return 0; - } - - /* Make destination address. */ - memset (&sin, 0, sizeof (struct sockaddr_in)); - sin.sin_family = AF_INET; + zlog_debug("rip_send_packet %s > %s (%s)", + inet_ntoa(ifc->address->u.prefix4), dst, + ifc->ifp->name); + } + + if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) { + /* + * ZEBRA_IFA_SECONDARY is set on linux when an interface is + * configured + * with multiple addresses on the same subnet: the first address + * on the subnet is configured "primary", and all subsequent + * addresses + * on that subnet are treated as "secondary" addresses. + * In order to avoid routing-table bloat on other rip listeners, + * we do not send out RIP packets with ZEBRA_IFA_SECONDARY + * source addrs. + * XXX Since Linux is the only system for which the + * ZEBRA_IFA_SECONDARY + * flag is set, we would end up sending a packet for a + * "secondary" + * source address on non-linux systems. + */ + if (IS_RIP_DEBUG_PACKET) + zlog_debug("duplicate dropped"); + return 0; + } + + /* Make destination address. */ + memset(&sin, 0, sizeof(struct sockaddr_in)); + sin.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin.sin_len = sizeof (struct sockaddr_in); + sin.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - /* When destination is specified, use it's port and address. */ - if (to) - { - sin.sin_port = to->sin_port; - sin.sin_addr = to->sin_addr; - } - else - { - sin.sin_port = htons (RIP_PORT_DEFAULT); - sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); + /* When destination is specified, use it's port and address. */ + if (to) { + sin.sin_port = to->sin_port; + sin.sin_addr = to->sin_addr; + } else { + sin.sin_port = htons(RIP_PORT_DEFAULT); + sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP); - rip_interface_multicast_set (rip->sock, ifc); - } + rip_interface_multicast_set(rip->sock, ifc); + } - ret = sendto (rip->sock, buf, size, 0, (struct sockaddr *)&sin, - sizeof (struct sockaddr_in)); + ret = sendto(rip->sock, buf, size, 0, (struct sockaddr *)&sin, + sizeof(struct sockaddr_in)); - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("SEND to %s.%d", inet_ntoa(sin.sin_addr), - ntohs (sin.sin_port)); + if (IS_RIP_DEBUG_EVENT) + zlog_debug("SEND to %s.%d", inet_ntoa(sin.sin_addr), + ntohs(sin.sin_port)); - if (ret < 0) - zlog_warn ("can't send packet : %s", safe_strerror (errno)); + if (ret < 0) + zlog_warn("can't send packet : %s", safe_strerror(errno)); - return ret; + return ret; } /* Add redistributed route to RIP table. */ -void -rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, - ifindex_t ifindex, struct in_addr *nexthop, - unsigned int metric, unsigned char distance, - route_tag_t tag) -{ - int ret; - struct route_node *rp = NULL; - struct rip_info *rinfo = NULL, newinfo; - struct list *list = NULL; +void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p, + ifindex_t ifindex, struct in_addr *nexthop, + unsigned int metric, unsigned char distance, + route_tag_t tag) +{ + int ret; + struct route_node *rp = NULL; + struct rip_info *rinfo = NULL, newinfo; + struct list *list = NULL; + + /* Redistribute route */ + ret = rip_destination_check(p->prefix); + if (!ret) + return; + + rp = route_node_get(rip->table, (struct prefix *)p); + + memset(&newinfo, 0, sizeof(struct rip_info)); + newinfo.type = type; + newinfo.sub_type = sub_type; + newinfo.ifindex = ifindex; + newinfo.metric = 1; + newinfo.external_metric = metric; + newinfo.distance = distance; + if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */ + newinfo.tag = tag; + newinfo.rp = rp; + if (nexthop) + newinfo.nexthop = *nexthop; + + if ((list = rp->info) != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + + if (rinfo->type == ZEBRA_ROUTE_CONNECT + && rinfo->sub_type == RIP_ROUTE_INTERFACE + && rinfo->metric != RIP_METRIC_INFINITY) { + route_unlock_node(rp); + return; + } - /* Redistribute route */ - ret = rip_destination_check (p->prefix); - if (! ret) - return; - - rp = route_node_get (rip->table, (struct prefix *) p); - - memset (&newinfo, 0, sizeof (struct rip_info)); - newinfo.type = type; - newinfo.sub_type = sub_type; - newinfo.ifindex = ifindex; - newinfo.metric = 1; - newinfo.external_metric = metric; - newinfo.distance = distance; - if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */ - newinfo.tag = tag; - newinfo.rp = rp; - if (nexthop) - newinfo.nexthop = *nexthop; - - if ((list = rp->info) != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - - if (rinfo->type == ZEBRA_ROUTE_CONNECT - && rinfo->sub_type == RIP_ROUTE_INTERFACE - && rinfo->metric != RIP_METRIC_INFINITY) - { - route_unlock_node (rp); - return; + /* Manually configured RIP route check. */ + if (rinfo->type == ZEBRA_ROUTE_RIP + && ((rinfo->sub_type == RIP_ROUTE_STATIC) + || (rinfo->sub_type == RIP_ROUTE_DEFAULT))) { + if (type != ZEBRA_ROUTE_RIP + || ((sub_type != RIP_ROUTE_STATIC) + && (sub_type != RIP_ROUTE_DEFAULT))) { + route_unlock_node(rp); + return; + } + } + + rinfo = rip_ecmp_replace(&newinfo); + route_unlock_node(rp); + } else + rinfo = rip_ecmp_add(&newinfo); + + if (IS_RIP_DEBUG_EVENT) { + if (!nexthop) + zlog_debug( + "Redistribute new prefix %s/%d on the interface %s", + inet_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(ifindex, VRF_DEFAULT)); + else + zlog_debug( + "Redistribute new prefix %s/%d with nexthop %s on the interface %s", + inet_ntoa(p->prefix), p->prefixlen, + inet_ntoa(rinfo->nexthop), + ifindex2ifname(ifindex, VRF_DEFAULT)); } - /* Manually configured RIP route check. */ - if (rinfo->type == ZEBRA_ROUTE_RIP - && ((rinfo->sub_type == RIP_ROUTE_STATIC) || - (rinfo->sub_type == RIP_ROUTE_DEFAULT)) ) - { - if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) && - (sub_type != RIP_ROUTE_DEFAULT))) - { - route_unlock_node (rp); - return; - } - } - - rinfo = rip_ecmp_replace (&newinfo); - route_unlock_node (rp); - } - else - rinfo = rip_ecmp_add (&newinfo); - - if (IS_RIP_DEBUG_EVENT) { - if (!nexthop) - zlog_debug ("Redistribute new prefix %s/%d on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); - else - zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop), - ifindex2ifname(ifindex, VRF_DEFAULT)); - } - - rip_event (RIP_TRIGGERED_UPDATE, 0); + rip_event(RIP_TRIGGERED_UPDATE, 0); } /* Delete redistributed route from RIP table. */ -void -rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, - ifindex_t ifindex) -{ - int ret; - struct route_node *rp; - struct rip_info *rinfo; - - ret = rip_destination_check (p->prefix); - if (! ret) - return; - - rp = route_node_lookup (rip->table, (struct prefix *) p); - if (rp) - { - struct list *list = rp->info; - - if (list != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - if (rinfo != NULL - && rinfo->type == type - && rinfo->sub_type == sub_type - && rinfo->ifindex == ifindex) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIP_METRIC_INFINITY; - RIP_TIMER_ON (rinfo->t_garbage_collect, - rip_garbage_collect, rip->garbage_time); - RIP_TIMER_OFF (rinfo->t_timeout); - rinfo->flags |= RIP_RTF_CHANGED; - - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Poisone %s/%d on the interface %s with an " - "infinity metric [delete]", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex, VRF_DEFAULT)); - - rip_event (RIP_TRIGGERED_UPDATE, 0); - } - } - route_unlock_node (rp); - } +void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p, + ifindex_t ifindex) +{ + int ret; + struct route_node *rp; + struct rip_info *rinfo; + + ret = rip_destination_check(p->prefix); + if (!ret) + return; + + rp = route_node_lookup(rip->table, (struct prefix *)p); + if (rp) { + struct list *list = rp->info; + + if (list != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + if (rinfo != NULL && rinfo->type == type + && rinfo->sub_type == sub_type + && rinfo->ifindex == ifindex) { + /* Perform poisoned reverse. */ + rinfo->metric = RIP_METRIC_INFINITY; + RIP_TIMER_ON(rinfo->t_garbage_collect, + rip_garbage_collect, + rip->garbage_time); + RIP_TIMER_OFF(rinfo->t_timeout); + rinfo->flags |= RIP_RTF_CHANGED; + + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "Poisone %s/%d on the interface %s with an " + "infinity metric [delete]", + inet_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(ifindex, + VRF_DEFAULT)); + + rip_event(RIP_TRIGGERED_UPDATE, 0); + } + } + route_unlock_node(rp); + } } /* Response to request called from rip_read ().*/ -static void -rip_request_process (struct rip_packet *packet, int size, - struct sockaddr_in *from, struct connected *ifc) -{ - caddr_t lim; - struct rte *rte; - struct prefix_ipv4 p; - struct route_node *rp; - struct rip_info *rinfo; - struct rip_interface *ri; - - /* Does not reponse to the requests on the loopback interfaces */ - if (if_is_loopback (ifc->ifp)) - return; - - /* Check RIP process is enabled on this interface. */ - ri = ifc->ifp->info; - if (! ri->running) - return; - - /* When passive interface is specified, suppress responses */ - if (ri->passive) - return; - - /* RIP peer update. */ - rip_peer_update (from, packet->version); - - lim = ((caddr_t) packet) + size; - rte = packet->rte; - - /* The Request is processed entry by entry. If there are no - entries, no response is given. */ - if (lim == (caddr_t) rte) - return; - - /* There is one special case. If there is exactly one entry in the - request, and it has an address family identifier of zero and a - metric of infinity (i.e., 16), then this is a request to send the - entire routing table. */ - if (lim == ((caddr_t) (rte + 1)) && - ntohs (rte->family) == 0 && - ntohl (rte->metric) == RIP_METRIC_INFINITY) - { - /* All route with split horizon */ - rip_output_process (ifc, from, rip_all_route, packet->version); - } - else - { - if (ntohs (rte->family) != AF_INET) - return; +static void rip_request_process(struct rip_packet *packet, int size, + struct sockaddr_in *from, struct connected *ifc) +{ + caddr_t lim; + struct rte *rte; + struct prefix_ipv4 p; + struct route_node *rp; + struct rip_info *rinfo; + struct rip_interface *ri; + + /* Does not reponse to the requests on the loopback interfaces */ + if (if_is_loopback(ifc->ifp)) + return; + + /* Check RIP process is enabled on this interface. */ + ri = ifc->ifp->info; + if (!ri->running) + return; + + /* When passive interface is specified, suppress responses */ + if (ri->passive) + return; + + /* RIP peer update. */ + rip_peer_update(from, packet->version); + + lim = ((caddr_t)packet) + size; + rte = packet->rte; + + /* The Request is processed entry by entry. If there are no + entries, no response is given. */ + if (lim == (caddr_t)rte) + return; + + /* There is one special case. If there is exactly one entry in the + request, and it has an address family identifier of zero and a + metric of infinity (i.e., 16), then this is a request to send the + entire routing table. */ + if (lim == ((caddr_t)(rte + 1)) && ntohs(rte->family) == 0 + && ntohl(rte->metric) == RIP_METRIC_INFINITY) { + /* All route with split horizon */ + rip_output_process(ifc, from, rip_all_route, packet->version); + } else { + if (ntohs(rte->family) != AF_INET) + return; + + /* Examine the list of RTEs in the Request one by one. For each + entry, look up the destination in the router's routing + database and, if there is a route, put that route's metric in + the metric field of the RTE. If there is no explicit route + to the specified destination, put infinity in the metric + field. Once all the entries have been filled in, change the + command from Request to Response and send the datagram back + to the requestor. */ + p.family = AF_INET; + + for (; ((caddr_t)rte) < lim; rte++) { + p.prefix = rte->prefix; + p.prefixlen = ip_masklen(rte->mask); + apply_mask_ipv4(&p); + + rp = route_node_lookup(rip->table, (struct prefix *)&p); + if (rp) { + rinfo = listgetdata( + listhead((struct list *)rp->info)); + rte->metric = htonl(rinfo->metric); + route_unlock_node(rp); + } else + rte->metric = htonl(RIP_METRIC_INFINITY); + } + packet->command = RIP_RESPONSE; - /* Examine the list of RTEs in the Request one by one. For each - entry, look up the destination in the router's routing - database and, if there is a route, put that route's metric in - the metric field of the RTE. If there is no explicit route - to the specified destination, put infinity in the metric - field. Once all the entries have been filled in, change the - command from Request to Response and send the datagram back - to the requestor. */ - p.family = AF_INET; - - for (; ((caddr_t) rte) < lim; rte++) - { - p.prefix = rte->prefix; - p.prefixlen = ip_masklen (rte->mask); - apply_mask_ipv4 (&p); - - rp = route_node_lookup (rip->table, (struct prefix *) &p); - if (rp) - { - rinfo = listgetdata (listhead ((struct list *)rp->info)); - rte->metric = htonl (rinfo->metric); - route_unlock_node (rp); - } - else - rte->metric = htonl (RIP_METRIC_INFINITY); - } - packet->command = RIP_RESPONSE; - - rip_send_packet ((u_char *)packet, size, from, ifc); - } - rip_global_queries++; + rip_send_packet((u_char *)packet, size, from, ifc); + } + rip_global_queries++; } #if RIP_RECVMSG /* Set IPv6 packet info to the socket. */ -static int -setsockopt_pktinfo (int sock) +static int setsockopt_pktinfo(int sock) { - int ret; - int val = 1; - - ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)); - if (ret < 0) - zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno)); - return ret; + int ret; + int val = 1; + + ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)); + if (ret < 0) + zlog_warn("Can't setsockopt IP_PKTINFO : %s", + safe_strerror(errno)); + return ret; } /* Read RIP packet by recvmsg function. */ -int -rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from, - ifindex_t *ifindex) -{ - int ret; - struct msghdr msg; - struct iovec iov; - struct cmsghdr *ptr; - char adata[1024]; - - msg.msg_name = (void *) from; - msg.msg_namelen = sizeof (struct sockaddr_in); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = (void *) adata; - msg.msg_controllen = sizeof adata; - iov.iov_base = buf; - iov.iov_len = size; - - ret = recvmsg (sock, &msg, 0); - if (ret < 0) - return ret; - - for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr)) - if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO) - { - struct in_pktinfo *pktinfo; - int i; +int rip_recvmsg(int sock, u_char *buf, int size, struct sockaddr_in *from, + ifindex_t *ifindex) +{ + int ret; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *ptr; + char adata[1024]; + + msg.msg_name = (void *)from; + msg.msg_namelen = sizeof(struct sockaddr_in); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = (void *)adata; + msg.msg_controllen = sizeof adata; + iov.iov_base = buf; + iov.iov_len = size; + + ret = recvmsg(sock, &msg, 0); + if (ret < 0) + return ret; - pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr); - i = pktinfo->ipi_ifindex; - } - return ret; + for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; + ptr = CMSG_NXTHDR(&msg, ptr)) + if (ptr->cmsg_level == IPPROTO_IP + && ptr->cmsg_type == IP_PKTINFO) { + struct in_pktinfo *pktinfo; + int i; + + pktinfo = (struct in_pktinfo *)CMSG_DATA(ptr); + i = pktinfo->ipi_ifindex; + } + return ret; } /* RIP packet read function. */ -int -rip_read_new (struct thread *t) -{ - int ret; - int sock; - char buf[RIP_PACKET_MAXSIZ]; - struct sockaddr_in from; - ifindex_t ifindex; - - /* Fetch socket then register myself. */ - sock = THREAD_FD (t); - rip_event (RIP_READ, sock); - - /* Read RIP packet. */ - ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex); - if (ret < 0) - { - zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno)); - return ret; - } - - return ret; +int rip_read_new(struct thread *t) +{ + int ret; + int sock; + char buf[RIP_PACKET_MAXSIZ]; + struct sockaddr_in from; + ifindex_t ifindex; + + /* Fetch socket then register myself. */ + sock = THREAD_FD(t); + rip_event(RIP_READ, sock); + + /* Read RIP packet. */ + ret = rip_recvmsg(sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex); + if (ret < 0) { + zlog_warn("Can't read RIP packet: %s", safe_strerror(errno)); + return ret; + } + + return ret; } #endif /* RIP_RECVMSG */ /* First entry point of RIP packet. */ -static int -rip_read (struct thread *t) -{ - int sock; - int ret; - int rtenum; - union rip_buf rip_buf; - struct rip_packet *packet; - struct sockaddr_in from; - int len; - int vrecv; - socklen_t fromlen; - struct interface *ifp = NULL; - struct connected *ifc; - struct rip_interface *ri; - struct prefix p; - - /* Fetch socket then register myself. */ - sock = THREAD_FD (t); - rip->t_read = NULL; - - /* Add myself to tne next event */ - rip_event (RIP_READ, sock); - - /* RIPd manages only IPv4. */ - memset (&from, 0, sizeof (struct sockaddr_in)); - fromlen = sizeof (struct sockaddr_in); - - len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0, - (struct sockaddr *) &from, &fromlen); - if (len < 0) - { - zlog_info ("recvfrom failed: %s", safe_strerror (errno)); - return len; - } - - /* Check is this packet comming from myself? */ - if (if_check_address (from.sin_addr)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("ignore packet comes from myself"); - return -1; - } - - /* Which interface is this packet comes from. */ - ifc = if_lookup_address ((void *)&from.sin_addr, AF_INET, VRF_DEFAULT); - if (ifc) - ifp = ifc->ifp; - - /* RIP packet received */ - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RECV packet from %s port %d on %s", - inet_ntoa (from.sin_addr), ntohs (from.sin_port), - ifp ? ifp->name : "unknown"); - - /* If this packet come from unknown interface, ignore it. */ - if (ifp == NULL) - { - zlog_info ("rip_read: cannot find interface for packet from %s port %d", - inet_ntoa(from.sin_addr), ntohs (from.sin_port)); - return -1; - } - - p.family = AF_INET; - p.u.prefix4 = from.sin_addr; - p.prefixlen = IPV4_MAX_BITLEN; - - ifc = connected_lookup_prefix (ifp, &p); - - if (ifc == NULL) - { - zlog_info ("rip_read: cannot find connected address for packet from %s " - "port %d on interface %s", - inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name); - return -1; - } - - /* Packet length check. */ - if (len < RIP_PACKET_MINSIZ) - { - zlog_warn ("packet size %d is smaller than minimum size %d", - len, RIP_PACKET_MINSIZ); - rip_peer_bad_packet (&from); - return len; - } - if (len > RIP_PACKET_MAXSIZ) - { - zlog_warn ("packet size %d is larger than max size %d", - len, RIP_PACKET_MAXSIZ); - rip_peer_bad_packet (&from); - return len; - } - - /* Packet alignment check. */ - if ((len - RIP_PACKET_MINSIZ) % 20) - { - zlog_warn ("packet size %d is wrong for RIP packet alignment", len); - rip_peer_bad_packet (&from); - return len; - } - - /* Set RTE number. */ - rtenum = ((len - RIP_PACKET_MINSIZ) / 20); - - /* For easy to handle. */ - packet = &rip_buf.rip_packet; - - /* RIP version check. */ - if (packet->version == 0) - { - zlog_info ("version 0 with command %d received.", packet->command); - rip_peer_bad_packet (&from); - return -1; - } - - /* Dump RIP packet. */ - if (IS_RIP_DEBUG_RECV) - rip_packet_dump (packet, len, "RECV"); - - /* RIP version adjust. This code should rethink now. RFC1058 says - that "Version 1 implementations are to ignore this extra data and - process only the fields specified in this document.". So RIPv3 - packet should be treated as RIPv1 ignoring must be zero field. */ - if (packet->version > RIPv2) - packet->version = RIPv2; - - /* Is RIP running or is this RIP neighbor ?*/ - ri = ifp->info; - if (! ri->running && ! rip_neighbor_lookup (&from)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIP is not enabled on interface %s.", ifp->name); - rip_peer_bad_packet (&from); - return -1; - } - - /* RIP Version check. RFC2453, 4.6 and 5.1 */ - vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? - rip->version_recv : ri->ri_receive); - if (vrecv == RI_RIP_VERSION_NONE || - ((packet->version == RIPv1) && !(vrecv & RIPv1)) || - ((packet->version == RIPv2) && !(vrecv & RIPv2))) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug (" packet's v%d doesn't fit to if version spec", - packet->version); - rip_peer_bad_packet (&from); - return -1; - } - - /* RFC2453 5.2 If the router is not configured to authenticate RIP-2 - messages, then RIP-1 and unauthenticated RIP-2 messages will be - accepted; authenticated RIP-2 messages shall be discarded. */ - if ((ri->auth_type == RIP_NO_AUTH) - && rtenum - && (packet->version == RIPv2) - && (packet->rte->family == htons(RIP_FAMILY_AUTH))) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("packet RIPv%d is dropped because authentication disabled", - packet->version); - rip_peer_bad_packet (&from); - return -1; - } - - /* RFC: - If the router is configured to authenticate RIP-2 messages, then - RIP-1 messages and RIP-2 messages which pass authentication - testing shall be accepted; unauthenticated and failed - authentication RIP-2 messages shall be discarded. For maximum - security, RIP-1 messages should be ignored when authentication is - in use (see section 4.1); otherwise, the routing information from - authenticated messages will be propagated by RIP-1 routers in an - unauthenticated manner. - */ - /* We make an exception for RIPv1 REQUEST packets, to which we'll - * always reply regardless of authentication settings, because: - * - * - if there other authorised routers on-link, the REQUESTor can - * passively obtain the routing updates anyway - * - if there are no other authorised routers on-link, RIP can - * easily be disabled for the link to prevent giving out information - * on state of this routers RIP routing table.. - * - * I.e. if RIPv1 has any place anymore these days, it's as a very - * simple way to distribute routing information (e.g. to embedded - * hosts / appliances) and the ability to give out RIPv1 - * routing-information freely, while still requiring RIPv2 - * authentication for any RESPONSEs might be vaguely useful. - */ - if (ri->auth_type != RIP_NO_AUTH - && packet->version == RIPv1) - { - /* Discard RIPv1 messages other than REQUESTs */ - if (packet->command != RIP_REQUEST) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv1" " dropped because authentication enabled"); - rip_peer_bad_packet (&from); - return -1; - } - } - else if (ri->auth_type != RIP_NO_AUTH) - { - const char *auth_desc; - - if (rtenum == 0) - { - /* There definitely is no authentication in the packet. */ - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 authentication failed: no auth RTE in packet"); - rip_peer_bad_packet (&from); - return -1; - } - - /* First RTE must be an Authentication Family RTE */ - if (packet->rte->family != htons(RIP_FAMILY_AUTH)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2" " dropped because authentication enabled"); - rip_peer_bad_packet (&from); - return -1; - } - - /* Check RIPv2 authentication. */ - switch (ntohs(packet->rte->tag)) - { - case RIP_AUTH_SIMPLE_PASSWORD: - auth_desc = "simple"; - ret = rip_auth_simple_password (packet->rte, &from, ifp); - break; - - case RIP_AUTH_MD5: - auth_desc = "MD5"; - ret = rip_auth_md5 (packet, &from, len, ifp); - /* Reset RIP packet length to trim MD5 data. */ - len = ret; - break; - - default: - ret = 0; - auth_desc = "unknown type"; - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 Unknown authentication type %d", - ntohs (packet->rte->tag)); - } - - if (ret) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 %s authentication success", auth_desc); - } - else - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIPv2 %s authentication failure", auth_desc); - rip_peer_bad_packet (&from); - return -1; - } - } - - /* Process each command. */ - switch (packet->command) - { - case RIP_RESPONSE: - rip_response_process (packet, len, &from, ifc); - break; - case RIP_REQUEST: - case RIP_POLL: - rip_request_process (packet, len, &from, ifc); - break; - case RIP_TRACEON: - case RIP_TRACEOFF: - zlog_info ("Obsolete command %s received, please sent it to routed", - lookup_msg (rip_msg, packet->command, NULL)); - rip_peer_bad_packet (&from); - break; - case RIP_POLL_ENTRY: - zlog_info ("Obsolete command %s received", - lookup_msg (rip_msg, packet->command, NULL)); - rip_peer_bad_packet (&from); - break; - default: - zlog_info ("Unknown RIP command %d received", packet->command); - rip_peer_bad_packet (&from); - break; - } - - return len; +static int rip_read(struct thread *t) +{ + int sock; + int ret; + int rtenum; + union rip_buf rip_buf; + struct rip_packet *packet; + struct sockaddr_in from; + int len; + int vrecv; + socklen_t fromlen; + struct interface *ifp = NULL; + struct connected *ifc; + struct rip_interface *ri; + struct prefix p; + + /* Fetch socket then register myself. */ + sock = THREAD_FD(t); + rip->t_read = NULL; + + /* Add myself to tne next event */ + rip_event(RIP_READ, sock); + + /* RIPd manages only IPv4. */ + memset(&from, 0, sizeof(struct sockaddr_in)); + fromlen = sizeof(struct sockaddr_in); + + len = recvfrom(sock, (char *)&rip_buf.buf, sizeof(rip_buf.buf), 0, + (struct sockaddr *)&from, &fromlen); + if (len < 0) { + zlog_info("recvfrom failed: %s", safe_strerror(errno)); + return len; + } + + /* Check is this packet comming from myself? */ + if (if_check_address(from.sin_addr)) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("ignore packet comes from myself"); + return -1; + } + + /* Which interface is this packet comes from. */ + ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, VRF_DEFAULT); + if (ifc) + ifp = ifc->ifp; + + /* RIP packet received */ + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RECV packet from %s port %d on %s", + inet_ntoa(from.sin_addr), ntohs(from.sin_port), + ifp ? ifp->name : "unknown"); + + /* If this packet come from unknown interface, ignore it. */ + if (ifp == NULL) { + zlog_info( + "rip_read: cannot find interface for packet from %s port %d", + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); + return -1; + } + + p.family = AF_INET; + p.u.prefix4 = from.sin_addr; + p.prefixlen = IPV4_MAX_BITLEN; + + ifc = connected_lookup_prefix(ifp, &p); + + if (ifc == NULL) { + zlog_info( + "rip_read: cannot find connected address for packet from %s " + "port %d on interface %s", + inet_ntoa(from.sin_addr), ntohs(from.sin_port), + ifp->name); + return -1; + } + + /* Packet length check. */ + if (len < RIP_PACKET_MINSIZ) { + zlog_warn("packet size %d is smaller than minimum size %d", len, + RIP_PACKET_MINSIZ); + rip_peer_bad_packet(&from); + return len; + } + if (len > RIP_PACKET_MAXSIZ) { + zlog_warn("packet size %d is larger than max size %d", len, + RIP_PACKET_MAXSIZ); + rip_peer_bad_packet(&from); + return len; + } + + /* Packet alignment check. */ + if ((len - RIP_PACKET_MINSIZ) % 20) { + zlog_warn("packet size %d is wrong for RIP packet alignment", + len); + rip_peer_bad_packet(&from); + return len; + } + + /* Set RTE number. */ + rtenum = ((len - RIP_PACKET_MINSIZ) / 20); + + /* For easy to handle. */ + packet = &rip_buf.rip_packet; + + /* RIP version check. */ + if (packet->version == 0) { + zlog_info("version 0 with command %d received.", + packet->command); + rip_peer_bad_packet(&from); + return -1; + } + + /* Dump RIP packet. */ + if (IS_RIP_DEBUG_RECV) + rip_packet_dump(packet, len, "RECV"); + + /* RIP version adjust. This code should rethink now. RFC1058 says + that "Version 1 implementations are to ignore this extra data and + process only the fields specified in this document.". So RIPv3 + packet should be treated as RIPv1 ignoring must be zero field. */ + if (packet->version > RIPv2) + packet->version = RIPv2; + + /* Is RIP running or is this RIP neighbor ?*/ + ri = ifp->info; + if (!ri->running && !rip_neighbor_lookup(&from)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("RIP is not enabled on interface %s.", + ifp->name); + rip_peer_bad_packet(&from); + return -1; + } + + /* RIP Version check. RFC2453, 4.6 and 5.1 */ + vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv + : ri->ri_receive); + if (vrecv == RI_RIP_VERSION_NONE + || ((packet->version == RIPv1) && !(vrecv & RIPv1)) + || ((packet->version == RIPv2) && !(vrecv & RIPv2))) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + " packet's v%d doesn't fit to if version spec", + packet->version); + rip_peer_bad_packet(&from); + return -1; + } + + /* RFC2453 5.2 If the router is not configured to authenticate RIP-2 + messages, then RIP-1 and unauthenticated RIP-2 messages will be + accepted; authenticated RIP-2 messages shall be discarded. */ + if ((ri->auth_type == RIP_NO_AUTH) && rtenum + && (packet->version == RIPv2) + && (packet->rte->family == htons(RIP_FAMILY_AUTH))) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug( + "packet RIPv%d is dropped because authentication disabled", + packet->version); + rip_peer_bad_packet(&from); + return -1; + } + + /* RFC: + If the router is configured to authenticate RIP-2 messages, then + RIP-1 messages and RIP-2 messages which pass authentication + testing shall be accepted; unauthenticated and failed + authentication RIP-2 messages shall be discarded. For maximum + security, RIP-1 messages should be ignored when authentication is + in use (see section 4.1); otherwise, the routing information from + authenticated messages will be propagated by RIP-1 routers in an + unauthenticated manner. + */ + /* We make an exception for RIPv1 REQUEST packets, to which we'll + * always reply regardless of authentication settings, because: + * + * - if there other authorised routers on-link, the REQUESTor can + * passively obtain the routing updates anyway + * - if there are no other authorised routers on-link, RIP can + * easily be disabled for the link to prevent giving out information + * on state of this routers RIP routing table.. + * + * I.e. if RIPv1 has any place anymore these days, it's as a very + * simple way to distribute routing information (e.g. to embedded + * hosts / appliances) and the ability to give out RIPv1 + * routing-information freely, while still requiring RIPv2 + * authentication for any RESPONSEs might be vaguely useful. + */ + if (ri->auth_type != RIP_NO_AUTH && packet->version == RIPv1) { + /* Discard RIPv1 messages other than REQUESTs */ + if (packet->command != RIP_REQUEST) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv1" + " dropped because authentication enabled"); + rip_peer_bad_packet(&from); + return -1; + } + } else if (ri->auth_type != RIP_NO_AUTH) { + const char *auth_desc; + + if (rtenum == 0) { + /* There definitely is no authentication in the packet. + */ + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv2 authentication failed: no auth RTE in packet"); + rip_peer_bad_packet(&from); + return -1; + } + + /* First RTE must be an Authentication Family RTE */ + if (packet->rte->family != htons(RIP_FAMILY_AUTH)) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv2" + " dropped because authentication enabled"); + rip_peer_bad_packet(&from); + return -1; + } + + /* Check RIPv2 authentication. */ + switch (ntohs(packet->rte->tag)) { + case RIP_AUTH_SIMPLE_PASSWORD: + auth_desc = "simple"; + ret = rip_auth_simple_password(packet->rte, &from, ifp); + break; + + case RIP_AUTH_MD5: + auth_desc = "MD5"; + ret = rip_auth_md5(packet, &from, len, ifp); + /* Reset RIP packet length to trim MD5 data. */ + len = ret; + break; + + default: + ret = 0; + auth_desc = "unknown type"; + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv2 Unknown authentication type %d", + ntohs(packet->rte->tag)); + } + + if (ret) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("RIPv2 %s authentication success", + auth_desc); + } else { + if (IS_RIP_DEBUG_PACKET) + zlog_debug("RIPv2 %s authentication failure", + auth_desc); + rip_peer_bad_packet(&from); + return -1; + } + } + + /* Process each command. */ + switch (packet->command) { + case RIP_RESPONSE: + rip_response_process(packet, len, &from, ifc); + break; + case RIP_REQUEST: + case RIP_POLL: + rip_request_process(packet, len, &from, ifc); + break; + case RIP_TRACEON: + case RIP_TRACEOFF: + zlog_info( + "Obsolete command %s received, please sent it to routed", + lookup_msg(rip_msg, packet->command, NULL)); + rip_peer_bad_packet(&from); + break; + case RIP_POLL_ENTRY: + zlog_info("Obsolete command %s received", + lookup_msg(rip_msg, packet->command, NULL)); + rip_peer_bad_packet(&from); + break; + default: + zlog_info("Unknown RIP command %d received", packet->command); + rip_peer_bad_packet(&from); + break; + } + + return len; } /* Write routing table entry to the stream and return next index of the routing table entry in the stream. */ -static int -rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p, - u_char version, struct rip_info *rinfo) -{ - struct in_addr mask; - - /* Write routing table entry. */ - if (version == RIPv1) - { - stream_putw (s, AF_INET); - stream_putw (s, 0); - stream_put_ipv4 (s, p->prefix.s_addr); - stream_put_ipv4 (s, 0); - stream_put_ipv4 (s, 0); - stream_putl (s, rinfo->metric_out); - } - else - { - masklen2ip (p->prefixlen, &mask); - - stream_putw (s, AF_INET); - stream_putw (s, rinfo->tag_out); - stream_put_ipv4 (s, p->prefix.s_addr); - stream_put_ipv4 (s, mask.s_addr); - stream_put_ipv4 (s, rinfo->nexthop_out.s_addr); - stream_putl (s, rinfo->metric_out); - } - - return ++num; +static int rip_write_rte(int num, struct stream *s, struct prefix_ipv4 *p, + u_char version, struct rip_info *rinfo) +{ + struct in_addr mask; + + /* Write routing table entry. */ + if (version == RIPv1) { + stream_putw(s, AF_INET); + stream_putw(s, 0); + stream_put_ipv4(s, p->prefix.s_addr); + stream_put_ipv4(s, 0); + stream_put_ipv4(s, 0); + stream_putl(s, rinfo->metric_out); + } else { + masklen2ip(p->prefixlen, &mask); + + stream_putw(s, AF_INET); + stream_putw(s, rinfo->tag_out); + stream_put_ipv4(s, p->prefix.s_addr); + stream_put_ipv4(s, mask.s_addr); + stream_put_ipv4(s, rinfo->nexthop_out.s_addr); + stream_putl(s, rinfo->metric_out); + } + + return ++num; } /* Send update to the ifp or spcified neighbor. */ -void -rip_output_process (struct connected *ifc, struct sockaddr_in *to, - int route_type, u_char version) -{ - int ret; - struct stream *s; - struct route_node *rp; - struct rip_info *rinfo; - struct rip_interface *ri; - struct prefix_ipv4 *p; - struct prefix_ipv4 classfull; - struct prefix_ipv4 ifaddrclass; - struct key *key = NULL; - /* this might need to made dynamic if RIP ever supported auth methods - with larger key string sizes */ - char auth_str[RIP_AUTH_SIMPLE_SIZE]; - size_t doff = 0; /* offset of digest offset field */ - int num = 0; - int rtemax; - int subnetted = 0; - struct list *list = NULL; - struct listnode *listnode = NULL; +void rip_output_process(struct connected *ifc, struct sockaddr_in *to, + int route_type, u_char version) +{ + int ret; + struct stream *s; + struct route_node *rp; + struct rip_info *rinfo; + struct rip_interface *ri; + struct prefix_ipv4 *p; + struct prefix_ipv4 classfull; + struct prefix_ipv4 ifaddrclass; + struct key *key = NULL; + /* this might need to made dynamic if RIP ever supported auth methods + with larger key string sizes */ + char auth_str[RIP_AUTH_SIMPLE_SIZE]; + size_t doff = 0; /* offset of digest offset field */ + int num = 0; + int rtemax; + int subnetted = 0; + struct list *list = NULL; + struct listnode *listnode = NULL; + + /* Logging output event. */ + if (IS_RIP_DEBUG_EVENT) { + if (to) + zlog_debug("update routes to neighbor %s", + inet_ntoa(to->sin_addr)); + else + zlog_debug("update routes on interface %s ifindex %d", + ifc->ifp->name, ifc->ifp->ifindex); + } - /* Logging output event. */ - if (IS_RIP_DEBUG_EVENT) - { - if (to) - zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr)); - else - zlog_debug ("update routes on interface %s ifindex %d", - ifc->ifp->name, ifc->ifp->ifindex); - } - - /* Set output stream. */ - s = rip->obuf; - - /* Reset stream and RTE counter. */ - stream_reset (s); - rtemax = RIP_MAX_RTE; - - /* Get RIP interface. */ - ri = ifc->ifp->info; - - /* If output interface is in simple password authentication mode, we - need space for authentication data. */ - if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) - rtemax -= 1; - - /* If output interface is in MD5 authentication mode, we need space - for authentication header and data. */ - if (ri->auth_type == RIP_AUTH_MD5) - rtemax -= 2; - - /* If output interface is in simple password authentication mode - and string or keychain is specified we need space for auth. data */ - if (ri->auth_type != RIP_NO_AUTH) - { - if (ri->key_chain) - { - struct keychain *keychain; - - keychain = keychain_lookup (ri->key_chain); - if (keychain) - key = key_lookup_for_send (keychain); - } - /* to be passed to auth functions later */ - rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE); - } - - if (version == RIPv1) - { - memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4)); - apply_classful_mask_ipv4 (&ifaddrclass); - subnetted = 0; - if (ifc->address->prefixlen > ifaddrclass.prefixlen) - subnetted = 1; - } - - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL && listcount (list) != 0) - { - rinfo = listgetdata (listhead (list)); - /* For RIPv1, if we are subnetted, output subnets in our network */ - /* that have the same mask as the output "interface". For other */ - /* networks, only the classfull version is output. */ - - if (version == RIPv1) - { - p = (struct prefix_ipv4 *) &rp->p; - - if (IS_RIP_DEBUG_PACKET) - zlog_debug("RIPv1 mask check, %s/%d considered for output", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen); - - if (subnetted && - prefix_match ((struct prefix *) &ifaddrclass, &rp->p)) - { - if ((ifc->address->prefixlen != rp->p.prefixlen) && - (rp->p.prefixlen != 32)) - continue; - } - else - { - memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4)); - apply_classful_mask_ipv4(&classfull); - if (rp->p.u.prefix4.s_addr != 0 && - classfull.prefixlen != rp->p.prefixlen) - continue; - } - if (IS_RIP_DEBUG_PACKET) - zlog_debug("RIPv1 mask check, %s/%d made it through", - inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen); - } - else - p = (struct prefix_ipv4 *) &rp->p; - - /* Apply output filters. */ - ret = rip_filter (RIP_FILTER_OUT, p, ri); - if (ret < 0) - continue; - - /* Changed route only output. */ - if (route_type == rip_changed_route && - (! (rinfo->flags & RIP_RTF_CHANGED))) - continue; - - /* Split horizon. */ - /* if (split_horizon == rip_split_horizon) */ - if (ri->split_horizon == RIP_SPLIT_HORIZON) - { - /* - * We perform split horizon for RIP and connected route. - * For rip routes, we want to suppress the route if we would - * end up sending the route back on the interface that we - * learned it from, with a higher metric. For connected routes, - * we suppress the route if the prefix is a subset of the - * source address that we are going to use for the packet - * (in order to handle the case when multiple subnets are - * configured on the same interface). - */ - int suppress = 0; - struct rip_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if (tmp_rinfo->type == ZEBRA_ROUTE_RIP && - tmp_rinfo->ifindex == ifc->ifp->ifindex) - { - suppress = 1; - break; - } - - if (!suppress && rinfo->type == ZEBRA_ROUTE_CONNECT && - prefix_match((struct prefix *)p, ifc->address)) - suppress = 1; - - if (suppress) - continue; - } - - /* Preparation for route-map. */ - rinfo->metric_set = 0; - rinfo->nexthop_out.s_addr = 0; - rinfo->metric_out = rinfo->metric; - rinfo->tag_out = rinfo->tag; - rinfo->ifindex_out = ifc->ifp->ifindex; - - /* In order to avoid some local loops, - * if the RIP route has a nexthop via this interface, keep the nexthop, - * otherwise set it to 0. The nexthop should not be propagated - * beyond the local broadcast/multicast area in order - * to avoid an IGP multi-level recursive look-up. - * see (4.4) - */ - if (rinfo->ifindex == ifc->ifp->ifindex) - rinfo->nexthop_out = rinfo->nexthop; - - /* Interface route-map */ - if (ri->routemap[RIP_FILTER_OUT]) - { - ret = route_map_apply (ri->routemap[RIP_FILTER_OUT], - (struct prefix *) p, RMAP_RIP, - rinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("RIP %s/%d is filtered by route-map out", - inet_ntoa (p->prefix), p->prefixlen); - continue; - } - } - - /* Apply redistribute route map - continue, if deny */ - if (rip->route_map[rinfo->type].name - && rinfo->sub_type != RIP_ROUTE_INTERFACE) - { - ret = route_map_apply (rip->route_map[rinfo->type].map, - (struct prefix *)p, RMAP_RIP, rinfo); - - if (ret == RMAP_DENYMATCH) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug ("%s/%d is filtered by route-map", - inet_ntoa (p->prefix), p->prefixlen); - continue; - } - } - - /* When route-map does not set metric. */ - if (! rinfo->metric_set) - { - /* If redistribute metric is set. */ - if (rip->route_map[rinfo->type].metric_config - && rinfo->metric != RIP_METRIC_INFINITY) - { - rinfo->metric_out = rip->route_map[rinfo->type].metric; - } - else - { - /* If the route is not connected or localy generated - one, use default-metric value*/ - if (rinfo->type != ZEBRA_ROUTE_RIP - && rinfo->type != ZEBRA_ROUTE_CONNECT - && rinfo->metric != RIP_METRIC_INFINITY) - rinfo->metric_out = rip->default_metric; - } - } - - /* Apply offset-list */ - if (rinfo->metric != RIP_METRIC_INFINITY) - rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out); - - if (rinfo->metric_out > RIP_METRIC_INFINITY) - rinfo->metric_out = RIP_METRIC_INFINITY; - - /* Perform split-horizon with poisoned reverse - * for RIP and connected routes. - **/ - if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) { - /* - * We perform split horizon for RIP and connected route. - * For rip routes, we want to suppress the route if we would - * end up sending the route back on the interface that we - * learned it from, with a higher metric. For connected routes, - * we suppress the route if the prefix is a subset of the - * source address that we are going to use for the packet - * (in order to handle the case when multiple subnets are - * configured on the same interface). - */ - struct rip_info *tmp_rinfo = NULL; - - for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo)) - if (tmp_rinfo->type == ZEBRA_ROUTE_RIP && - tmp_rinfo->ifindex == ifc->ifp->ifindex) - rinfo->metric_out = RIP_METRIC_INFINITY; - if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT && - prefix_match((struct prefix *)p, ifc->address)) - rinfo->metric_out = RIP_METRIC_INFINITY; - } - - /* Prepare preamble, auth headers, if needs be */ - if (num == 0) - { - stream_putc (s, RIP_RESPONSE); - stream_putc (s, version); - stream_putw (s, 0); - - /* auth header for !v1 && !no_auth */ - if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) ) - doff = rip_auth_header_write (s, ri, key, auth_str, - RIP_AUTH_SIMPLE_SIZE); - } - - /* Write RTE to the stream. */ - num = rip_write_rte (num, s, p, version, rinfo); - if (num == rtemax) - { - if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) - rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE); - - ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), - to, ifc); - - if (ret >= 0 && IS_RIP_DEBUG_SEND) - rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), - stream_get_endp(s), "SEND"); - num = 0; - stream_reset (s); - } - } - - /* Flush unwritten RTE. */ - if (num != 0) - { - if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) - rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE); - - ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc); - - if (ret >= 0 && IS_RIP_DEBUG_SEND) - rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), - stream_get_endp (s), "SEND"); - stream_reset (s); - } - - /* Statistics updates. */ - ri->sent_updates++; + /* Set output stream. */ + s = rip->obuf; + + /* Reset stream and RTE counter. */ + stream_reset(s); + rtemax = RIP_MAX_RTE; + + /* Get RIP interface. */ + ri = ifc->ifp->info; + + /* If output interface is in simple password authentication mode, we + need space for authentication data. */ + if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD) + rtemax -= 1; + + /* If output interface is in MD5 authentication mode, we need space + for authentication header and data. */ + if (ri->auth_type == RIP_AUTH_MD5) + rtemax -= 2; + + /* If output interface is in simple password authentication mode + and string or keychain is specified we need space for auth. data */ + if (ri->auth_type != RIP_NO_AUTH) { + if (ri->key_chain) { + struct keychain *keychain; + + keychain = keychain_lookup(ri->key_chain); + if (keychain) + key = key_lookup_for_send(keychain); + } + /* to be passed to auth functions later */ + rip_auth_prepare_str_send(ri, key, auth_str, + RIP_AUTH_SIMPLE_SIZE); + } + + if (version == RIPv1) { + memcpy(&ifaddrclass, ifc->address, sizeof(struct prefix_ipv4)); + apply_classful_mask_ipv4(&ifaddrclass); + subnetted = 0; + if (ifc->address->prefixlen > ifaddrclass.prefixlen) + subnetted = 1; + } + + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL && listcount(list) != 0) { + rinfo = listgetdata(listhead(list)); + /* For RIPv1, if we are subnetted, output subnets in our + * network */ + /* that have the same mask as the output "interface". + * For other */ + /* networks, only the classfull version is output. */ + + if (version == RIPv1) { + p = (struct prefix_ipv4 *)&rp->p; + + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv1 mask check, %s/%d considered for output", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen); + + if (subnetted + && prefix_match( + (struct prefix *)&ifaddrclass, + &rp->p)) { + if ((ifc->address->prefixlen + != rp->p.prefixlen) + && (rp->p.prefixlen != 32)) + continue; + } else { + memcpy(&classfull, &rp->p, + sizeof(struct prefix_ipv4)); + apply_classful_mask_ipv4(&classfull); + if (rp->p.u.prefix4.s_addr != 0 + && classfull.prefixlen + != rp->p.prefixlen) + continue; + } + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIPv1 mask check, %s/%d made it through", + inet_ntoa(rp->p.u.prefix4), + rp->p.prefixlen); + } else + p = (struct prefix_ipv4 *)&rp->p; + + /* Apply output filters. */ + ret = rip_filter(RIP_FILTER_OUT, p, ri); + if (ret < 0) + continue; + + /* Changed route only output. */ + if (route_type == rip_changed_route + && (!(rinfo->flags & RIP_RTF_CHANGED))) + continue; + + /* Split horizon. */ + /* if (split_horizon == rip_split_horizon) */ + if (ri->split_horizon == RIP_SPLIT_HORIZON) { + /* + * We perform split horizon for RIP and + * connected route. + * For rip routes, we want to suppress the route + * if we would + * end up sending the route back on the + * interface that we + * learned it from, with a higher metric. For + * connected routes, + * we suppress the route if the prefix is a + * subset of the + * source address that we are going to use for + * the packet + * (in order to handle the case when multiple + * subnets are + * configured on the same interface). + */ + int suppress = 0; + struct rip_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if (tmp_rinfo->type == ZEBRA_ROUTE_RIP + && tmp_rinfo->ifindex + == ifc->ifp->ifindex) { + suppress = 1; + break; + } + + if (!suppress + && rinfo->type == ZEBRA_ROUTE_CONNECT + && prefix_match((struct prefix *)p, + ifc->address)) + suppress = 1; + + if (suppress) + continue; + } + + /* Preparation for route-map. */ + rinfo->metric_set = 0; + rinfo->nexthop_out.s_addr = 0; + rinfo->metric_out = rinfo->metric; + rinfo->tag_out = rinfo->tag; + rinfo->ifindex_out = ifc->ifp->ifindex; + + /* In order to avoid some local loops, + * if the RIP route has a nexthop via this interface, + * keep the nexthop, + * otherwise set it to 0. The nexthop should not be + * propagated + * beyond the local broadcast/multicast area in order + * to avoid an IGP multi-level recursive look-up. + * see (4.4) + */ + if (rinfo->ifindex == ifc->ifp->ifindex) + rinfo->nexthop_out = rinfo->nexthop; + + /* Interface route-map */ + if (ri->routemap[RIP_FILTER_OUT]) { + ret = route_map_apply( + ri->routemap[RIP_FILTER_OUT], + (struct prefix *)p, RMAP_RIP, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "RIP %s/%d is filtered by route-map out", + inet_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* Apply redistribute route map - continue, if deny */ + if (rip->route_map[rinfo->type].name + && rinfo->sub_type != RIP_ROUTE_INTERFACE) { + ret = route_map_apply( + rip->route_map[rinfo->type].map, + (struct prefix *)p, RMAP_RIP, rinfo); + + if (ret == RMAP_DENYMATCH) { + if (IS_RIP_DEBUG_PACKET) + zlog_debug( + "%s/%d is filtered by route-map", + inet_ntoa(p->prefix), + p->prefixlen); + continue; + } + } + + /* When route-map does not set metric. */ + if (!rinfo->metric_set) { + /* If redistribute metric is set. */ + if (rip->route_map[rinfo->type].metric_config + && rinfo->metric != RIP_METRIC_INFINITY) { + rinfo->metric_out = + rip->route_map[rinfo->type] + .metric; + } else { + /* If the route is not connected or + localy generated + one, use default-metric value*/ + if (rinfo->type != ZEBRA_ROUTE_RIP + && rinfo->type + != ZEBRA_ROUTE_CONNECT + && rinfo->metric + != RIP_METRIC_INFINITY) + rinfo->metric_out = + rip->default_metric; + } + } + + /* Apply offset-list */ + if (rinfo->metric != RIP_METRIC_INFINITY) + rip_offset_list_apply_out(p, ifc->ifp, + &rinfo->metric_out); + + if (rinfo->metric_out > RIP_METRIC_INFINITY) + rinfo->metric_out = RIP_METRIC_INFINITY; + + /* Perform split-horizon with poisoned reverse + * for RIP and connected routes. + **/ + if (ri->split_horizon + == RIP_SPLIT_HORIZON_POISONED_REVERSE) { + /* + * We perform split horizon for RIP and + * connected route. + * For rip routes, we want to suppress the route + * if we would + * end up sending the route back on the + * interface that we + * learned it from, with a higher metric. For + * connected routes, + * we suppress the route if the prefix is a + * subset of the + * source address that we are going to use for + * the packet + * (in order to handle the case when multiple + * subnets are + * configured on the same interface). + */ + struct rip_info *tmp_rinfo = NULL; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + tmp_rinfo)) + if (tmp_rinfo->type == ZEBRA_ROUTE_RIP + && tmp_rinfo->ifindex + == ifc->ifp->ifindex) + rinfo->metric_out = + RIP_METRIC_INFINITY; + if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT + && prefix_match((struct prefix *)p, + ifc->address)) + rinfo->metric_out = RIP_METRIC_INFINITY; + } + + /* Prepare preamble, auth headers, if needs be */ + if (num == 0) { + stream_putc(s, RIP_RESPONSE); + stream_putc(s, version); + stream_putw(s, 0); + + /* auth header for !v1 && !no_auth */ + if ((ri->auth_type != RIP_NO_AUTH) + && (version != RIPv1)) + doff = rip_auth_header_write( + s, ri, key, auth_str, + RIP_AUTH_SIMPLE_SIZE); + } + + /* Write RTE to the stream. */ + num = rip_write_rte(num, s, p, version, rinfo); + if (num == rtemax) { + if (version == RIPv2 + && ri->auth_type == RIP_AUTH_MD5) + rip_auth_md5_set(s, ri, doff, auth_str, + RIP_AUTH_SIMPLE_SIZE); + + ret = rip_send_packet(STREAM_DATA(s), + stream_get_endp(s), to, + ifc); + + if (ret >= 0 && IS_RIP_DEBUG_SEND) + rip_packet_dump((struct rip_packet *) + STREAM_DATA(s), + stream_get_endp(s), + "SEND"); + num = 0; + stream_reset(s); + } + } + + /* Flush unwritten RTE. */ + if (num != 0) { + if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) + rip_auth_md5_set(s, ri, doff, auth_str, + RIP_AUTH_SIMPLE_SIZE); + + ret = rip_send_packet(STREAM_DATA(s), stream_get_endp(s), to, + ifc); + + if (ret >= 0 && IS_RIP_DEBUG_SEND) + rip_packet_dump((struct rip_packet *)STREAM_DATA(s), + stream_get_endp(s), "SEND"); + stream_reset(s); + } + + /* Statistics updates. */ + ri->sent_updates++; } /* Send RIP packet to the interface. */ -static void -rip_update_interface (struct connected *ifc, u_char version, int route_type) -{ - struct interface *ifp = ifc->ifp; - struct rip_interface *ri = ifp->info; - struct sockaddr_in to; - - /* When RIP version is 2 and multicast enable interface. */ - if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast (ifp)) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("multicast announce on %s ", ifp->name); - - rip_output_process (ifc, NULL, route_type, version); - return; - } - - /* If we can't send multicast packet, send it with unicast. */ - if (if_is_broadcast (ifp) || if_is_pointopoint (ifp)) - { - if (ifc->address->family == AF_INET) - { - /* Destination address and port setting. */ - memset (&to, 0, sizeof (struct sockaddr_in)); - if (ifc->destination) - /* use specified broadcast or peer destination addr */ - to.sin_addr = ifc->destination->u.prefix4; - else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN) - /* calculate the appropriate broadcast address */ - to.sin_addr.s_addr = - ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr, - ifc->address->prefixlen); - else - /* do not know where to send the packet */ - return; - to.sin_port = htons (RIP_PORT_DEFAULT); - - if (IS_RIP_DEBUG_EVENT) - zlog_debug("%s announce to %s on %s", - CONNECTED_PEER(ifc) ? "unicast" : "broadcast", - inet_ntoa (to.sin_addr), ifp->name); - - rip_output_process (ifc, &to, route_type, version); - } - } +static void rip_update_interface(struct connected *ifc, u_char version, + int route_type) +{ + struct interface *ifp = ifc->ifp; + struct rip_interface *ri = ifp->info; + struct sockaddr_in to; + + /* When RIP version is 2 and multicast enable interface. */ + if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast(ifp)) { + if (IS_RIP_DEBUG_EVENT) + zlog_debug("multicast announce on %s ", ifp->name); + + rip_output_process(ifc, NULL, route_type, version); + return; + } + + /* If we can't send multicast packet, send it with unicast. */ + if (if_is_broadcast(ifp) || if_is_pointopoint(ifp)) { + if (ifc->address->family == AF_INET) { + /* Destination address and port setting. */ + memset(&to, 0, sizeof(struct sockaddr_in)); + if (ifc->destination) + /* use specified broadcast or peer destination + * addr */ + to.sin_addr = ifc->destination->u.prefix4; + else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN) + /* calculate the appropriate broadcast address + */ + to.sin_addr.s_addr = ipv4_broadcast_addr( + ifc->address->u.prefix4.s_addr, + ifc->address->prefixlen); + else + /* do not know where to send the packet */ + return; + to.sin_port = htons(RIP_PORT_DEFAULT); + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("%s announce to %s on %s", + CONNECTED_PEER(ifc) ? "unicast" + : "broadcast", + inet_ntoa(to.sin_addr), ifp->name); + + rip_output_process(ifc, &to, route_type, version); + } + } } /* Update send to all interface and neighbor. */ -static void -rip_update_process (int route_type) -{ - struct listnode *node; - struct listnode *ifnode, *ifnnode; - struct connected *connected; - struct interface *ifp; - struct rip_interface *ri; - struct route_node *rp; - struct sockaddr_in to; - struct prefix *p; - - /* Send RIP update to each interface. */ - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - if (if_is_loopback (ifp)) - continue; - - if (! if_is_operative (ifp)) - continue; - - /* Fetch RIP interface information. */ - ri = ifp->info; - - /* When passive interface is specified, suppress announce to the - interface. */ - if (ri->passive) - continue; - - if (ri->running) - { - /* - * If there is no version configuration in the interface, - * use rip's version setting. - */ - int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? - rip->version_send : ri->ri_send); - - if (IS_RIP_DEBUG_EVENT) - zlog_debug("SEND UPDATE to %s ifindex %d", - ifp->name, ifp->ifindex); - - /* send update on each connected network */ - for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected)) - { - if (connected->address->family == AF_INET) - { - if (vsend & RIPv1) - rip_update_interface (connected, RIPv1, route_type); - if ((vsend & RIPv2) && if_is_multicast(ifp)) - rip_update_interface (connected, RIPv2, route_type); +static void rip_update_process(int route_type) +{ + struct listnode *node; + struct listnode *ifnode, *ifnnode; + struct connected *connected; + struct interface *ifp; + struct rip_interface *ri; + struct route_node *rp; + struct sockaddr_in to; + struct prefix *p; + + /* Send RIP update to each interface. */ + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + if (if_is_loopback(ifp)) + continue; + + if (!if_is_operative(ifp)) + continue; + + /* Fetch RIP interface information. */ + ri = ifp->info; + + /* When passive interface is specified, suppress announce to the + interface. */ + if (ri->passive) + continue; + + if (ri->running) { + /* + * If there is no version configuration in the + * interface, + * use rip's version setting. + */ + int vsend = ((ri->ri_send == RI_RIP_UNSPEC) + ? rip->version_send + : ri->ri_send); + + if (IS_RIP_DEBUG_EVENT) + zlog_debug("SEND UPDATE to %s ifindex %d", + ifp->name, ifp->ifindex); + + /* send update on each connected network */ + for (ALL_LIST_ELEMENTS(ifp->connected, ifnode, ifnnode, + connected)) { + if (connected->address->family == AF_INET) { + if (vsend & RIPv1) + rip_update_interface( + connected, RIPv1, + route_type); + if ((vsend & RIPv2) + && if_is_multicast(ifp)) + rip_update_interface( + connected, RIPv2, + route_type); + } + } + } + } + + /* RIP send updates to each neighbor. */ + for (rp = route_top(rip->neighbor); rp; rp = route_next(rp)) + if (rp->info != NULL) { + p = &rp->p; + + connected = if_lookup_address(&p->u.prefix4, AF_INET, + VRF_DEFAULT); + if (!connected) { + zlog_warn( + "Neighbor %s doesnt have connected interface!", + inet_ntoa(p->u.prefix4)); + continue; + } + + /* Set destination address and port */ + memset(&to, 0, sizeof(struct sockaddr_in)); + to.sin_addr = p->u.prefix4; + to.sin_port = htons(RIP_PORT_DEFAULT); + + /* RIP version is rip's configuration. */ + rip_output_process(connected, &to, route_type, + rip->version_send); } - } - } - } - - /* RIP send updates to each neighbor. */ - for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) - if (rp->info != NULL) - { - p = &rp->p; - - connected = if_lookup_address (&p->u.prefix4, AF_INET, VRF_DEFAULT); - if (! connected) - { - zlog_warn ("Neighbor %s doesnt have connected interface!", - inet_ntoa (p->u.prefix4)); - continue; - } - - /* Set destination address and port */ - memset (&to, 0, sizeof (struct sockaddr_in)); - to.sin_addr = p->u.prefix4; - to.sin_port = htons (RIP_PORT_DEFAULT); - - /* RIP version is rip's configuration. */ - rip_output_process (connected, &to, route_type, rip->version_send); - } } /* RIP's periodical timer. */ -static int -rip_update (struct thread *t) +static int rip_update(struct thread *t) { - /* Clear timer pointer. */ - rip->t_update = NULL; + /* Clear timer pointer. */ + rip->t_update = NULL; - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("update timer fire!"); + if (IS_RIP_DEBUG_EVENT) + zlog_debug("update timer fire!"); - /* Process update output. */ - rip_update_process (rip_all_route); + /* Process update output. */ + rip_update_process(rip_all_route); - /* Triggered updates may be suppressed if a regular update is due by - the time the triggered update would be sent. */ - RIP_TIMER_OFF (rip->t_triggered_interval); - rip->trigger = 0; + /* Triggered updates may be suppressed if a regular update is due by + the time the triggered update would be sent. */ + RIP_TIMER_OFF(rip->t_triggered_interval); + rip->trigger = 0; - /* Register myself. */ - rip_event (RIP_UPDATE_EVENT, 0); + /* Register myself. */ + rip_event(RIP_UPDATE_EVENT, 0); - return 0; + return 0; } /* Walk down the RIP routing table then clear changed flag. */ -static void -rip_clear_changed_flag (void) +static void rip_clear_changed_flag(void) { - struct route_node *rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; + struct route_node *rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - UNSET_FLAG (rinfo->flags, RIP_RTF_CHANGED); - /* This flag can be set only on the first entry. */ - break; - } + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + UNSET_FLAG(rinfo->flags, RIP_RTF_CHANGED); + /* This flag can be set only on the first entry. + */ + break; + } } /* Triggered update interval timer. */ -static int -rip_triggered_interval (struct thread *t) +static int rip_triggered_interval(struct thread *t) { - int rip_triggered_update (struct thread *); + int rip_triggered_update(struct thread *); - rip->t_triggered_interval = NULL; + rip->t_triggered_interval = NULL; - if (rip->trigger) - { - rip->trigger = 0; - rip_triggered_update (t); - } - return 0; -} + if (rip->trigger) { + rip->trigger = 0; + rip_triggered_update(t); + } + return 0; +} /* Execute triggered update. */ -static int -rip_triggered_update (struct thread *t) +static int rip_triggered_update(struct thread *t) { - int interval; + int interval; - /* Clear thred pointer. */ - rip->t_triggered_update = NULL; + /* Clear thred pointer. */ + rip->t_triggered_update = NULL; - /* Cancel interval timer. */ - RIP_TIMER_OFF (rip->t_triggered_interval); - rip->trigger = 0; + /* Cancel interval timer. */ + RIP_TIMER_OFF(rip->t_triggered_interval); + rip->trigger = 0; - /* Logging triggered update. */ - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("triggered update!"); + /* Logging triggered update. */ + if (IS_RIP_DEBUG_EVENT) + zlog_debug("triggered update!"); - /* Split Horizon processing is done when generating triggered - updates as well as normal updates (see section 2.6). */ - rip_update_process (rip_changed_route); + /* Split Horizon processing is done when generating triggered + updates as well as normal updates (see section 2.6). */ + rip_update_process(rip_changed_route); - /* Once all of the triggered updates have been generated, the route - change flags should be cleared. */ - rip_clear_changed_flag (); + /* Once all of the triggered updates have been generated, the route + change flags should be cleared. */ + rip_clear_changed_flag(); - /* After a triggered update is sent, a timer should be set for a - random interval between 1 and 5 seconds. If other changes that - would trigger updates occur before the timer expires, a single - update is triggered when the timer expires. */ - interval = (random () % 5) + 1; + /* After a triggered update is sent, a timer should be set for a + random interval between 1 and 5 seconds. If other changes that + would trigger updates occur before the timer expires, a single + update is triggered when the timer expires. */ + interval = (random() % 5) + 1; - rip->t_triggered_interval = NULL; - thread_add_timer(master, rip_triggered_interval, NULL, interval, - &rip->t_triggered_interval); + rip->t_triggered_interval = NULL; + thread_add_timer(master, rip_triggered_interval, NULL, interval, + &rip->t_triggered_interval); - return 0; + return 0; } /* Withdraw redistributed route. */ -void -rip_redistribute_withdraw (int type) +void rip_redistribute_withdraw(int type) +{ + struct route_node *rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + + if (!rip) + return; + + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if (rinfo->type == type + && rinfo->sub_type != RIP_ROUTE_INTERFACE) { + /* Perform poisoned reverse. */ + rinfo->metric = RIP_METRIC_INFINITY; + RIP_TIMER_ON(rinfo->t_garbage_collect, + rip_garbage_collect, + rip->garbage_time); + RIP_TIMER_OFF(rinfo->t_timeout); + rinfo->flags |= RIP_RTF_CHANGED; + + if (IS_RIP_DEBUG_EVENT) { + struct prefix_ipv4 *p = + (struct prefix_ipv4 *)&rp->p; + + zlog_debug( + "Poisone %s/%d on the interface %s with an infinity metric [withdraw]", + inet_ntoa(p->prefix), + p->prefixlen, + ifindex2ifname(rinfo->ifindex, + VRF_DEFAULT)); + } + + rip_event(RIP_TRIGGERED_UPDATE, 0); + } + } +} + +/* Create new RIP instance and set it to global variable. */ +static int rip_create(void) { - struct route_node *rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; + rip = XCALLOC(MTYPE_RIP, sizeof(struct rip)); - if (!rip) - return; + /* Set initial value. */ + rip->version_send = RI_RIP_VERSION_2; + rip->version_recv = RI_RIP_VERSION_1_AND_2; + rip->update_time = RIP_UPDATE_TIMER_DEFAULT; + rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; + rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; + rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if (rinfo->type == type - && rinfo->sub_type != RIP_ROUTE_INTERFACE) - { - /* Perform poisoned reverse. */ - rinfo->metric = RIP_METRIC_INFINITY; - RIP_TIMER_ON (rinfo->t_garbage_collect, - rip_garbage_collect, rip->garbage_time); - RIP_TIMER_OFF (rinfo->t_timeout); - rinfo->flags |= RIP_RTF_CHANGED; + /* Initialize RIP routig table. */ + rip->table = route_table_init(); + rip->route = route_table_init(); + rip->neighbor = route_table_init(); - if (IS_RIP_DEBUG_EVENT) { - struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p; + /* Make output stream. */ + rip->obuf = stream_new(1500); - zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); - } + /* Make socket. */ + rip->sock = rip_create_socket(); + if (rip->sock < 0) + return rip->sock; - rip_event (RIP_TRIGGERED_UPDATE, 0); - } - } -} + /* Create read and timer thread. */ + rip_event(RIP_READ, rip->sock); + rip_event(RIP_UPDATE_EVENT, 1); -/* Create new RIP instance and set it to global variable. */ -static int -rip_create (void) -{ - rip = XCALLOC (MTYPE_RIP, sizeof (struct rip)); + QOBJ_REG(rip, rip); - /* Set initial value. */ - rip->version_send = RI_RIP_VERSION_2; - rip->version_recv = RI_RIP_VERSION_1_AND_2; - rip->update_time = RIP_UPDATE_TIMER_DEFAULT; - rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; - rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; - rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; - - /* Initialize RIP routig table. */ - rip->table = route_table_init (); - rip->route = route_table_init (); - rip->neighbor = route_table_init (); + return 0; +} - /* Make output stream. */ - rip->obuf = stream_new (1500); +/* Sned RIP request to the destination. */ +int rip_request_send(struct sockaddr_in *to, struct interface *ifp, + u_char version, struct connected *connected) +{ + struct rte *rte; + struct rip_packet rip_packet; + struct listnode *node, *nnode; + + memset(&rip_packet, 0, sizeof(rip_packet)); + + rip_packet.command = RIP_REQUEST; + rip_packet.version = version; + rte = rip_packet.rte; + rte->metric = htonl(RIP_METRIC_INFINITY); + + if (connected) { + /* + * connected is only sent for ripv1 case, or when + * interface does not support multicast. Caller loops + * over each connected address for this case. + */ + if (rip_send_packet((u_char *)&rip_packet, sizeof(rip_packet), + to, connected) + != sizeof(rip_packet)) + return -1; + else + return sizeof(rip_packet); + } - /* Make socket. */ - rip->sock = rip_create_socket (); - if (rip->sock < 0) - return rip->sock; + /* send request on each connected network */ + for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) { + struct prefix_ipv4 *p; - /* Create read and timer thread. */ - rip_event (RIP_READ, rip->sock); - rip_event (RIP_UPDATE_EVENT, 1); + p = (struct prefix_ipv4 *)connected->address; - QOBJ_REG (rip, rip); + if (p->family != AF_INET) + continue; - return 0; + if (rip_send_packet((u_char *)&rip_packet, sizeof(rip_packet), + to, connected) + != sizeof(rip_packet)) + return -1; + } + return sizeof(rip_packet); } -/* Sned RIP request to the destination. */ -int -rip_request_send (struct sockaddr_in *to, struct interface *ifp, - u_char version, struct connected *connected) -{ - struct rte *rte; - struct rip_packet rip_packet; - struct listnode *node, *nnode; - - memset (&rip_packet, 0, sizeof (rip_packet)); - - rip_packet.command = RIP_REQUEST; - rip_packet.version = version; - rte = rip_packet.rte; - rte->metric = htonl (RIP_METRIC_INFINITY); - - if (connected) - { - /* - * connected is only sent for ripv1 case, or when - * interface does not support multicast. Caller loops - * over each connected address for this case. - */ - if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet), - to, connected) != sizeof (rip_packet)) - return -1; - else - return sizeof (rip_packet); - } - - /* send request on each connected network */ - for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected)) - { - struct prefix_ipv4 *p; - - p = (struct prefix_ipv4 *) connected->address; - - if (p->family != AF_INET) - continue; - - if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet), - to, connected) != sizeof (rip_packet)) - return -1; - } - return sizeof (rip_packet); -} - -static int -rip_update_jitter (unsigned long time) +static int rip_update_jitter(unsigned long time) { #define JITTER_BOUND 4 - /* We want to get the jitter to +/- 1/JITTER_BOUND the interval. - Given that, we cannot let time be less than JITTER_BOUND seconds. - The RIPv2 RFC says jitter should be small compared to - update_time. We consider 1/JITTER_BOUND to be small. - */ - - int jitter_input = time; - int jitter; - - if (jitter_input < JITTER_BOUND) - jitter_input = JITTER_BOUND; - - jitter = (((random () % ((jitter_input * 2) + 1)) - jitter_input)); - - return jitter/JITTER_BOUND; -} - -void -rip_event (enum rip_event event, int sock) -{ - int jitter = 0; - - switch (event) - { - case RIP_READ: - rip->t_read = NULL; - thread_add_read(master, rip_read, NULL, sock, &rip->t_read); - break; - case RIP_UPDATE_EVENT: - RIP_TIMER_OFF (rip->t_update); - jitter = rip_update_jitter (rip->update_time); - thread_add_timer(master, rip_update, NULL, sock ? 2 : rip->update_time + jitter, - &rip->t_update); - break; - case RIP_TRIGGERED_UPDATE: - if (rip->t_triggered_interval) - rip->trigger = 1; - else thread_add_event(master, rip_triggered_update, NULL, 0, - &rip->t_triggered_update); - break; - default: - break; - } + /* We want to get the jitter to +/- 1/JITTER_BOUND the interval. + Given that, we cannot let time be less than JITTER_BOUND seconds. + The RIPv2 RFC says jitter should be small compared to + update_time. We consider 1/JITTER_BOUND to be small. + */ + + int jitter_input = time; + int jitter; + + if (jitter_input < JITTER_BOUND) + jitter_input = JITTER_BOUND; + + jitter = (((random() % ((jitter_input * 2) + 1)) - jitter_input)); + + return jitter / JITTER_BOUND; +} + +void rip_event(enum rip_event event, int sock) +{ + int jitter = 0; + + switch (event) { + case RIP_READ: + rip->t_read = NULL; + thread_add_read(master, rip_read, NULL, sock, &rip->t_read); + break; + case RIP_UPDATE_EVENT: + RIP_TIMER_OFF(rip->t_update); + jitter = rip_update_jitter(rip->update_time); + thread_add_timer(master, rip_update, NULL, + sock ? 2 : rip->update_time + jitter, + &rip->t_update); + break; + case RIP_TRIGGERED_UPDATE: + if (rip->t_triggered_interval) + rip->trigger = 1; + else + thread_add_event(master, rip_triggered_update, NULL, 0, + &rip->t_triggered_update); + break; + default: + break; + } } DEFUN_NOSH (router_rip, @@ -2806,21 +2794,19 @@ DEFUN_NOSH (router_rip, "Enable a routing process\n" "Routing Information Protocol (RIP)\n") { - int ret; + int ret; - /* If rip is not enabled before. */ - if (! rip) - { - ret = rip_create (); - if (ret < 0) - { - zlog_info ("Can't create RIP"); - return CMD_WARNING_CONFIG_FAILED; + /* If rip is not enabled before. */ + if (!rip) { + ret = rip_create(); + if (ret < 0) { + zlog_info("Can't create RIP"); + return CMD_WARNING_CONFIG_FAILED; + } } - } - VTY_PUSH_CONTEXT(RIP_NODE, rip); + VTY_PUSH_CONTEXT(RIP_NODE, rip); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_router_rip, @@ -2830,9 +2816,9 @@ DEFUN (no_router_rip, "Enable a routing process\n" "Routing Information Protocol (RIP)\n") { - if (rip) - rip_clean (); - return CMD_SUCCESS; + if (rip) + rip_clean(); + return CMD_SUCCESS; } DEFUN (rip_version, @@ -2841,19 +2827,18 @@ DEFUN (rip_version, "Set routing protocol version\n" "version\n") { - int idx_number = 1; - int version; + int idx_number = 1; + int version; - version = atoi (argv[idx_number]->arg); - if (version != RIPv1 && version != RIPv2) - { - vty_out (vty, "invalid rip version %d\n",version); - return CMD_WARNING_CONFIG_FAILED; - } - rip->version_send = version; - rip->version_recv = version; + version = atoi(argv[idx_number]->arg); + if (version != RIPv1 && version != RIPv2) { + vty_out(vty, "invalid rip version %d\n", version); + return CMD_WARNING_CONFIG_FAILED; + } + rip->version_send = version; + rip->version_recv = version; - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rip_version, @@ -2863,11 +2848,11 @@ DEFUN (no_rip_version, "Set routing protocol version\n" "Version\n") { - /* Set RIP version to the default. */ - rip->version_send = RI_RIP_VERSION_2; - rip->version_recv = RI_RIP_VERSION_1_AND_2; + /* Set RIP version to the default. */ + rip->version_send = RI_RIP_VERSION_2; + rip->version_recv = RI_RIP_VERSION_1_AND_2; - return CMD_SUCCESS; + return CMD_SUCCESS; } @@ -2877,34 +2862,33 @@ DEFUN (rip_route, "RIP static route configuration\n" "IP prefix <network>/<length>\n") { - int idx_ipv4_prefixlen = 1; - int ret; - struct prefix_ipv4 p; - struct route_node *node; + int idx_ipv4_prefixlen = 1; + int ret; + struct prefix_ipv4 p; + struct route_node *node; - ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p); - if (ret < 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv4 (&p); + ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + if (ret < 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv4(&p); - /* For router rip configuration. */ - node = route_node_get (rip->route, (struct prefix *) &p); + /* For router rip configuration. */ + node = route_node_get(rip->route, (struct prefix *)&p); - if (node->info) - { - vty_out (vty, "There is already same static route.\n"); - route_unlock_node (node); - return CMD_WARNING_CONFIG_FAILED; - } + if (node->info) { + vty_out(vty, "There is already same static route.\n"); + route_unlock_node(node); + return CMD_WARNING_CONFIG_FAILED; + } - node->info = (void *)1; + node->info = (void *)1; - rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0, 0); + rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, + 0, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } DEFUN (no_rip_route, @@ -2914,34 +2898,33 @@ DEFUN (no_rip_route, "RIP static route configuration\n" "IP prefix <network>/<length>\n") { - int idx_ipv4_prefixlen = 2; - int ret; - struct prefix_ipv4 p; - struct route_node *node; + int idx_ipv4_prefixlen = 2; + int ret; + struct prefix_ipv4 p; + struct route_node *node; - ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p); - if (ret < 0) - { - vty_out (vty, "Malformed address\n"); - return CMD_WARNING_CONFIG_FAILED; - } - apply_mask_ipv4 (&p); - - /* For router rip configuration. */ - node = route_node_lookup (rip->route, (struct prefix *) &p); - if (! node) - { - vty_out (vty, "Can't find route %s.\n",argv[idx_ipv4_prefixlen]->arg); - return CMD_WARNING_CONFIG_FAILED; - } + ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + if (ret < 0) { + vty_out(vty, "Malformed address\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask_ipv4(&p); + + /* For router rip configuration. */ + node = route_node_lookup(rip->route, (struct prefix *)&p); + if (!node) { + vty_out(vty, "Can't find route %s.\n", + argv[idx_ipv4_prefixlen]->arg); + return CMD_WARNING_CONFIG_FAILED; + } - rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); - route_unlock_node (node); + rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0); + route_unlock_node(node); - node->info = NULL; - route_unlock_node (node); + node->info = NULL; + route_unlock_node(node); - return CMD_SUCCESS; + return CMD_SUCCESS; } #if 0 @@ -2967,13 +2950,12 @@ DEFUN (rip_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - int idx_number = 1; - if (rip) - { - rip->default_metric = atoi (argv[idx_number]->arg); - /* rip_update_default_metric (); */ - } - return CMD_SUCCESS; + int idx_number = 1; + if (rip) { + rip->default_metric = atoi(argv[idx_number]->arg); + /* rip_update_default_metric (); */ + } + return CMD_SUCCESS; } DEFUN (no_rip_default_metric, @@ -2983,12 +2965,11 @@ DEFUN (no_rip_default_metric, "Set a metric of redistribute routes\n" "Default metric\n") { - if (rip) - { - rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; - /* rip_update_default_metric (); */ - } - return CMD_SUCCESS; + if (rip) { + rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; + /* rip_update_default_metric (); */ + } + return CMD_SUCCESS; } @@ -3001,46 +2982,46 @@ DEFUN (rip_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - int idx_number = 2; - int idx_number_2 = 3; - int idx_number_3 = 4; - unsigned long update; - unsigned long timeout; - unsigned long garbage; - char *endptr = NULL; - unsigned long RIP_TIMER_MAX = 2147483647; - unsigned long RIP_TIMER_MIN = 5; - - update = strtoul (argv[idx_number]->arg, &endptr, 10); - if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0') - { - vty_out (vty, "update timer value error\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - timeout = strtoul (argv[idx_number_2]->arg, &endptr, 10); - if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0') - { - vty_out (vty, "timeout timer value error\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - garbage = strtoul (argv[idx_number_3]->arg, &endptr, 10); - if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0') - { - vty_out (vty, "garbage timer value error\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - /* Set each timer value. */ - rip->update_time = update; - rip->timeout_time = timeout; - rip->garbage_time = garbage; - - /* Reset update timer thread. */ - rip_event (RIP_UPDATE_EVENT, 0); - - return CMD_SUCCESS; + int idx_number = 2; + int idx_number_2 = 3; + int idx_number_3 = 4; + unsigned long update; + unsigned long timeout; + unsigned long garbage; + char *endptr = NULL; + unsigned long RIP_TIMER_MAX = 2147483647; + unsigned long RIP_TIMER_MIN = 5; + + update = strtoul(argv[idx_number]->arg, &endptr, 10); + if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN + || *endptr != '\0') { + vty_out(vty, "update timer value error\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + timeout = strtoul(argv[idx_number_2]->arg, &endptr, 10); + if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN + || *endptr != '\0') { + vty_out(vty, "timeout timer value error\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + garbage = strtoul(argv[idx_number_3]->arg, &endptr, 10); + if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN + || *endptr != '\0') { + vty_out(vty, "garbage timer value error\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Set each timer value. */ + rip->update_time = update; + rip->timeout_time = timeout; + rip->garbage_time = garbage; + + /* Reset update timer thread. */ + rip_event(RIP_UPDATE_EVENT, 0); + + return CMD_SUCCESS; } DEFUN (no_rip_timers, @@ -3053,210 +3034,193 @@ DEFUN (no_rip_timers, "Routing information timeout timer. Default is 180.\n" "Garbage collection timer. Default is 120.\n") { - /* Set each timer value to the default. */ - rip->update_time = RIP_UPDATE_TIMER_DEFAULT; - rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; - rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; + /* Set each timer value to the default. */ + rip->update_time = RIP_UPDATE_TIMER_DEFAULT; + rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; + rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; - /* Reset update timer thread. */ - rip_event (RIP_UPDATE_EVENT, 0); + /* Reset update timer thread. */ + rip_event(RIP_UPDATE_EVENT, 0); - return CMD_SUCCESS; + return CMD_SUCCESS; } - struct route_table *rip_distance_table; -struct rip_distance -{ - /* Distance value for the IP source prefix. */ - u_char distance; +struct rip_distance { + /* Distance value for the IP source prefix. */ + u_char distance; - /* Name of the access-list to be matched. */ - char *access_list; + /* Name of the access-list to be matched. */ + char *access_list; }; -static struct rip_distance * -rip_distance_new (void) +static struct rip_distance *rip_distance_new(void) { - return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance)); + return XCALLOC(MTYPE_RIP_DISTANCE, sizeof(struct rip_distance)); } -static void -rip_distance_free (struct rip_distance *rdistance) -{ - XFREE (MTYPE_RIP_DISTANCE, rdistance); -} - -static int -rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str, - const char *access_list_str) -{ - int ret; - struct prefix_ipv4 p; - u_char distance; - struct route_node *rn; - struct rip_distance *rdistance; - - ret = str2prefix_ipv4 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - distance = atoi (distance_str); - - /* Get RIP distance node. */ - rn = route_node_get (rip_distance_table, (struct prefix *) &p); - if (rn->info) - { - rdistance = rn->info; - route_unlock_node (rn); - } - else - { - rdistance = rip_distance_new (); - rn->info = rdistance; - } - - /* Set distance value. */ - rdistance->distance = distance; - - /* Reset access-list configuration. */ - if (rdistance->access_list) - { - free (rdistance->access_list); - rdistance->access_list = NULL; - } - if (access_list_str) - rdistance->access_list = strdup (access_list_str); - - return CMD_SUCCESS; -} - -static int -rip_distance_unset (struct vty *vty, const char *distance_str, - const char *ip_str, const char *access_list_str) -{ - int ret; - struct prefix_ipv4 p; - struct route_node *rn; - struct rip_distance *rdistance; - - ret = str2prefix_ipv4 (ip_str, &p); - if (ret == 0) - { - vty_out (vty, "Malformed prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rn = route_node_lookup (rip_distance_table, (struct prefix *)&p); - if (! rn) - { - vty_out (vty, "Can't find specified prefix\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - rdistance = rn->info; - - if (rdistance->access_list) - free (rdistance->access_list); - rip_distance_free (rdistance); - - rn->info = NULL; - route_unlock_node (rn); - route_unlock_node (rn); - - return CMD_SUCCESS; +static void rip_distance_free(struct rip_distance *rdistance) +{ + XFREE(MTYPE_RIP_DISTANCE, rdistance); } -static void -rip_distance_reset (void) +static int rip_distance_set(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) { - struct route_node *rn; - struct rip_distance *rdistance; + int ret; + struct prefix_ipv4 p; + u_char distance; + struct route_node *rn; + struct rip_distance *rdistance; + + ret = str2prefix_ipv4(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + distance = atoi(distance_str); + + /* Get RIP distance node. */ + rn = route_node_get(rip_distance_table, (struct prefix *)&p); + if (rn->info) { + rdistance = rn->info; + route_unlock_node(rn); + } else { + rdistance = rip_distance_new(); + rn->info = rdistance; + } + + /* Set distance value. */ + rdistance->distance = distance; + + /* Reset access-list configuration. */ + if (rdistance->access_list) { + free(rdistance->access_list); + rdistance->access_list = NULL; + } + if (access_list_str) + rdistance->access_list = strdup(access_list_str); + + return CMD_SUCCESS; +} + +static int rip_distance_unset(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) +{ + int ret; + struct prefix_ipv4 p; + struct route_node *rn; + struct rip_distance *rdistance; + + ret = str2prefix_ipv4(ip_str, &p); + if (ret == 0) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rn = route_node_lookup(rip_distance_table, (struct prefix *)&p); + if (!rn) { + vty_out(vty, "Can't find specified prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + rdistance = rn->info; - for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) - if ((rdistance = rn->info) != NULL) - { if (rdistance->access_list) - free (rdistance->access_list); - rip_distance_free (rdistance); + free(rdistance->access_list); + rip_distance_free(rdistance); + rn->info = NULL; - route_unlock_node (rn); - } + route_unlock_node(rn); + route_unlock_node(rn); + + return CMD_SUCCESS; } -/* Apply RIP information to distance method. */ -u_char -rip_distance_apply (struct rip_info *rinfo) -{ - struct route_node *rn; - struct prefix_ipv4 p; - struct rip_distance *rdistance; - struct access_list *alist; - - if (! rip) - return 0; - - memset (&p, 0, sizeof (struct prefix_ipv4)); - p.family = AF_INET; - p.prefix = rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; - - /* Check source address. */ - rn = route_node_match (rip_distance_table, (struct prefix *) &p); - if (rn) - { - rdistance = rn->info; - route_unlock_node (rn); - - if (rdistance->access_list) - { - alist = access_list_lookup (AFI_IP, rdistance->access_list); - if (alist == NULL) - return 0; - if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY) - return 0; +static void rip_distance_reset(void) +{ + struct route_node *rn; + struct rip_distance *rdistance; - return rdistance->distance; + for (rn = route_top(rip_distance_table); rn; rn = route_next(rn)) + if ((rdistance = rn->info) != NULL) { + if (rdistance->access_list) + free(rdistance->access_list); + rip_distance_free(rdistance); + rn->info = NULL; + route_unlock_node(rn); + } +} + +/* Apply RIP information to distance method. */ +u_char rip_distance_apply(struct rip_info *rinfo) +{ + struct route_node *rn; + struct prefix_ipv4 p; + struct rip_distance *rdistance; + struct access_list *alist; + + if (!rip) + return 0; + + memset(&p, 0, sizeof(struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; + + /* Check source address. */ + rn = route_node_match(rip_distance_table, (struct prefix *)&p); + if (rn) { + rdistance = rn->info; + route_unlock_node(rn); + + if (rdistance->access_list) { + alist = access_list_lookup(AFI_IP, + rdistance->access_list); + if (alist == NULL) + return 0; + if (access_list_apply(alist, &rinfo->rp->p) + == FILTER_DENY) + return 0; + + return rdistance->distance; + } else + return rdistance->distance; } - else - return rdistance->distance; - } - if (rip->distance) - return rip->distance; + if (rip->distance) + return rip->distance; - return 0; + return 0; } -static void -rip_distance_show (struct vty *vty) -{ - struct route_node *rn; - struct rip_distance *rdistance; - int header = 1; - char buf[BUFSIZ]; - - vty_out (vty, " Distance: (default is %d)\n", - rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT); - - for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) - if ((rdistance = rn->info) != NULL) - { - if (header) - { - vty_out (vty," Address Distance List\n"); - header = 0; - } - sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen); - vty_out (vty, " %-20s %4d %s\n", - buf, rdistance->distance, - rdistance->access_list ? rdistance->access_list : ""); - } +static void rip_distance_show(struct vty *vty) +{ + struct route_node *rn; + struct rip_distance *rdistance; + int header = 1; + char buf[BUFSIZ]; + + vty_out(vty, " Distance: (default is %d)\n", + rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT); + + for (rn = route_top(rip_distance_table); rn; rn = route_next(rn)) + if ((rdistance = rn->info) != NULL) { + if (header) { + vty_out(vty, + " Address Distance List\n"); + header = 0; + } + sprintf(buf, "%s/%d", inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + vty_out(vty, " %-20s %4d %s\n", buf, + rdistance->distance, + rdistance->access_list ? rdistance->access_list + : ""); + } } DEFUN (rip_distance, @@ -3265,9 +3229,9 @@ DEFUN (rip_distance, "Administrative distance\n" "Distance value\n") { - int idx_number = 1; - rip->distance = atoi (argv[idx_number]->arg); - return CMD_SUCCESS; + int idx_number = 1; + rip->distance = atoi(argv[idx_number]->arg); + return CMD_SUCCESS; } DEFUN (no_rip_distance, @@ -3277,8 +3241,8 @@ DEFUN (no_rip_distance, "Administrative distance\n" "Distance value\n") { - rip->distance = 0; - return CMD_SUCCESS; + rip->distance = 0; + return CMD_SUCCESS; } DEFUN (rip_distance_source, @@ -3288,10 +3252,11 @@ DEFUN (rip_distance_source, "Distance value\n" "IP source prefix\n") { - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - rip_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + rip_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } DEFUN (no_rip_distance_source, @@ -3302,10 +3267,11 @@ DEFUN (no_rip_distance_source, "Distance value\n" "IP source prefix\n") { - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - rip_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL); - return CMD_SUCCESS; + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + rip_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } DEFUN (rip_distance_source_access_list, @@ -3316,11 +3282,12 @@ DEFUN (rip_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - int idx_number = 1; - int idx_ipv4_prefixlen = 2; - int idx_word = 3; - rip_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + int idx_word = 3; + rip_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; } DEFUN (no_rip_distance_source_access_list, @@ -3332,51 +3299,50 @@ DEFUN (no_rip_distance_source_access_list, "IP source prefix\n" "Access list name\n") { - int idx_number = 2; - int idx_ipv4_prefixlen = 3; - int idx_word = 4; - rip_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); - return CMD_SUCCESS; + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + int idx_word = 4; + rip_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; } /* Update ECMP routes to zebra when ECMP is disabled. */ -static void -rip_ecmp_disable (void) -{ - struct route_node *rp; - struct rip_info *rinfo, *tmp_rinfo; - struct list *list; - struct listnode *node, *nextnode; - - if (!rip) - return; - - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL && listcount (list) > 1) - { - rinfo = listgetdata (listhead (list)); - if (!rip_route_rte (rinfo)) - continue; - - /* Drop all other entries, except the first one. */ - for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo)) - if (tmp_rinfo != rinfo) - { - RIP_TIMER_OFF (tmp_rinfo->t_timeout); - RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect); - list_delete_node (list, node); - rip_info_free (tmp_rinfo); - } - - /* Update zebra. */ - rip_zebra_ipv4_add (rp); - - /* Set the route change flag. */ - SET_FLAG (rinfo->flags, RIP_RTF_CHANGED); - - /* Signal the output process to trigger an update. */ - rip_event (RIP_TRIGGERED_UPDATE, 0); - } +static void rip_ecmp_disable(void) +{ + struct route_node *rp; + struct rip_info *rinfo, *tmp_rinfo; + struct list *list; + struct listnode *node, *nextnode; + + if (!rip) + return; + + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL && listcount(list) > 1) { + rinfo = listgetdata(listhead(list)); + if (!rip_route_rte(rinfo)) + continue; + + /* Drop all other entries, except the first one. */ + for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo)) + if (tmp_rinfo != rinfo) { + RIP_TIMER_OFF(tmp_rinfo->t_timeout); + RIP_TIMER_OFF( + tmp_rinfo->t_garbage_collect); + list_delete_node(list, node); + rip_info_free(tmp_rinfo); + } + + /* Update zebra. */ + rip_zebra_ipv4_add(rp); + + /* Set the route change flag. */ + SET_FLAG(rinfo->flags, RIP_RTF_CHANGED); + + /* Signal the output process to trigger an update. */ + rip_event(RIP_TRIGGERED_UPDATE, 0); + } } DEFUN (rip_allow_ecmp, @@ -3384,15 +3350,14 @@ DEFUN (rip_allow_ecmp, "allow-ecmp", "Allow Equal Cost MultiPath\n") { - if (rip->ecmp) - { - vty_out (vty, "ECMP is already enabled.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (rip->ecmp) { + vty_out(vty, "ECMP is already enabled.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - rip->ecmp = 1; - zlog_info ("ECMP is enabled."); - return CMD_SUCCESS; + rip->ecmp = 1; + zlog_info("ECMP is enabled."); + return CMD_SUCCESS; } DEFUN (no_rip_allow_ecmp, @@ -3401,62 +3366,55 @@ DEFUN (no_rip_allow_ecmp, NO_STR "Allow Equal Cost MultiPath\n") { - if (!rip->ecmp) - { - vty_out (vty, "ECMP is already disabled.\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (!rip->ecmp) { + vty_out(vty, "ECMP is already disabled.\n"); + return CMD_WARNING_CONFIG_FAILED; + } - rip->ecmp = 0; - zlog_info ("ECMP is disabled."); - rip_ecmp_disable (); - return CMD_SUCCESS; + rip->ecmp = 0; + zlog_info("ECMP is disabled."); + rip_ecmp_disable(); + return CMD_SUCCESS; } /* Print out routes update time. */ -static void -rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo) +static void rip_vty_out_uptime(struct vty *vty, struct rip_info *rinfo) { - time_t clock; - struct tm *tm; + time_t clock; + struct tm *tm; #define TIME_BUF 25 - char timebuf [TIME_BUF]; - struct thread *thread; - - if ((thread = rinfo->t_timeout) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } - else if ((thread = rinfo->t_garbage_collect) != NULL) - { - clock = thread_timer_remain_second (thread); - tm = gmtime (&clock); - strftime (timebuf, TIME_BUF, "%M:%S", tm); - vty_out (vty, "%5s", timebuf); - } -} - -static const char * -rip_route_type_print (int sub_type) -{ - switch (sub_type) - { - case RIP_ROUTE_RTE: - return "n"; - case RIP_ROUTE_STATIC: - return "s"; - case RIP_ROUTE_DEFAULT: - return "d"; - case RIP_ROUTE_REDISTRIBUTE: - return "r"; - case RIP_ROUTE_INTERFACE: - return "i"; - default: - return "?"; - } + char timebuf[TIME_BUF]; + struct thread *thread; + + if ((thread = rinfo->t_timeout) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } else if ((thread = rinfo->t_garbage_collect) != NULL) { + clock = thread_timer_remain_second(thread); + tm = gmtime(&clock); + strftime(timebuf, TIME_BUF, "%M:%S", tm); + vty_out(vty, "%5s", timebuf); + } +} + +static const char *rip_route_type_print(int sub_type) +{ + switch (sub_type) { + case RIP_ROUTE_RTE: + return "n"; + case RIP_ROUTE_STATIC: + return "s"; + case RIP_ROUTE_DEFAULT: + return "d"; + case RIP_ROUTE_REDISTRIBUTE: + return "r"; + case RIP_ROUTE_INTERFACE: + return "i"; + default: + return "?"; + } } DEFUN (show_ip_rip, @@ -3466,76 +3424,83 @@ DEFUN (show_ip_rip, IP_STR "Show RIP routes\n") { - struct route_node *np; - struct rip_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; - - if (! rip) - return CMD_SUCCESS; - - vty_out (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n" - "Sub-codes:\n" - " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n" - " (i) - interface\n\n" - " Network Next Hop Metric From Tag Time\n"); - - for (np = route_top (rip->table); np; np = route_next (np)) - if ((list = np->info) != NULL) - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - int len; - - len = vty_out (vty, "%c(%s) %s/%d", - /* np->lock, For debugging. */ - zebra_route_char(rinfo->type), - rip_route_type_print (rinfo->sub_type), - inet_ntoa (np->p.u.prefix4), np->p.prefixlen); - - len = 24 - len; - - if (len > 0) - vty_out (vty, "%*s", len, " "); - - if (rinfo->nexthop.s_addr) - vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop), - rinfo->metric); - else - vty_out (vty, "0.0.0.0 %2d ", rinfo->metric); - - /* Route which exist in kernel routing table. */ - if ((rinfo->type == ZEBRA_ROUTE_RIP) && - (rinfo->sub_type == RIP_ROUTE_RTE)) - { - vty_out (vty, "%-15s ", inet_ntoa (rinfo->from)); - vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag); - rip_vty_out_uptime (vty, rinfo); - } - else if (rinfo->metric == RIP_METRIC_INFINITY) - { - vty_out (vty, "self "); - vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag); - rip_vty_out_uptime (vty, rinfo); - } - else - { - if (rinfo->external_metric) - { - len = vty_out (vty, "self (%s:%d)", - zebra_route_string(rinfo->type), - rinfo->external_metric); - len = 16 - len; - if (len > 0) - vty_out (vty, "%*s", len, " "); - } - else - vty_out (vty, "self "); - vty_out (vty, "%3"ROUTE_TAG_PRI, (route_tag_t)rinfo->tag); - } - - vty_out (vty, "\n"); - } - return CMD_SUCCESS; + struct route_node *np; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (!rip) + return CMD_SUCCESS; + + vty_out(vty, + "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n" + "Sub-codes:\n" + " (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n" + " (i) - interface\n\n" + " Network Next Hop Metric From Tag Time\n"); + + for (np = route_top(rip->table); np; np = route_next(np)) + if ((list = np->info) != NULL) + for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) { + int len; + + len = vty_out( + vty, "%c(%s) %s/%d", + /* np->lock, For debugging. */ + zebra_route_char(rinfo->type), + rip_route_type_print(rinfo->sub_type), + inet_ntoa(np->p.u.prefix4), + np->p.prefixlen); + + len = 24 - len; + + if (len > 0) + vty_out(vty, "%*s", len, " "); + + if (rinfo->nexthop.s_addr) + vty_out(vty, "%-20s %2d ", + inet_ntoa(rinfo->nexthop), + rinfo->metric); + else + vty_out(vty, + "0.0.0.0 %2d ", + rinfo->metric); + + /* Route which exist in kernel routing table. */ + if ((rinfo->type == ZEBRA_ROUTE_RIP) + && (rinfo->sub_type == RIP_ROUTE_RTE)) { + vty_out(vty, "%-15s ", + inet_ntoa(rinfo->from)); + vty_out(vty, "%3" ROUTE_TAG_PRI " ", + (route_tag_t)rinfo->tag); + rip_vty_out_uptime(vty, rinfo); + } else if (rinfo->metric + == RIP_METRIC_INFINITY) { + vty_out(vty, "self "); + vty_out(vty, "%3" ROUTE_TAG_PRI " ", + (route_tag_t)rinfo->tag); + rip_vty_out_uptime(vty, rinfo); + } else { + if (rinfo->external_metric) { + len = vty_out( + vty, "self (%s:%d)", + zebra_route_string( + rinfo->type), + rinfo->external_metric); + len = 16 - len; + if (len > 0) + vty_out(vty, "%*s", len, + " "); + } else + vty_out(vty, + "self "); + vty_out(vty, "%3" ROUTE_TAG_PRI, + (route_tag_t)rinfo->tag); + } + + vty_out(vty, "\n"); + } + return CMD_SUCCESS; } /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */ @@ -3547,534 +3512,508 @@ DEFUN (show_ip_rip_status, "Show RIP routes\n" "IP routing protocol process parameters and statistics\n") { - struct listnode *node; - struct interface *ifp; - struct rip_interface *ri; - extern const struct message ri_version_msg[]; - const char *send_version; - const char *receive_version; - - if (! rip) - return CMD_SUCCESS; - - vty_out (vty, "Routing Protocol is \"rip\"\n"); - vty_out (vty, " Sending updates every %ld seconds with +/-50%%,", - rip->update_time); - vty_out (vty, " next due in %lu seconds\n", - thread_timer_remain_second(rip->t_update)); - vty_out (vty, " Timeout after %ld seconds,", rip->timeout_time); - vty_out (vty, " garbage collect after %ld seconds\n",rip->garbage_time); - - /* Filtering status show. */ - config_show_distribute (vty); - - /* Default metric information. */ - vty_out (vty, " Default redistribution metric is %d\n", - rip->default_metric); - - /* Redistribute information. */ - vty_out (vty, " Redistributing:"); - config_write_rip_redistribute (vty, 0); - vty_out (vty, "\n"); - - vty_out (vty, " Default version control: send version %s,", - lookup_msg(ri_version_msg,rip->version_send, NULL)); - if (rip->version_recv == RI_RIP_VERSION_1_AND_2) - vty_out (vty, " receive any version \n"); - else - vty_out (vty, " receive version %s \n", - lookup_msg(ri_version_msg,rip->version_recv, NULL)); - - vty_out (vty, " Interface Send Recv Key-chain\n"); - - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; - - if (!ri->running) - continue; - - if (ri->enable_network || ri->enable_interface) - { - if (ri->ri_send == RI_RIP_UNSPEC) - send_version = lookup_msg(ri_version_msg, rip->version_send, NULL); - else - send_version = lookup_msg(ri_version_msg, ri->ri_send, NULL); - - if (ri->ri_receive == RI_RIP_UNSPEC) - receive_version = lookup_msg(ri_version_msg, rip->version_recv, NULL); - else - receive_version = lookup_msg(ri_version_msg, ri->ri_receive, NULL); - - vty_out (vty, " %-17s%-3s %-3s %s\n", ifp->name, - send_version, - receive_version, - ri->key_chain ? ri->key_chain : ""); - } - } - - vty_out (vty, " Routing for Networks:\n"); - config_write_rip_network (vty, 0); - - { - int found_passive = 0; - for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) - { - ri = ifp->info; - - if ((ri->enable_network || ri->enable_interface) && ri->passive) - { - if (!found_passive) - { - vty_out (vty, " Passive Interface(s):\n"); - found_passive = 1; - } - vty_out (vty, " %s\n", ifp->name); - } - } - } - - vty_out (vty, " Routing Information Sources:\n"); - vty_out (vty, - " Gateway BadPackets BadRoutes Distance Last Update\n"); - rip_peer_display (vty); - - rip_distance_show (vty); + struct listnode *node; + struct interface *ifp; + struct rip_interface *ri; + extern const struct message ri_version_msg[]; + const char *send_version; + const char *receive_version; + + if (!rip) + return CMD_SUCCESS; + + vty_out(vty, "Routing Protocol is \"rip\"\n"); + vty_out(vty, " Sending updates every %ld seconds with +/-50%%,", + rip->update_time); + vty_out(vty, " next due in %lu seconds\n", + thread_timer_remain_second(rip->t_update)); + vty_out(vty, " Timeout after %ld seconds,", rip->timeout_time); + vty_out(vty, " garbage collect after %ld seconds\n", rip->garbage_time); + + /* Filtering status show. */ + config_show_distribute(vty); + + /* Default metric information. */ + vty_out(vty, " Default redistribution metric is %d\n", + rip->default_metric); + + /* Redistribute information. */ + vty_out(vty, " Redistributing:"); + config_write_rip_redistribute(vty, 0); + vty_out(vty, "\n"); + + vty_out(vty, " Default version control: send version %s,", + lookup_msg(ri_version_msg, rip->version_send, NULL)); + if (rip->version_recv == RI_RIP_VERSION_1_AND_2) + vty_out(vty, " receive any version \n"); + else + vty_out(vty, " receive version %s \n", + lookup_msg(ri_version_msg, rip->version_recv, NULL)); + + vty_out(vty, " Interface Send Recv Key-chain\n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; + + if (!ri->running) + continue; + + if (ri->enable_network || ri->enable_interface) { + if (ri->ri_send == RI_RIP_UNSPEC) + send_version = + lookup_msg(ri_version_msg, + rip->version_send, NULL); + else + send_version = lookup_msg(ri_version_msg, + ri->ri_send, NULL); + + if (ri->ri_receive == RI_RIP_UNSPEC) + receive_version = + lookup_msg(ri_version_msg, + rip->version_recv, NULL); + else + receive_version = lookup_msg( + ri_version_msg, ri->ri_receive, NULL); + + vty_out(vty, " %-17s%-3s %-3s %s\n", ifp->name, + send_version, receive_version, + ri->key_chain ? ri->key_chain : ""); + } + } - return CMD_SUCCESS; -} + vty_out(vty, " Routing for Networks:\n"); + config_write_rip_network(vty, 0); -/* RIP configuration write function. */ -static int -config_write_rip (struct vty *vty) -{ - int write = 0; - struct route_node *rn; - struct rip_distance *rdistance; - - if (rip) - { - /* Router RIP statement. */ - vty_out (vty, "router rip\n"); - write++; - - /* RIP version statement. Default is RIP version 2. */ - if (rip->version_send != RI_RIP_VERSION_2 - || rip->version_recv != RI_RIP_VERSION_1_AND_2) - vty_out (vty, " version %d\n",rip->version_send); - - /* RIP timer configuration. */ - if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT - || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT - || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT) - vty_out (vty, " timers basic %lu %lu %lu\n", - rip->update_time, - rip->timeout_time, - rip->garbage_time); - - /* Default information configuration. */ - if (rip->default_information) { - if (rip->default_information_route_map) - vty_out (vty, " default-information originate route-map %s\n", - rip->default_information_route_map); - else - vty_out (vty," default-information originate\n"); + int found_passive = 0; + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + ri = ifp->info; + + if ((ri->enable_network || ri->enable_interface) + && ri->passive) { + if (!found_passive) { + vty_out(vty, + " Passive Interface(s):\n"); + found_passive = 1; + } + vty_out(vty, " %s\n", ifp->name); + } + } } - /* Redistribute configuration. */ - config_write_rip_redistribute (vty, 1); - - /* RIP offset-list configuration. */ - config_write_rip_offset_list (vty); + vty_out(vty, " Routing Information Sources:\n"); + vty_out(vty, + " Gateway BadPackets BadRoutes Distance Last Update\n"); + rip_peer_display(vty); - /* RIP enabled network and interface configuration. */ - config_write_rip_network (vty, 1); - - /* RIP default metric configuration */ - if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT) - vty_out (vty, " default-metric %d\n", - rip->default_metric); + rip_distance_show(vty); - /* Distribute configuration. */ - write += config_write_distribute (vty); + return CMD_SUCCESS; +} - /* Interface routemap configuration */ - write += config_write_if_rmap (vty); +/* RIP configuration write function. */ +static int config_write_rip(struct vty *vty) +{ + int write = 0; + struct route_node *rn; + struct rip_distance *rdistance; + + if (rip) { + /* Router RIP statement. */ + vty_out(vty, "router rip\n"); + write++; + + /* RIP version statement. Default is RIP version 2. */ + if (rip->version_send != RI_RIP_VERSION_2 + || rip->version_recv != RI_RIP_VERSION_1_AND_2) + vty_out(vty, " version %d\n", rip->version_send); + + /* RIP timer configuration. */ + if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT + || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT + || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT) + vty_out(vty, " timers basic %lu %lu %lu\n", + rip->update_time, rip->timeout_time, + rip->garbage_time); + + /* Default information configuration. */ + if (rip->default_information) { + if (rip->default_information_route_map) + vty_out(vty, + " default-information originate route-map %s\n", + rip->default_information_route_map); + else + vty_out(vty, + " default-information originate\n"); + } - /* Distance configuration. */ - if (rip->distance) - vty_out (vty, " distance %d\n", rip->distance); + /* Redistribute configuration. */ + config_write_rip_redistribute(vty, 1); + + /* RIP offset-list configuration. */ + config_write_rip_offset_list(vty); + + /* RIP enabled network and interface configuration. */ + config_write_rip_network(vty, 1); + + /* RIP default metric configuration */ + if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT) + vty_out(vty, " default-metric %d\n", + rip->default_metric); + + /* Distribute configuration. */ + write += config_write_distribute(vty); + + /* Interface routemap configuration */ + write += config_write_if_rmap(vty); + + /* Distance configuration. */ + if (rip->distance) + vty_out(vty, " distance %d\n", rip->distance); + + /* RIP source IP prefix distance configuration. */ + for (rn = route_top(rip_distance_table); rn; + rn = route_next(rn)) + if ((rdistance = rn->info) != NULL) + vty_out(vty, " distance %d %s/%d %s\n", + rdistance->distance, + inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen, + rdistance->access_list + ? rdistance->access_list + : ""); + + /* ECMP configuration. */ + if (rip->ecmp) + vty_out(vty, " allow-ecmp\n"); + + /* RIP static route configuration. */ + for (rn = route_top(rip->route); rn; rn = route_next(rn)) + if (rn->info) + vty_out(vty, " route %s/%d\n", + inet_ntoa(rn->p.u.prefix4), + rn->p.prefixlen); + } + return write; +} - /* RIP source IP prefix distance configuration. */ - for (rn = route_top (rip_distance_table); rn; rn = route_next (rn)) - if ((rdistance = rn->info) != NULL) - vty_out (vty, " distance %d %s/%d %s\n", rdistance->distance, - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, - rdistance->access_list ? rdistance->access_list : ""); +/* RIP node structure. */ +static struct cmd_node rip_node = {RIP_NODE, "%s(config-router)# ", 1}; - /* ECMP configuration. */ - if (rip->ecmp) - vty_out (vty, " allow-ecmp\n"); +/* Distribute-list update functions. */ +static void rip_distribute_update(struct distribute *dist) +{ + struct interface *ifp; + struct rip_interface *ri; + struct access_list *alist; + struct prefix_list *plist; - /* RIP static route configuration. */ - for (rn = route_top (rip->route); rn; rn = route_next (rn)) - if (rn->info) - vty_out (vty, " route %s/%d\n", - inet_ntoa (rn->p.u.prefix4), - rn->p.prefixlen); + if (!dist->ifname) + return; - } - return write; -} + ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; -/* RIP node structure. */ -static struct cmd_node rip_node = -{ - RIP_NODE, - "%s(config-router)# ", - 1 -}; + ri = ifp->info; -/* Distribute-list update functions. */ -static void -rip_distribute_update (struct distribute *dist) -{ - struct interface *ifp; - struct rip_interface *ri; - struct access_list *alist; - struct prefix_list *plist; - - if (! dist->ifname) - return; - - ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; - - ri = ifp->info; - - if (dist->list[DISTRIBUTE_V4_IN]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]); - if (alist) - ri->list[RIP_FILTER_IN] = alist; - else - ri->list[RIP_FILTER_IN] = NULL; - } - else - ri->list[RIP_FILTER_IN] = NULL; - - if (dist->list[DISTRIBUTE_V4_OUT]) - { - alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]); - if (alist) - ri->list[RIP_FILTER_OUT] = alist; - else - ri->list[RIP_FILTER_OUT] = NULL; - } - else - ri->list[RIP_FILTER_OUT] = NULL; - - if (dist->prefix[DISTRIBUTE_V4_IN]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]); - if (plist) - ri->prefix[RIP_FILTER_IN] = plist; - else - ri->prefix[RIP_FILTER_IN] = NULL; - } - else - ri->prefix[RIP_FILTER_IN] = NULL; - - if (dist->prefix[DISTRIBUTE_V4_OUT]) - { - plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]); - if (plist) - ri->prefix[RIP_FILTER_OUT] = plist; - else - ri->prefix[RIP_FILTER_OUT] = NULL; - } - else - ri->prefix[RIP_FILTER_OUT] = NULL; -} - -void -rip_distribute_update_interface (struct interface *ifp) -{ - struct distribute *dist; - - dist = distribute_lookup (ifp->name); - if (dist) - rip_distribute_update (dist); + if (dist->list[DISTRIBUTE_V4_IN]) { + alist = access_list_lookup(AFI_IP, + dist->list[DISTRIBUTE_V4_IN]); + if (alist) + ri->list[RIP_FILTER_IN] = alist; + else + ri->list[RIP_FILTER_IN] = NULL; + } else + ri->list[RIP_FILTER_IN] = NULL; + + if (dist->list[DISTRIBUTE_V4_OUT]) { + alist = access_list_lookup(AFI_IP, + dist->list[DISTRIBUTE_V4_OUT]); + if (alist) + ri->list[RIP_FILTER_OUT] = alist; + else + ri->list[RIP_FILTER_OUT] = NULL; + } else + ri->list[RIP_FILTER_OUT] = NULL; + + if (dist->prefix[DISTRIBUTE_V4_IN]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[DISTRIBUTE_V4_IN]); + if (plist) + ri->prefix[RIP_FILTER_IN] = plist; + else + ri->prefix[RIP_FILTER_IN] = NULL; + } else + ri->prefix[RIP_FILTER_IN] = NULL; + + if (dist->prefix[DISTRIBUTE_V4_OUT]) { + plist = prefix_list_lookup(AFI_IP, + dist->prefix[DISTRIBUTE_V4_OUT]); + if (plist) + ri->prefix[RIP_FILTER_OUT] = plist; + else + ri->prefix[RIP_FILTER_OUT] = NULL; + } else + ri->prefix[RIP_FILTER_OUT] = NULL; +} + +void rip_distribute_update_interface(struct interface *ifp) +{ + struct distribute *dist; + + dist = distribute_lookup(ifp->name); + if (dist) + rip_distribute_update(dist); } /* Update all interface's distribute list. */ /* ARGSUSED */ -static void -rip_distribute_update_all (struct prefix_list *notused) +static void rip_distribute_update_all(struct prefix_list *notused) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_distribute_update_interface (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_distribute_update_interface(ifp); } /* ARGSUSED */ -static void -rip_distribute_update_all_wrapper(struct access_list *notused) +static void rip_distribute_update_all_wrapper(struct access_list *notused) { - rip_distribute_update_all(NULL); + rip_distribute_update_all(NULL); } /* Delete all added rip route. */ -void -rip_clean (void) +void rip_clean(void) { - int i; - struct route_node *rp; - struct rip_info *rinfo = NULL; - struct list *list = NULL; - struct listnode *listnode = NULL; + int i; + struct route_node *rp; + struct rip_info *rinfo = NULL; + struct list *list = NULL; + struct listnode *listnode = NULL; + + if (rip) { + QOBJ_UNREG(rip); + + /* Clear RIP routes */ + for (rp = route_top(rip->table); rp; rp = route_next(rp)) + if ((list = rp->info) != NULL) { + rinfo = listgetdata(listhead(list)); + if (rip_route_rte(rinfo)) + rip_zebra_ipv4_delete(rp); + + for (ALL_LIST_ELEMENTS_RO(list, listnode, + rinfo)) { + RIP_TIMER_OFF(rinfo->t_timeout); + RIP_TIMER_OFF(rinfo->t_garbage_collect); + rip_info_free(rinfo); + } + list_delete(list); + rp->info = NULL; + route_unlock_node(rp); + } + + /* Cancel RIP related timers. */ + RIP_TIMER_OFF(rip->t_update); + RIP_TIMER_OFF(rip->t_triggered_update); + RIP_TIMER_OFF(rip->t_triggered_interval); + + /* Cancel read thread. */ + THREAD_READ_OFF(rip->t_read); + + /* Close RIP socket. */ + if (rip->sock >= 0) { + close(rip->sock); + rip->sock = -1; + } - if (rip) - { - QOBJ_UNREG (rip); - - /* Clear RIP routes */ - for (rp = route_top (rip->table); rp; rp = route_next (rp)) - if ((list = rp->info) != NULL) - { - rinfo = listgetdata (listhead (list)); - if (rip_route_rte (rinfo)) - rip_zebra_ipv4_delete (rp); - - for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo)) - { - RIP_TIMER_OFF (rinfo->t_timeout); - RIP_TIMER_OFF (rinfo->t_garbage_collect); - rip_info_free (rinfo); - } - list_delete (list); - rp->info = NULL; - route_unlock_node (rp); - } - - /* Cancel RIP related timers. */ - RIP_TIMER_OFF (rip->t_update); - RIP_TIMER_OFF (rip->t_triggered_update); - RIP_TIMER_OFF (rip->t_triggered_interval); - - /* Cancel read thread. */ - THREAD_READ_OFF (rip->t_read); - - /* Close RIP socket. */ - if (rip->sock >= 0) - { - close (rip->sock); - rip->sock = -1; - } - - /* Static RIP route configuration. */ - for (rp = route_top (rip->route); rp; rp = route_next (rp)) - if (rp->info) - { - rp->info = NULL; - route_unlock_node (rp); - } - - /* RIP neighbor configuration. */ - for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) - if (rp->info) - { - rp->info = NULL; - route_unlock_node (rp); - } - - /* Redistribute related clear. */ - if (rip->default_information_route_map) - free (rip->default_information_route_map); - - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (rip->route_map[i].name) - free (rip->route_map[i].name); - - XFREE (MTYPE_ROUTE_TABLE, rip->table); - XFREE (MTYPE_ROUTE_TABLE, rip->route); - XFREE (MTYPE_ROUTE_TABLE, rip->neighbor); - - XFREE (MTYPE_RIP, rip); - rip = NULL; - } - - rip_clean_network (); - rip_passive_nondefault_clean (); - rip_offset_clean (); - rip_interfaces_clean (); - rip_distance_reset (); - rip_redistribute_clean (); + /* Static RIP route configuration. */ + for (rp = route_top(rip->route); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } + + /* RIP neighbor configuration. */ + for (rp = route_top(rip->neighbor); rp; rp = route_next(rp)) + if (rp->info) { + rp->info = NULL; + route_unlock_node(rp); + } + + /* Redistribute related clear. */ + if (rip->default_information_route_map) + free(rip->default_information_route_map); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (rip->route_map[i].name) + free(rip->route_map[i].name); + + XFREE(MTYPE_ROUTE_TABLE, rip->table); + XFREE(MTYPE_ROUTE_TABLE, rip->route); + XFREE(MTYPE_ROUTE_TABLE, rip->neighbor); + + XFREE(MTYPE_RIP, rip); + rip = NULL; + } + + rip_clean_network(); + rip_passive_nondefault_clean(); + rip_offset_clean(); + rip_interfaces_clean(); + rip_distance_reset(); + rip_redistribute_clean(); } /* Reset all values to the default settings. */ -void -rip_reset (void) +void rip_reset(void) { - /* Reset global counters. */ - rip_global_route_changes = 0; - rip_global_queries = 0; + /* Reset global counters. */ + rip_global_route_changes = 0; + rip_global_queries = 0; - /* Call ripd related reset functions. */ - rip_debug_reset (); - rip_route_map_reset (); + /* Call ripd related reset functions. */ + rip_debug_reset(); + rip_route_map_reset(); - /* Call library reset functions. */ - vty_reset (); - access_list_reset (); - prefix_list_reset (); + /* Call library reset functions. */ + vty_reset(); + access_list_reset(); + prefix_list_reset(); - distribute_list_reset (); + distribute_list_reset(); - rip_interfaces_reset (); - rip_distance_reset (); + rip_interfaces_reset(); + rip_distance_reset(); - rip_zclient_reset (); + rip_zclient_reset(); } -static void -rip_if_rmap_update (struct if_rmap *if_rmap) +static void rip_if_rmap_update(struct if_rmap *if_rmap) { - struct interface *ifp; - struct rip_interface *ri; - struct route_map *rmap; + struct interface *ifp; + struct rip_interface *ri; + struct route_map *rmap; - ifp = if_lookup_by_name (if_rmap->ifname, VRF_DEFAULT); - if (ifp == NULL) - return; + ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT); + if (ifp == NULL) + return; - ri = ifp->info; + ri = ifp->info; - if (if_rmap->routemap[IF_RMAP_IN]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]); - if (rmap) - ri->routemap[IF_RMAP_IN] = rmap; - else - ri->routemap[IF_RMAP_IN] = NULL; - } - else - ri->routemap[RIP_FILTER_IN] = NULL; + if (if_rmap->routemap[IF_RMAP_IN]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]); + if (rmap) + ri->routemap[IF_RMAP_IN] = rmap; + else + ri->routemap[IF_RMAP_IN] = NULL; + } else + ri->routemap[RIP_FILTER_IN] = NULL; - if (if_rmap->routemap[IF_RMAP_OUT]) - { - rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]); - if (rmap) - ri->routemap[IF_RMAP_OUT] = rmap; - else - ri->routemap[IF_RMAP_OUT] = NULL; - } - else - ri->routemap[RIP_FILTER_OUT] = NULL; + if (if_rmap->routemap[IF_RMAP_OUT]) { + rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]); + if (rmap) + ri->routemap[IF_RMAP_OUT] = rmap; + else + ri->routemap[IF_RMAP_OUT] = NULL; + } else + ri->routemap[RIP_FILTER_OUT] = NULL; } -void -rip_if_rmap_update_interface (struct interface *ifp) +void rip_if_rmap_update_interface(struct interface *ifp) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap; - if_rmap = if_rmap_lookup (ifp->name); - if (if_rmap) - rip_if_rmap_update (if_rmap); + if_rmap = if_rmap_lookup(ifp->name); + if (if_rmap) + rip_if_rmap_update(if_rmap); } -static void -rip_routemap_update_redistribute (void) +static void rip_routemap_update_redistribute(void) { - int i; + int i; - if (rip) - { - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - { - if (rip->route_map[i].name) - rip->route_map[i].map = - route_map_lookup_by_name (rip->route_map[i].name); + if (rip) { + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (rip->route_map[i].name) + rip->route_map[i].map = + route_map_lookup_by_name( + rip->route_map[i].name); + } } - } } /* ARGSUSED */ -static void -rip_routemap_update (const char *notused) +static void rip_routemap_update(const char *notused) { - struct interface *ifp; - struct listnode *node, *nnode; + struct interface *ifp; + struct listnode *node, *nnode; - for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) - rip_if_rmap_update_interface (ifp); + for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) + rip_if_rmap_update_interface(ifp); - rip_routemap_update_redistribute (); + rip_routemap_update_redistribute(); } /* Allocate new rip structure and set default value. */ -void -rip_init (void) -{ - /* Install top nodes. */ - install_node (&rip_node, config_write_rip); - - /* Install rip commands. */ - install_element (VIEW_NODE, &show_ip_rip_cmd); - install_element (VIEW_NODE, &show_ip_rip_status_cmd); - install_element (CONFIG_NODE, &router_rip_cmd); - install_element (CONFIG_NODE, &no_router_rip_cmd); - - install_default (RIP_NODE); - install_element (RIP_NODE, &rip_version_cmd); - install_element (RIP_NODE, &no_rip_version_cmd); - install_element (RIP_NODE, &rip_default_metric_cmd); - install_element (RIP_NODE, &no_rip_default_metric_cmd); - install_element (RIP_NODE, &rip_timers_cmd); - install_element (RIP_NODE, &no_rip_timers_cmd); - install_element (RIP_NODE, &rip_route_cmd); - install_element (RIP_NODE, &no_rip_route_cmd); - install_element (RIP_NODE, &rip_distance_cmd); - install_element (RIP_NODE, &no_rip_distance_cmd); - install_element (RIP_NODE, &rip_distance_source_cmd); - install_element (RIP_NODE, &no_rip_distance_source_cmd); - install_element (RIP_NODE, &rip_distance_source_access_list_cmd); - install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd); - install_element (RIP_NODE, &rip_allow_ecmp_cmd); - install_element (RIP_NODE, &no_rip_allow_ecmp_cmd); - - /* Debug related init. */ - rip_debug_init (); - - /* Access list install. */ - access_list_init (); - access_list_add_hook (rip_distribute_update_all_wrapper); - access_list_delete_hook (rip_distribute_update_all_wrapper); - - /* Prefix list initialize.*/ - prefix_list_init (); - prefix_list_add_hook (rip_distribute_update_all); - prefix_list_delete_hook (rip_distribute_update_all); - - /* Distribute list install. */ - distribute_list_init (RIP_NODE); - distribute_list_add_hook (rip_distribute_update); - distribute_list_delete_hook (rip_distribute_update); - - /* Route-map */ - rip_route_map_init (); - rip_offset_init (); - - route_map_add_hook (rip_routemap_update); - route_map_delete_hook (rip_routemap_update); - - if_rmap_init (RIP_NODE); - if_rmap_hook_add (rip_if_rmap_update); - if_rmap_hook_delete (rip_if_rmap_update); - - /* Distance control. */ - rip_distance_table = route_table_init (); +void rip_init(void) +{ + /* Install top nodes. */ + install_node(&rip_node, config_write_rip); + + /* Install rip commands. */ + install_element(VIEW_NODE, &show_ip_rip_cmd); + install_element(VIEW_NODE, &show_ip_rip_status_cmd); + install_element(CONFIG_NODE, &router_rip_cmd); + install_element(CONFIG_NODE, &no_router_rip_cmd); + + install_default(RIP_NODE); + install_element(RIP_NODE, &rip_version_cmd); + install_element(RIP_NODE, &no_rip_version_cmd); + install_element(RIP_NODE, &rip_default_metric_cmd); + install_element(RIP_NODE, &no_rip_default_metric_cmd); + install_element(RIP_NODE, &rip_timers_cmd); + install_element(RIP_NODE, &no_rip_timers_cmd); + install_element(RIP_NODE, &rip_route_cmd); + install_element(RIP_NODE, &no_rip_route_cmd); + install_element(RIP_NODE, &rip_distance_cmd); + install_element(RIP_NODE, &no_rip_distance_cmd); + install_element(RIP_NODE, &rip_distance_source_cmd); + install_element(RIP_NODE, &no_rip_distance_source_cmd); + install_element(RIP_NODE, &rip_distance_source_access_list_cmd); + install_element(RIP_NODE, &no_rip_distance_source_access_list_cmd); + install_element(RIP_NODE, &rip_allow_ecmp_cmd); + install_element(RIP_NODE, &no_rip_allow_ecmp_cmd); + + /* Debug related init. */ + rip_debug_init(); + + /* Access list install. */ + access_list_init(); + access_list_add_hook(rip_distribute_update_all_wrapper); + access_list_delete_hook(rip_distribute_update_all_wrapper); + + /* Prefix list initialize.*/ + prefix_list_init(); + prefix_list_add_hook(rip_distribute_update_all); + prefix_list_delete_hook(rip_distribute_update_all); + + /* Distribute list install. */ + distribute_list_init(RIP_NODE); + distribute_list_add_hook(rip_distribute_update); + distribute_list_delete_hook(rip_distribute_update); + + /* Route-map */ + rip_route_map_init(); + rip_offset_init(); + + route_map_add_hook(rip_routemap_update); + route_map_delete_hook(rip_routemap_update); + + if_rmap_init(RIP_NODE); + if_rmap_hook_add(rip_if_rmap_update); + if_rmap_hook_delete(rip_if_rmap_update); + + /* Distance control. */ + rip_distance_table = route_table_init(); } diff --git a/ripd/ripd.h b/ripd/ripd.h index a8e65d1236..895a48c3db 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -98,255 +98,245 @@ #define RIP_AUTH_MD5_COMPAT_SIZE RIP_RTE_SIZE /* RIP structure. */ -struct rip -{ - /* RIP socket. */ - int sock; - - /* Default version of rip instance. */ - int version_send; /* version 1 or 2 (but not both) */ - int version_recv; /* version 1 or 2 or both */ - - /* Output buffer of RIP. */ - struct stream *obuf; - - /* RIP routing information base. */ - struct route_table *table; - - /* RIP only static routing information. */ - struct route_table *route; - - /* RIP neighbor. */ - struct route_table *neighbor; - - /* RIP threads. */ - struct thread *t_read; - - /* Update and garbage timer. */ - struct thread *t_update; - - /* Triggered update hack. */ - int trigger; - struct thread *t_triggered_update; - struct thread *t_triggered_interval; - - /* RIP timer values. */ - unsigned long update_time; - unsigned long timeout_time; - unsigned long garbage_time; - - /* RIP default metric. */ - int default_metric; - - /* RIP default-information originate. */ - u_char default_information; - char *default_information_route_map; - - /* RIP default distance. */ - u_char distance; - struct route_table *distance_table; - - /* RIP ECMP flag */ - unsigned int ecmp; - - /* For redistribute route map. */ - struct - { - char *name; - struct route_map *map; - int metric_config; - u_int32_t metric; - } route_map[ZEBRA_ROUTE_MAX]; - - QOBJ_FIELDS +struct rip { + /* RIP socket. */ + int sock; + + /* Default version of rip instance. */ + int version_send; /* version 1 or 2 (but not both) */ + int version_recv; /* version 1 or 2 or both */ + + /* Output buffer of RIP. */ + struct stream *obuf; + + /* RIP routing information base. */ + struct route_table *table; + + /* RIP only static routing information. */ + struct route_table *route; + + /* RIP neighbor. */ + struct route_table *neighbor; + + /* RIP threads. */ + struct thread *t_read; + + /* Update and garbage timer. */ + struct thread *t_update; + + /* Triggered update hack. */ + int trigger; + struct thread *t_triggered_update; + struct thread *t_triggered_interval; + + /* RIP timer values. */ + unsigned long update_time; + unsigned long timeout_time; + unsigned long garbage_time; + + /* RIP default metric. */ + int default_metric; + + /* RIP default-information originate. */ + u_char default_information; + char *default_information_route_map; + + /* RIP default distance. */ + u_char distance; + struct route_table *distance_table; + + /* RIP ECMP flag */ + unsigned int ecmp; + + /* For redistribute route map. */ + struct { + char *name; + struct route_map *map; + int metric_config; + u_int32_t metric; + } route_map[ZEBRA_ROUTE_MAX]; + + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(rip) /* RIP routing table entry which belong to rip_packet. */ -struct rte -{ - u_int16_t family; /* Address family of this route. */ - u_int16_t tag; /* Route Tag which included in RIP2 packet. */ - struct in_addr prefix; /* Prefix of rip route. */ - struct in_addr mask; /* Netmask of rip route. */ - struct in_addr nexthop; /* Next hop of rip route. */ - u_int32_t metric; /* Metric value of rip route. */ +struct rte { + u_int16_t family; /* Address family of this route. */ + u_int16_t tag; /* Route Tag which included in RIP2 packet. */ + struct in_addr prefix; /* Prefix of rip route. */ + struct in_addr mask; /* Netmask of rip route. */ + struct in_addr nexthop; /* Next hop of rip route. */ + u_int32_t metric; /* Metric value of rip route. */ }; /* RIP packet structure. */ -struct rip_packet -{ - unsigned char command; /* Command type of RIP packet. */ - unsigned char version; /* RIP version which coming from peer. */ - unsigned char pad1; /* Padding of RIP packet header. */ - unsigned char pad2; /* Same as above. */ - struct rte rte[1]; /* Address structure. */ +struct rip_packet { + unsigned char command; /* Command type of RIP packet. */ + unsigned char version; /* RIP version which coming from peer. */ + unsigned char pad1; /* Padding of RIP packet header. */ + unsigned char pad2; /* Same as above. */ + struct rte rte[1]; /* Address structure. */ }; /* Buffer to read RIP packet. */ -union rip_buf -{ - struct rip_packet rip_packet; - char buf[RIP_PACKET_MAXSIZ]; +union rip_buf { + struct rip_packet rip_packet; + char buf[RIP_PACKET_MAXSIZ]; }; /* RIP route information. */ -struct rip_info -{ - /* This route's type. */ - int type; +struct rip_info { + /* This route's type. */ + int type; - /* Sub type. */ - int sub_type; + /* Sub type. */ + int sub_type; - /* RIP nexthop. */ - struct in_addr nexthop; - struct in_addr from; + /* RIP nexthop. */ + struct in_addr nexthop; + struct in_addr from; - /* Which interface does this route come from. */ - ifindex_t ifindex; + /* Which interface does this route come from. */ + ifindex_t ifindex; - /* Metric of this route. */ - u_int32_t metric; + /* Metric of this route. */ + u_int32_t metric; - /* External metric of this route. - if learnt from an externalm proto */ - u_int32_t external_metric; + /* External metric of this route. + if learnt from an externalm proto */ + u_int32_t external_metric; - /* Tag information of this route. */ - u_int16_t tag; + /* Tag information of this route. */ + u_int16_t tag; - /* Flags of RIP route. */ +/* Flags of RIP route. */ #define RIP_RTF_FIB 1 #define RIP_RTF_CHANGED 2 - u_char flags; + u_char flags; - /* Garbage collect timer. */ - struct thread *t_timeout; - struct thread *t_garbage_collect; + /* Garbage collect timer. */ + struct thread *t_timeout; + struct thread *t_garbage_collect; - /* Route-map futures - this variables can be changed. */ - struct in_addr nexthop_out; - u_char metric_set; - u_int32_t metric_out; - u_int16_t tag_out; - ifindex_t ifindex_out; + /* Route-map futures - this variables can be changed. */ + struct in_addr nexthop_out; + u_char metric_set; + u_int32_t metric_out; + u_int16_t tag_out; + ifindex_t ifindex_out; - struct route_node *rp; + struct route_node *rp; - u_char distance; + u_char distance; #ifdef NEW_RIP_TABLE - struct rip_info *next; - struct rip_info *prev; + struct rip_info *next; + struct rip_info *prev; #endif /* NEW_RIP_TABLE */ }; typedef enum { - RIP_NO_SPLIT_HORIZON = 0, - RIP_SPLIT_HORIZON, - RIP_SPLIT_HORIZON_POISONED_REVERSE + RIP_NO_SPLIT_HORIZON = 0, + RIP_SPLIT_HORIZON, + RIP_SPLIT_HORIZON_POISONED_REVERSE } split_horizon_policy_t; /* RIP specific interface configuration. */ -struct rip_interface -{ - /* RIP is enabled on this interface. */ - int enable_network; - int enable_interface; +struct rip_interface { + /* RIP is enabled on this interface. */ + int enable_network; + int enable_interface; - /* RIP is running on this interface. */ - int running; + /* RIP is running on this interface. */ + int running; - /* RIP version control. */ - int ri_send; - int ri_receive; + /* RIP version control. */ + int ri_send; + int ri_receive; - /* RIPv2 broadcast mode */ - int v2_broadcast; + /* RIPv2 broadcast mode */ + int v2_broadcast; - /* RIPv2 authentication type. */ - int auth_type; + /* RIPv2 authentication type. */ + int auth_type; - /* RIPv2 authentication string. */ - char *auth_str; + /* RIPv2 authentication string. */ + char *auth_str; - /* RIPv2 authentication key chain. */ - char *key_chain; + /* RIPv2 authentication key chain. */ + char *key_chain; - /* value to use for md5->auth_len */ - u_int8_t md5_auth_len; + /* value to use for md5->auth_len */ + u_int8_t md5_auth_len; - /* Split horizon flag. */ - split_horizon_policy_t split_horizon; - split_horizon_policy_t split_horizon_default; + /* Split horizon flag. */ + split_horizon_policy_t split_horizon; + split_horizon_policy_t split_horizon_default; - /* For filter type slot. */ +/* For filter type slot. */ #define RIP_FILTER_IN 0 #define RIP_FILTER_OUT 1 #define RIP_FILTER_MAX 2 - /* Access-list. */ - struct access_list *list[RIP_FILTER_MAX]; + /* Access-list. */ + struct access_list *list[RIP_FILTER_MAX]; - /* Prefix-list. */ - struct prefix_list *prefix[RIP_FILTER_MAX]; + /* Prefix-list. */ + struct prefix_list *prefix[RIP_FILTER_MAX]; - /* Route-map. */ - struct route_map *routemap[RIP_FILTER_MAX]; + /* Route-map. */ + struct route_map *routemap[RIP_FILTER_MAX]; - /* Wake up thread. */ - struct thread *t_wakeup; + /* Wake up thread. */ + struct thread *t_wakeup; - /* Interface statistics. */ - int recv_badpackets; - int recv_badroutes; - int sent_updates; + /* Interface statistics. */ + int recv_badpackets; + int recv_badroutes; + int sent_updates; - /* Passive interface. */ - int passive; + /* Passive interface. */ + int passive; }; /* RIP peer information. */ -struct rip_peer -{ - /* Peer address. */ - struct in_addr addr; +struct rip_peer { + /* Peer address. */ + struct in_addr addr; - /* Peer RIP tag value. */ - int domain; + /* Peer RIP tag value. */ + int domain; - /* Last update time. */ - time_t uptime; + /* Last update time. */ + time_t uptime; - /* Peer RIP version. */ - u_char version; + /* Peer RIP version. */ + u_char version; - /* Statistics. */ - int recv_badpackets; - int recv_badroutes; + /* Statistics. */ + int recv_badpackets; + int recv_badroutes; - /* Timeout thread. */ - struct thread *t_timeout; + /* Timeout thread. */ + struct thread *t_timeout; }; -struct rip_md5_info -{ - u_int16_t family; - u_int16_t type; - u_int16_t packet_len; - u_char keyid; - u_char auth_len; - u_int32_t sequence; - u_int32_t reserv1; - u_int32_t reserv2; +struct rip_md5_info { + u_int16_t family; + u_int16_t type; + u_int16_t packet_len; + u_char keyid; + u_char auth_len; + u_int32_t sequence; + u_int32_t reserv1; + u_int32_t reserv2; }; -struct rip_md5_data -{ - u_int16_t family; - u_int16_t type; - u_char digest[16]; +struct rip_md5_data { + u_int16_t family; + u_int16_t type; + u_char digest[16]; }; /* RIP accepet/announce methods. */ @@ -362,11 +352,10 @@ struct rip_md5_data #define RIP_DEFAULT_METRIC_DEFAULT 1 /* RIP event. */ -enum rip_event -{ - RIP_READ, - RIP_UPDATE_EVENT, - RIP_TRIGGERED_UPDATE, +enum rip_event { + RIP_READ, + RIP_UPDATE_EVENT, + RIP_TRIGGERED_UPDATE, }; /* Macro for timer turn on. */ @@ -376,62 +365,64 @@ enum rip_event #define RIP_TIMER_OFF(X) THREAD_TIMER_OFF(X) /* Prototypes. */ -extern void rip_init (void); -extern void rip_reset (void); -extern void rip_clean (void); -extern void rip_clean_network (void); -extern void rip_interfaces_clean (void); -extern void rip_interfaces_reset (void); -extern void rip_passive_nondefault_clean (void); -extern void rip_if_init (void); -extern void rip_if_down_all (void); -extern void rip_route_map_init (void); -extern void rip_route_map_reset (void); +extern void rip_init(void); +extern void rip_reset(void); +extern void rip_clean(void); +extern void rip_clean_network(void); +extern void rip_interfaces_clean(void); +extern void rip_interfaces_reset(void); +extern void rip_passive_nondefault_clean(void); +extern void rip_if_init(void); +extern void rip_if_down_all(void); +extern void rip_route_map_init(void); +extern void rip_route_map_reset(void); extern void rip_zclient_init(struct thread_master *); extern void rip_zclient_stop(void); -extern void rip_zclient_reset (void); -extern void rip_offset_init (void); -extern int if_check_address (struct in_addr addr); - -extern int rip_request_send (struct sockaddr_in *, struct interface *, u_char, - struct connected *); -extern int rip_neighbor_lookup (struct sockaddr_in *); - -extern int rip_redistribute_check (int); -extern void rip_redistribute_add (int, int, struct prefix_ipv4 *, ifindex_t, - struct in_addr *, unsigned int, unsigned char, - route_tag_t); -extern void rip_redistribute_delete (int, int, struct prefix_ipv4 *, ifindex_t); -extern void rip_redistribute_withdraw (int); -extern void rip_zebra_ipv4_add (struct route_node *); -extern void rip_zebra_ipv4_delete (struct route_node *); -extern void rip_interface_multicast_set (int, struct connected *); -extern void rip_distribute_update_interface (struct interface *); -extern void rip_if_rmap_update_interface (struct interface *); - -extern int config_write_rip_network (struct vty *, int); -extern int config_write_rip_offset_list (struct vty *); -extern int config_write_rip_redistribute (struct vty *, int); - -extern void rip_peer_init (void); -extern void rip_peer_update (struct sockaddr_in *, u_char); -extern void rip_peer_bad_route (struct sockaddr_in *); -extern void rip_peer_bad_packet (struct sockaddr_in *); -extern void rip_peer_display (struct vty *); -extern struct rip_peer *rip_peer_lookup (struct in_addr *); -extern struct rip_peer *rip_peer_lookup_next (struct in_addr *); - -extern int rip_offset_list_apply_in (struct prefix_ipv4 *, struct interface *, u_int32_t *); -extern int rip_offset_list_apply_out (struct prefix_ipv4 *, struct interface *, u_int32_t *); -extern void rip_offset_clean (void); - -extern void rip_info_free (struct rip_info *); -extern u_char rip_distance_apply (struct rip_info *); -extern void rip_redistribute_clean (void); - -extern struct rip_info *rip_ecmp_add (struct rip_info *); -extern struct rip_info *rip_ecmp_replace (struct rip_info *); -extern struct rip_info *rip_ecmp_delete (struct rip_info *); +extern void rip_zclient_reset(void); +extern void rip_offset_init(void); +extern int if_check_address(struct in_addr addr); + +extern int rip_request_send(struct sockaddr_in *, struct interface *, u_char, + struct connected *); +extern int rip_neighbor_lookup(struct sockaddr_in *); + +extern int rip_redistribute_check(int); +extern void rip_redistribute_add(int, int, struct prefix_ipv4 *, ifindex_t, + struct in_addr *, unsigned int, unsigned char, + route_tag_t); +extern void rip_redistribute_delete(int, int, struct prefix_ipv4 *, ifindex_t); +extern void rip_redistribute_withdraw(int); +extern void rip_zebra_ipv4_add(struct route_node *); +extern void rip_zebra_ipv4_delete(struct route_node *); +extern void rip_interface_multicast_set(int, struct connected *); +extern void rip_distribute_update_interface(struct interface *); +extern void rip_if_rmap_update_interface(struct interface *); + +extern int config_write_rip_network(struct vty *, int); +extern int config_write_rip_offset_list(struct vty *); +extern int config_write_rip_redistribute(struct vty *, int); + +extern void rip_peer_init(void); +extern void rip_peer_update(struct sockaddr_in *, u_char); +extern void rip_peer_bad_route(struct sockaddr_in *); +extern void rip_peer_bad_packet(struct sockaddr_in *); +extern void rip_peer_display(struct vty *); +extern struct rip_peer *rip_peer_lookup(struct in_addr *); +extern struct rip_peer *rip_peer_lookup_next(struct in_addr *); + +extern int rip_offset_list_apply_in(struct prefix_ipv4 *, struct interface *, + u_int32_t *); +extern int rip_offset_list_apply_out(struct prefix_ipv4 *, struct interface *, + u_int32_t *); +extern void rip_offset_clean(void); + +extern void rip_info_free(struct rip_info *); +extern u_char rip_distance_apply(struct rip_info *); +extern void rip_redistribute_clean(void); + +extern struct rip_info *rip_ecmp_add(struct rip_info *); +extern struct rip_info *rip_ecmp_replace(struct rip_info *); +extern struct rip_info *rip_ecmp_delete(struct rip_info *); /* There is only one rip strucutre. */ extern struct rip *rip; @@ -443,7 +434,7 @@ extern struct thread_master *master; extern long rip_global_route_changes; extern long rip_global_queries; -DECLARE_HOOK(rip_ifaddr_add, (struct connected *ifc), (ifc)) -DECLARE_HOOK(rip_ifaddr_del, (struct connected *ifc), (ifc)) +DECLARE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc)) +DECLARE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc)) #endif /* _ZEBRA_RIP_H */ |
