X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fifupdown.c;h=37185327b68056f469deb7d339d3a14f6a744136;hb=ea2a1064b33bfb4fe0493659f43ed074cfe80067;hp=dda530a99bf4742033858c594511a89da0bb93d0;hpb=eebe31d9979917242bd55274cd153ef08a289480;p=oweals%2Fbusybox.git diff --git a/networking/ifupdown.c b/networking/ifupdown.c index dda530a99..37185327b 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -1,9 +1,14 @@ /* * ifupdown for busybox - * Based on ifupdown by Anthony Towns + * Copyright (c) 2002 Glenn McGrath + * + * Based on ifupdown v 0.6.4 by Anthony Towns * Copyright (c) 1999 Anthony Towns * - * Remove checks for kernel version, assume kernel version 2.2.0 or better + * Changes to upstream version + * Remove checks for kernel version, assume kernel version 2.2.0 or better. + * Lines in the interfaces file cannot wrap. + * To adhere to the FHS, the default state file is /var/run/ifstate. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,31 +40,32 @@ #include #include -#include "busybox.h" -#include "config.h" +#include "libbb.h" -#define IFUPDOWN_VERSION "0.6.4" +#define MAX_OPT_DEPTH 10 +#define EUNBALBRACK 10001 +#define EUNDEFVAR 10002 +#define EUNBALPER 10000 -typedef struct interface_defn interface_defn; +typedef struct interface_defn_s interface_defn_t; typedef int (execfn)(char *command); -typedef int (command_set)(interface_defn *ifd, execfn *e); +typedef int (command_set)(interface_defn_t *ifd, execfn *e); -typedef struct method { +typedef struct method_s { char *name; command_set *up; command_set *down; -} method; +} method_t; -typedef struct address_family { +typedef struct address_family_s { char *name; int n_methods; - method *method; -} address_family; + method_t *method; +} address_family_t; -#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING -typedef struct mapping_defn { - struct mapping_defn *next; +typedef struct mapping_defn_s { + struct mapping_defn_s *next; int max_matches; int n_matches; @@ -70,47 +76,35 @@ typedef struct mapping_defn { int max_mappings; int n_mappings; char **mapping; -} mapping_defn; -#endif +} mapping_defn_t; -typedef struct variable { +typedef struct variable_s { char *name; char *value; -} variable; +} variable_t; -struct interface_defn { - struct interface_defn *next; +struct interface_defn_s { + struct interface_defn_s *next; char *iface; - address_family *address_family; - method *method; + address_family_t *address_family; + method_t *method; int automatic; int max_options; int n_options; - variable *option; + variable_t *option; }; -typedef struct interfaces_file { - int max_autointerfaces; - int n_autointerfaces; - char **autointerfaces; - - interface_defn *ifaces; -#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING - mapping_defn *mappings; -#endif -} interfaces_file; - -#define MAX_OPT_DEPTH 10 -#define EUNBALBRACK 10001 -#define EUNDEFVAR 10002 -#define MAX_VARNAME 32 -#define EUNBALPER 10000 +typedef struct interfaces_file_s { + llist_t *autointerfaces; + interface_defn_t *ifaces; + mapping_defn_t *mappings; +} interfaces_file_t; -static int no_act = 0; -static int verbose = 0; +static char no_act = 0; +static char verbose = 0; static char **environ = NULL; static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length) @@ -141,7 +135,7 @@ static int strncmpz(char *l, char *r, size_t llen) } } -static char *get_var(char *id, size_t idlen, interface_defn *ifd) +static char *get_var(char *id, size_t idlen, interface_defn_t *ifd) { int i; @@ -158,7 +152,7 @@ static char *get_var(char *id, size_t idlen, interface_defn *ifd) return(NULL); } -static char *parse(char *command, interface_defn *ifd) +static char *parse(char *command, interface_defn_t *ifd) { char *result = NULL; @@ -249,7 +243,7 @@ static char *parse(char *command, interface_defn *ifd) return(result); } -static int execute(char *command, interface_defn *ifd, execfn *exec) +static int execute(char *command, interface_defn_t *ifd, execfn *exec) { char *out; int ret; @@ -266,7 +260,7 @@ static int execute(char *command, interface_defn *ifd, execfn *exec) } #ifdef CONFIG_FEATURE_IFUPDOWN_IPX -static int static_up_ipx(interface_defn *ifd, execfn *exec) +static int static_up_ipx(interface_defn_t *ifd, execfn *exec) { if (!execute("ipx_interface add %iface% %frame% %netnum%", ifd, exec)) { return(0); @@ -274,7 +268,7 @@ static int static_up_ipx(interface_defn *ifd, execfn *exec) return(1); } -static int static_down_ipx(interface_defn *ifd, execfn *exec) +static int static_down_ipx(interface_defn_t *ifd, execfn *exec) { if (!execute("ipx_interface del %iface% %frame%", ifd, exec)) { return(0); @@ -282,7 +276,7 @@ static int static_down_ipx(interface_defn *ifd, execfn *exec) return(1); } -static int dynamic_up(interface_defn *ifd, execfn *exec) +static int dynamic_up(interface_defn_t *ifd, execfn *exec) { if (!execute("ipx_interface add %iface% %frame%", ifd, exec)) { return(0); @@ -290,7 +284,7 @@ static int dynamic_up(interface_defn *ifd, execfn *exec) return(1); } -static int dynamic_down(interface_defn *ifd, execfn *exec) +static int dynamic_down(interface_defn_t *ifd, execfn *exec) { if (!execute("ipx_interface del %iface% %frame%", ifd, exec)) { return(0); @@ -298,20 +292,20 @@ static int dynamic_down(interface_defn *ifd, execfn *exec) return(1); } -static method methods_ipx[] = { +static method_t methods_ipx[] = { { "dynamic", dynamic_up, dynamic_down, }, { "static", static_up_ipx, static_down_ipx, }, }; -address_family addr_ipx = { +address_family_t addr_ipx = { "ipx", - sizeof(methods_ipx) / sizeof(struct method), + sizeof(methods_ipx) / sizeof(method_t), methods_ipx }; #endif /* IFUP_FEATURE_IPX */ #ifdef CONFIG_FEATURE_IFUPDOWN_IPV6 -static int loopback_up6(interface_defn *ifd, execfn *exec) +static int loopback_up6(interface_defn_t *ifd, execfn *exec) { if (!execute("ifconfig %iface% add ::1", ifd, exec)) { return(0); @@ -319,15 +313,15 @@ static int loopback_up6(interface_defn *ifd, execfn *exec) return(1); } -static int loopback_down6(interface_defn *ifd, execfn *exec) +static int loopback_down6(interface_defn_t *ifd, execfn *exec) { - if (!execute("ifconfig %iface% del ::1", ifd, exec)) + if (!execute("ifconfig %iface% del ::1", ifd, exec)) { return(0); } return(1); } -static int static_up6(interface_defn *ifd, execfn *exec) +static int static_up6(interface_defn_t *ifd, execfn *exec) { if (!execute("ifconfig %iface% [[media %media%]] [[hw %hwaddress%]] [[mtu %mtu%]] up", ifd, exec)) { return(0); @@ -341,7 +335,7 @@ static int static_up6(interface_defn *ifd, execfn *exec) return(1); } -static int static_down6(interface_defn *ifd, execfn *exec) +static int static_down6(interface_defn_t *ifd, execfn *exec) { if (!execute("ifconfig %iface% down", ifd, exec)) { return(0); @@ -349,7 +343,7 @@ static int static_down6(interface_defn *ifd, execfn *exec) return(1); } -static int v4tunnel_up(interface_defn *ifd, execfn *exec) +static int v4tunnel_up(interface_defn_t *ifd, execfn *exec) { if (!execute("ip tunnel add %iface% mode sit remote %endpoint% [[local %local%]] [[ttl %ttl%]]", ifd, exec)) { return(0); @@ -366,7 +360,7 @@ static int v4tunnel_up(interface_defn *ifd, execfn *exec) return(1); } -static int v4tunnel_down(interface_defn * ifd, execfn * exec) +static int v4tunnel_down(interface_defn_t * ifd, execfn * exec) { if (!execute("ip tunnel del %iface%", ifd, exec)) { return(0); @@ -374,21 +368,21 @@ static int v4tunnel_down(interface_defn * ifd, execfn * exec) return(1); } -static method methods6[] = { +static method_t methods6[] = { { "v4tunnel", v4tunnel_up, v4tunnel_down, }, { "static", static_up6, static_down6, }, { "loopback", loopback_up6, loopback_down6, }, }; -address_family addr_inet6 = { +address_family_t addr_inet6 = { "inet6", - sizeof(methods6) / sizeof(struct method), + sizeof(methods6) / sizeof(method_t), methods6 }; #endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */ #ifdef CONFIG_FEATURE_IFUPDOWN_IPV4 -static int loopback_up(interface_defn *ifd, execfn *exec) +static int loopback_up(interface_defn_t *ifd, execfn *exec) { if (!execute("ifconfig %iface% 127.0.0.1 up", ifd, exec)) { return(0); @@ -396,15 +390,15 @@ static int loopback_up(interface_defn *ifd, execfn *exec) return(1); } -static int loopback_down(interface_defn *ifd, execfn *exec) +static int loopback_down(interface_defn_t *ifd, execfn *exec) { - if (!execute("ifconfig %iface% down", ifd, exec)) { + if (!execute("ifconfig %iface% 127.0.0.1 down", ifd, exec)) { return(0); } return(1); } -static int static_up(interface_defn *ifd, execfn *exec) +static int static_up(interface_defn_t *ifd, execfn *exec) { if (!execute("ifconfig %iface% %address% netmask %netmask% [[broadcast %broadcast%]] [[pointopoint %pointopoint%]] [[media %media%]] [[mtu %mtu%]] [[hw %hwaddress%]] up", ifd, exec)) { @@ -416,7 +410,7 @@ static int static_up(interface_defn *ifd, execfn *exec) return(1); } -static int static_down(interface_defn *ifd, execfn *exec) +static int static_down(interface_defn_t *ifd, execfn *exec) { if (!execute("[[ route del default gw %gateway% %iface% ]]", ifd, exec)) { return(0); @@ -438,7 +432,7 @@ static int execable(char *program) return(0); } -static int dhcp_up(interface_defn *ifd, execfn *exec) +static int dhcp_up(interface_defn_t *ifd, execfn *exec) { if (execable("/sbin/dhclient")) { if (!execute("dhclient -pf /var/run/dhclient.%iface%.pid %iface%", ifd, exec)) { @@ -460,10 +454,10 @@ static int dhcp_up(interface_defn *ifd, execfn *exec) return(1); } -static int dhcp_down(interface_defn *ifd, execfn *exec) +static int dhcp_down(interface_defn_t *ifd, execfn *exec) { if (execable("/sbin/dhclient")) { - if (!execute("cat /var/run/dhclient.%iface%.pid | xargs -i kill -TERM {}", ifd, exec)) { + if (!execute("kill -9 `cat /var/run/udhcpc.%iface%.pid`", ifd, exec)) { return(0); } } else if (execable("/sbin/pump")) { @@ -471,7 +465,7 @@ static int dhcp_down(interface_defn *ifd, execfn *exec) return(0); } } else if (execable("/sbin/udhcpc")) { - if (!execute("cat /var/run/udhcpc.%iface%.pid | xargs -i kill -TERM {}", ifd, exec)) { + if (!execute("kill -9 `cat /var/run/udhcpc.%iface%.pid`", ifd, exec)) { return(0); } } else if (execable("/sbin/dhcpcd")) { @@ -485,7 +479,7 @@ static int dhcp_down(interface_defn *ifd, execfn *exec) return(1); } -static int bootp_up(interface_defn *ifd, execfn *exec) +static int bootp_up(interface_defn_t *ifd, execfn *exec) { if (!execute("bootpc [[--bootfile %bootfile%]] --dev %iface% [[--server %server%]] [[--hwaddr %hwaddr%]] --returniffail --serverbcast", ifd, exec)) { return 0; @@ -493,7 +487,7 @@ static int bootp_up(interface_defn *ifd, execfn *exec) return 1; } -static int bootp_down(interface_defn *ifd, execfn *exec) +static int bootp_down(interface_defn_t *ifd, execfn *exec) { if (!execute("ifconfig down %iface%", ifd, exec)) { return 0; @@ -501,7 +495,7 @@ static int bootp_down(interface_defn *ifd, execfn *exec) return 1; } -static int ppp_up(interface_defn *ifd, execfn *exec) +static int ppp_up(interface_defn_t *ifd, execfn *exec) { if (!execute("pon [[%provider%]]", ifd, exec)) { return 0; @@ -509,7 +503,7 @@ static int ppp_up(interface_defn *ifd, execfn *exec) return 1; } -static int ppp_down(interface_defn *ifd, execfn *exec) +static int ppp_down(interface_defn_t *ifd, execfn *exec) { if (!execute("poff [[%provider%]]", ifd, exec)) { return 0; @@ -517,7 +511,7 @@ static int ppp_down(interface_defn *ifd, execfn *exec) return 1; } -static int wvdial_up(interface_defn *ifd, execfn *exec) +static int wvdial_up(interface_defn_t *ifd, execfn *exec) { if (!execute("/sbin/start-stop-daemon --start -x /usr/bin/wvdial -p /var/run/wvdial.%iface% -b -m -- [[ %provider% ]]", ifd, exec)) { return 0; @@ -525,7 +519,7 @@ static int wvdial_up(interface_defn *ifd, execfn *exec) return 1; } -static int wvdial_down(interface_defn *ifd, execfn *exec) +static int wvdial_down(interface_defn_t *ifd, execfn *exec) { if (!execute ("/sbin/start-stop-daemon --stop -x /usr/bin/wvdial -p /var/run/wvdial.%iface% -s 2", ifd, exec)) { return 0; @@ -533,7 +527,7 @@ static int wvdial_down(interface_defn *ifd, execfn *exec) return 1; } -static method methods[] = { +static method_t methods[] = { { "wvdial", wvdial_up, wvdial_down, }, { "ppp", ppp_up, ppp_down, }, { "static", static_up, static_down, }, @@ -542,9 +536,9 @@ static method methods[] = { { "loopback", loopback_up, loopback_down, }, }; -address_family addr_inet = { +address_family_t addr_inet = { "inet", - sizeof(methods) / sizeof(struct method), + sizeof(methods) / sizeof(method_t), methods }; @@ -573,7 +567,7 @@ static char *next_word(char *buf, char *word, int maxlen) return buf; } -static address_family *get_address_family(address_family *af[], char *name) +static address_family_t *get_address_family(address_family_t *af[], char *name) { int i; @@ -585,7 +579,7 @@ static address_family *get_address_family(address_family *af[], char *name) return NULL; } -static method *get_method(address_family *af, char *name) +static method_t *get_method(address_family_t *af, char *name) { int i; @@ -597,7 +591,7 @@ static method *get_method(address_family *af, char *name) return(NULL); } -static int duplicate_if(interface_defn *ifa, interface_defn *ifb) +static int duplicate_if(interface_defn_t *ifa, interface_defn_t *ifb) { if (strcmp(ifa->iface, ifb->iface) != 0) { return(0); @@ -608,107 +602,55 @@ static int duplicate_if(interface_defn *ifa, interface_defn *ifb) return(1); } -static int get_line(char **result, size_t * result_len, FILE * f, int *line) +static const llist_t *find_list_string(const llist_t *list, const char *string) { - size_t pos; - - do { - pos = 0; - do { - if (*result_len - pos < 10) { - char *newstr = xrealloc(*result, *result_len * 2 + 80); - *result = newstr; - *result_len = *result_len * 2 + 80; - } - - if (!fgets(*result + pos, *result_len - pos, f)) { - if (ferror(f) == 0 && pos == 0) - return 0; - if (ferror(f) != 0) - return 0; - } - pos += xstrlen(*result + pos); - } while (pos == *result_len - 1 && (*result)[pos - 1] != '\n'); - - if (pos != 0 && (*result)[pos - 1] == '\n') { - (*result)[--pos] = '\0'; + while (list) { + if (strcmp(list->data, string) == 0) { + return(list); } - - (*line)++; - { - int first = 0; - - while (isspace((*result)[first]) && (*result)[first]) { - first++; - } - - memmove(*result, *result + first, pos - first + 1); - pos -= first; - } - } while ((*result)[0] == '#'); - - while ((*result)[pos - 1] == '\\') { - (*result)[--pos] = '\0'; - do { - if (*result_len - pos < 10) { - char *newstr = xrealloc(*result, *result_len * 2 + 80); - *result = newstr; - *result_len = *result_len * 2 + 80; - } - - if (!fgets(*result + pos, *result_len - pos, f)) { - if (ferror(f) == 0 && pos == 0) - return 0; - if (ferror(f) != 0) - return 0; - } - pos += xstrlen(*result + pos); - } while (pos == *result_len - 1 && (*result)[pos - 1] != '\n'); - - if (pos != 0 && (*result)[pos - 1] == '\n') { - (*result)[--pos] = '\0'; - } - (*line)++; - } - - while (isspace((*result)[pos - 1])) { /* remove trailing whitespace */ - pos--; + list = list->link; } - (*result)[pos] = '\0'; - - return 1; + return(NULL); } -static interfaces_file *read_interfaces(char *filename) +static interfaces_file_t *read_interfaces(char *filename) { - interface_defn *currif = NULL; - interfaces_file *defn; + interface_defn_t *currif = NULL; + interfaces_file_t *defn; #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING - mapping_defn *currmap = NULL; + mapping_defn_t *currmap = NULL; #endif FILE *f; char firstword[80]; char *buf = NULL; char *rest; - int line; - size_t buf_len = 0; +// int line; enum { NONE, IFACE, MAPPING } currently_processing = NONE; - defn = xmalloc(sizeof(interfaces_file)); - defn->max_autointerfaces = defn->n_autointerfaces = 0; + defn = xmalloc(sizeof(interfaces_file_t)); +// defn->max_autointerfaces = defn->n_autointerfaces = 0; defn->autointerfaces = NULL; -#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING defn->mappings = NULL; -#endif defn->ifaces = NULL; f = fopen(filename, "r"); if (f == NULL) { return NULL; } - line = 0; - while (get_line(&buf, &buf_len, f, &line)) { + while ((buf = get_line_from_file(f)) != NULL) { + char *end; + + if (buf[0] == '#') { + continue; + } + end = last_char_is(buf, '\n'); + if (end) { + *end = '\0'; + } + while ((end = last_char_is(buf, ' ')) != NULL) { + *end = '\0'; + } rest = next_word(buf, firstword, 80); if (rest == NULL) { continue; /* blank line */ @@ -716,7 +658,7 @@ static interfaces_file *read_interfaces(char *filename) if (strcmp(firstword, "mapping") == 0) { #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING - currmap = xmalloc(sizeof(mapping_defn)); + currmap = xmalloc(sizeof(mapping_defn_t)); currmap->max_matches = 0; currmap->n_matches = 0; currmap->match = NULL; @@ -734,21 +676,21 @@ static interfaces_file *read_interfaces(char *filename) currmap->mapping = NULL; currmap->script = NULL; { - mapping_defn **where = &defn->mappings; + mapping_defn_t **where = &defn->mappings; while (*where != NULL) { where = &(*where)->next; } *where = currmap; currmap->next = NULL; } - currently_processing = MAPPING; #endif + currently_processing = MAPPING; } else if (strcmp(firstword, "iface") == 0) { { char iface_name[80]; char address_family_name[80]; char method_name[80]; - address_family *addr_fams[] = { + address_family_t *addr_fams[] = { #ifdef CONFIG_FEATURE_IFUPDOWN_IPV4 &addr_inet, #endif @@ -761,19 +703,19 @@ static interfaces_file *read_interfaces(char *filename) NULL }; - currif = xmalloc(sizeof(interface_defn)); + currif = xmalloc(sizeof(interface_defn_t)); rest = next_word(rest, iface_name, 80); rest = next_word(rest, address_family_name, 80); rest = next_word(rest, method_name, 80); if (rest == NULL) { - error_msg("%s:%d: too few parameters for iface line", filename, line); + error_msg("too few parameters for line \"%s\"", buf); return NULL; } if (rest[0] != '\0') { - error_msg("%s:%d: too many parameters for iface line", filename, line); + error_msg("too many parameters \"%s\"", buf); return NULL; } @@ -781,13 +723,13 @@ static interfaces_file *read_interfaces(char *filename) currif->address_family = get_address_family(addr_fams, address_family_name); if (!currif->address_family) { - error_msg("%s:%d: unknown address type", filename, line); + error_msg("unknown address type \"%s\"", buf); return NULL; } currif->method = get_method(currif->address_family, method_name); if (!currif->method) { - error_msg("%s:%d: unknown method", filename, line); + error_msg("unknown method \"%s\"", buf); return NULL; } @@ -798,11 +740,11 @@ static interfaces_file *read_interfaces(char *filename) { - interface_defn **where = &defn->ifaces; + interface_defn_t **where = &defn->ifaces; while (*where != NULL) { if (duplicate_if(*where, currif)) { - error_msg("%s:%d: duplicate interface", filename, line); + error_msg("duplicate interface \"%s\"", buf); return NULL; } where = &(*where)->next; @@ -815,26 +757,14 @@ static interfaces_file *read_interfaces(char *filename) currently_processing = IFACE; } else if (strcmp(firstword, "auto") == 0) { while ((rest = next_word(rest, firstword, 80))) { - int i; - for (i = 0; i < defn->n_autointerfaces; i++) { - if (strcmp(firstword, defn->autointerfaces[i]) == 0) { - perror_msg("%s:%d: interface declared auto twice", filename, line); - return NULL; - } - } - - if (defn->n_autointerfaces == defn->max_autointerfaces) { - char **tmp; - - defn->max_autointerfaces *= 2; - defn->max_autointerfaces++; - tmp = xrealloc(defn->autointerfaces, sizeof(*tmp) * defn->max_autointerfaces); - defn->autointerfaces = tmp; + /* Check the interface isnt already listed */ + if (find_list_string(defn->autointerfaces, firstword)) { + perror_msg_and_die("interface declared auto twice \"%s\"", buf); } - defn->autointerfaces[defn->n_autointerfaces] = xstrdup(firstword); - defn->n_autointerfaces++; + /* Add the interface to the list */ + defn->autointerfaces = llist_add_to(defn->autointerfaces, strdup(firstword)); } currently_processing = NONE; } else { @@ -844,7 +774,7 @@ static interfaces_file *read_interfaces(char *filename) int i; if (xstrlen(rest) == 0) { - error_msg("%s:%d: option with empty value", filename, line); + error_msg("option with empty value \"%s\"", buf); return NULL; } @@ -854,14 +784,14 @@ static interfaces_file *read_interfaces(char *filename) && strcmp(firstword, "post-down") != 0) { for (i = 0; i < currif->n_options; i++) { if (strcmp(currif->option[i].name, firstword) == 0) { - error_msg("%s:%d: duplicate option", filename, line); + error_msg("duplicate option \"%s\"", buf); return NULL; } } } } if (currif->n_options >= currif->max_options) { - variable *opt; + variable_t *opt; currif->max_options = currif->max_options + 10; opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options); @@ -883,7 +813,7 @@ static interfaces_file *read_interfaces(char *filename) #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING if (strcmp(firstword, "script") == 0) { if (currmap->script != NULL) { - error_msg("%s:%d: duplicate script in mapping", filename, line); + error_msg("duplicate script in mapping \"%s\"", buf); return NULL; } else { currmap->script = xstrdup(rest); @@ -896,14 +826,14 @@ static interfaces_file *read_interfaces(char *filename) currmap->mapping[currmap->n_mappings] = xstrdup(rest); currmap->n_mappings++; } else { - error_msg("%s:%d: misplaced option", filename, line); + error_msg("misplaced option \"%s\"", buf); return NULL; } #endif break; case NONE: default: - error_msg("%s:%d: misplaced option", filename, line); + error_msg("misplaced option \"%s\"", buf); return NULL; } } @@ -913,7 +843,6 @@ static interfaces_file *read_interfaces(char *filename) return NULL; } fclose(f); - line = -1; return defn; } @@ -949,7 +878,7 @@ static char *setlocalenv(char *format, char *name, char *value) return result; } -static void set_environ(interface_defn *iface, char *mode) +static void set_environ(interface_defn_t *iface, char *mode) { char **environend; int i; @@ -1017,10 +946,10 @@ static int doit(char *str) return (1); } -static int execute_all(interface_defn *ifd, execfn *exec, char *opt) +static int execute_all(interface_defn_t *ifd, execfn *exec, const char *opt) { int i; - char buf[100]; + char *buf; for (i = 0; i < ifd->n_options; i++) { if (strcmp(ifd->option[i].name, opt) == 0) { @@ -1030,13 +959,14 @@ static int execute_all(interface_defn *ifd, execfn *exec, char *opt) } } - sprintf(buf, "run-parts /etc/network/if-%s.d", opt); - (*exec) (buf); - + buf = xmalloc(xstrlen(opt) + 19); + sprintf(buf, "/etc/network/if-%s.d", opt); + run_parts(&buf, 0); + free(buf); return (1); } -static int iface_up(interface_defn *iface) +static int iface_up(interface_defn_t *iface) { if (!iface->method->up(iface, check)) { return (-1); @@ -1056,7 +986,7 @@ static int iface_up(interface_defn *iface) return (1); } -static int iface_down(interface_defn *iface) +static int iface_down(interface_defn_t *iface) { if (!iface->method->down(iface, check)) { return (-1); @@ -1128,7 +1058,7 @@ static int popen2(FILE **in, FILE **out, char *command, ...) /* unreached */ } -static int run_mapping(char *physical, char *logical, int len, mapping_defn * map) +static int run_mapping(char *physical, char *logical, int len, mapping_defn_t * map) { FILE *in, *out; int i, status; @@ -1156,52 +1086,38 @@ static int run_mapping(char *physical, char *logical, int len, mapping_defn * ma return 1; } -#endif /* CONFIG_FEATURE_IFUPDOWN_MAPPING */ - +#endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */ -static int lookfor_iface(char **ifaces, int n_ifaces, char *iface) +static llist_t *find_iface_state(llist_t *state_list, const char *iface) { - int i; + unsigned short iface_len = xstrlen(iface); + llist_t *search = state_list; - for (i = 0; i < n_ifaces; i++) { - if (strncmp(iface, ifaces[i], xstrlen(iface)) == 0) { - if (ifaces[i][xstrlen(iface)] == '=') { - return i; - } + while (search) { + if ((strncmp(search->data, iface, iface_len) == 0) && + (search->data[iface_len] == '=')) { + return(search); } + search = search->link; } - - return(-1); -} - -static void add_to_state(char ***ifaces, int *n_ifaces, int *max_ifaces, char *new_iface) -{ - if (*max_ifaces == *n_ifaces) { - *max_ifaces = (*max_ifaces * 2) + 1; - *ifaces = xrealloc(*ifaces, sizeof(**ifaces) * *max_ifaces); - } - - (*ifaces)[(*n_ifaces)++] = new_iface; + return(NULL); } extern int ifupdown_main(int argc, char **argv) { - int (*cmds) (interface_defn *) = NULL; - interfaces_file *defn; + int (*cmds) (interface_defn_t *) = NULL; + interfaces_file_t *defn; FILE *state_fp = NULL; - char **target_iface = NULL; - char **state = NULL; /* list of iface=liface */ + llist_t *state_list = NULL; + llist_t *target_list = NULL; char *interfaces = "/etc/network/interfaces"; - char *statefile = "/etc/network/ifstate"; + const char *statefile = "/var/run/ifstate"; - int do_all = 0; #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING int run_mappings = 1; #endif + int do_all = 0; int force = 0; - int n_target_ifaces = 0; - int n_state = 0; - int max_state = 0; int i; if (applet_name[2] == 'u') { @@ -1212,7 +1128,11 @@ extern int ifupdown_main(int argc, char **argv) cmds = iface_down; } +#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING while ((i = getopt(argc, argv, "i:hvnamf")) != -1) { +#else + while ((i = getopt(argc, argv, "i:hvnaf")) != -1) { +#endif switch (i) { case 'i': /* interfaces */ interfaces = xstrdup(optarg); @@ -1255,108 +1175,82 @@ extern int ifupdown_main(int argc, char **argv) error_msg_and_die("couldn't read interfaces file \"%s\"", interfaces); } - state_fp = fopen(statefile, no_act ? "r" : "a+"); - if (state_fp == NULL && !no_act) { - perror_msg_and_die("failed to open statefile %s", statefile); + if (no_act) { + state_fp = fopen(statefile, "r"); + } else { + state_fp = xfopen(statefile, "a+"); } + /* Read the previous state from the state file */ if (state_fp != NULL) { - char buf[80]; - char *p; - - if (!no_act) { - int flags; - struct flock lock; - const int state_fd = fileno(state_fp); - - flags = fcntl(state_fd, F_GETFD); - if ((flags < 0) || (fcntl(state_fd, F_SETFD, flags | FD_CLOEXEC) < 0)) { - perror_msg_and_die("failed to set FD_CLOEXEC on statefile %s", statefile); - } - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - - if (fcntl(state_fd, F_SETLKW, &lock) < 0) { - perror_msg_and_die("failed to lock statefile %s", statefile); - } - } - - rewind(state_fp); - while ((p = fgets(buf, sizeof buf, state_fp)) != NULL) { - char *pch; - - pch = buf + xstrlen(buf) - 1; - while (pch > buf && isspace(*pch)) { - pch--; - } - *(pch + 1) = '\0'; - - pch = buf; - while (isspace(*pch)) { - pch++; - } - - add_to_state(&state, &n_state, &max_state, xstrdup(pch)); + char *start; + while ((start = get_line_from_file(state_fp)) != NULL) { + char *end_ptr; + /* We should only need to check for a single character */ + end_ptr = start + strcspn(start, " \t\n"); + *end_ptr = '\0'; + state_list = llist_add_to(state_list, start); } } + /* Create a list of interfaces to work on */ if (do_all) { if (cmds == iface_up) { - target_iface = defn->autointerfaces; - n_target_ifaces = defn->n_autointerfaces; + target_list = defn->autointerfaces; } else if (cmds == iface_down) { - target_iface = state; - n_target_ifaces = n_state; + const llist_t *list = state_list; + while (list) { + target_list = llist_add_to(target_list, strdup(list->data)); + list = list->link; + } } } else { - target_iface = argv + optind; - n_target_ifaces = argc - optind; + target_list = llist_add_to(target_list, argv[optind]); } - for (i = 0; i < n_target_ifaces; i++) { - interface_defn *currif; - char iface[80]; - char liface[80]; + /* Update the interfaces */ + while (target_list) { + interface_defn_t *currif; + char *iface; + char *liface; char *pch; int okay = 0; - strncpy(iface, target_iface[i], sizeof(iface)); - iface[sizeof(iface) - 1] = '\0'; + iface = strdup(target_list->data); + target_list = target_list->link; - if ((pch = strchr(iface, '='))) { + pch = strchr(iface, '='); + if (pch) { *pch = '\0'; - strncpy(liface, pch + 1, sizeof(liface)); - liface[sizeof(liface) - 1] = '\0'; + liface = strdup(pch + 1); } else { - strncpy(liface, iface, sizeof(liface)); - liface[sizeof(liface) - 1] = '\0'; + liface = strdup(iface); } + if (!force) { - int already_up = lookfor_iface(state, n_state, iface);; + const llist_t *iface_state = find_iface_state(state_list, iface); if (cmds == iface_up) { /* ifup */ - if (already_up != -1) { + if (iface_state) { error_msg("interface %s already configured", iface); continue; } } else { /* ifdown */ - if (already_up == -1) { + if (iface_state == NULL) { error_msg("interface %s not configured", iface); continue; } - strncpy(liface, strchr(state[already_up], '=') + 1, 80); - liface[79] = 0; + pch = strchr(iface_state->data, '='); + liface = strdup(pch + 1); } } + #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING if ((cmds == iface_up) && run_mappings) { - mapping_defn *currmap; + mapping_defn_t *currmap; for (currmap = defn->mappings; currmap; currmap = currmap->next) { @@ -1378,26 +1272,19 @@ extern int ifupdown_main(int argc, char **argv) char *oldiface = currif->iface; okay = 1; - currif->iface = iface; if (verbose) { error_msg("Configuring interface %s=%s (%s)", iface, liface, currif->address_family->name); } - switch (cmds(currif)) { - case -1: + /* Call the cmds function pointer, does either iface_up() or iface_down() */ + if (cmds(currif) == -1) { printf ("Don't seem to be have all the variables for %s/%s.\n", liface, currif->address_family->name); - break; - case 0: - /* this wasn't entirely successful, should it be added to - * the state file? - */ - case 1: - /* successful */ } + currif->iface = oldiface; } } @@ -1405,37 +1292,54 @@ extern int ifupdown_main(int argc, char **argv) if (!okay && !force) { error_msg("Ignoring unknown interface %s=%s.", iface, liface); } else { - int already_up = lookfor_iface(state, n_state, iface); + llist_t *iface_state = find_iface_state(state_list, iface); if (cmds == iface_up) { char *newiface = xmalloc(xstrlen(iface) + 1 + xstrlen(liface) + 1); sprintf(newiface, "%s=%s", iface, liface); - if (already_up == -1) { - add_to_state(&state, &n_state, &max_state, newiface); + if (iface_state == NULL) { + state_list = llist_add_to(state_list, newiface); } else { - free(state[already_up]); - state[already_up] = newiface; + free(iface_state->data); + iface_state->data = newiface; } } else if (cmds == iface_down) { - if (already_up != -1) { - state[already_up] = state[--n_state]; + /* Remove an interface from the linked list */ + if (iface_state) { + /* This needs to be done better */ + free(iface_state->data); + free(iface_state->link); + if (iface_state->link) { + iface_state->data = iface_state->link->data; + iface_state->link = iface_state->link->link; + } else { + iface_state->data = NULL; + iface_state->link = NULL; + } } } } - if (state_fp != NULL && !no_act) { - if (ftruncate(fileno(state_fp), 0) < 0) { - error_msg_and_die("failed to truncate statefile %s: %s", statefile, strerror(errno)); - } + } + + /* Actually write the new state */ + if (state_fp != NULL && !no_act) { + if (ftruncate(fileno(state_fp), 0) < 0) { + error_msg_and_die("failed to truncate statefile %s: %s", statefile, strerror(errno)); + } + + rewind(state_fp); - rewind(state_fp); - for (i = 0; i < n_state; i++) { - fputs(state[i], state_fp); + while (state_list) { + if (state_list->data) { + fputs(state_list->data, state_fp); fputc('\n', state_fp); } - fflush(state_fp); + state_list = state_list->link; } + fflush(state_fp); } + /* Cleanup */ if (state_fp != NULL) { fclose(state_fp); state_fp = NULL;