mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 14:33:09 +00:00
lib: fix setting of IPv4 multicast sockopts on OpenBSD
OpenBSD doesn't support the "ifindex hack" derived from RFC 1724 which allows an ifindex to be encoded in the imr_interface field (in_addr) of the ip_mreq structure. OpenBSD also doesn't support the RFC3678 Protocol-Independent socket API extensions, which allows an interface to be specified by its ifindex. With that said, in OpenBSD we still need to specify an interface by its IP address. This patch adds an exception in the multicast sockopt functions to handle this case. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
288b91e0bd
commit
4a3867d0d3
@ -219,6 +219,7 @@ setsockopt_ipv6_tclass(int sock, int tclass)
|
|||||||
int
|
int
|
||||||
setsockopt_ipv4_multicast(int sock,
|
setsockopt_ipv4_multicast(int sock,
|
||||||
int optname,
|
int optname,
|
||||||
|
struct in_addr if_addr,
|
||||||
unsigned int mcast_addr,
|
unsigned int mcast_addr,
|
||||||
unsigned int ifindex)
|
unsigned int ifindex)
|
||||||
{
|
{
|
||||||
@ -279,18 +280,20 @@ setsockopt_ipv4_multicast(int sock,
|
|||||||
#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK) /* #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 ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
|
assert(optname == IP_ADD_MEMBERSHIP || optname == IP_DROP_MEMBERSHIP);
|
||||||
|
|
||||||
m.s_addr = htonl(ifindex);
|
|
||||||
|
|
||||||
memset (&mreq, 0, sizeof(mreq));
|
memset (&mreq, 0, sizeof(mreq));
|
||||||
mreq.imr_multiaddr.s_addr = mcast_addr;
|
mreq.imr_multiaddr.s_addr = mcast_addr;
|
||||||
mreq.imr_interface = m;
|
#if !defined __OpenBSD__
|
||||||
|
mreq.imr_interface.s_addr = htonl (ifindex);
|
||||||
|
#else
|
||||||
|
mreq.imr_interface.s_addr = if_addr.s_addr;
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
|
ret = setsockopt (sock, IPPROTO_IP, optname, (void *)&mreq, sizeof(mreq));
|
||||||
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
if ((ret < 0) && (optname == IP_ADD_MEMBERSHIP) && (errno == EADDRINUSE))
|
||||||
{
|
{
|
||||||
@ -318,7 +321,7 @@ setsockopt_ipv4_multicast(int sock,
|
|||||||
* Set IP_MULTICAST_IF socket option in an OS-dependent manner.
|
* Set IP_MULTICAST_IF socket option in an OS-dependent manner.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
setsockopt_ipv4_multicast_if(int sock,
|
setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr,
|
||||||
unsigned int ifindex)
|
unsigned int ifindex)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -336,7 +339,11 @@ setsockopt_ipv4_multicast_if(int sock,
|
|||||||
#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK)
|
#elif defined(HAVE_BSD_STRUCT_IP_MREQ_HACK)
|
||||||
struct in_addr m;
|
struct in_addr m;
|
||||||
|
|
||||||
m.s_addr = htonl(ifindex);
|
#if !defined __OpenBSD__
|
||||||
|
m.s_addr = htonl (ifindex);
|
||||||
|
#else
|
||||||
|
m.s_addr = if_addr.s_addr;
|
||||||
|
#endif
|
||||||
|
|
||||||
return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m));
|
return setsockopt (sock, IPPROTO_IP, IP_MULTICAST_IF, (void *)&m, sizeof(m));
|
||||||
#else
|
#else
|
||||||
|
@ -83,9 +83,10 @@ extern int setsockopt_ipv6_tclass (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_ipv4_multicast_if(int sock,
|
extern int setsockopt_ipv4_multicast_if(int sock, struct in_addr if_addr,
|
||||||
unsigned int ifindex);
|
unsigned int ifindex);
|
||||||
extern int setsockopt_ipv4_multicast(int sock, int optname,
|
extern int setsockopt_ipv4_multicast(int sock, int optname,
|
||||||
|
struct in_addr if_addr,
|
||||||
unsigned int mcast_addr,
|
unsigned int mcast_addr,
|
||||||
unsigned int ifindex);
|
unsigned int ifindex);
|
||||||
extern int setsockopt_ipv4_tos(int sock, int tos);
|
extern int setsockopt_ipv4_tos(int sock, int tos);
|
||||||
|
@ -53,7 +53,7 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
|
||||||
htonl (OSPF_ALLSPFROUTERS),
|
p->u.prefix4, 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, "
|
||||||
@ -74,7 +74,7 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
|
||||||
htonl (OSPF_ALLSPFROUTERS),
|
p->u.prefix4, 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, "
|
||||||
@ -95,7 +95,7 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
|
||||||
htonl (OSPF_ALLDROUTERS),
|
p->u.prefix4, 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, "
|
||||||
@ -116,7 +116,7 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
|
ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
|
||||||
htonl (OSPF_ALLDROUTERS),
|
p->u.prefix4, 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,7 +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_ipv4_multicast_if (top->fd, ifindex);
|
ret = setsockopt_ipv4_multicast_if (top->fd, p->u.prefix4, 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",
|
||||||
|
@ -80,6 +80,7 @@ ipv4_multicast_join (int sock,
|
|||||||
|
|
||||||
ret = setsockopt_ipv4_multicast (sock,
|
ret = setsockopt_ipv4_multicast (sock,
|
||||||
IP_ADD_MEMBERSHIP,
|
IP_ADD_MEMBERSHIP,
|
||||||
|
ifa,
|
||||||
group.s_addr,
|
group.s_addr,
|
||||||
ifindex);
|
ifindex);
|
||||||
|
|
||||||
@ -101,6 +102,7 @@ ipv4_multicast_leave (int sock,
|
|||||||
|
|
||||||
ret = setsockopt_ipv4_multicast (sock,
|
ret = setsockopt_ipv4_multicast (sock,
|
||||||
IP_DROP_MEMBERSHIP,
|
IP_DROP_MEMBERSHIP,
|
||||||
|
ifa,
|
||||||
group.s_addr,
|
group.s_addr,
|
||||||
ifindex);
|
ifindex);
|
||||||
|
|
||||||
@ -136,9 +138,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);
|
||||||
|
|
||||||
if (setsockopt_ipv4_multicast_if (sock, connected->ifp->ifindex) < 0)
|
addr = CONNECTED_ID(connected)->u.prefix4;
|
||||||
|
|
||||||
|
if (setsockopt_ipv4_multicast_if (sock, addr, 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 "
|
||||||
"ifindex %d for interface %s",
|
"ifindex %d for interface %s",
|
||||||
|
Loading…
Reference in New Issue
Block a user