On 2013/01/03 00:27, Stuart Henderson wrote: > On 2013/01/01 18:26, Raphael Mazelier wrote: > > I resent to ports since I think this list is more readen than ports-bugs. > > Will take a look, thanks. > > > I wrote a first 'naive' patch wich work, at least for me. (attached) > > I was difficult to make a clean patch because quagga broke/change > > their multicast api in lib/sockopt.c, removing (struct iface *iface) > > parameter from their functions, and using (struct ip_mreq mreq) seems > > not working. So I just reuse the old code and paste it directly in > > opsf_network.c. Hope that more experimented people could make a > > better patch and send it upstream. > > This affects RIP too - I prefer to add a patch to the quagga port > which reverts their relevant commits for now. > > A nicer fix would be to support the RFC3678 API in the kernel. >
Can you give this a spin please? Diff below, or there's a tar of the whole quagga/ port directory attached if you have trouble applying it. Index: Makefile =================================================================== RCS file: /cvs/ports/net/quagga/Makefile,v retrieving revision 1.31 diff -u -p -r1.31 Makefile --- Makefile 8 Dec 2012 18:42:43 -0000 1.31 +++ Makefile 3 Jan 2013 00:48:29 -0000 @@ -3,7 +3,7 @@ COMMENT= multi-threaded routing daemon DISTNAME= quagga-0.99.21 -REVISION= 0 +REVISION= 1 SHARED_LIBS= ospf 0.0 \ ospfapiclient 0.0 \ zebra 0.0 Index: patches/patch-lib_sockopt_c =================================================================== RCS file: patches/patch-lib_sockopt_c diff -N patches/patch-lib_sockopt_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-lib_sockopt_c 3 Jan 2013 00:48:29 -0000 @@ -0,0 +1,237 @@ +$OpenBSD$ + +Revert 69bf3a39; does not work on at least (Open/Net)BSD. +This can be put back if we get RFC3678 support. + +--- lib/sockopt.c.orig Thu Jan 3 00:29:56 2013 ++++ lib/sockopt.c Thu Jan 3 00:29:45 2013 +@@ -197,7 +197,7 @@ setsockopt_ipv6_tclass(int sock, int tclass) + + /* + * Process multicast socket options for IPv4 in an OS-dependent manner. +- * Supported options are IP_{ADD,DROP}_MEMBERSHIP. ++ * Supported options are IP_MULTICAST_IF and IP_{ADD,DROP}_MEMBERSHIP. + * + * Many operating systems have a limit on the number of groups that + * can be joined per socket (where each group and local address +@@ -217,133 +217,121 @@ setsockopt_ipv6_tclass(int sock, int tclass) + * allow leaves, or implicitly leave all groups joined to down interfaces. + */ + int +-setsockopt_ipv4_multicast(int sock, ++setsockopt_multicast_ipv4(int sock, + int optname, ++ struct in_addr if_addr /* required */, + unsigned int mcast_addr, +- unsigned int ifindex) ++ unsigned int ifindex /* optional: if non-zero, may be ++ used instead of if_addr */) + { +-#ifdef HAVE_RFC3678 +- struct group_req gr; +- struct sockaddr_in *si; +- int ret; +- memset (&gr, 0, sizeof(gr)); +- si = (struct sockaddr_in *)&gr.gr_group; +- gr.gr_interface = ifindex; +- si->sin_family = AF_INET; +-#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN +- si->sin_len = sizeof(struct sockaddr_in); +-#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +- si->sin_addr.s_addr = mcast_addr; +- ret = setsockopt(sock, IPPROTO_IP, (optname == IP_ADD_MEMBERSHIP) ? +- MCAST_JOIN_GROUP : MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr)); +- if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) +- { +- setsockopt(sock, IPPROTO_IP, MCAST_LEAVE_GROUP, (void *)&gr, sizeof(gr)); +- ret = setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void *)&gr, sizeof(gr)); +- } +- return ret; + +-#elif defined(HAVE_STRUCT_IP_MREQN_IMR_IFINDEX) && !defined(__FreeBSD__) ++#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX ++ /* This is better because it uses ifindex directly */ + struct ip_mreqn mreqn; + int ret; + +- assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); +- memset (&mreqn, 0, sizeof(mreqn)); +- +- mreqn.imr_multiaddr.s_addr = mcast_addr; +- mreqn.imr_ifindex = ifindex; +- +- ret = setsockopt(sock, IPPROTO_IP, optname, +- (void *)&mreqn, sizeof(mreqn)); +- if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) ++ switch (optname) + { +- /* see above: handle possible problem when interface comes back up */ +- char buf[1][INET_ADDRSTRLEN]; +- zlog_info("setsockopt_ipv4_multicast attempting to drop and " +- "re-add (fd %d, mcast %s, ifindex %u)", +- sock, +- inet_ntop(AF_INET, &mreqn.imr_multiaddr, +- buf[0], sizeof(buf[0])), ifindex); +- setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, +- (void *)&mreqn, sizeof(mreqn)); +- ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, +- (void *)&mreqn, sizeof(mreqn)); ++ case IP_MULTICAST_IF: ++ case IP_ADD_MEMBERSHIP: ++ case IP_DROP_MEMBERSHIP: ++ memset (&mreqn, 0, sizeof(mreqn)); ++ ++ if (mcast_addr) ++ mreqn.imr_multiaddr.s_addr = mcast_addr; ++ ++ if (ifindex) ++ mreqn.imr_ifindex = ifindex; ++ else ++ mreqn.imr_address = if_addr; ++ ++ ret = setsockopt(sock, IPPROTO_IP, optname, ++ (void *)&mreqn, sizeof(mreqn)); ++ if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) ++ { ++ /* see above: handle possible problem when interface comes back up */ ++ char buf[2][INET_ADDRSTRLEN]; ++ zlog_info("setsockopt_multicast_ipv4 attempting to drop and " ++ "re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)", ++ sock, ++ inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])), ++ inet_ntop(AF_INET, &mreqn.imr_multiaddr, ++ buf[1], sizeof(buf[1])), ifindex); ++ setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, ++ (void *)&mreqn, sizeof(mreqn)); ++ ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, ++ (void *)&mreqn, sizeof(mreqn)); ++ } ++ return ret; ++ break; ++ ++ default: ++ /* Can out and give an understandable error */ ++ errno = EINVAL; ++ return -1; ++ break; + } +- return ret; + + /* Example defines for another OS, boilerplate off other code in this + function, AND handle optname as per other sections for consistency !! */ + /* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ + /* Add your favourite OS here! */ + +-#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */ ++#else /* #if OS_TYPE */ + /* standard BSD API */ + + struct in_addr m; + struct ip_mreq mreq; + int ret; + +- assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); ++#ifdef HAVE_BSD_STRUCT_IP_MREQ_HACK ++ if (ifindex) ++ m.s_addr = htonl(ifindex); ++ else ++#endif ++ m = if_addr; + +- m.s_addr = htonl(ifindex); +- +- memset (&mreq, 0, sizeof(mreq)); +- mreq.imr_multiaddr.s_addr = mcast_addr; +- mreq.imr_interface = m; +- +- ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq)); +- if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) ++ switch (optname) + { +- /* see above: handle possible problem when interface comes back up */ +- char buf[1][INET_ADDRSTRLEN]; +- zlog_info("setsockopt_ipv4_multicast attempting to drop and " +- "re-add (fd %d, mcast %s, ifindex %u)", +- sock, +- inet_ntop(AF_INET, &mreq.imr_multiaddr, +- buf[0], sizeof(buf[0])), ifindex); +- setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, +- (void *)&mreq, sizeof(mreq)); +- ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, +- (void *)&mreq, sizeof(mreq)); +- } +- return ret; ++ case IP_MULTICAST_IF: ++ return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m)); ++ break; + +-#else +- #error "Unsupported multicast API" ++ case IP_ADD_MEMBERSHIP: ++ case IP_DROP_MEMBERSHIP: ++ memset (&mreq, 0, sizeof(mreq)); ++ mreq.imr_multiaddr.s_addr = mcast_addr; ++ mreq.imr_interface = m; ++ ++ ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq)); ++ if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE)) ++ { ++ /* see above: handle possible problem when interface comes back up */ ++ char buf[2][INET_ADDRSTRLEN]; ++ zlog_info("setsockopt_multicast_ipv4 attempting to drop and " ++ "re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)", ++ sock, ++ inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])), ++ inet_ntop(AF_INET, &mreq.imr_multiaddr, ++ buf[1], sizeof(buf[1])), ifindex); ++ setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, ++ (void *)&mreq, sizeof(mreq)); ++ ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, ++ (void *)&mreq, sizeof(mreq)); ++ } ++ return ret; ++ break; ++ ++ default: ++ /* Can out and give an understandable error */ ++ errno = EINVAL; ++ return -1; ++ break; ++ } + #endif /* #if OS_TYPE */ + + } + +-/* +- * Set IP_MULTICAST_IF socket option in an OS-dependent manner. +- */ +-int +-setsockopt_ipv4_multicast_if(int sock, +- unsigned int ifindex) +-{ +- +-#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX +- struct ip_mreqn mreqn; +- memset (&mreqn, 0, sizeof(mreqn)); +- +- mreqn.imr_ifindex = ifindex; +- return setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreqn, sizeof(mreqn)); +- +- /* Example defines for another OS, boilerplate off other code in this +- function */ +- /* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */ +- /* Add your favourite OS here! */ +-#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) +- struct in_addr m; +- +- m.s_addr = htonl(ifindex); +- +- return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m)); +-#else +- #error "Unsupported multicast API" +-#endif +-} +- + static int + setsockopt_ipv4_ifindex (int sock, int val) + { Index: patches/patch-lib_sockopt_h =================================================================== RCS file: patches/patch-lib_sockopt_h diff -N patches/patch-lib_sockopt_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-lib_sockopt_h 3 Jan 2013 00:48:29 -0000 @@ -0,0 +1,25 @@ +$OpenBSD$ + +Revert 69bf3a39; does not work on at least (Open/Net)BSD. +This can be put back if we get RFC3678 support. + +--- lib/sockopt.h.orig Tue Apr 17 14:56:26 2012 ++++ lib/sockopt.h Thu Jan 3 00:24:26 2013 +@@ -83,11 +83,13 @@ extern int setsockopt_ipv6_tclass (int, int); + (((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \ + ? SOPT_SIZE_CMSG_PKTINFO_IPV6()) + +-extern int setsockopt_ipv4_multicast_if(int sock, +- unsigned int ifindex); +-extern int setsockopt_ipv4_multicast(int sock, int optname, ++extern int setsockopt_multicast_ipv4(int sock, int optname, ++ struct in_addr if_addr ++ /* required: interface to join on */, + unsigned int mcast_addr, +- unsigned int ifindex); ++ unsigned int ifindex ++ /* optional: if non-zero, may be used ++ instead of if_addr */); + extern int setsockopt_ipv4_tos(int sock, int tos); + + /* Ask for, and get, ifindex, by whatever method is supported. */ Index: patches/patch-ospfd_ospf_network_c =================================================================== RCS file: patches/patch-ospfd_ospf_network_c diff -N patches/patch-ospfd_ospf_network_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-ospfd_ospf_network_c 3 Jan 2013 00:48:29 -0000 @@ -0,0 +1,61 @@ +$OpenBSD$ + +Revert 69bf3a39; does not work on at least (Open/Net)BSD. +This can be put back if we get RFC3678 support. + +--- ospfd/ospf_network.c.orig Tue Apr 17 14:56:26 2012 ++++ ospfd/ospf_network.c Thu Jan 3 00:24:26 2013 +@@ -52,8 +52,8 @@ ospf_if_add_allspfrouters (struct ospf *top, struct pr + { + int ret; + +- ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, +- htonl (OSPF_ALLSPFROUTERS), ++ ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP, ++ p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), + ifindex); + if (ret < 0) + zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " +@@ -73,8 +73,8 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct p + { + int ret; + +- ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, +- htonl (OSPF_ALLSPFROUTERS), ++ ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP, ++ p->u.prefix4, htonl (OSPF_ALLSPFROUTERS), + ifindex); + if (ret < 0) + zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " +@@ -94,8 +94,8 @@ ospf_if_add_alldrouters (struct ospf *top, struct pref + { + int ret; + +- ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP, +- htonl (OSPF_ALLDROUTERS), ++ ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP, ++ p->u.prefix4, htonl (OSPF_ALLDROUTERS), + ifindex); + if (ret < 0) + zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, " +@@ -115,8 +115,8 @@ ospf_if_drop_alldrouters (struct ospf *top, struct pre + { + int ret; + +- ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP, +- htonl (OSPF_ALLDROUTERS), ++ ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP, ++ p->u.prefix4, htonl (OSPF_ALLDROUTERS), + ifindex); + if (ret < 0) + zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, " +@@ -151,7 +151,8 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix * + zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", + top->fd, safe_strerror (errno)); + +- ret = setsockopt_ipv4_multicast_if (top->fd, ifindex); ++ ret = setsockopt_multicast_ipv4 (top->fd, IP_MULTICAST_IF, ++ p->u.prefix4, 0, ifindex); + if (ret < 0) + zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, " + "ifindex %u): %s", Index: patches/patch-ripd_rip_interface_c =================================================================== RCS file: patches/patch-ripd_rip_interface_c diff -N patches/patch-ripd_rip_interface_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-ripd_rip_interface_c 3 Jan 2013 00:48:29 -0000 @@ -0,0 +1,51 @@ +$OpenBSD$ + +Revert 69bf3a39; does not work on at least (Open/Net)BSD. +This can be put back if we get RFC3678 support. + +--- ripd/rip_interface.c.orig Tue Apr 17 14:56:26 2012 ++++ ripd/rip_interface.c Thu Jan 3 00:24:26 2013 +@@ -78,8 +78,9 @@ ipv4_multicast_join (int sock, + { + int ret; + +- ret = setsockopt_ipv4_multicast (sock, ++ ret = setsockopt_multicast_ipv4 (sock, + IP_ADD_MEMBERSHIP, ++ ifa, + group.s_addr, + ifindex); + +@@ -99,8 +100,9 @@ ipv4_multicast_leave (int sock, + { + int ret; + +- ret = setsockopt_ipv4_multicast (sock, ++ ret = setsockopt_multicast_ipv4 (sock, + IP_DROP_MEMBERSHIP, ++ ifa, + group.s_addr, + ifindex); + +@@ -136,13 +138,18 @@ rip_interface_new (void) + void + rip_interface_multicast_set (int sock, struct connected *connected) + { ++ struct in_addr addr; ++ + assert (connected != NULL); + +- if (setsockopt_ipv4_multicast_if (sock, connected->ifp->ifindex) < 0) ++ addr = CONNECTED_ID(connected)->u.prefix4; ++ ++ if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0, ++ 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, ++ "source address %s for interface %s", ++ sock, inet_ntoa(addr), + connected->ifp->name); + } +
quagga.tgz
Description: application/tar-gz