From cc1131ab011afc4f06c1a967e9c0cbd77cc88d58 Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 15 Oct 2003 23:20:17 +0000 Subject: 2003-10-15 sowmini.varadhan@sun.com * ripd/ripd.c: (rip_send_packet) use rip->sock for mcast sends, instead of creating one socket per send. send source addr to rip_update_interface. (rip_update_process) should send an update on every connected network for each interface. (rip_request_send) should send a request on every connected network for each interface. * ripd/ripd.h: update prototype for rip_interface_multicast_set * ripd/rip_interface.c: (rip_interface_multicast_set) reorganized so that it can be called repeatedly for aliased interfaces (on multiple networks). --- ripd/rip_interface.c | 27 ++++++--------- ripd/ripd.c | 95 ++++++++++++++++++++++++++++++++++++---------------- ripd/ripd.h | 2 +- 3 files changed, 78 insertions(+), 46 deletions(-) (limited to 'ripd') diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 2668e7dc..e3aea186 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -137,28 +137,25 @@ rip_interface_new () } void -rip_interface_multicast_set (int sock, struct interface *ifp) +rip_interface_multicast_set (int sock, struct connected *connected, + int if_pointopoint) { int ret; - listnode node; struct servent *sp; struct sockaddr_in from; - - for (node = listhead (ifp->connected); node; nextnode (node)) - { - struct prefix_ipv4 *p; - struct connected *connected; struct in_addr addr; + struct prefix_ipv4 *p; - connected = getdata (node); + if (if_pointopoint) + p = (struct prefix_ipv4 *) connected->destination; + else p = (struct prefix_ipv4 *) connected->address; - if (p->family == AF_INET) - { addr = p->prefix; + if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, - addr, 0, ifp->ifindex) < 0) + addr, 0, 0) < 0) { zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock); return; @@ -176,6 +173,7 @@ rip_interface_multicast_set (int sock, struct interface *ifp) /* Address shoud be any address. */ from.sin_family = AF_INET; + addr = ((struct prefix_ipv4 *) connected->address)->prefix; from.sin_addr = addr; #ifdef HAVE_SIN_LEN from.sin_len = sizeof (struct sockaddr_in); @@ -184,12 +182,11 @@ rip_interface_multicast_set (int sock, struct interface *ifp) if (ripd_privs.change (ZPRIVS_RAISE)) zlog_err ("rip_interface_multicast_set: could not raise privs"); - ret = bind (sock, (struct sockaddr *) & from, - sizeof (struct sockaddr_in)); + bind (sock, NULL, 0); /* unbind any previous association */ + ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in)); if (ret < 0) { zlog_warn ("Can't bind socket: %s", strerror (errno)); - return; } if (ripd_privs.change (ZPRIVS_LOWER)) @@ -198,8 +195,6 @@ rip_interface_multicast_set (int sock, struct interface *ifp) return; } - } -} /* Send RIP request packet to specified interface. */ void diff --git a/ripd/ripd.c b/ripd/ripd.c index 68f49ac2..accac5e9 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -60,7 +60,8 @@ long rip_global_queries = 0; void rip_event (enum rip_event, int); void rip_output_process (struct interface *, struct prefix *, - struct sockaddr_in *, int, u_char); + struct sockaddr_in *, int, u_char, + struct prefix_ipv4 *); /* RIP output routes type. */ enum @@ -1238,7 +1239,6 @@ rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to, { int ret; struct sockaddr_in sin; - int sock; /* Make destination address. */ memset (&sin, 0, sizeof (struct sockaddr_in)); @@ -1250,39 +1250,29 @@ rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to, /* When destination is specified, use it's port and address. */ if (to) { - sock = rip->sock; - sin.sin_port = to->sin_port; sin.sin_addr = to->sin_addr; } else { - sock = socket (AF_INET, SOCK_DGRAM, 0); - - sockopt_broadcast (sock); - sockopt_reuseaddr (sock); - sockopt_reuseport (sock); sin.sin_port = htons (RIP_PORT_DEFAULT); sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); - /* Set multicast interface. */ - rip_interface_multicast_set (sock, ifp); + /* caller has set multicast interface */ + } - ret = sendto (sock, buf, size, 0, (struct sockaddr *)&sin, + ret = sendto (rip->sock, buf, size, 0, (struct sockaddr *)&sin, sizeof (struct sockaddr_in)); if (IS_RIP_DEBUG_EVENT) - zlog_info ("SEND to socket %d port %d addr %s", - sock, ntohs (sin.sin_port), inet_ntoa(sin.sin_addr)); + zlog_info ("SEND to %s.%d", inet_ntoa(sin.sin_addr), + ntohs (sin.sin_port)); if (ret < 0) zlog_warn ("can't send packet : %s", strerror (errno)); - if (! to) - close (sock); - return ret; } @@ -1454,8 +1444,19 @@ rip_request_process (struct rip_packet *packet, int size, ntohs (rte->family) == 0 && ntohl (rte->metric) == RIP_METRIC_INFINITY) { + struct prefix_ipv4 saddr; + + /* saddr will be used for determining which routes to split-horizon. + Since the source address we'll pick will be on the same subnet as the + destination, for the purpose of split-horizoning, we'll + pretend that "from" is our source address. */ + saddr.family = AF_INET; + saddr.prefixlen = IPV4_MAX_BITLEN; + saddr.prefix = from->sin_addr; + /* All route with split horizon */ - rip_output_process (ifp, NULL, from, rip_all_route, packet->version); + rip_output_process (ifp, NULL, from, rip_all_route, packet->version, + &saddr); } else { @@ -1979,7 +1980,8 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p, /* Send update to the ifp or spcified neighbor. */ void rip_output_process (struct interface *ifp, struct prefix *ifaddr, - struct sockaddr_in *to, int route_type, u_char version) + struct sockaddr_in *to, int route_type, u_char version, + struct prefix_ipv4 *saddr) { int ret; struct stream *s; @@ -2118,7 +2120,7 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr, /* We perform split horizon for RIP and connected route. */ if ((rinfo->type == ZEBRA_ROUTE_RIP || rinfo->type == ZEBRA_ROUTE_CONNECT) && - rinfo->ifindex == ifp->ifindex) + prefix_match((struct prefix *)p, (struct prefix *)saddr)) continue; } @@ -2247,7 +2249,8 @@ rip_output_process (struct interface *ifp, struct prefix *ifaddr, /* Send RIP packet to the interface. */ void -rip_update_interface (struct interface *ifp, u_char version, int route_type) +rip_update_interface (struct interface *ifp, u_char version, int route_type, + struct prefix_ipv4 *saddr) { struct prefix_ipv4 *p; struct connected *connected; @@ -2260,7 +2263,8 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type) if (IS_RIP_DEBUG_EVENT) zlog_info ("multicast announce on %s ", ifp->name); - rip_output_process (ifp, NULL, NULL, route_type, rip->version_send); + rip_output_process (ifp, NULL, NULL, route_type, rip->version_send, + saddr); return; } @@ -2288,7 +2292,7 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type) inet_ntoa (to.sin_addr), ifp->name); rip_output_process (ifp, connected->address, &to, route_type, - rip->version_send); + rip->version_send, saddr); } } } @@ -2298,7 +2302,8 @@ rip_update_interface (struct interface *ifp, u_char version, int route_type) void rip_update_process (int route_type) { - listnode node; + listnode node, ifnode; + struct connected *connected; struct interface *ifp; struct rip_interface *ri; struct route_node *rp; @@ -2336,15 +2341,29 @@ rip_update_process (int route_type) ifp->ifindex); } + /* send update on each connected network */ + + LIST_LOOP(ifp->connected, connected, ifnode) + { + struct prefix_ipv4 *ifaddr; + + /* 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); + + ifaddr = (struct prefix_ipv4 *) connected->address; + + if (ifaddr->family != AF_INET) + continue; + + rip_interface_multicast_set(rip->sock, connected, + if_is_pointopoint(ifp)); if (vsend & RIPv1) - rip_update_interface (ifp, RIPv1, route_type); + rip_update_interface (ifp, RIPv1, route_type, ifaddr); if (vsend & RIPv2) - rip_update_interface (ifp, RIPv2, route_type); + rip_update_interface (ifp, RIPv2, route_type, ifaddr); } } } @@ -2369,7 +2388,7 @@ rip_update_process (int route_type) to.sin_port = htons (RIP_PORT_DEFAULT); /* RIP version is rip's configuration. */ - rip_output_process (ifp, NULL, &to, route_type, rip->version_send); + rip_output_process (ifp, NULL, &to, route_type, rip->version_send, p); } } @@ -2549,6 +2568,8 @@ rip_request_send (struct sockaddr_in *to, struct interface *ifp, { struct rte *rte; struct rip_packet rip_packet; + listnode node; + struct connected *connected; memset (&rip_packet, 0, sizeof (rip_packet)); @@ -2557,7 +2578,23 @@ rip_request_send (struct sockaddr_in *to, struct interface *ifp, rte = rip_packet.rte; rte->metric = htonl (RIP_METRIC_INFINITY); - return rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), to, ifp); + /* send request on each connected network */ + LIST_LOOP(ifp->connected, connected, node) + { + struct prefix_ipv4 *p; + + p = (struct prefix_ipv4 *) connected->address; + + if (p->family != AF_INET) + continue; + + rip_interface_multicast_set(rip->sock, connected, + if_is_pointopoint(ifp)); + if (rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), + to, ifp) != sizeof (rip_packet)) + return -1; + } + return sizeof (rip_packet); } int diff --git a/ripd/ripd.h b/ripd/ripd.h index dc2f64d0..29e4f67c 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -385,7 +385,7 @@ void rip_redistribute_delete (int, int, struct prefix_ipv4 *, unsigned int); void rip_redistribute_withdraw (int); void rip_zebra_ipv4_add (struct prefix_ipv4 *, struct in_addr *, u_int32_t, u_char); void rip_zebra_ipv4_delete (struct prefix_ipv4 *, struct in_addr *, u_int32_t); -void rip_interface_multicast_set (int, struct interface *); +void rip_interface_multicast_set (int, struct connected *, int); void rip_distribute_update_interface (struct interface *); void rip_if_rmap_update_interface (struct interface *); -- cgit v1.2.1