X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fifupdown.c;h=37185327b68056f469deb7d339d3a14f6a744136;hb=ea2a1064b33bfb4fe0493659f43ed074cfe80067;hp=b0f526770071683d082b726b06540737fdb4df67;hpb=83bcba26c01d945d1964d6d5de715a2356a858cf;p=oweals%2Fbusybox.git diff --git a/networking/ifupdown.c b/networking/ifupdown.c index b0f526770..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 @@ -36,30 +41,31 @@ #include #include "libbb.h" -//#include "busybox.h" -//#include "config.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; -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,44 +76,35 @@ typedef struct mapping_defn { int max_mappings; int n_mappings; char **mapping; -} mapping_defn; +} 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; - mapping_defn *mappings; -} interfaces_file; +typedef struct interfaces_file_s { + llist_t *autointerfaces; + interface_defn_t *ifaces; + mapping_defn_t *mappings; +} interfaces_file_t; -#define MAX_OPT_DEPTH 10 -#define EUNBALBRACK 10001 -#define EUNDEFVAR 10002 -#define MAX_VARNAME 32 -#define EUNBALPER 10000 - -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) @@ -138,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; @@ -155,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; @@ -246,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; @@ -263,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); @@ -271,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); @@ -279,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); @@ -287,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); @@ -295,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); @@ -316,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); @@ -338,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); @@ -346,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); @@ -363,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); @@ -371,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); @@ -393,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)) { @@ -413,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); @@ -435,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)) { @@ -457,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 kill", ifd, exec)) { + if (!execute("kill -9 `cat /var/run/udhcpc.%iface%.pid`", ifd, exec)) { return(0); } } else if (execable("/sbin/pump")) { @@ -468,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 kill", ifd, exec)) { + if (!execute("kill -9 `cat /var/run/udhcpc.%iface%.pid`", ifd, exec)) { return(0); } } else if (execable("/sbin/dhcpcd")) { @@ -482,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; @@ -490,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; @@ -498,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; @@ -506,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; @@ -514,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; @@ -522,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; @@ -530,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, }, @@ -539,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 }; @@ -570,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; @@ -582,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; @@ -594,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); @@ -605,93 +602,34 @@ 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; - mapping_defn *currmap = NULL; + interface_defn_t *currif = NULL; + interfaces_file_t *defn; +#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING + 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; defn->mappings = NULL; defn->ifaces = NULL; @@ -699,16 +637,28 @@ static interfaces_file *read_interfaces(char *filename) 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 */ } if (strcmp(firstword, "mapping") == 0) { - currmap = xmalloc(sizeof(mapping_defn)); +#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING + currmap = xmalloc(sizeof(mapping_defn_t)); currmap->max_matches = 0; currmap->n_matches = 0; currmap->match = NULL; @@ -726,20 +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; } +#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 @@ -752,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; } @@ -772,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; } @@ -789,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; @@ -806,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 { @@ -835,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; } @@ -845,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); @@ -871,9 +810,10 @@ static interfaces_file *read_interfaces(char *filename) currif->n_options++; break; case MAPPING: +#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); @@ -886,13 +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; } } @@ -902,7 +843,6 @@ static interfaces_file *read_interfaces(char *filename) return NULL; } fclose(f); - line = -1; return defn; } @@ -938,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; @@ -1006,7 +946,7 @@ static int doit(char *str) return (1); } -static int execute_all(interface_defn *ifd, execfn *exec, const char *opt) +static int execute_all(interface_defn_t *ifd, execfn *exec, const char *opt) { int i; char *buf; @@ -1026,7 +966,7 @@ static int execute_all(interface_defn *ifd, execfn *exec, const char *opt) 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); @@ -1046,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); @@ -1064,6 +1004,7 @@ static int iface_down(interface_defn *iface) return (1); } +#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING static int popen2(FILE **in, FILE **out, char *command, ...) { va_list ap; @@ -1117,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; @@ -1145,49 +1086,38 @@ static int run_mapping(char *physical, char *logical, int len, mapping_defn * ma return 1; } +#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') { @@ -1198,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); @@ -1212,9 +1146,11 @@ extern int ifupdown_main(int argc, char **argv) case 'n': /* no-act */ no_act = 1; break; +#ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING case 'm': /* no-mappings */ run_mappings = 0; break; +#endif case 'f': /* force */ force = 1; break; @@ -1239,107 +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) { @@ -1354,32 +1265,26 @@ extern int ifupdown_main(int argc, char **argv) } } } +#endif for (currif = defn->ifaces; currif; currif = currif->next) { if (strcmp(liface, currif->iface) == 0) { 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; } } @@ -1387,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;