From 2f3eaa65d516cc9b503141da15b0c4032c949af0 Mon Sep 17 00:00:00 2001 From: phk Date: Wed, 30 Jul 2008 11:56:15 +0000 Subject: Update routed to use the RFC 3678 protocol-independent multicast API. Use IP_MULTICAST_IF with struct ip_mreqn (obtained from Linux) to tell the stack which interface index to use for sending IPv4 datagrams. Submitted by: bms Tested by: phk --- sbin/routed/defs.h | 15 ---------- sbin/routed/if.c | 31 ++++++++++----------- sbin/routed/main.c | 26 ++++++++--------- sbin/routed/output.c | 33 ++++++---------------- sbin/routed/rdisc.c | 79 +++++++++++++++++++++------------------------------- 5 files changed, 66 insertions(+), 118 deletions(-) (limited to 'sbin/routed') diff --git a/sbin/routed/defs.h b/sbin/routed/defs.h index 9860e4d..ff6e8ab 100644 --- a/sbin/routed/defs.h +++ b/sbin/routed/defs.h @@ -121,21 +121,6 @@ #define _HAVE_SIN_LEN #endif -/* Turn on if IP_{ADD,DROP}_MEMBERSHIP and IP_MULTICAST_IF considers address - * within 0.0.0.0/8 as interface index. - */ -#ifdef __FreeBSD__ -#define MCAST_IFINDEX -#endif - -/* Turn on if IP_DROP_MEMBERSHIP and IP_ADD_MEMBERSHIP do not look at - * the dstaddr of point-to-point interfaces. - * #define MCAST_PPP_BUG - */ -#ifdef MCAST_IFINDEX -#undef MCAST_PPP_BUG -#endif - #define DAY (24*60*60) #define NEVER DAY /* a long time */ #define EPOCH NEVER /* bias time by this to avoid <0 */ diff --git a/sbin/routed/if.c b/sbin/routed/if.c index f8038f6a..09b03af 100644 --- a/sbin/routed/if.c +++ b/sbin/routed/if.c @@ -452,7 +452,6 @@ check_remote(struct interface *ifp) static void ifdel(struct interface *ifp) { - struct ip_mreq m; struct interface *ifp1; @@ -491,25 +490,23 @@ ifdel(struct interface *ifp) ifdel(ifp1); } - if ((ifp->int_if_flags & IFF_MULTICAST) -#ifdef MCAST_PPP_BUG - && !(ifp->int_if_flags & IFF_POINTOPOINT) -#endif - && rip_sock >= 0) { - m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP); -#ifdef MCAST_IFINDEX - m.imr_interface.s_addr = htonl(ifp->int_index); -#else - m.imr_interface.s_addr = ((ifp->int_if_flags - & IFF_POINTOPOINT) - ? ifp->int_dstaddr - : ifp->int_addr); + if ((ifp->int_if_flags & IFF_MULTICAST) && rip_sock >= 0) { + struct group_req gr; + struct sockaddr_in *sin; + + memset(&gr, 0, sizeof(gr)); + gr.gr_interface = ifp->int_index; + sin = (struct sockaddr_in *)&gr.gr_group; + sin->sin_family = AF_INET; +#ifdef _HAVE_SIN_LEN + sin->sin_len = sizeof(struct sockaddr_in); #endif - if (setsockopt(rip_sock,IPPROTO_IP,IP_DROP_MEMBERSHIP, - &m, sizeof(m)) < 0 + sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP); + if (setsockopt(rip_sock, IPPROTO_IP, MCAST_LEAVE_GROUP, + &gr, sizeof(gr)) < 0 && errno != EADDRNOTAVAIL && !TRACEACTIONS) - LOGERR("setsockopt(IP_DROP_MEMBERSHIP RIP)"); + LOGERR("setsockopt(MCAST_LEAVE_GROUP RIP)"); if (rip_sock_mcast == ifp) rip_sock_mcast = 0; } diff --git a/sbin/routed/main.c b/sbin/routed/main.c index 7c3c5ac..674d232 100644 --- a/sbin/routed/main.c +++ b/sbin/routed/main.c @@ -713,25 +713,23 @@ rip_off(void) static void rip_mcast_on(struct interface *ifp) { - struct ip_mreq m; + struct group_req gr; + struct sockaddr_in *sin; if (!IS_RIP_IN_OFF(ifp->int_state) && (ifp->int_if_flags & IFF_MULTICAST) -#ifdef MCAST_PPP_BUG - && !(ifp->int_if_flags & IFF_POINTOPOINT) -#endif && !(ifp->int_state & IS_ALIAS)) { - m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP); -#ifdef MCAST_IFINDEX - m.imr_interface.s_addr = htonl(ifp->int_index); -#else - m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT) - ? ifp->int_dstaddr - : ifp->int_addr); + memset(&gr, 0, sizeof(gr)); + gr.gr_interface = ifp->int_index; + sin = (struct sockaddr_in *)&gr.gr_group; + sin->sin_family = AF_INET; +#ifdef _HAVE_SIN_LEN + sin->sin_len = sizeof(struct sockaddr_in); #endif - if (setsockopt(rip_sock,IPPROTO_IP, IP_ADD_MEMBERSHIP, - &m, sizeof(m)) < 0) - LOGERR("setsockopt(IP_ADD_MEMBERSHIP RIP)"); + sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP); + if (setsockopt(rip_sock, IPPROTO_IP, MCAST_JOIN_GROUP, + &gr, sizeof(gr)) < 0) + LOGERR("setsockopt(MCAST_JOIN_GROUP RIP)"); } } diff --git a/sbin/routed/output.c b/sbin/routed/output.c index c9db470..c555c21 100644 --- a/sbin/routed/output.c +++ b/sbin/routed/output.c @@ -104,7 +104,6 @@ output(enum output_type type, int flags; const char *msg; int res; - naddr tgt_mcast; int soc; int serrno; @@ -150,31 +149,17 @@ output(enum output_type type, } else { msg = "Send mcast"; if (rip_sock_mcast != ifp) { -#ifdef MCAST_IFINDEX - /* specify ifindex */ - tgt_mcast = htonl(ifp->int_index); -#else -#ifdef MCAST_PPP_BUG - /* Do not specify the primary interface - * explicitly if we have the multicast - * point-to-point kernel bug, since the - * kernel will do the wrong thing if the - * local address of a point-to-point link - * is the same as the address of an ordinary - * interface. - */ - if (ifp->int_addr == myaddr) { - tgt_mcast = 0; - } else -#endif - tgt_mcast = ifp->int_addr; -#endif + struct ip_mreqn mreqn; + + memset(&mreqn, 0, sizeof(struct ip_mreqn)); + mreqn.imr_ifindex = ifp->int_index; if (0 > setsockopt(rip_sock, - IPPROTO_IP, IP_MULTICAST_IF, - &tgt_mcast, - sizeof(tgt_mcast))) { + IPPROTO_IP, + IP_MULTICAST_IF, + &mreqn, + sizeof(mreqn))) { serrno = errno; - LOGERR("setsockopt(rip_sock," + LOGERR("setsockopt(rip_sock, " "IP_MULTICAST_IF)"); errno = serrno; ifp = 0; diff --git a/sbin/routed/rdisc.c b/sbin/routed/rdisc.c index 047b3d1..496f212 100644 --- a/sbin/routed/rdisc.c +++ b/sbin/routed/rdisc.c @@ -168,7 +168,8 @@ void set_rdisc_mg(struct interface *ifp, int on) /* 0=turn it off */ { - struct ip_mreq m; + struct group_req gr; + struct sockaddr_in *sin; if (rdisc_sock < 0) { /* Create the raw socket so that we can hear at least @@ -185,39 +186,35 @@ set_rdisc_mg(struct interface *ifp, return; } -#ifdef MCAST_PPP_BUG - if (ifp->int_if_flags & IFF_POINTOPOINT) - return; -#endif - memset(&m, 0, sizeof(m)); -#ifdef MCAST_IFINDEX - m.imr_interface.s_addr = htonl(ifp->int_index); -#else - m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT) - ? ifp->int_dstaddr - : ifp->int_addr); + memset(&gr, 0, sizeof(gr)); + gr.gr_interface = ifp->int_index; + sin = (struct sockaddr_in *)&gr.gr_group; + sin->sin_family = AF_INET; +#ifdef _HAVE_SIN_LEN + sin->sin_len = sizeof(struct sockaddr_in); #endif + if (supplier || (ifp->int_state & IS_NO_ADV_IN) || !on) { /* stop listening to advertisements */ if (ifp->int_state & IS_ALL_HOSTS) { - m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); + sin->sin_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); if (setsockopt(rdisc_sock, IPPROTO_IP, - IP_DROP_MEMBERSHIP, - &m, sizeof(m)) < 0) - LOGERR("IP_DROP_MEMBERSHIP ALLHOSTS"); + MCAST_LEAVE_GROUP, + &gr, sizeof(gr)) < 0) + LOGERR("MCAST_LEAVE_GROUP ALLHOSTS"); ifp->int_state &= ~IS_ALL_HOSTS; } } else if (!(ifp->int_state & IS_ALL_HOSTS)) { /* start listening to advertisements */ - m.imr_multiaddr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); - if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, - &m, sizeof(m)) < 0) { - LOGERR("IP_ADD_MEMBERSHIP ALLHOSTS"); + sin->sin_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); + if (setsockopt(rdisc_sock, IPPROTO_IP, MCAST_JOIN_GROUP, + &gr, sizeof(gr)) < 0) { + LOGERR("MCAST_JOIN_GROUP ALLHOSTS"); } else { ifp->int_state |= IS_ALL_HOSTS; } @@ -229,21 +226,21 @@ set_rdisc_mg(struct interface *ifp, /* stop listening to solicitations */ if (ifp->int_state & IS_ALL_ROUTERS) { - m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP); + sin->sin_addr.s_addr = htonl(INADDR_ALLROUTERS_GROUP); if (setsockopt(rdisc_sock, IPPROTO_IP, - IP_DROP_MEMBERSHIP, - &m, sizeof(m)) < 0) - LOGERR("IP_DROP_MEMBERSHIP ALLROUTERS"); + MCAST_LEAVE_GROUP, + &gr, sizeof(gr)) < 0) + LOGERR("MCAST_LEAVE_GROUP ALLROUTERS"); ifp->int_state &= ~IS_ALL_ROUTERS; } } else if (!(ifp->int_state & IS_ALL_ROUTERS)) { /* start hearing solicitations */ - m.imr_multiaddr.s_addr=htonl(INADDR_ALLROUTERS_GROUP); - if (setsockopt(rdisc_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, - &m, sizeof(m)) < 0) { - LOGERR("IP_ADD_MEMBERSHIP ALLROUTERS"); + sin->sin_addr.s_addr = htonl(INADDR_ALLROUTERS_GROUP); + if (setsockopt(rdisc_sock, IPPROTO_IP, MCAST_JOIN_GROUP, + &gr, sizeof(gr)) < 0) { + LOGERR("MCAST_JOIN_GROUP ALLROUTERS"); } else { ifp->int_state |= IS_ALL_ROUTERS; } @@ -699,7 +696,6 @@ send_rdisc(union ad_u *p, struct sockaddr_in rsin; int flags; const char *msg; - naddr tgt_mcast; memset(&rsin, 0, sizeof(rsin)); @@ -736,27 +732,14 @@ send_rdisc(union ad_u *p, } if (rdisc_sock_mcast != ifp) { /* select the right interface. */ -#ifdef MCAST_IFINDEX - /* specify ifindex */ - tgt_mcast = htonl(ifp->int_index); -#else -#ifdef MCAST_PPP_BUG - /* Do not specify the primary interface explicitly - * if we have the multicast point-to-point kernel - * bug, since the kernel will do the wrong thing - * if the local address of a point-to-point link - * is the same as the address of an ordinary - * interface. - */ - if (ifp->int_addr == myaddr) { - tgt_mcast = 0; - } else -#endif - tgt_mcast = ifp->int_addr; -#endif + struct ip_mreqn mreqn; + + memset(&mreqn, 0, sizeof(struct ip_mreqn)); + mreqn.imr_ifindex = ifp->int_index; if (0 > setsockopt(rdisc_sock, IPPROTO_IP, IP_MULTICAST_IF, - &tgt_mcast, sizeof(tgt_mcast))) { + &mreqn, + sizeof(mreqn))) { LOGERR("setsockopt(rdisc_sock," "IP_MULTICAST_IF)"); rdisc_sock_mcast = 0; -- cgit v1.1