3 * Copyright (c) 2002 Glenn McGrath <bug1@optushome.com.au>
5 * Based on ifupdown v 0.6.4 by Anthony Towns
6 * Copyright (c) 1999 Anthony Towns <aj@azure.humbug.org.au>
8 * Changes to upstream version
9 * Remove checks for kernel version, assume kernel version 2.2.0 or better.
10 * Lines in the interfaces file cannot wrap.
11 * To adhere to the FHS, the default state file is /var/run/ifstate.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include <sys/utsname.h>
45 #define MAX_OPT_DEPTH 10
46 #define EUNBALBRACK 10001
47 #define EUNDEFVAR 10002
48 #define EUNBALPER 10000
50 typedef struct interface_defn_s interface_defn_t;
52 typedef int (execfn)(char *command);
53 typedef int (command_set)(interface_defn_t *ifd, execfn *e);
55 typedef struct method_s {
61 typedef struct address_family_s {
67 typedef struct mapping_defn_s {
68 struct mapping_defn_s *next;
81 typedef struct variable_s {
86 struct interface_defn_s {
87 struct interface_defn_s *next;
90 address_family_t *address_family;
100 typedef struct interfaces_file_s {
101 llist_t *autointerfaces;
102 interface_defn_t *ifaces;
103 mapping_defn_t *mappings;
106 static char no_act = 0;
107 static char verbose = 0;
108 static char **environ = NULL;
110 static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length)
112 if (*pos + str_length >= *len) {
115 newbuf = xrealloc(*buf, *len * 2 + str_length + 1);
117 *len = *len * 2 + str_length + 1;
120 while (str_length-- >= 1) {
121 (*buf)[(*pos)++] = *str;
127 static int strncmpz(char *l, char *r, size_t llen)
129 int i = strncmp(l, r, llen);
138 static char *get_var(char *id, size_t idlen, interface_defn_t *ifd)
142 if (strncmpz(id, "iface", idlen) == 0) {
145 for (i = 0; i < ifd->n_options; i++) {
146 if (strncmpz(id, ifd->option[i].name, idlen) == 0) {
147 return (ifd->option[i].value);
155 static char *parse(char *command, interface_defn_t *ifd)
159 size_t pos = 0, len = 0;
160 size_t old_pos[MAX_OPT_DEPTH] = { 0 };
161 int okay[MAX_OPT_DEPTH] = { 1 };
168 addstr(&result, &len, &pos, command, 1);
173 addstr(&result, &len, &pos, command + 1, 1);
176 addstr(&result, &len, &pos, command, 1);
181 if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) {
182 old_pos[opt_depth] = pos;
187 addstr(&result, &len, &pos, "[", 1);
192 if (command[1] == ']' && opt_depth > 1) {
194 if (!okay[opt_depth]) {
195 pos = old_pos[opt_depth];
200 addstr(&result, &len, &pos, "]", 1);
210 nextpercent = strchr(command, '%');
217 varvalue = get_var(command, nextpercent - command, ifd);
220 addstr(&result, &len, &pos, varvalue, xstrlen(varvalue));
222 okay[opt_depth - 1] = 0;
225 command = nextpercent + 1;
246 static int execute(char *command, interface_defn_t *ifd, execfn *exec)
251 out = parse(command, ifd);
262 #ifdef CONFIG_FEATURE_IFUPDOWN_IPX
263 static int static_up_ipx(interface_defn_t *ifd, execfn *exec)
265 if (!execute("ipx_interface add %iface% %frame% %netnum%", ifd, exec)) {
271 static int static_down_ipx(interface_defn_t *ifd, execfn *exec)
273 if (!execute("ipx_interface del %iface% %frame%", ifd, exec)) {
279 static int dynamic_up(interface_defn_t *ifd, execfn *exec)
281 if (!execute("ipx_interface add %iface% %frame%", ifd, exec)) {
287 static int dynamic_down(interface_defn_t *ifd, execfn *exec)
289 if (!execute("ipx_interface del %iface% %frame%", ifd, exec)) {
295 static method_t methods_ipx[] = {
296 { "dynamic", dynamic_up, dynamic_down, },
297 { "static", static_up_ipx, static_down_ipx, },
300 address_family_t addr_ipx = {
302 sizeof(methods_ipx) / sizeof(method_t),
305 #endif /* IFUP_FEATURE_IPX */
307 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV6
308 static int loopback_up6(interface_defn_t *ifd, execfn *exec)
310 if (!execute("ifconfig %iface% add ::1", ifd, exec)) {
316 static int loopback_down6(interface_defn_t *ifd, execfn *exec)
318 if (!execute("ifconfig %iface% del ::1", ifd, exec)) {
324 static int static_up6(interface_defn_t *ifd, execfn *exec)
326 if (!execute("ifconfig %iface% [[media %media%]] [[hw %hwaddress%]] [[mtu %mtu%]] up", ifd, exec)) {
329 if (!execute("ifconfig %iface% add %address%/%netmask%", ifd, exec)) {
332 if (!execute("[[ route -A inet6 add ::/0 gw %gateway% ]]", ifd, exec)) {
338 static int static_down6(interface_defn_t *ifd, execfn *exec)
340 if (!execute("ifconfig %iface% down", ifd, exec)) {
346 static int v4tunnel_up(interface_defn_t *ifd, execfn *exec)
348 if (!execute("ip tunnel add %iface% mode sit remote %endpoint% [[local %local%]] [[ttl %ttl%]]", ifd, exec)) {
351 if (!execute("ip link set %iface% up", ifd, exec)) {
354 if (!execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec)) {
357 if (!execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec)) {
363 static int v4tunnel_down(interface_defn_t * ifd, execfn * exec)
365 if (!execute("ip tunnel del %iface%", ifd, exec)) {
371 static method_t methods6[] = {
372 { "v4tunnel", v4tunnel_up, v4tunnel_down, },
373 { "static", static_up6, static_down6, },
374 { "loopback", loopback_up6, loopback_down6, },
377 address_family_t addr_inet6 = {
379 sizeof(methods6) / sizeof(method_t),
382 #endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */
384 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV4
385 static int loopback_up(interface_defn_t *ifd, execfn *exec)
387 if (!execute("ifconfig %iface% 127.0.0.1 up", ifd, exec)) {
393 static int loopback_down(interface_defn_t *ifd, execfn *exec)
395 if (!execute("ifconfig %iface% 127.0.0.1 down", ifd, exec)) {
401 static int static_up(interface_defn_t *ifd, execfn *exec)
403 if (!execute("ifconfig %iface% %address% netmask %netmask% [[broadcast %broadcast%]] [[pointopoint %pointopoint%]] [[media %media%]] [[mtu %mtu%]] [[hw %hwaddress%]] up",
407 if (!execute("[[ route add default gw %gateway% %iface% ]]", ifd, exec)) {
413 static int static_down(interface_defn_t *ifd, execfn *exec)
415 if (!execute("[[ route del default gw %gateway% %iface% ]]", ifd, exec)) {
418 if (!execute("ifconfig %iface% down", ifd, exec)) {
424 static int execable(char *program)
427 if (0 == stat(program, &buf)) {
428 if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode)) {
435 static int dhcp_up(interface_defn_t *ifd, execfn *exec)
437 if (execable("/sbin/dhclient")) {
438 if (!execute("dhclient -pf /var/run/dhclient.%iface%.pid %iface%", ifd, exec)) {
441 } else if (execable("/sbin/pump")) {
442 if (!execute("pump -i %iface% [[-h %hostname%]] [[-l %leasehours%]]", ifd, exec)) {
445 } else if (execable("/sbin/udhcpc")) {
446 if (!execute("udhcpc -n -p /var/run/udhcpc.%iface%.pid -i %iface% [[-H %hostname%]] [[-c %clientid%]]", ifd, exec)) {
449 } else if (execable("/sbin/dhcpcd")) {
450 if (!execute("dhcpcd [[-h %hostname%]] [[-i %vendor%]] [[-I %clientid%]] [[-l %leasetime%]] %iface%", ifd, exec)) {
457 static int dhcp_down(interface_defn_t *ifd, execfn *exec)
459 if (execable("/sbin/dhclient")) {
460 if (!execute("kill -9 `cat /var/run/udhcpc.%iface%.pid`", ifd, exec)) {
463 } else if (execable("/sbin/pump")) {
464 if (!execute("pump -i %iface% -k", ifd, exec)) {
467 } else if (execable("/sbin/udhcpc")) {
468 if (!execute("kill -9 `cat /var/run/udhcpc.%iface%.pid`", ifd, exec)) {
471 } else if (execable("/sbin/dhcpcd")) {
472 if (!execute("dhcpcd -k %iface%", ifd, exec)) {
476 if (!execute("ifconfig %iface% down", ifd, exec)) {
482 static int bootp_up(interface_defn_t *ifd, execfn *exec)
484 if (!execute("bootpc [[--bootfile %bootfile%]] --dev %iface% [[--server %server%]] [[--hwaddr %hwaddr%]] --returniffail --serverbcast", ifd, exec)) {
490 static int bootp_down(interface_defn_t *ifd, execfn *exec)
492 if (!execute("ifconfig down %iface%", ifd, exec)) {
498 static int ppp_up(interface_defn_t *ifd, execfn *exec)
500 if (!execute("pon [[%provider%]]", ifd, exec)) {
506 static int ppp_down(interface_defn_t *ifd, execfn *exec)
508 if (!execute("poff [[%provider%]]", ifd, exec)) {
514 static int wvdial_up(interface_defn_t *ifd, execfn *exec)
516 if (!execute("/sbin/start-stop-daemon --start -x /usr/bin/wvdial -p /var/run/wvdial.%iface% -b -m -- [[ %provider% ]]", ifd, exec)) {
522 static int wvdial_down(interface_defn_t *ifd, execfn *exec)
524 if (!execute ("/sbin/start-stop-daemon --stop -x /usr/bin/wvdial -p /var/run/wvdial.%iface% -s 2", ifd, exec)) {
530 static method_t methods[] = {
531 { "wvdial", wvdial_up, wvdial_down, },
532 { "ppp", ppp_up, ppp_down, },
533 { "static", static_up, static_down, },
534 { "bootp", bootp_up, bootp_down, },
535 { "dhcp", dhcp_up, dhcp_down, },
536 { "loopback", loopback_up, loopback_down, },
539 address_family_t addr_inet = {
541 sizeof(methods) / sizeof(method_t),
545 #endif /* ifdef CONFIG_FEATURE_IFUPDOWN_IPV4 */
547 static char *next_word(char *buf, char *word, int maxlen)
554 while (!isspace(*buf) && *buf) {
563 while (isspace(*buf) && *buf) {
570 static address_family_t *get_address_family(address_family_t *af[], char *name)
574 for (i = 0; af[i]; i++) {
575 if (strcmp(af[i]->name, name) == 0) {
582 static method_t *get_method(address_family_t *af, char *name)
586 for (i = 0; i < af->n_methods; i++) {
587 if (strcmp(af->method[i].name, name) == 0) {
588 return &af->method[i];
594 static int duplicate_if(interface_defn_t *ifa, interface_defn_t *ifb)
596 if (strcmp(ifa->iface, ifb->iface) != 0) {
599 if (ifa->address_family != ifb->address_family) {
605 static const llist_t *find_list_string(const llist_t *list, const char *string)
608 if (strcmp(list->data, string) == 0) {
616 static interfaces_file_t *read_interfaces(char *filename)
618 interface_defn_t *currif = NULL;
619 interfaces_file_t *defn;
620 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
621 mapping_defn_t *currmap = NULL;
629 enum { NONE, IFACE, MAPPING } currently_processing = NONE;
631 defn = xmalloc(sizeof(interfaces_file_t));
632 // defn->max_autointerfaces = defn->n_autointerfaces = 0;
633 defn->autointerfaces = NULL;
634 defn->mappings = NULL;
636 f = fopen(filename, "r");
641 while ((buf = get_line_from_file(f)) != NULL) {
647 end = last_char_is(buf, '\n');
651 while ((end = last_char_is(buf, ' ')) != NULL) {
654 rest = next_word(buf, firstword, 80);
656 continue; /* blank line */
659 if (strcmp(firstword, "mapping") == 0) {
660 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
661 currmap = xmalloc(sizeof(mapping_defn_t));
662 currmap->max_matches = 0;
663 currmap->n_matches = 0;
664 currmap->match = NULL;
666 while ((rest = next_word(rest, firstword, 80))) {
667 if (currmap->max_matches == currmap->n_matches) {
668 currmap->max_matches = currmap->max_matches * 2 + 1;
669 currmap->match = xrealloc(currmap->match, sizeof(currmap->match) * currmap->max_matches);
672 currmap->match[currmap->n_matches++] = xstrdup(firstword);
674 currmap->max_mappings = 0;
675 currmap->n_mappings = 0;
676 currmap->mapping = NULL;
677 currmap->script = NULL;
679 mapping_defn_t **where = &defn->mappings;
680 while (*where != NULL) {
681 where = &(*where)->next;
684 currmap->next = NULL;
687 currently_processing = MAPPING;
688 } else if (strcmp(firstword, "iface") == 0) {
691 char address_family_name[80];
692 char method_name[80];
693 address_family_t *addr_fams[] = {
694 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV4
697 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV6
700 #ifdef CONFIG_FEATURE_IFUPDOWN_IPX
706 currif = xmalloc(sizeof(interface_defn_t));
708 rest = next_word(rest, iface_name, 80);
709 rest = next_word(rest, address_family_name, 80);
710 rest = next_word(rest, method_name, 80);
713 error_msg("too few parameters for line \"%s\"", buf);
717 if (rest[0] != '\0') {
718 error_msg("too many parameters \"%s\"", buf);
722 currif->iface = xstrdup(iface_name);
724 currif->address_family = get_address_family(addr_fams, address_family_name);
725 if (!currif->address_family) {
726 error_msg("unknown address type \"%s\"", buf);
730 currif->method = get_method(currif->address_family, method_name);
731 if (!currif->method) {
732 error_msg("unknown method \"%s\"", buf);
736 currif->automatic = 1;
737 currif->max_options = 0;
738 currif->n_options = 0;
739 currif->option = NULL;
743 interface_defn_t **where = &defn->ifaces;
745 while (*where != NULL) {
746 if (duplicate_if(*where, currif)) {
747 error_msg("duplicate interface \"%s\"", buf);
750 where = &(*where)->next;
757 currently_processing = IFACE;
758 } else if (strcmp(firstword, "auto") == 0) {
759 while ((rest = next_word(rest, firstword, 80))) {
761 /* Check the interface isnt already listed */
762 if (find_list_string(defn->autointerfaces, firstword)) {
763 perror_msg_and_die("interface declared auto twice \"%s\"", buf);
766 /* Add the interface to the list */
767 defn->autointerfaces = llist_add_to(defn->autointerfaces, strdup(firstword));
769 currently_processing = NONE;
771 switch (currently_processing) {
776 if (xstrlen(rest) == 0) {
777 error_msg("option with empty value \"%s\"", buf);
781 if (strcmp(firstword, "up") != 0
782 && strcmp(firstword, "down") != 0
783 && strcmp(firstword, "pre-up") != 0
784 && strcmp(firstword, "post-down") != 0) {
785 for (i = 0; i < currif->n_options; i++) {
786 if (strcmp(currif->option[i].name, firstword) == 0) {
787 error_msg("duplicate option \"%s\"", buf);
793 if (currif->n_options >= currif->max_options) {
796 currif->max_options = currif->max_options + 10;
797 opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options);
798 currif->option = opt;
800 currif->option[currif->n_options].name = xstrdup(firstword);
801 currif->option[currif->n_options].value = xstrdup(rest);
802 if (!currif->option[currif->n_options].name) {
806 if (!currif->option[currif->n_options].value) {
813 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
814 if (strcmp(firstword, "script") == 0) {
815 if (currmap->script != NULL) {
816 error_msg("duplicate script in mapping \"%s\"", buf);
819 currmap->script = xstrdup(rest);
821 } else if (strcmp(firstword, "map") == 0) {
822 if (currmap->max_mappings == currmap->n_mappings) {
823 currmap->max_mappings = currmap->max_mappings * 2 + 1;
824 currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings);
826 currmap->mapping[currmap->n_mappings] = xstrdup(rest);
827 currmap->n_mappings++;
829 error_msg("misplaced option \"%s\"", buf);
836 error_msg("misplaced option \"%s\"", buf);
841 if (ferror(f) != 0) {
842 perror_msg("%s", filename);
850 static int check(char *str)
852 return (str != NULL);
855 static char *setlocalenv(char *format, char *name, char *value)
861 result = xmalloc(xstrlen(format) + xstrlen(name) + xstrlen(value) + 1);
863 sprintf(result, format, name, value);
865 for (here = there = result; *there != '=' && *there; there++) {
869 *there = toupper(*there);
871 if (isalnum(*there) || *there == '_') {
876 memmove(here, there, xstrlen(there) + 1);
881 static void set_environ(interface_defn_t *iface, char *mode)
885 const int n_env_entries = iface->n_options + 5;
888 if (environ != NULL) {
889 for (ppch = environ; *ppch; ppch++) {
896 environ = xmalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ ));
897 environend = environ;
900 for (i = 0; i < iface->n_options; i++) {
901 if (strcmp(iface->option[i].name, "up") == 0
902 || strcmp(iface->option[i].name, "down") == 0
903 || strcmp(iface->option[i].name, "pre-up") == 0
904 || strcmp(iface->option[i].name, "post-down") == 0) {
907 *(environend++) = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value);
911 *(environend++) = setlocalenv("%s=%s", "IFACE", iface->iface);
913 *(environend++) = setlocalenv("%s=%s", "ADDRFAM", iface->address_family->name);
915 *(environend++) = setlocalenv("%s=%s", "METHOD", iface->method->name);
917 *(environend++) = setlocalenv("%s=%s", "MODE", mode);
919 *(environend++) = setlocalenv("%s=%s", "PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
923 static int doit(char *str)
925 if (verbose || no_act) {
926 error_msg("%s", str);
933 switch (child = fork()) {
934 case -1: /* failure */
937 execle("/bin/sh", "/bin/sh", "-c", str, NULL, environ);
939 default: /* parent */
941 waitpid(child, &status, 0);
942 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
949 static int execute_all(interface_defn_t *ifd, execfn *exec, const char *opt)
954 for (i = 0; i < ifd->n_options; i++) {
955 if (strcmp(ifd->option[i].name, opt) == 0) {
956 if (!(*exec) (ifd->option[i].value)) {
962 buf = xmalloc(xstrlen(opt) + 19);
963 sprintf(buf, "/etc/network/if-%s.d", opt);
969 static int iface_up(interface_defn_t *iface)
971 if (!iface->method->up(iface, check)) {
975 set_environ(iface, "start");
976 if (!execute_all(iface, doit, "pre-up")) {
979 if (!iface->method->up(iface, doit)) {
982 if (!execute_all(iface, doit, "up")) {
989 static int iface_down(interface_defn_t *iface)
991 if (!iface->method->down(iface, check)) {
994 set_environ(iface, "stop");
995 if (!execute_all(iface, doit, "down")) {
998 if (!iface->method->down(iface, doit)) {
1001 if (!execute_all(iface, doit, "post-down")) {
1007 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
1008 static int popen2(FILE **in, FILE **out, char *command, ...)
1011 char *argv[11] = { command };
1013 int infd[2], outfd[2];
1017 va_start(ap, command);
1018 while ((argc < 10) && (argv[argc] = va_arg(ap, char *))) {
1021 argv[argc] = NULL; /* make sure */
1024 if (pipe(infd) != 0) {
1028 if (pipe(outfd) != 0) {
1035 switch (pid = fork()) {
1036 case -1: /* failure */
1049 execvp(command, argv);
1051 default: /* parent */
1052 *in = fdopen(infd[1], "w");
1053 *out = fdopen(outfd[0], "r");
1061 static int run_mapping(char *physical, char *logical, int len, mapping_defn_t * map)
1068 pid = popen2(&in, &out, map->script, physical, NULL);
1072 for (i = 0; i < map->n_mappings; i++) {
1073 fprintf(in, "%s\n", map->mapping[i]);
1076 waitpid(pid, &status, 0);
1077 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
1078 if (fgets(logical, len, out)) {
1079 char *pch = logical + xstrlen(logical) - 1;
1081 while (pch >= logical && isspace(*pch))
1089 #endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */
1091 static llist_t *find_iface_state(llist_t *state_list, const char *iface)
1093 unsigned short iface_len = xstrlen(iface);
1094 llist_t *search = state_list;
1097 if ((strncmp(search->data, iface, iface_len) == 0) &&
1098 (search->data[iface_len] == '=')) {
1101 search = search->link;
1106 extern int ifupdown_main(int argc, char **argv)
1108 int (*cmds) (interface_defn_t *) = NULL;
1109 interfaces_file_t *defn;
1110 FILE *state_fp = NULL;
1111 llist_t *state_list = NULL;
1112 llist_t *target_list = NULL;
1113 char *interfaces = "/etc/network/interfaces";
1114 const char *statefile = "/var/run/ifstate";
1116 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
1117 int run_mappings = 1;
1123 if (applet_name[2] == 'u') {
1127 /* ifdown command */
1131 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
1132 while ((i = getopt(argc, argv, "i:hvnamf")) != -1) {
1134 while ((i = getopt(argc, argv, "i:hvnaf")) != -1) {
1137 case 'i': /* interfaces */
1138 interfaces = xstrdup(optarg);
1140 case 'v': /* verbose */
1146 case 'n': /* no-act */
1149 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
1150 case 'm': /* no-mappings */
1154 case 'f': /* force */
1163 if (argc - optind > 0) {
1173 defn = read_interfaces(interfaces);
1175 error_msg_and_die("couldn't read interfaces file \"%s\"", interfaces);
1179 state_fp = fopen(statefile, "r");
1181 state_fp = xfopen(statefile, "a+");
1184 /* Read the previous state from the state file */
1185 if (state_fp != NULL) {
1187 while ((start = get_line_from_file(state_fp)) != NULL) {
1189 /* We should only need to check for a single character */
1190 end_ptr = start + strcspn(start, " \t\n");
1192 state_list = llist_add_to(state_list, start);
1196 /* Create a list of interfaces to work on */
1198 if (cmds == iface_up) {
1199 target_list = defn->autointerfaces;
1200 } else if (cmds == iface_down) {
1201 const llist_t *list = state_list;
1203 target_list = llist_add_to(target_list, strdup(list->data));
1208 target_list = llist_add_to(target_list, argv[optind]);
1212 /* Update the interfaces */
1213 while (target_list) {
1214 interface_defn_t *currif;
1220 iface = strdup(target_list->data);
1221 target_list = target_list->link;
1223 pch = strchr(iface, '=');
1226 liface = strdup(pch + 1);
1228 liface = strdup(iface);
1232 const llist_t *iface_state = find_iface_state(state_list, iface);
1234 if (cmds == iface_up) {
1237 error_msg("interface %s already configured", iface);
1242 if (iface_state == NULL) {
1243 error_msg("interface %s not configured", iface);
1246 pch = strchr(iface_state->data, '=');
1247 liface = strdup(pch + 1);
1251 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
1252 if ((cmds == iface_up) && run_mappings) {
1253 mapping_defn_t *currmap;
1255 for (currmap = defn->mappings; currmap; currmap = currmap->next) {
1257 for (i = 0; i < currmap->n_matches; i++) {
1258 if (fnmatch(currmap->match[i], liface, 0) != 0)
1261 error_msg("Running mapping script %s on %s", currmap->script, liface);
1263 run_mapping(iface, liface, sizeof(liface), currmap);
1270 for (currif = defn->ifaces; currif; currif = currif->next) {
1271 if (strcmp(liface, currif->iface) == 0) {
1272 char *oldiface = currif->iface;
1275 currif->iface = iface;
1278 error_msg("Configuring interface %s=%s (%s)", iface, liface, currif->address_family->name);
1281 /* Call the cmds function pointer, does either iface_up() or iface_down() */
1282 if (cmds(currif) == -1) {
1284 ("Don't seem to be have all the variables for %s/%s.\n",
1285 liface, currif->address_family->name);
1288 currif->iface = oldiface;
1292 if (!okay && !force) {
1293 error_msg("Ignoring unknown interface %s=%s.", iface, liface);
1295 llist_t *iface_state = find_iface_state(state_list, iface);
1297 if (cmds == iface_up) {
1298 char *newiface = xmalloc(xstrlen(iface) + 1 + xstrlen(liface) + 1);
1299 sprintf(newiface, "%s=%s", iface, liface);
1300 if (iface_state == NULL) {
1301 state_list = llist_add_to(state_list, newiface);
1303 free(iface_state->data);
1304 iface_state->data = newiface;
1306 } else if (cmds == iface_down) {
1307 /* Remove an interface from the linked list */
1309 /* This needs to be done better */
1310 free(iface_state->data);
1311 free(iface_state->link);
1312 if (iface_state->link) {
1313 iface_state->data = iface_state->link->data;
1314 iface_state->link = iface_state->link->link;
1316 iface_state->data = NULL;
1317 iface_state->link = NULL;
1324 /* Actually write the new state */
1325 if (state_fp != NULL && !no_act) {
1326 if (ftruncate(fileno(state_fp), 0) < 0) {
1327 error_msg_and_die("failed to truncate statefile %s: %s", statefile, strerror(errno));
1332 while (state_list) {
1333 if (state_list->data) {
1334 fputs(state_list->data, state_fp);
1335 fputc('\n', state_fp);
1337 state_list = state_list->link;
1343 if (state_fp != NULL) {