mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-04 05:16:19 +00:00
lib: simplify interface of setsockopt_multicast_ipv4().
* sockopt.[ch] (setsockopt_ipv4_multicast): ifindex is now mandatory (all non-ancient OSes can use it anyway), and if_addr parameter (the address of the interface) is now gone. (setsockopt_ipv4_multicast_if): IP_MULTICAST_IF processing moved to this new function * ospf_network.c (ospf_if_add_allspfrouters, ospf_if_drop_allspfrouters, ospf_if_add_alldrouters, ospf_if_drop_alldrouters, ospf_if_ipmulticast), rip_interface.c (ipv4_multicast_join, ipv4_multicast_leave, rip_interface_new): adapt to the new interface
This commit is contained in:
parent
9fa6be78ec
commit
bf510e9bc0
@ -184,7 +184,7 @@ getsockopt_ipv6_ifindex (struct msghdr *msgh)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Process multicast socket options for IPv4 in an OS-dependent manner.
|
* Process multicast socket options for IPv4 in an OS-dependent manner.
|
||||||
* Supported options are IP_MULTICAST_IF and IP_{ADD,DROP}_MEMBERSHIP.
|
* Supported options are IP_{ADD,DROP}_MEMBERSHIP.
|
||||||
*
|
*
|
||||||
* Many operating systems have a limit on the number of groups that
|
* Many operating systems have a limit on the number of groups that
|
||||||
* can be joined per socket (where each group and local address
|
* can be joined per socket (where each group and local address
|
||||||
@ -204,22 +204,18 @@ getsockopt_ipv6_ifindex (struct msghdr *msgh)
|
|||||||
* allow leaves, or implicitly leave all groups joined to down interfaces.
|
* allow leaves, or implicitly leave all groups joined to down interfaces.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
setsockopt_multicast_ipv4(int sock,
|
setsockopt_ipv4_multicast(int sock,
|
||||||
int optname,
|
int optname,
|
||||||
struct in_addr if_addr /* required */,
|
|
||||||
unsigned int mcast_addr,
|
unsigned int mcast_addr,
|
||||||
unsigned int ifindex /* optional: if non-zero, may be
|
unsigned int ifindex)
|
||||||
used instead of if_addr */)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
|
#ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
|
||||||
/* This is better because it uses ifindex directly */
|
|
||||||
struct ip_mreqn mreqn;
|
struct ip_mreqn mreqn;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (optname)
|
switch (optname)
|
||||||
{
|
{
|
||||||
case IP_MULTICAST_IF:
|
|
||||||
case IP_ADD_MEMBERSHIP:
|
case IP_ADD_MEMBERSHIP:
|
||||||
case IP_DROP_MEMBERSHIP:
|
case IP_DROP_MEMBERSHIP:
|
||||||
memset (&mreqn, 0, sizeof(mreqn));
|
memset (&mreqn, 0, sizeof(mreqn));
|
||||||
@ -227,23 +223,19 @@ setsockopt_multicast_ipv4(int sock,
|
|||||||
if (mcast_addr)
|
if (mcast_addr)
|
||||||
mreqn.imr_multiaddr.s_addr = mcast_addr;
|
mreqn.imr_multiaddr.s_addr = mcast_addr;
|
||||||
|
|
||||||
if (ifindex)
|
mreqn.imr_ifindex = ifindex;
|
||||||
mreqn.imr_ifindex = ifindex;
|
|
||||||
else
|
|
||||||
mreqn.imr_address = if_addr;
|
|
||||||
|
|
||||||
ret = setsockopt(sock, IPPROTO_IP, optname,
|
ret = setsockopt(sock, IPPROTO_IP, optname,
|
||||||
(void *)&mreqn, sizeof(mreqn));
|
(void *)&mreqn, sizeof(mreqn));
|
||||||
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
||||||
{
|
{
|
||||||
/* see above: handle possible problem when interface comes back up */
|
/* see above: handle possible problem when interface comes back up */
|
||||||
char buf[2][INET_ADDRSTRLEN];
|
char buf[1][INET_ADDRSTRLEN];
|
||||||
zlog_info("setsockopt_multicast_ipv4 attempting to drop and "
|
zlog_info("setsockopt_ipv4_multicast attempting to drop and "
|
||||||
"re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)",
|
"re-add (fd %d, mcast %s, ifindex %u)",
|
||||||
sock,
|
sock,
|
||||||
inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])),
|
|
||||||
inet_ntop(AF_INET, &mreqn.imr_multiaddr,
|
inet_ntop(AF_INET, &mreqn.imr_multiaddr,
|
||||||
buf[1], sizeof(buf[1])), ifindex);
|
buf[0], sizeof(buf[0])), ifindex);
|
||||||
setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
||||||
(void *)&mreqn, sizeof(mreqn));
|
(void *)&mreqn, sizeof(mreqn));
|
||||||
ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||||
@ -264,26 +256,17 @@ setsockopt_multicast_ipv4(int sock,
|
|||||||
/* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */
|
/* #elif defined(BOGON_NIX) && EXAMPLE_VERSION_CODE > -100000 */
|
||||||
/* Add your favourite OS here! */
|
/* Add your favourite OS here! */
|
||||||
|
|
||||||
#else /* #if OS_TYPE */
|
#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #if OS_TYPE */
|
||||||
/* standard BSD API */
|
/* standard BSD API */
|
||||||
|
|
||||||
struct in_addr m;
|
struct in_addr m;
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#ifdef HAVE_BSD_STRUCT_IP_MREQ_HACK
|
m.s_addr = htonl(ifindex);
|
||||||
if (ifindex)
|
|
||||||
m.s_addr = htonl(ifindex);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
m = if_addr;
|
|
||||||
|
|
||||||
switch (optname)
|
switch (optname)
|
||||||
{
|
{
|
||||||
case IP_MULTICAST_IF:
|
|
||||||
return setsockopt (sock, IPPROTO_IP, optname, (void *)&m, sizeof(m));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IP_ADD_MEMBERSHIP:
|
case IP_ADD_MEMBERSHIP:
|
||||||
case IP_DROP_MEMBERSHIP:
|
case IP_DROP_MEMBERSHIP:
|
||||||
memset (&mreq, 0, sizeof(mreq));
|
memset (&mreq, 0, sizeof(mreq));
|
||||||
@ -294,13 +277,12 @@ setsockopt_multicast_ipv4(int sock,
|
|||||||
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
||||||
{
|
{
|
||||||
/* see above: handle possible problem when interface comes back up */
|
/* see above: handle possible problem when interface comes back up */
|
||||||
char buf[2][INET_ADDRSTRLEN];
|
char buf[1][INET_ADDRSTRLEN];
|
||||||
zlog_info("setsockopt_multicast_ipv4 attempting to drop and "
|
zlog_info("setsockopt_ipv4_multicast attempting to drop and "
|
||||||
"re-add (fd %d, ifaddr %s, mcast %s, ifindex %u)",
|
"re-add (fd %d, mcast %s, ifindex %u)",
|
||||||
sock,
|
sock,
|
||||||
inet_ntop(AF_INET, &if_addr, buf[0], sizeof(buf[0])),
|
|
||||||
inet_ntop(AF_INET, &mreq.imr_multiaddr,
|
inet_ntop(AF_INET, &mreq.imr_multiaddr,
|
||||||
buf[1], sizeof(buf[1])), ifindex);
|
buf[0], sizeof(buf[0])), ifindex);
|
||||||
setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
setsockopt (sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
||||||
(void *)&mreq, sizeof(mreq));
|
(void *)&mreq, sizeof(mreq));
|
||||||
ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
ret = setsockopt (sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||||
@ -315,10 +297,41 @@ setsockopt_multicast_ipv4(int sock,
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#error "Unsupported multicast API"
|
||||||
#endif /* #if OS_TYPE */
|
#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;
|
||||||
|
|
||||||
|
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
|
static int
|
||||||
setsockopt_ipv4_ifindex (int sock, int val)
|
setsockopt_ipv4_ifindex (int sock, int val)
|
||||||
{
|
{
|
||||||
|
@ -82,13 +82,11 @@ extern int setsockopt_ipv6_multicast_loop (int, int);
|
|||||||
(((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \
|
(((af) == AF_INET) : SOPT_SIZE_CMSG_IFINDEX_IPV4() \
|
||||||
? SOPT_SIZE_CMSG_PKTINFO_IPV6())
|
? SOPT_SIZE_CMSG_PKTINFO_IPV6())
|
||||||
|
|
||||||
extern int setsockopt_multicast_ipv4(int sock, int optname,
|
extern int setsockopt_ipv4_multicast_if(int sock,
|
||||||
struct in_addr if_addr
|
unsigned int ifindex);
|
||||||
/* required: interface to join on */,
|
extern int setsockopt_ipv4_multicast(int sock, int optname,
|
||||||
unsigned int mcast_addr,
|
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);
|
extern int setsockopt_ipv4_tos(int sock, int tos);
|
||||||
|
|
||||||
/* Ask for, and get, ifindex, by whatever method is supported. */
|
/* Ask for, and get, ifindex, by whatever method is supported. */
|
||||||
|
@ -52,8 +52,8 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
|
||||||
p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
|
htonl (OSPF_ALLSPFROUTERS),
|
||||||
ifindex);
|
ifindex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
|
zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
|
||||||
@ -73,8 +73,8 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
|
||||||
p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
|
htonl (OSPF_ALLSPFROUTERS),
|
||||||
ifindex);
|
ifindex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
|
zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
|
||||||
@ -94,8 +94,8 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
|
||||||
p->u.prefix4, htonl (OSPF_ALLDROUTERS),
|
htonl (OSPF_ALLDROUTERS),
|
||||||
ifindex);
|
ifindex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
|
zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
|
||||||
@ -115,8 +115,8 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
|
||||||
p->u.prefix4, htonl (OSPF_ALLDROUTERS),
|
htonl (OSPF_ALLDROUTERS),
|
||||||
ifindex);
|
ifindex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
|
zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
|
||||||
@ -151,8 +151,7 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex)
|
|||||||
zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
|
zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
|
||||||
top->fd, safe_strerror (errno));
|
top->fd, safe_strerror (errno));
|
||||||
|
|
||||||
ret = setsockopt_multicast_ipv4 (top->fd, IP_MULTICAST_IF,
|
ret = setsockopt_ipv4_multicast_if (top->fd, ifindex);
|
||||||
p->u.prefix4, 0, ifindex);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
|
zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
|
||||||
"ifindex %u): %s",
|
"ifindex %u): %s",
|
||||||
|
@ -78,9 +78,8 @@ ipv4_multicast_join (int sock,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_multicast_ipv4 (sock,
|
ret = setsockopt_ipv4_multicast (sock,
|
||||||
IP_ADD_MEMBERSHIP,
|
IP_ADD_MEMBERSHIP,
|
||||||
ifa,
|
|
||||||
group.s_addr,
|
group.s_addr,
|
||||||
ifindex);
|
ifindex);
|
||||||
|
|
||||||
@ -100,9 +99,8 @@ ipv4_multicast_leave (int sock,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_multicast_ipv4 (sock,
|
ret = setsockopt_ipv4_multicast (sock,
|
||||||
IP_DROP_MEMBERSHIP,
|
IP_DROP_MEMBERSHIP,
|
||||||
ifa,
|
|
||||||
group.s_addr,
|
group.s_addr,
|
||||||
ifindex);
|
ifindex);
|
||||||
|
|
||||||
@ -138,18 +136,13 @@ rip_interface_new (void)
|
|||||||
void
|
void
|
||||||
rip_interface_multicast_set (int sock, struct connected *connected)
|
rip_interface_multicast_set (int sock, struct connected *connected)
|
||||||
{
|
{
|
||||||
struct in_addr addr;
|
|
||||||
|
|
||||||
assert (connected != NULL);
|
assert (connected != NULL);
|
||||||
|
|
||||||
addr = CONNECTED_ID(connected)->u.prefix4;
|
if (setsockopt_ipv4_multicast_if (sock, connected->ifp->ifindex) < 0)
|
||||||
|
|
||||||
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 "
|
zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to "
|
||||||
"source address %s for interface %s",
|
"ifindex %d for interface %s",
|
||||||
sock, inet_ntoa(addr),
|
sock, connected->ifp->ifindex,
|
||||||
connected->ifp->name);
|
connected->ifp->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user