Prevent opening an interface if the transmission socket fails.
authorHenning Rogge <hrogge@googlemail.com>
Tue, 18 May 2010 12:46:58 +0000 (14:46 +0200)
committerHenning Rogge <hrogge@googlemail.com>
Tue, 18 May 2010 12:46:58 +0000 (14:46 +0200)
IPv6 interfaces need some time to update the local routing table, so handle them
with the interface polling later if necessary.

src/linux/kernel_routes_nl.c
src/linux/net.c
src/unix/ifnet.c

index c71aa10..805ba4a 100644 (file)
@@ -121,12 +121,12 @@ static void netlink_process_link(struct nlmsghdr *h)
   struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(h);
   struct interface *iface;
   struct olsr_if *oif;
+  char namebuffer[IF_NAMESIZE];
 
   iface = if_ifwithindex(ifi->ifi_index);
   oif = NULL;
-  if (iface == NULL && (ifi->ifi_flags & IFF_UP) != 0) {
-    char namebuffer[IF_NAMESIZE];
 
+  if (iface == NULL && (ifi->ifi_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) {
     if (if_indextoname(ifi->ifi_index, namebuffer)) {
       if ((oif = olsrif_ifwithname(namebuffer)) != NULL) {
         /* try to take interface up, will trigger ifchange */
@@ -141,8 +141,12 @@ static void netlink_process_link(struct nlmsghdr *h)
 
   if (iface == NULL && oif == NULL) {
     /* this is not an OLSR interface */
-    olsr_trigger_ifchange(ifi->ifi_index, NULL,
-        (ifi->ifi_flags & IFF_UP) == 0 ? IFCHG_IF_REMOVE : IFCHG_IF_ADD);
+    if ((ifi->ifi_flags & IFF_UP) != 0 && (ifi->ifi_flags & IFF_RUNNING) != 0) {
+      olsr_trigger_ifchange(ifi->ifi_index, NULL, IFCHG_IF_ADD);
+    }
+    else if ((ifi->ifi_flags & IFF_UP) == 0 && (ifi->ifi_flags & IFF_RUNNING) == 0){
+      olsr_trigger_ifchange(ifi->ifi_index, NULL, IFCHG_IF_REMOVE);
+    }
   }
 }
 
@@ -178,6 +182,8 @@ static void rtnetlink_read(int sock, void *data __attribute__ ((unused)), unsign
               len, ret, plen);
       return;
     }
+
+    fprintf(stderr, "Netlink message: %x\n", nlh->nlmsg_type);
     if ((nlh->nlmsg_type == RTM_NEWLINK) || ( nlh->nlmsg_type == RTM_DELLINK)) {
       /* handle ifup/ifdown */
       netlink_process_link(nlh);
index 24d9daf..5283f3a 100644 (file)
@@ -511,13 +511,18 @@ getsocket6(int bufspace, struct interface *ifp)
   memset(&sin, 0, sizeof(sin));
   sin.sin6_family = AF_INET6;
   sin.sin6_port = htons(olsr_cnf->olsrport);
+  sin.sin6_scope_id = ifp->if_index;
 
   if(bufspace <= 0) {
     memcpy(&sin.sin6_addr, &ifp->int6_addr.sin6_addr, sizeof(struct in6_addr));
   }
 
   if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
-    perror("bind");
+    struct ipaddr_str buf;
+    OLSR_PRINTF(1, "Error, cannot bind address %s to %s-socket: %s (%d)\n",
+        inet_ntop(sin.sin6_family, &sin.sin6_addr, buf.buf, sizeof(buf)),
+        bufspace <= 0 ? "transmit" : "receive",
+        strerror(errno), errno);
     syslog(LOG_ERR, "bind: %m");
     close(sock);
     return (-1);
index 394db96..b3f4b82 100644 (file)
@@ -703,53 +703,39 @@ chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
     OLSR_PRINTF(1, "\tMulticast: %s\n", ip6_to_string(&buf, &ifs.int6_multaddr.sin6_addr));
   }
 
-  ifp = olsr_malloc(sizeof(struct interface), "Interface update 2");
-
-  iface->configured = 1;
-  iface->interf = ifp;
-
-  /* XXX bad code */
-  memcpy(ifp, &ifs, sizeof(struct interface));
-
-  /* initialize backpointer */
-  ifp->olsr_if = iface;
-
-  ifp->immediate_send_tc = (iface->cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval);
-  if (olsr_cnf->max_jitter == 0) {
-    /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
-    olsr_cnf->max_jitter =
-      ifp->immediate_send_tc ? iface->cnf->tc_params.emission_interval : iface->cnf->hello_params.emission_interval;
-  }
-
   name_size = strlen(if_basename(ifr.ifr_name)) + 1;
-  ifp->gen_properties = NULL;
-  ifp->int_name = olsr_malloc(name_size, "Interface update 3");
-  strscpy(ifp->int_name, if_basename(ifr.ifr_name), name_size);
-  ifp->int_next = ifnet;
-  ifnet = ifp;
+  ifs.int_name = olsr_malloc(name_size, "Interface update 3");
+  strscpy(ifs.int_name, if_basename(ifr.ifr_name), name_size);
 
   if (olsr_cnf->ip_version == AF_INET) {
     /* IP version 4 */
-    ifp->ip_addr.v4 = ifp->int_addr.sin_addr;
+    ifs.ip_addr.v4 = ifs.int_addr.sin_addr;
     /*
      *We create one socket for each interface and bind
      *the socket to it. This to ensure that we can control
      *on what interface the message is transmitted
      */
 
-    ifp->olsr_socket = getsocket(BUFSPACE, ifp);
-    ifp->send_socket = getsocket(0, ifp);
+    ifs.olsr_socket = getsocket(BUFSPACE, &ifs);
+    ifs.send_socket = getsocket(0, &ifs);
 
-    if (ifp->olsr_socket < 0) {
+    if (ifs.olsr_socket < 0) {
       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
       olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
       olsr_cnf->exit_value = EXIT_FAILURE;
+      free(ifs.int_name);
       kill(getpid(), SIGINT);
+      return 0;
+    }
+    if (ifs.send_socket < 0) {
+      OLSR_PRINTF(1, "Warning, transmission socket could not be initialized. Abort if-up.\n");
+      close (ifs.olsr_socket);
+      free(ifs.int_name);
+      return 0;
     }
-
   } else {
     /* IP version 6 */
-    ifp->ip_addr.v6 = ifp->int6_addr.sin6_addr;
+    ifs.ip_addr.v6 = ifs.int6_addr.sin6_addr;
 
     /*
      *We create one socket for each interface and bind
@@ -757,20 +743,49 @@ chk_if_up(struct olsr_if *iface, int debuglvl __attribute__ ((unused)))
      *on what interface the message is transmitted
      */
 
-    ifp->olsr_socket = getsocket6(BUFSPACE, ifp);
-    ifp->send_socket = getsocket6(0, ifp);
+    ifs.olsr_socket = getsocket6(BUFSPACE, &ifs);
+    ifs.send_socket = getsocket6(0, &ifs);
 
-    join_mcast(ifp, ifp->olsr_socket);
-
-    if (ifp->olsr_socket < 0) {
+    if (ifs.olsr_socket < 0) {
       fprintf(stderr, "Could not initialize socket... exiting!\n\n");
       olsr_syslog(OLSR_LOG_ERR, "Could not initialize socket... exiting!\n\n");
       olsr_cnf->exit_value = EXIT_FAILURE;
+      free(ifs.int_name);
       kill(getpid(), SIGINT);
+      return 0;
+    }
+    if (ifs.send_socket < 0) {
+      OLSR_PRINTF(1, "Warning, transmission socket could not be initialized. Abort if-up.\n");
+      close (ifs.olsr_socket);
+      free(ifs.int_name);
+      return 0;
     }
 
+    join_mcast(&ifs, ifs.olsr_socket);
   }
 
+  ifp = olsr_malloc(sizeof(struct interface), "Interface update 2");
+
+  iface->configured = 1;
+  iface->interf = ifp;
+
+  /* XXX bad code */
+  memcpy(ifp, &ifs, sizeof(struct interface));
+
+  /* initialize backpointer */
+  ifp->olsr_if = iface;
+
+  ifp->immediate_send_tc = (iface->cnf->tc_params.emission_interval < iface->cnf->hello_params.emission_interval);
+  if (olsr_cnf->max_jitter == 0) {
+    /* max_jitter determines the max time to store to-be-send-messages, correlated with random() */
+    olsr_cnf->max_jitter =
+      ifp->immediate_send_tc ? iface->cnf->tc_params.emission_interval : iface->cnf->hello_params.emission_interval;
+  }
+
+  ifp->gen_properties = NULL;
+  ifp->int_next = ifnet;
+  ifnet = ifp;
+
   set_buffer_timer(ifp);
 
   /* Register socket */