Print this page
want lxinit to support link-local routes

@@ -488,25 +488,51 @@
 
         (void) close(s);
         return (0);
 }
 
+static int lxi_route_send_msg(struct rt_msghdr * rtm)
+{
+    int sockfd, len;
+
+    if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
+        lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
+        return (-1);
+    }
+
+    if ((len = write(sockfd, (const void *)rtm, rtm->rtm_msglen)) < 0) {
+        lxi_warn("could not write rtmsg: %s", strerror(errno));
+        close(sockfd);
+        return (-1);
+    } else if (len < rtm->rtm_msglen) {
+        lxi_warn("write() rtmsg incomplete");
+        close(sockfd);
+        return (-1);
+    }
+
+    close(sockfd);
+    return (0);
+}
+
 static int
 lxi_iface_gateway(const char *iface, const char *dst, int dstpfx,
-    const char *gwaddr)
+    const char *gwaddr, int llroute)
 {
-        int idx, len, sockfd;
+        int idx;
         char rtbuf[RTMBUFSZ];
         struct rt_msghdr *rtm = (struct rt_msghdr *)rtbuf;
         struct sockaddr_in *dst_sin = (struct sockaddr_in *)
             (rtbuf + sizeof (struct rt_msghdr));
         struct sockaddr_in *gw_sin = (struct sockaddr_in *)(dst_sin + 1);
         struct sockaddr_in *netmask_sin = (struct sockaddr_in *)(gw_sin + 1);
 
         (void) bzero(rtm, RTMBUFSZ);
         rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
+        
+        if(!llroute) 
         rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY;
+        
         rtm->rtm_msglen = sizeof (rtbuf);
         rtm->rtm_pid = getpid();
         rtm->rtm_type = RTM_ADD;
         rtm->rtm_version = RTM_VERSION;
 

@@ -514,10 +540,19 @@
         /*
          * The destination and netmask components have already been zeroed,
          * which represents the default gateway.  If we were passed a more
          * specific destination network, use that instead.
          */
+
+        if(dstpfx == -1) {
+          /*
+           * no prefix was specified; assume a prefix length of 32,
+           * which seems in line with the behavior of vmadm. 
+           */
+           dstpfx = 32;
+        }
+
         dst_sin->sin_family = AF_INET;
         netmask_sin->sin_family = AF_INET;
         if (dst != NULL) {
                 struct sockaddr *mask = (struct sockaddr *)netmask_sin;
 

@@ -541,27 +576,11 @@
                         return (-1);
                 }
                 rtm->rtm_index = idx;
         }
 
-        if ((sockfd = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
-                lxi_warn("socket(PF_ROUTE): %s\n", strerror(errno));
-                return (-1);
-        }
-
-        if ((len = write(sockfd, rtbuf, rtm->rtm_msglen)) < 0) {
-                lxi_warn("could not write rtmsg: %s", strerror(errno));
-                close(sockfd);
-                return (-1);
-        } else if (len < rtm->rtm_msglen) {
-                lxi_warn("write() rtmsg incomplete");
-                close(sockfd);
-                return (-1);
-        }
-
-        close(sockfd);
-        return (0);
+        return lxi_route_send_msg(rtm);
 }
 
 static void
 lxi_net_loopback()
 {

@@ -632,11 +651,11 @@
         if (zonecfg_setnwifent(handle) != Z_OK)
                 return;
         while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
                 const char *iface = lookup.zone_nwif_physical;
                 struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
-                const char *ipaddrs, *primary, *gateway;
+                const char *ipaddrs;
                 char ipaddrs_copy[MAXNAMELEN], cidraddr[BUFSIZ],
                     *ipaddr, *tmp, *lasts;
                 boolean_t first_ipv4_configured = B_FALSE;
                 boolean_t *ficp = &first_ipv4_configured;
 

@@ -682,50 +701,54 @@
                         } else if (lxi_iface_ip(iface, ipaddr, ficp) < 0) {
                                 lxi_warn("Unable to add new IP address (%s) "
                                     "to interface %s", ipaddr, iface);
                         }
                 }
-
-                if (zone_find_attr(attrs, "primary", &primary) == 0 &&
-                    strncmp(primary, "true", MAXNAMELEN) == 0 &&
-                    zone_find_attr(attrs, "gateway", &gateway) == 0) {
-                        lxi_iface_gateway(iface, NULL, 0, gateway);
                 }
-        }
 
         if (do_addrconf) {
                 lxi_net_ndpd_start();
         }
 
         (void) zonecfg_endnwifent(handle);
 }
 
 static void
-lxi_net_static_route(const char *line)
+lxi_net_setup_gateways(zone_dochandle_t handle)
 {
-        /*
-         * Each static route line is a string of the form:
-         *
-         *      "10.77.77.2|10.1.1.0/24|false"
-         *
-         * i.e. gateway address, destination network, and whether this is
-         * a "link local" route or a next hop route.
-         */
-        custr_t *cu = NULL;
-        char *gw = NULL, *dst = NULL;
-        int pfx = -1;
-        int i;
+    struct zone_nwiftab lookup;
 
-        if (custr_alloc(&cu) != 0) {
-                lxi_err("custr_alloc failure");
+    if (zonecfg_setnwifent(handle) != Z_OK)
+        return;
+    while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
+        const char *iface = lookup.zone_nwif_physical;
+        struct zone_res_attrtab *attrs = lookup.zone_nwif_attrp;
+        const char *primary, *gateway;
+
+        if (zone_find_attr(attrs, "primary", &primary) == 0 &&
+            strncmp(primary, "true", MAXNAMELEN) == 0 &&
+            zone_find_attr(attrs, "gateway", &gateway) == 0) {
+            lxi_iface_gateway(iface, NULL, 0, gateway, 0);
         }
+    }
 
+    (void) zonecfg_endnwifent(handle);
+}
+
+static void
+lxi_parse_route_line(const char *line, custr_t *cu, char *gw, char *dst, int* pfx, int gwlen, int dstlen)
+{
+     int i;
+     int havegw = 0, havedst = 0, nopfx = 0;
+
         for (i = 0; line[i] != '\0'; i++) {
-                if (gw == NULL) {
+        if (!havegw) {
                         if (line[i] == '|') {
-                                if ((gw = strdup(custr_cstr(cu))) == NULL) {
-                                        lxi_err("strdup failure");
+                if ((strlcpy(gw, custr_cstr(cu), gwlen) ) == 0) {
+                    lxi_err("strlcpy failure");
+                } else {
+                    havegw = 1;
                                 }
                                 custr_reset(cu);
                         } else {
                                 if (custr_appendc(cu, line[i]) != 0) {
                                         lxi_err("custr_appendc failure");

@@ -732,27 +755,32 @@
                                 }
                         }
                         continue;
                 }
 
-                if (dst == NULL) {
-                        if (line[i] == '/') {
-                                if ((dst = strdup(custr_cstr(cu))) == NULL) {
-                                        lxi_err("strdup failure");
+        if (!havedst) {
+            if (line[i] == '/' || line[i] == '|') {
+                if ((strlcpy(dst, custr_cstr(cu), dstlen)) == 0) {
+                    lxi_err("strlcpy failure");
+                } else {
+                    havedst = 1;
+                    if(line[i] == '|') {
+                      nopfx = 1;
                                 }
+                }
                                 custr_reset(cu);
                         } else {
                                 if (custr_appendc(cu, line[i]) != 0) {
                                         lxi_err("custr_appendc failure");
                                 }
                         }
                         continue;
                 }
 
-                if (pfx == -1) {
+        if (*pfx == -1 && !nopfx) {
                         if (line[i] == '|') {
-                                pfx = atoi(custr_cstr(cu));
+                *pfx = atoi(custr_cstr(cu));
                                 custr_reset(cu);
                         } else {
                                 if (custr_appendc(cu, line[i]) != 0) {
                                         lxi_err("custr_appendc failure");
                                 }

@@ -763,29 +791,74 @@
                 if (custr_appendc(cu, line[i]) != 0) {
                         lxi_err("custr_appendc failure");
                 }
         }
 
+    return;
+}
+
+static void
+lxi_net_process_route_line(const char *line, int llonly)
+{
         /*
-         * We currently only support "next hop" routes, so ensure that
-         * "linklocal" is false:
+         * Each static route line is a string of the form:
+         *
+         *      "10.77.77.2|10.1.1.0/24|false"
+         *
+         * i.e. gateway address, destination network, and whether this is
+         * a "link local" route or a next hop route.
+         *
+         * passing a true value  to the llonly argument to this method causes only 
+         * those lines with the link-local flag to be processed and vice-versa
          */
-        if (strcmp(custr_cstr(cu), "false") != 0) {
-                lxi_warn("invalid static route: %s", line);
+        custr_t *cu = NULL;
+        int pfx = -1;
+        char gw[INET6_ADDRSTRLEN];
+        char dst[INET6_ADDRSTRLEN];
+
+        if (custr_alloc(&cu) != 0) {
+                lxi_err("custr_alloc failure");
         }
 
-        if (lxi_iface_gateway(NULL, dst, pfx, gw) != 0) {
-                lxi_err("failed to add route: %s/%d -> %s", dst, pfx, gw);
+        lxi_parse_route_line(line, cu, gw, dst, &pfx, sizeof(gw), sizeof(dst));
+
+        if (llonly && strcmp(custr_cstr(cu), "true") == 0) {
+          if (lxi_iface_gateway(NULL, dst, pfx, gw, 1) != 0) {
+                lxi_err("failed to add link-local route: %s/%d -> %s", dst, pfx, gw);
         }
+        } else if(!llonly && strcmp(custr_cstr(cu), "false") == 0) {
+          if (lxi_iface_gateway(NULL, dst, pfx, gw, 0) != 0) {
+                lxi_err("failed to add next-hop route: %s/%d -> %s", dst, pfx, gw);
+          }
+        } else if(strcmp(custr_cstr(cu), "true") != 0 && strcmp(custr_cstr(cu), "false") != 0) {
+          /*
+           * try to be helpful when we encounter something we don't expect.
+           */
+          lxi_warn("skipping unknown static route defined in line %s, parsed link-local flag=%s", line, custr_cstr(cu));
+        }
 
         custr_free(cu);
-        free(gw);
-        free(dst);
 }
 
 static void
-lxi_net_static_routes(void)
+lxi_net_static_route(const char * line) {
+        /* 
+         * process only those lines where the link-local field is false.
+         */   
+        lxi_net_process_route_line(line, 0);
+}
+
+static void 
+lxi_net_linklocal_route(const char * line) {
+        /*
+         * processes only those lines where the link-local field is true.
+         */
+        lxi_net_process_route_line(line, 1); 
+}
+
+static void
+lxi_run_routeinfo(void * callback)
 {
         const char *cmd = "/native/usr/lib/brand/lx/routeinfo";
         char *const argv[] = { "routeinfo", NULL };
         char *const envp[] = { NULL };
         int code;

@@ -794,11 +867,11 @@
 
         if (stat(cmd, &st) != 0 || !S_ISREG(st.st_mode)) {
                 /*
                  * This binary is (potentially) shipped from another
                  * consolidation.  If it does not exist, then the platform does
-                 * not currently support static routes for LX-branded zones.
+         * not currently support link-local or static routes for LX-branded zones.
                  */
                 return;
         }
 
         /*

@@ -805,16 +878,29 @@
          * Run the command, firing the callback for each line that it
          * outputs.  When this function returns, static route processing
          * is complete.
          */
         if (run_command(cmd, argv, envp, errbuf, sizeof (errbuf),
-            lxi_net_static_route, &code) != 0 || code != 0) {
+                    callback, &code) != 0 || code != 0) {
                 lxi_err("failed to run \"%s\": %s", cmd, errbuf);
         }
 }
 
 static void
+lxi_net_linklocal_routes(void)
+{
+        lxi_run_routeinfo(lxi_net_linklocal_route);
+}
+
+
+static void
+lxi_net_static_routes(void)
+{
+        lxi_run_routeinfo(lxi_net_static_route);
+}
+
+static void
 lxi_config_close(zone_dochandle_t handle)
 {
         zonecfg_fini_handle(handle);
 }
 

@@ -915,10 +1001,14 @@
         lxi_net_ipadm_open();
 
         handle = lxi_config_open();
         lxi_net_loopback();
         lxi_net_setup(handle);
+
+        lxi_net_linklocal_routes();
+        lxi_net_setup_gateways(handle);
+
         lxi_config_close(handle);
 
         lxi_net_static_routes();
 
         lxi_net_ipadm_close();