miniupnpc: Fix usage of IP_MULTICAST_IF with struct ip_mreqn
When struct ip_mreqn is passed to IP_MULTICAST_IF setsockopt option it is always required to set also ipv4 source address. Otherwise Linux kernel will choose default system multicast ipv4 address which does not have to belong to chosen interface specified in struct ip_mreqn. Therefore on system with more multicast interfaces and more ipv4 addresses, it may happen that interface chosen by upnpc -m option would use ipv4 address which does not belong to this interface. This change is fixing above issue and ensure that if interface is chosen by upnpc -m option then source address which belongs to this interface would be used. Without this change upnpc -m eth1 can send multicast traffic over interface eth1 but with source ipv4 address of interface eth0, which obviously would be rejected by upnp gateway.
This commit is contained in:
parent
36a6913970
commit
bfbe42d392
|
@ -66,7 +66,7 @@ struct sockaddr_un {
|
||||||
#define HAS_IP_MREQN
|
#define HAS_IP_MREQN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(HAS_IP_MREQN) && !defined(_WIN32)
|
#ifndef _WIN32
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#if defined(__sun) || defined(__HAIKU__)
|
#if defined(__sun) || defined(__HAIKU__)
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
|
@ -735,10 +735,24 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
||||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef HAS_IP_MREQN
|
|
||||||
/* was not an ip address, try with an interface name */
|
/* was not an ip address, try with an interface name */
|
||||||
|
#ifndef _WIN32
|
||||||
|
#ifdef HAS_IP_MREQN
|
||||||
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
|
struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
|
||||||
|
#endif
|
||||||
|
struct ifreq ifr;
|
||||||
|
int ifrlen = sizeof(ifr);
|
||||||
|
strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
|
||||||
|
ifr.ifr_name[IFNAMSIZ-1] = '\0';
|
||||||
|
if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
||||||
|
{
|
||||||
|
PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
|
||||||
|
#ifdef HAS_IP_MREQN
|
||||||
memset(&reqn, 0, sizeof(struct ip_mreqn));
|
memset(&reqn, 0, sizeof(struct ip_mreqn));
|
||||||
|
reqn.imr_address.s_addr = mc_if.s_addr;
|
||||||
reqn.imr_ifindex = if_nametoindex(multicastif);
|
reqn.imr_ifindex = if_nametoindex(multicastif);
|
||||||
if(reqn.imr_ifindex == 0)
|
if(reqn.imr_ifindex == 0)
|
||||||
{
|
{
|
||||||
|
@ -751,20 +765,12 @@ ssdpDiscoverDevices(const char * const deviceTypes[],
|
||||||
{
|
{
|
||||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||||
}
|
}
|
||||||
#elif !defined(_WIN32)
|
#else
|
||||||
struct ifreq ifr;
|
|
||||||
int ifrlen = sizeof(ifr);
|
|
||||||
strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
|
|
||||||
ifr.ifr_name[IFNAMSIZ-1] = '\0';
|
|
||||||
if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
|
|
||||||
{
|
|
||||||
PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)");
|
|
||||||
}
|
|
||||||
mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
|
|
||||||
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
|
if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
|
||||||
{
|
{
|
||||||
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("Setting of multicast interface not supported with interface name.\n");
|
printf("Setting of multicast interface not supported with interface name.\n");
|
||||||
|
|
Loading…
Reference in New Issue