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
This commit is contained in:
parent
8f4a1f3a83
commit
68b22388a0
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=180993
@ -121,21 +121,6 @@
|
|||||||
#define _HAVE_SIN_LEN
|
#define _HAVE_SIN_LEN
|
||||||
#endif
|
#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 DAY (24*60*60)
|
||||||
#define NEVER DAY /* a long time */
|
#define NEVER DAY /* a long time */
|
||||||
#define EPOCH NEVER /* bias time by this to avoid <0 */
|
#define EPOCH NEVER /* bias time by this to avoid <0 */
|
||||||
|
@ -452,7 +452,6 @@ check_remote(struct interface *ifp)
|
|||||||
static void
|
static void
|
||||||
ifdel(struct interface *ifp)
|
ifdel(struct interface *ifp)
|
||||||
{
|
{
|
||||||
struct ip_mreq m;
|
|
||||||
struct interface *ifp1;
|
struct interface *ifp1;
|
||||||
|
|
||||||
|
|
||||||
@ -491,25 +490,23 @@ ifdel(struct interface *ifp)
|
|||||||
ifdel(ifp1);
|
ifdel(ifp1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ifp->int_if_flags & IFF_MULTICAST)
|
if ((ifp->int_if_flags & IFF_MULTICAST) && rip_sock >= 0) {
|
||||||
#ifdef MCAST_PPP_BUG
|
struct group_req gr;
|
||||||
&& !(ifp->int_if_flags & IFF_POINTOPOINT)
|
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
|
#endif
|
||||||
&& rip_sock >= 0) {
|
sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
|
||||||
m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
|
if (setsockopt(rip_sock, IPPROTO_IP, MCAST_LEAVE_GROUP,
|
||||||
#ifdef MCAST_IFINDEX
|
&gr, sizeof(gr)) < 0
|
||||||
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);
|
|
||||||
#endif
|
|
||||||
if (setsockopt(rip_sock,IPPROTO_IP,IP_DROP_MEMBERSHIP,
|
|
||||||
&m, sizeof(m)) < 0
|
|
||||||
&& errno != EADDRNOTAVAIL
|
&& errno != EADDRNOTAVAIL
|
||||||
&& !TRACEACTIONS)
|
&& !TRACEACTIONS)
|
||||||
LOGERR("setsockopt(IP_DROP_MEMBERSHIP RIP)");
|
LOGERR("setsockopt(MCAST_LEAVE_GROUP RIP)");
|
||||||
if (rip_sock_mcast == ifp)
|
if (rip_sock_mcast == ifp)
|
||||||
rip_sock_mcast = 0;
|
rip_sock_mcast = 0;
|
||||||
}
|
}
|
||||||
|
@ -713,25 +713,23 @@ rip_off(void)
|
|||||||
static void
|
static void
|
||||||
rip_mcast_on(struct interface *ifp)
|
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)
|
if (!IS_RIP_IN_OFF(ifp->int_state)
|
||||||
&& (ifp->int_if_flags & IFF_MULTICAST)
|
&& (ifp->int_if_flags & IFF_MULTICAST)
|
||||||
#ifdef MCAST_PPP_BUG
|
|
||||||
&& !(ifp->int_if_flags & IFF_POINTOPOINT)
|
|
||||||
#endif
|
|
||||||
&& !(ifp->int_state & IS_ALIAS)) {
|
&& !(ifp->int_state & IS_ALIAS)) {
|
||||||
m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP);
|
memset(&gr, 0, sizeof(gr));
|
||||||
#ifdef MCAST_IFINDEX
|
gr.gr_interface = ifp->int_index;
|
||||||
m.imr_interface.s_addr = htonl(ifp->int_index);
|
sin = (struct sockaddr_in *)&gr.gr_group;
|
||||||
#else
|
sin->sin_family = AF_INET;
|
||||||
m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
|
#ifdef _HAVE_SIN_LEN
|
||||||
? ifp->int_dstaddr
|
sin->sin_len = sizeof(struct sockaddr_in);
|
||||||
: ifp->int_addr);
|
|
||||||
#endif
|
#endif
|
||||||
if (setsockopt(rip_sock,IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
|
||||||
&m, sizeof(m)) < 0)
|
if (setsockopt(rip_sock, IPPROTO_IP, MCAST_JOIN_GROUP,
|
||||||
LOGERR("setsockopt(IP_ADD_MEMBERSHIP RIP)");
|
&gr, sizeof(gr)) < 0)
|
||||||
|
LOGERR("setsockopt(MCAST_JOIN_GROUP RIP)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,6 @@ output(enum output_type type,
|
|||||||
int flags;
|
int flags;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
int res;
|
int res;
|
||||||
naddr tgt_mcast;
|
|
||||||
int soc;
|
int soc;
|
||||||
int serrno;
|
int serrno;
|
||||||
|
|
||||||
@ -150,31 +149,17 @@ output(enum output_type type,
|
|||||||
} else {
|
} else {
|
||||||
msg = "Send mcast";
|
msg = "Send mcast";
|
||||||
if (rip_sock_mcast != ifp) {
|
if (rip_sock_mcast != ifp) {
|
||||||
#ifdef MCAST_IFINDEX
|
struct ip_mreqn mreqn;
|
||||||
/* specify ifindex */
|
|
||||||
tgt_mcast = htonl(ifp->int_index);
|
memset(&mreqn, 0, sizeof(struct ip_mreqn));
|
||||||
#else
|
mreqn.imr_ifindex = ifp->int_index;
|
||||||
#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
|
|
||||||
if (0 > setsockopt(rip_sock,
|
if (0 > setsockopt(rip_sock,
|
||||||
IPPROTO_IP, IP_MULTICAST_IF,
|
IPPROTO_IP,
|
||||||
&tgt_mcast,
|
IP_MULTICAST_IF,
|
||||||
sizeof(tgt_mcast))) {
|
&mreqn,
|
||||||
|
sizeof(mreqn))) {
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
LOGERR("setsockopt(rip_sock,"
|
LOGERR("setsockopt(rip_sock, "
|
||||||
"IP_MULTICAST_IF)");
|
"IP_MULTICAST_IF)");
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
ifp = 0;
|
ifp = 0;
|
||||||
|
@ -168,7 +168,8 @@ void
|
|||||||
set_rdisc_mg(struct interface *ifp,
|
set_rdisc_mg(struct interface *ifp,
|
||||||
int on) /* 0=turn it off */
|
int on) /* 0=turn it off */
|
||||||
{
|
{
|
||||||
struct ip_mreq m;
|
struct group_req gr;
|
||||||
|
struct sockaddr_in *sin;
|
||||||
|
|
||||||
if (rdisc_sock < 0) {
|
if (rdisc_sock < 0) {
|
||||||
/* Create the raw socket so that we can hear at least
|
/* Create the raw socket so that we can hear at least
|
||||||
@ -185,39 +186,35 @@ set_rdisc_mg(struct interface *ifp,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MCAST_PPP_BUG
|
memset(&gr, 0, sizeof(gr));
|
||||||
if (ifp->int_if_flags & IFF_POINTOPOINT)
|
gr.gr_interface = ifp->int_index;
|
||||||
return;
|
sin = (struct sockaddr_in *)&gr.gr_group;
|
||||||
#endif
|
sin->sin_family = AF_INET;
|
||||||
memset(&m, 0, sizeof(m));
|
#ifdef _HAVE_SIN_LEN
|
||||||
#ifdef MCAST_IFINDEX
|
sin->sin_len = sizeof(struct sockaddr_in);
|
||||||
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);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (supplier
|
if (supplier
|
||||||
|| (ifp->int_state & IS_NO_ADV_IN)
|
|| (ifp->int_state & IS_NO_ADV_IN)
|
||||||
|| !on) {
|
|| !on) {
|
||||||
/* stop listening to advertisements
|
/* stop listening to advertisements
|
||||||
*/
|
*/
|
||||||
if (ifp->int_state & IS_ALL_HOSTS) {
|
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,
|
if (setsockopt(rdisc_sock, IPPROTO_IP,
|
||||||
IP_DROP_MEMBERSHIP,
|
MCAST_LEAVE_GROUP,
|
||||||
&m, sizeof(m)) < 0)
|
&gr, sizeof(gr)) < 0)
|
||||||
LOGERR("IP_DROP_MEMBERSHIP ALLHOSTS");
|
LOGERR("MCAST_LEAVE_GROUP ALLHOSTS");
|
||||||
ifp->int_state &= ~IS_ALL_HOSTS;
|
ifp->int_state &= ~IS_ALL_HOSTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!(ifp->int_state & IS_ALL_HOSTS)) {
|
} else if (!(ifp->int_state & IS_ALL_HOSTS)) {
|
||||||
/* start listening to advertisements
|
/* start listening to advertisements
|
||||||
*/
|
*/
|
||||||
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_ADD_MEMBERSHIP,
|
if (setsockopt(rdisc_sock, IPPROTO_IP, MCAST_JOIN_GROUP,
|
||||||
&m, sizeof(m)) < 0) {
|
&gr, sizeof(gr)) < 0) {
|
||||||
LOGERR("IP_ADD_MEMBERSHIP ALLHOSTS");
|
LOGERR("MCAST_JOIN_GROUP ALLHOSTS");
|
||||||
} else {
|
} else {
|
||||||
ifp->int_state |= IS_ALL_HOSTS;
|
ifp->int_state |= IS_ALL_HOSTS;
|
||||||
}
|
}
|
||||||
@ -229,21 +226,21 @@ set_rdisc_mg(struct interface *ifp,
|
|||||||
/* stop listening to solicitations
|
/* stop listening to solicitations
|
||||||
*/
|
*/
|
||||||
if (ifp->int_state & IS_ALL_ROUTERS) {
|
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,
|
if (setsockopt(rdisc_sock, IPPROTO_IP,
|
||||||
IP_DROP_MEMBERSHIP,
|
MCAST_LEAVE_GROUP,
|
||||||
&m, sizeof(m)) < 0)
|
&gr, sizeof(gr)) < 0)
|
||||||
LOGERR("IP_DROP_MEMBERSHIP ALLROUTERS");
|
LOGERR("MCAST_LEAVE_GROUP ALLROUTERS");
|
||||||
ifp->int_state &= ~IS_ALL_ROUTERS;
|
ifp->int_state &= ~IS_ALL_ROUTERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!(ifp->int_state & IS_ALL_ROUTERS)) {
|
} else if (!(ifp->int_state & IS_ALL_ROUTERS)) {
|
||||||
/* start hearing solicitations
|
/* start hearing solicitations
|
||||||
*/
|
*/
|
||||||
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_ADD_MEMBERSHIP,
|
if (setsockopt(rdisc_sock, IPPROTO_IP, MCAST_JOIN_GROUP,
|
||||||
&m, sizeof(m)) < 0) {
|
&gr, sizeof(gr)) < 0) {
|
||||||
LOGERR("IP_ADD_MEMBERSHIP ALLROUTERS");
|
LOGERR("MCAST_JOIN_GROUP ALLROUTERS");
|
||||||
} else {
|
} else {
|
||||||
ifp->int_state |= IS_ALL_ROUTERS;
|
ifp->int_state |= IS_ALL_ROUTERS;
|
||||||
}
|
}
|
||||||
@ -699,7 +696,6 @@ send_rdisc(union ad_u *p,
|
|||||||
struct sockaddr_in rsin;
|
struct sockaddr_in rsin;
|
||||||
int flags;
|
int flags;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
naddr tgt_mcast;
|
|
||||||
|
|
||||||
|
|
||||||
memset(&rsin, 0, sizeof(rsin));
|
memset(&rsin, 0, sizeof(rsin));
|
||||||
@ -736,27 +732,14 @@ send_rdisc(union ad_u *p,
|
|||||||
}
|
}
|
||||||
if (rdisc_sock_mcast != ifp) {
|
if (rdisc_sock_mcast != ifp) {
|
||||||
/* select the right interface. */
|
/* select the right interface. */
|
||||||
#ifdef MCAST_IFINDEX
|
struct ip_mreqn mreqn;
|
||||||
/* specify ifindex */
|
|
||||||
tgt_mcast = htonl(ifp->int_index);
|
memset(&mreqn, 0, sizeof(struct ip_mreqn));
|
||||||
#else
|
mreqn.imr_ifindex = ifp->int_index;
|
||||||
#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
|
|
||||||
if (0 > setsockopt(rdisc_sock,
|
if (0 > setsockopt(rdisc_sock,
|
||||||
IPPROTO_IP, IP_MULTICAST_IF,
|
IPPROTO_IP, IP_MULTICAST_IF,
|
||||||
&tgt_mcast, sizeof(tgt_mcast))) {
|
&mreqn,
|
||||||
|
sizeof(mreqn))) {
|
||||||
LOGERR("setsockopt(rdisc_sock,"
|
LOGERR("setsockopt(rdisc_sock,"
|
||||||
"IP_MULTICAST_IF)");
|
"IP_MULTICAST_IF)");
|
||||||
rdisc_sock_mcast = 0;
|
rdisc_sock_mcast = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user