lib: use "protocol-independed API" from RFC3678, if that is available

(This commit is based on the patch from BZ#420, and should fix that bug.)

* configure.ac: detect availability of that API
* sockopt.c (setsockopt_ipv4_multicast): use it for join/leave IPv4
  multicast groups
This commit is contained in:
Dmitrij Tejblum 2011-08-22 11:39:35 +04:00 committed by Denis Ovsienko
parent ee7e75d38b
commit 10d04cdb41
2 changed files with 31 additions and 4 deletions

View file

@ -943,6 +943,15 @@ AC_TRY_COMPILE([#ifdef HAVE_SYS_PARAM_H
AC_DEFINE(HAVE_BSD_STRUCT_IP_MREQ_HACK,,[Can pass ifindex in struct ip_mreq])], AC_DEFINE(HAVE_BSD_STRUCT_IP_MREQ_HACK,,[Can pass ifindex in struct ip_mreq])],
AC_MSG_RESULT(no)) AC_MSG_RESULT(no))
AC_MSG_CHECKING([for RFC3678 protocol-independed API])
AC_TRY_COMPILE([
#include <sys/types.h>
#include <netinet/in.h>
], [struct group_req gr; int sock; setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void*)&gr, sizeof(gr));
], [AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_RFC3678,1,[Have RFC3678 protocol-independed API])],
AC_MSG_RESULT(no))
dnl --------------------------------------------------------------- dnl ---------------------------------------------------------------
dnl figure out how to check link-state dnl figure out how to check link-state
dnl --------------------------------------------------------------- dnl ---------------------------------------------------------------

View file

@ -209,17 +209,35 @@ setsockopt_ipv4_multicast(int sock,
unsigned int mcast_addr, unsigned int mcast_addr,
unsigned int ifindex) unsigned int ifindex)
{ {
#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;
#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX #elif defined(HAVE_STRUCT_IP_MREQN_IMR_IFINDEX) && !defined(__FreeBSD__)
struct ip_mreqn mreqn; struct ip_mreqn mreqn;
int ret; int ret;
assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP); assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
memset (&mreqn, 0, sizeof(mreqn)); memset (&mreqn, 0, sizeof(mreqn));
if (mcast_addr) mreqn.imr_multiaddr.s_addr = mcast_addr;
mreqn.imr_multiaddr.s_addr = mcast_addr;
mreqn.imr_ifindex = ifindex; mreqn.imr_ifindex = ifindex;
ret = setsockopt(sock, IPPROTO_IP, optname, ret = setsockopt(sock, IPPROTO_IP, optname,