ip_adapter: fix setting setsockopt() IP_MULTICAST_IF on Linux kernel < 3.5
authorHauke Mehrtens <hauke.mehrtens@lantiq.com>
Thu, 17 Dec 2015 12:59:57 +0000 (13:59 +0100)
committerJon A. Cruz <jonc@osg.samsung.com>
Mon, 11 Jan 2016 17:15:53 +0000 (17:15 +0000)
The struct ip_mreq is only support since Linux 3.5 and not on older Linux
versions for IP_MULTICAST_IF. On older and also on recent Linux kernel
versions using struct ip_mreqn (version with n at the end) is still supported.
See the man page for details: http://man7.org/linux/man-pages/man7/ip.7.html

Without this patch I was getting this error message when trying to send a
multicast message from a USB tethered Android phone:
E/IP_SERVER: send IP_MULTICAST_IF failed: Cannot assign requested address (using defualt)
after applying this patch this operation works and it looks like IoTivity
with IP works on the Android phone.

In parameter imr_ifindex the interface index should be provided, but if
it is set to 0 it gets ignored and should behave like the old code.

Change-Id: I6e8ad376357eee49b2cd29dc792092fe3f7af0b6
Signed-off-by: Hauke Mehrtens <hauke.mehrtens@lantiq.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/4651
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
resource/csdk/connectivity/src/ip_adapter/caipserver.c

index ef1508b..49bfdbf 100644 (file)
@@ -627,8 +627,9 @@ static void applyMulticastToInterface4(struct in_addr inaddr)
         return;
     }
 
-    struct ip_mreq mreq = { .imr_multiaddr = IPv4MulticastAddress,
-                            .imr_interface = inaddr};
+    struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
+                             .imr_address = inaddr,
+                             .imr_ifindex = 0 };
     if (setsockopt(caglobals.ip.m4.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof (mreq)))
     {
         if (EADDRINUSE != errno)
@@ -935,7 +936,8 @@ static void sendMulticastData4(const u_arraylist_t *iflist,
                                CAEndpoint_t *endpoint,
                                const void *data, uint32_t datalen)
 {
-    struct ip_mreq mreq = { .imr_multiaddr = IPv4MulticastAddress };
+    struct ip_mreqn mreq = { .imr_multiaddr = IPv4MulticastAddress,
+                             .imr_ifindex = 0 };
     OICStrcpy(endpoint->addr, sizeof(endpoint->addr), IPv4_MULTICAST);
     int fd = caglobals.ip.u4.fd;
 
@@ -958,7 +960,7 @@ static void sendMulticastData4(const u_arraylist_t *iflist,
 
         struct in_addr inaddr;
         inaddr.s_addr = ifitem->ipv4addr;
-        mreq.imr_interface = inaddr;
+        mreq.imr_address = inaddr;
         if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof (mreq)))
         {
             OIC_LOG_V(ERROR, TAG, "send IP_MULTICAST_IF failed: %s (using defualt)",