I forgot to add ip_mreqn support to IP_MULTICAST_IF and so the IP_ADD_MEMBERSHIP change is not fixing all the issues I have.
Linux supports calling IP_MULTICAST_IF with a struct in_addr, a struct ip_mreq, or a struct ip_mreqn. FreeBSD only does the first and last. I followed the Linux way because doing that was not that hard. In the end only the imr_ifindex field and the imr_address field need to be checked and if the imr_ifindex is 0 then just use the old code. If the imr_ifindex is set then use this for interface index and break early. Any opinions about this? -- :wq Claudio Index: netinet/ip_output.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_output.c,v retrieving revision 1.360 diff -u -p -r1.360 ip_output.c --- netinet/ip_output.c 11 Jan 2021 13:28:53 -0000 1.360 +++ netinet/ip_output.c 15 Jan 2021 12:20:26 -0000 @@ -1423,11 +1423,40 @@ ip_setmoptions(int optname, struct ip_mo /* * Select the interface for outgoing multicast packets. */ - if (m == NULL || m->m_len != sizeof(struct in_addr)) { + if (m == NULL) { + error = EINVAL; + break; + } + if (m->m_len == sizeof(struct in_addr)) { + addr = *(mtod(m, struct in_addr *)); + } else if (m->m_len == sizeof(struct ip_mreq) || + m->m_len == sizeof(struct ip_mreqn)) { + memset(&mreqn, 0, sizeof(mreqn)); + memcpy(&mreqn, mtod(m, void *), m->m_len); + + /* + * If an interface index is given use this + * index to set the imo_ifidx but check first + * that the interface actually exists. + * In the other case just set the addr to + * the imr_address and fall through to the + * regular code. + */ + if (mreqn.imr_ifindex != 0) { + ifp = if_get(mreqn.imr_ifindex); + if (ifp == NULL) { + error = EADDRNOTAVAIL; + break; + } + imo->imo_ifidx = ifp->if_index; + if_put(ifp); + break; + } else + addr = mreqn.imr_address; + } else { error = EINVAL; break; } - addr = *(mtod(m, struct in_addr *)); /* * INADDR_ANY is used to remove a previous selection. * When no interface is selected, a default one is