From db9f0bbdcd383323904a0fc259166e97cf93b826 Mon Sep 17 00:00:00 2001
From: Lionel Gauthier <lionel.gauthier@eurecom.fr>
Date: Mon, 10 Feb 2014 14:45:43 +0000
Subject: [PATCH] Bind to device (for vlan config)

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5068 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 openair-cn/SCTP/sctp_eNB_task.c | 77 ++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 5 deletions(-)

diff --git a/openair-cn/SCTP/sctp_eNB_task.c b/openair-cn/SCTP/sctp_eNB_task.c
index 4bab71d50b3..4455d0208ef 100644
--- a/openair-cn/SCTP/sctp_eNB_task.c
+++ b/openair-cn/SCTP/sctp_eNB_task.c
@@ -35,6 +35,11 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
 
 #include <netinet/in.h>
 #include <netinet/sctp.h>
@@ -120,14 +125,19 @@ void sctp_handle_new_association_req(
     const task_id_t requestor,
     const sctp_new_association_req_t * const sctp_new_association_req_p)
 {
-    int     sd;
-    int32_t assoc_id;
+    int                           sd;
+    int32_t                       assoc_id;
 
-    struct sctp_event_subscribe events;
+    struct sctp_event_subscribe   events;
 
-    struct sctp_cnx_list_elm_s *sctp_cnx = NULL;
-    enum sctp_connection_type_e connection_type = SCTP_TYPE_CLIENT;
+    struct sctp_cnx_list_elm_s   *sctp_cnx = NULL;
+    enum sctp_connection_type_e   connection_type = SCTP_TYPE_CLIENT;
 
+    struct ifreq                  ifr;
+    struct ifaddrs               *ifaddr, *ifa;
+    int                           family, s;
+    struct in_addr                in;
+    struct in6_addr               in6;
     /* Prepare a new SCTP association as requested by upper layer and try to connect
      * to remote host.
      */
@@ -162,6 +172,63 @@ void sctp_handle_new_association_req(
         return;
     }
 
+    // Bind to device ... or we could bind to address also
+    if (getifaddrs(&ifaddr) == -1) {
+        SCTP_ERROR("getifaddrs failed: %s\n", strerror(errno));
+        close(sd);
+    }
+    /* Walk through linked list, maintaining head pointer so we
+       can free list later */
+    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+        if (ifa->ifa_addr == NULL)
+            continue;
+
+        family = ifa->ifa_addr->sa_family;
+
+        /* For an AF_INET* interface address, display the address */
+        if (sctp_new_association_req_p->local_address.ipv4 && family == AF_INET) {
+            // compare address
+            s = inet_aton(sctp_new_association_req_p->local_address.ipv4_address,
+                    &in);
+            if (s > 0 ) {
+                if (((struct sockaddr_in*)ifa->ifa_addr)->sin_addr.s_addr == in.s_addr) {
+                    memset(&ifr, 0, sizeof(ifr));
+                    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), ifa->ifa_name);
+                    if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
+                        SCTP_ERROR("Setsockopt SOL_SOCKET failed: %s\n",
+                                   strerror(errno));
+                    } else {
+                        SCTP_DEBUG("Setsockopt SOL_SOCKET socket bound to : %s\n",
+                                ifa->ifa_name);
+                    }
+                    break;
+                }
+            }
+        } else if (sctp_new_association_req_p->local_address.ipv6 && family == AF_INET6) {
+            // compare address
+            s = inet_pton(AF_INET6,
+                    sctp_new_association_req_p->local_address.ipv6_address,
+                    &in6);
+            if (s == 1 ) {
+                if (memcmp(&((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr,
+                        &in6, sizeof(in6)) == 0) {
+                    memset(&ifr, 0, sizeof(ifr));
+                    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), ifa->ifa_name);
+                    if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
+                        SCTP_ERROR("Setsockopt SOL_SOCKET failed: %s\n",
+                                   strerror(errno));
+                    } else {
+                        SCTP_DEBUG("Setsockopt SOL_SOCKET socket bound to : %s\n",
+                                ifa->ifa_name);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+
+    freeifaddrs(ifaddr);
+
     /* Mark the socket as non-blocking */
     if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) {
         SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n",
-- 
GitLab