Steve Grubb writes:
[oweals/busybox.git] / networking / ifupdown.c
index 8170e80b39780c5367154fd1bf84a0806bca8593..ebf528d7130bcbc8bb5f9b871ceee82fb2ce0f27 100644 (file)
@@ -1,8 +1,8 @@
 /* vi: set sw=4 ts=4: */
 /*
  *  ifupdown for busybox
- *  Copyright (c) 2002 Glenn McGrath <bug1@optushome.com.au>
- *  Copyright (c) 2003 Erik Andersen <andersen@codepoet.org>
+ *  Copyright (c) 2002 Glenn McGrath <bug1@iinet.net.au>
+ *  Copyright (c) 2003-2004 Erik Andersen <andersen@codepoet.org>
  *
  *  Based on ifupdown v 0.6.4 by Anthony Towns
  *  Copyright (c) 1999 Anthony Towns <aj@azure.humbug.org.au>
@@ -56,7 +56,7 @@
 #if 0
 #define debug_noise(fmt, args...) printf(fmt, ## args)
 #else
-#define debug_noise(fmt, args...) 
+#define debug_noise(fmt, args...)
 #endif
 
 /* Forward declaration */
@@ -72,7 +72,7 @@ extern llist_t *llist_add_to_end(llist_t *list_head, char *data)
        new_item = xmalloc(sizeof(llist_t));
        new_item->data = data;
        new_item->link = NULL;
-       
+
        prev = NULL;
        tmp = list_head;
        while(tmp) {
@@ -80,7 +80,7 @@ extern llist_t *llist_add_to_end(llist_t *list_head, char *data)
                tmp = tmp->link;
        }
        if (prev) {
-               prev->link = new_item; 
+               prev->link = new_item;
        } else {
                list_head = new_item;
        }
@@ -123,7 +123,7 @@ struct variable_t
        char *value;
 };
 
-struct interface_defn_t 
+struct interface_defn_t
 {
        struct interface_defn_t *prev;
        struct interface_defn_t *next;
@@ -388,8 +388,8 @@ static int loopback_up6(struct interface_defn_t *ifd, execfn *exec)
 {
 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
        int result;
-       result = execute("ip link set %iface% up", ifd, exec);
-       result +=execute("ip addr add ::1 dev %iface% label %label%", ifd, exec);
+       result =execute("ip addr add ::1 dev %iface%", ifd, exec);
+       result += execute("ip link set %iface% up", ifd, exec);
        return( result);
 #else
        return( execute("ifconfig %iface% add ::1", ifd, exec));
@@ -409,8 +409,8 @@ static int static_up6(struct interface_defn_t *ifd, execfn *exec)
 {
        int result;
 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
-       result = execute("ip link set %iface% up", ifd, exec);
-       result += execute("ip addr add %address%/%netmask% dev %iface% label %label%", ifd, exec);
+       result = execute("ip addr add %address%/%netmask% dev %iface% [[label %label%]]", ifd, exec);
+       result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec);
        result += execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec);
 #else
        result = execute("ifconfig %iface% [[media %media%]] [[hw %hwaddress%]] [[mtu %mtu%]] up", ifd, exec);
@@ -436,7 +436,7 @@ static int v4tunnel_up(struct interface_defn_t *ifd, execfn *exec)
        result = execute("ip tunnel add %iface% mode sit remote "
                                "%endpoint% [[local %local%]] [[ttl %ttl%]]", ifd, exec);
        result += execute("ip link set %iface% up", ifd, exec);
-       result += execute("ip addr add %address%/%netmask% dev %iface% label %label%", ifd, exec);
+       result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec);
        result += execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec);
        return( result);
 }
@@ -467,8 +467,8 @@ static int loopback_up(struct interface_defn_t *ifd, execfn *exec)
 {
 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
        int result;
-       result = execute("ip link set %iface% up", ifd, exec);
-       result += execute("ip addr add 127.0.0.1/8 dev %iface% label %label%", ifd, exec);
+       result = execute("ip addr add 127.0.0.1/8 dev %iface%", ifd, exec);
+       result += execute("ip link set %iface% up", ifd, exec);
        return(result);
 #else
        return( execute("ifconfig %iface% 127.0.0.1 up", ifd, exec));
@@ -491,9 +491,9 @@ static int static_up(struct interface_defn_t *ifd, execfn *exec)
 {
        int result;
 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
-       result = execute("ip link set %iface% up", ifd, exec);
-       result += execute("ip addr add %address%/%bnmask% [[broadcast %broadcast%]] "
-                       "dev %iface% label %label%", ifd, exec);
+       result = execute("ip addr add %address%/%bnmask% [[broadcast %broadcast%]] "
+                       "dev %iface% [[peer %pointopoint%]] [[label %label%]]", ifd, exec);
+       result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec);
        result += execute("[[ ip route add default via %gateway% dev %iface% ]]", ifd, exec);
 #else
        result = execute("ifconfig %iface% %address% netmask %netmask% "
@@ -557,7 +557,7 @@ static int dhcp_down(struct interface_defn_t *ifd, execfn *exec)
        } else if (execable("/sbin/dhcpcd")) {
                result = execute("dhcpcd -k %iface%", ifd, exec);
        }
-       return (result || execute("ifconfig %iface% down", ifd, exec));
+       return (result || bootp_down(ifd, exec));
 }
 
 static int bootp_up(struct interface_defn_t *ifd, execfn *exec)
@@ -569,7 +569,11 @@ static int bootp_up(struct interface_defn_t *ifd, execfn *exec)
 
 static int bootp_down(struct interface_defn_t *ifd, execfn *exec)
 {
-       return( execute("ifconfig down %iface%", ifd, exec));
+#ifdef CONFIG_FEATURE_IFUPDOWN_IP
+       return(execute("ip link set %iface% down", ifd, exec));
+#else
+       return(execute("ifconfig %iface% down", ifd, exec));
+#endif
 }
 
 static int ppp_up(struct interface_defn_t *ifd, execfn *exec)
@@ -594,7 +598,7 @@ static int wvdial_down(struct interface_defn_t *ifd, execfn *exec)
                                "-p /var/run/wvdial.%iface% -s 2", ifd, exec));
 }
 
-static struct method_t methods[] = 
+static struct method_t methods[] =
 {
        { "wvdial", wvdial_up, wvdial_down, },
        { "ppp", ppp_up, ppp_down, },
@@ -604,7 +608,7 @@ static struct method_t methods[] =
        { "loopback", loopback_up, loopback_down, },
 };
 
-struct address_family_t addr_inet = 
+struct address_family_t addr_inet =
 {
        "inet",
        sizeof(methods) / sizeof(struct method_t),
@@ -881,7 +885,7 @@ static struct interfaces_file_t *read_interfaces(char *filename)
                                                perror(filename);
                                                return NULL;
                                        }
-                                       debug_noise("\t%s=%s\n", currif->option[currif->n_options].name, 
+                                       debug_noise("\t%s=%s\n", currif->option[currif->n_options].name,
                                                        currif->option[currif->n_options].value);
                                        currif->n_options++;
                                        break;
@@ -1005,7 +1009,7 @@ static int doit(char *str)
                        case -1:                /* failure */
                                return 0;
                        case 0:         /* child */
-                               execle("/bin/sh", "/bin/sh", "-c", str, NULL, environ);
+                               execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, environ);
                                exit(127);
                }
                waitpid(child, &status, 0);
@@ -1020,7 +1024,6 @@ static int execute_all(struct interface_defn_t *ifd, execfn *exec, const char *o
 {
        int i;
        char *buf;
-
        for (i = 0; i < ifd->n_options; i++) {
                if (strcmp(ifd->option[i].name, opt) == 0) {
                        if (!(*exec) (ifd->option[i].value)) {
@@ -1029,10 +1032,9 @@ static int execute_all(struct interface_defn_t *ifd, execfn *exec, const char *o
                }
        }
 
-       buf = xmalloc(bb_strlen(opt) + 19);
-       sprintf(buf, "/etc/network/if-%s.d", opt);
-       run_parts(&buf, 2);
-       free(buf);
+       bb_xasprintf(&buf, "run-parts /etc/network/if-%s.d", opt);
+       (*exec)(buf);
+
        return (1);
 }
 
@@ -1042,24 +1044,22 @@ static int check(char *str) {
 
 static int iface_up(struct interface_defn_t *iface)
 {
-       int result;
        if (!iface->method->up(iface,check)) return -1;
        set_environ(iface, "start");
-       result = execute_all(iface, doit, "pre-up");
-       result += iface->method->up(iface, doit);
-       result += execute_all(iface, doit, "up");
-       return(result);
+       if (!execute_all(iface, doit, "pre-up")) return 0;
+       if (!iface->method->up(iface, doit)) return 0;
+       if (!execute_all(iface, doit, "up")) return 0;
+       return 1;
 }
 
 static int iface_down(struct interface_defn_t *iface)
 {
-       int result;
        if (!iface->method->down(iface,check)) return -1;
        set_environ(iface, "stop");
-       result = execute_all(iface, doit, "down");
-       result += iface->method->down(iface, doit);
-       result += execute_all(iface, doit, "post-down");
-       return(result);
+       if (!execute_all(iface, doit, "down")) return 0;
+       if (!iface->method->down(iface, doit)) return 0;
+       if (!execute_all(iface, doit, "post-down")) return 0;
+       return 1;
 }
 
 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
@@ -1116,38 +1116,57 @@ static int popen2(FILE **in, FILE **out, char *command, ...)
        /* unreached */
 }
 
-static char * run_mapping(char *physical, char *logical, int len, struct mapping_defn_t * map)
+static char * run_mapping(char *physical, struct mapping_defn_t * map)
 {
        FILE *in, *out;
        int i, status;
        pid_t pid;
 
-       char *new_logical = NULL;
+       char *logical = bb_xstrdup(physical);
 
+       /* Run the mapping script. */
        pid = popen2(&in, &out, map->script, physical, NULL);
-       if (pid == 0) {
-               return 0;
-       }
+
+       /* popen2() returns 0 on failure. */
+       if (pid == 0)
+               return logical;
+
+       /* Write mappings to stdin of mapping script. */
        for (i = 0; i < map->n_mappings; i++) {
                fprintf(in, "%s\n", map->mapping[i]);
        }
        fclose(in);
        waitpid(pid, &status, 0);
+
        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
-               new_logical = (char *)xmalloc(MAX_INTERFACE_LENGTH);
+               /* If the mapping script exited successfully, try to
+                * grab a line of output and use that as the name of the
+                * logical interface. */
+               char *new_logical = (char *)xmalloc(MAX_INTERFACE_LENGTH);
 
                if (fgets(new_logical, MAX_INTERFACE_LENGTH, out)) {
+                       /* If we are able to read a line of output from the script,
+                        * remove any trailing whitespace and use this value
+                        * as the name of the logical interface. */
                        char *pch = new_logical + bb_strlen(new_logical) - 1;
 
                        while (pch >= new_logical && isspace(*pch))
                                *(pch--) = '\0';
+
+                       free(logical);
+                       logical = new_logical;
+               } else {
+                       /* If we are UNABLE to read a line of output, discard are
+                        * freshly allocated memory. */
+                       free(new_logical);
                }
        }
+
        fclose(out);
 
-       return new_logical ? new_logical : logical;
+       return logical;
 }
-#endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */
+#endif /* CONFIG_FEATURE_IFUPDOWN_MAPPING */
 
 static llist_t *find_iface_state(llist_t *state_list, const char *iface)
 {
@@ -1192,7 +1211,7 @@ extern int ifupdown_main(int argc, char **argv)
 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
        while ((i = getopt(argc, argv, "i:hvnamf")) != -1)
 #else
-               while ((i = getopt(argc, argv, "i:hvnaf")) != -1) 
+               while ((i = getopt(argc, argv, "i:hvnaf")) != -1)
 #endif
                {
                        switch (i) {
@@ -1230,7 +1249,7 @@ extern int ifupdown_main(int argc, char **argv)
                if (!do_all) {
                        bb_show_usage();
                }
-       }                       
+       }
 
        debug_noise("reading %s file:\n", interfaces);
        defn = read_interfaces(interfaces);
@@ -1278,8 +1297,8 @@ extern int ifupdown_main(int argc, char **argv)
                                list = list->link;
                        }
                        target_list = defn->autointerfaces;
-#endif 
-               } 
+#endif
+               }
        } else {
                target_list = llist_add_to_end(target_list, argv[optind]);
        }
@@ -1335,7 +1354,7 @@ extern int ifupdown_main(int argc, char **argv)
                                        if (verbose) {
                                                printf("Running mapping script %s on %s\n", currmap->script, liface);
                                        }
-                                       liface = run_mapping(iface, liface, sizeof(liface), currmap);
+                                       liface = run_mapping(iface, currmap);
                                        break;
                                }
                        }
@@ -1394,7 +1413,7 @@ extern int ifupdown_main(int argc, char **argv)
                                        } else {
                                                iface_state->data = NULL;
                                                iface_state->link = NULL;
-                                       }                                               
+                                       }
                                }
                        }
                }