diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2002-12-08 01:23:39 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2002-12-08 01:23:39 +0000 |
commit | 8e49caa54fd7921dc0cc3b925668c76a16a39414 (patch) | |
tree | 27fb1d6413343cc344c09ca8c04381aec6dc7012 | |
parent | 66125c806518f74a54232206d02e30a39b621232 (diff) | |
download | busybox-w32-8e49caa54fd7921dc0cc3b925668c76a16a39414.tar.gz busybox-w32-8e49caa54fd7921dc0cc3b925668c76a16a39414.tar.bz2 busybox-w32-8e49caa54fd7921dc0cc3b925668c76a16a39414.zip |
Start to cleanup handling of the state file, save some space and uses linked lists.
-rw-r--r-- | networking/ifupdown.c | 207 |
1 files changed, 104 insertions, 103 deletions
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 3e18df19e..37185327b 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -1,12 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * ifupdown for busybox | 2 | * ifupdown for busybox |
3 | * Based on ifupdown by Anthony Towns | 3 | * Copyright (c) 2002 Glenn McGrath <bug1@optushome.com.au> |
4 | * | ||
5 | * Based on ifupdown v 0.6.4 by Anthony Towns | ||
4 | * Copyright (c) 1999 Anthony Towns <aj@azure.humbug.org.au> | 6 | * Copyright (c) 1999 Anthony Towns <aj@azure.humbug.org.au> |
5 | * | 7 | * |
6 | * Changes to upstream version | 8 | * Changes to upstream version |
7 | * Remove checks for kernel version, assume kernel version 2.2.0 or better | 9 | * Remove checks for kernel version, assume kernel version 2.2.0 or better. |
8 | * Lines in the interfaces file cannot wrap. | 10 | * Lines in the interfaces file cannot wrap. |
9 | * The default state file is moved to /var/run/ifstate | 11 | * To adhere to the FHS, the default state file is /var/run/ifstate. |
10 | * | 12 | * |
11 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
@@ -39,10 +41,11 @@ | |||
39 | #include <unistd.h> | 41 | #include <unistd.h> |
40 | 42 | ||
41 | #include "libbb.h" | 43 | #include "libbb.h" |
42 | //#include "busybox.h" | ||
43 | //#include "config.h" | ||
44 | 44 | ||
45 | #define IFUPDOWN_VERSION "0.6.4" | 45 | #define MAX_OPT_DEPTH 10 |
46 | #define EUNBALBRACK 10001 | ||
47 | #define EUNDEFVAR 10002 | ||
48 | #define EUNBALPER 10000 | ||
46 | 49 | ||
47 | typedef struct interface_defn_s interface_defn_t; | 50 | typedef struct interface_defn_s interface_defn_t; |
48 | 51 | ||
@@ -95,22 +98,13 @@ struct interface_defn_s { | |||
95 | }; | 98 | }; |
96 | 99 | ||
97 | typedef struct interfaces_file_s { | 100 | typedef struct interfaces_file_s { |
98 | int max_autointerfaces; | 101 | llist_t *autointerfaces; |
99 | int n_autointerfaces; | ||
100 | char **autointerfaces; | ||
101 | |||
102 | interface_defn_t *ifaces; | 102 | interface_defn_t *ifaces; |
103 | mapping_defn_t *mappings; | 103 | mapping_defn_t *mappings; |
104 | } interfaces_file_t; | 104 | } interfaces_file_t; |
105 | 105 | ||
106 | #define MAX_OPT_DEPTH 10 | 106 | static char no_act = 0; |
107 | #define EUNBALBRACK 10001 | 107 | static char verbose = 0; |
108 | #define EUNDEFVAR 10002 | ||
109 | #define MAX_VARNAME 32 | ||
110 | #define EUNBALPER 10000 | ||
111 | |||
112 | static int no_act = 0; | ||
113 | static int verbose = 0; | ||
114 | static char **environ = NULL; | 108 | static char **environ = NULL; |
115 | 109 | ||
116 | static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length) | 110 | static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length) |
@@ -608,6 +602,17 @@ static int duplicate_if(interface_defn_t *ifa, interface_defn_t *ifb) | |||
608 | return(1); | 602 | return(1); |
609 | } | 603 | } |
610 | 604 | ||
605 | static const llist_t *find_list_string(const llist_t *list, const char *string) | ||
606 | { | ||
607 | while (list) { | ||
608 | if (strcmp(list->data, string) == 0) { | ||
609 | return(list); | ||
610 | } | ||
611 | list = list->link; | ||
612 | } | ||
613 | return(NULL); | ||
614 | } | ||
615 | |||
611 | static interfaces_file_t *read_interfaces(char *filename) | 616 | static interfaces_file_t *read_interfaces(char *filename) |
612 | { | 617 | { |
613 | interface_defn_t *currif = NULL; | 618 | interface_defn_t *currif = NULL; |
@@ -624,7 +629,7 @@ static interfaces_file_t *read_interfaces(char *filename) | |||
624 | enum { NONE, IFACE, MAPPING } currently_processing = NONE; | 629 | enum { NONE, IFACE, MAPPING } currently_processing = NONE; |
625 | 630 | ||
626 | defn = xmalloc(sizeof(interfaces_file_t)); | 631 | defn = xmalloc(sizeof(interfaces_file_t)); |
627 | defn->max_autointerfaces = defn->n_autointerfaces = 0; | 632 | // defn->max_autointerfaces = defn->n_autointerfaces = 0; |
628 | defn->autointerfaces = NULL; | 633 | defn->autointerfaces = NULL; |
629 | defn->mappings = NULL; | 634 | defn->mappings = NULL; |
630 | defn->ifaces = NULL; | 635 | defn->ifaces = NULL; |
@@ -752,26 +757,14 @@ static interfaces_file_t *read_interfaces(char *filename) | |||
752 | currently_processing = IFACE; | 757 | currently_processing = IFACE; |
753 | } else if (strcmp(firstword, "auto") == 0) { | 758 | } else if (strcmp(firstword, "auto") == 0) { |
754 | while ((rest = next_word(rest, firstword, 80))) { | 759 | while ((rest = next_word(rest, firstword, 80))) { |
755 | int i; | ||
756 | |||
757 | for (i = 0; i < defn->n_autointerfaces; i++) { | ||
758 | if (strcmp(firstword, defn->autointerfaces[i]) == 0) { | ||
759 | perror_msg("interface declared auto twice \"%s\"", buf); | ||
760 | return NULL; | ||
761 | } | ||
762 | } | ||
763 | |||
764 | if (defn->n_autointerfaces == defn->max_autointerfaces) { | ||
765 | char **tmp; | ||
766 | 760 | ||
767 | defn->max_autointerfaces *= 2; | 761 | /* Check the interface isnt already listed */ |
768 | defn->max_autointerfaces++; | 762 | if (find_list_string(defn->autointerfaces, firstword)) { |
769 | tmp = xrealloc(defn->autointerfaces, sizeof(*tmp) * defn->max_autointerfaces); | 763 | perror_msg_and_die("interface declared auto twice \"%s\"", buf); |
770 | defn->autointerfaces = tmp; | ||
771 | } | 764 | } |
772 | 765 | ||
773 | defn->autointerfaces[defn->n_autointerfaces] = xstrdup(firstword); | 766 | /* Add the interface to the list */ |
774 | defn->n_autointerfaces++; | 767 | defn->autointerfaces = llist_add_to(defn->autointerfaces, strdup(firstword)); |
775 | } | 768 | } |
776 | currently_processing = NONE; | 769 | currently_processing = NONE; |
777 | } else { | 770 | } else { |
@@ -1095,29 +1088,19 @@ static int run_mapping(char *physical, char *logical, int len, mapping_defn_t * | |||
1095 | } | 1088 | } |
1096 | #endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */ | 1089 | #endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */ |
1097 | 1090 | ||
1098 | static int lookfor_iface(char **ifaces, int n_ifaces, char *iface) | 1091 | static llist_t *find_iface_state(llist_t *state_list, const char *iface) |
1099 | { | 1092 | { |
1100 | int i; | 1093 | unsigned short iface_len = xstrlen(iface); |
1094 | llist_t *search = state_list; | ||
1101 | 1095 | ||
1102 | for (i = 0; i < n_ifaces; i++) { | 1096 | while (search) { |
1103 | if (strncmp(iface, ifaces[i], xstrlen(iface)) == 0) { | 1097 | if ((strncmp(search->data, iface, iface_len) == 0) && |
1104 | if (ifaces[i][xstrlen(iface)] == '=') { | 1098 | (search->data[iface_len] == '=')) { |
1105 | return i; | 1099 | return(search); |
1106 | } | ||
1107 | } | 1100 | } |
1101 | search = search->link; | ||
1108 | } | 1102 | } |
1109 | 1103 | return(NULL); | |
1110 | return(-1); | ||
1111 | } | ||
1112 | |||
1113 | static void add_to_state(char ***ifaces, int *n_ifaces, int *max_ifaces, char *new_iface) | ||
1114 | { | ||
1115 | if (*max_ifaces == *n_ifaces) { | ||
1116 | *max_ifaces = (*max_ifaces * 2) + 1; | ||
1117 | *ifaces = xrealloc(*ifaces, sizeof(**ifaces) * *max_ifaces); | ||
1118 | } | ||
1119 | |||
1120 | (*ifaces)[(*n_ifaces)++] = new_iface; | ||
1121 | } | 1104 | } |
1122 | 1105 | ||
1123 | extern int ifupdown_main(int argc, char **argv) | 1106 | extern int ifupdown_main(int argc, char **argv) |
@@ -1125,19 +1108,16 @@ extern int ifupdown_main(int argc, char **argv) | |||
1125 | int (*cmds) (interface_defn_t *) = NULL; | 1108 | int (*cmds) (interface_defn_t *) = NULL; |
1126 | interfaces_file_t *defn; | 1109 | interfaces_file_t *defn; |
1127 | FILE *state_fp = NULL; | 1110 | FILE *state_fp = NULL; |
1128 | char **target_iface = NULL; | 1111 | llist_t *state_list = NULL; |
1129 | char **state = NULL; /* list of iface=liface */ | 1112 | llist_t *target_list = NULL; |
1130 | char *interfaces = "/etc/network/interfaces"; | 1113 | char *interfaces = "/etc/network/interfaces"; |
1131 | char *statefile = "/var/run/ifstate"; | 1114 | const char *statefile = "/var/run/ifstate"; |
1132 | 1115 | ||
1133 | #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING | 1116 | #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING |
1134 | int run_mappings = 1; | 1117 | int run_mappings = 1; |
1135 | #endif | 1118 | #endif |
1136 | int do_all = 0; | 1119 | int do_all = 0; |
1137 | int force = 0; | 1120 | int force = 0; |
1138 | int n_target_ifaces = 0; | ||
1139 | int n_state = 0; | ||
1140 | int max_state = 0; | ||
1141 | int i; | 1121 | int i; |
1142 | 1122 | ||
1143 | if (applet_name[2] == 'u') { | 1123 | if (applet_name[2] == 'u') { |
@@ -1195,11 +1175,13 @@ extern int ifupdown_main(int argc, char **argv) | |||
1195 | error_msg_and_die("couldn't read interfaces file \"%s\"", interfaces); | 1175 | error_msg_and_die("couldn't read interfaces file \"%s\"", interfaces); |
1196 | } | 1176 | } |
1197 | 1177 | ||
1198 | state_fp = fopen(statefile, no_act ? "r" : "a+"); | 1178 | if (no_act) { |
1199 | if (state_fp == NULL && !no_act) { | 1179 | state_fp = fopen(statefile, "r"); |
1200 | perror_msg_and_die("failed to open statefile %s", statefile); | 1180 | } else { |
1181 | state_fp = xfopen(statefile, "a+"); | ||
1201 | } | 1182 | } |
1202 | 1183 | ||
1184 | /* Read the previous state from the state file */ | ||
1203 | if (state_fp != NULL) { | 1185 | if (state_fp != NULL) { |
1204 | char *start; | 1186 | char *start; |
1205 | while ((start = get_line_from_file(state_fp)) != NULL) { | 1187 | while ((start = get_line_from_file(state_fp)) != NULL) { |
@@ -1207,61 +1189,65 @@ extern int ifupdown_main(int argc, char **argv) | |||
1207 | /* We should only need to check for a single character */ | 1189 | /* We should only need to check for a single character */ |
1208 | end_ptr = start + strcspn(start, " \t\n"); | 1190 | end_ptr = start + strcspn(start, " \t\n"); |
1209 | *end_ptr = '\0'; | 1191 | *end_ptr = '\0'; |
1210 | add_to_state(&state, &n_state, &max_state, start); | 1192 | state_list = llist_add_to(state_list, start); |
1211 | } | 1193 | } |
1212 | } | 1194 | } |
1213 | 1195 | ||
1196 | /* Create a list of interfaces to work on */ | ||
1214 | if (do_all) { | 1197 | if (do_all) { |
1215 | if (cmds == iface_up) { | 1198 | if (cmds == iface_up) { |
1216 | target_iface = defn->autointerfaces; | 1199 | target_list = defn->autointerfaces; |
1217 | n_target_ifaces = defn->n_autointerfaces; | ||
1218 | } else if (cmds == iface_down) { | 1200 | } else if (cmds == iface_down) { |
1219 | target_iface = state; | 1201 | const llist_t *list = state_list; |
1220 | n_target_ifaces = n_state; | 1202 | while (list) { |
1203 | target_list = llist_add_to(target_list, strdup(list->data)); | ||
1204 | list = list->link; | ||
1205 | } | ||
1221 | } | 1206 | } |
1222 | } else { | 1207 | } else { |
1223 | target_iface = argv + optind; | 1208 | target_list = llist_add_to(target_list, argv[optind]); |
1224 | n_target_ifaces = argc - optind; | ||
1225 | } | 1209 | } |
1226 | 1210 | ||
1227 | 1211 | ||
1228 | for (i = 0; i < n_target_ifaces; i++) { | 1212 | /* Update the interfaces */ |
1213 | while (target_list) { | ||
1229 | interface_defn_t *currif; | 1214 | interface_defn_t *currif; |
1230 | char iface[80]; | 1215 | char *iface; |
1231 | char liface[80]; | 1216 | char *liface; |
1232 | char *pch; | 1217 | char *pch; |
1233 | int okay = 0; | 1218 | int okay = 0; |
1234 | 1219 | ||
1235 | strncpy(iface, target_iface[i], sizeof(iface)); | 1220 | iface = strdup(target_list->data); |
1236 | iface[sizeof(iface) - 1] = '\0'; | 1221 | target_list = target_list->link; |
1237 | 1222 | ||
1238 | if ((pch = strchr(iface, '='))) { | 1223 | pch = strchr(iface, '='); |
1224 | if (pch) { | ||
1239 | *pch = '\0'; | 1225 | *pch = '\0'; |
1240 | strncpy(liface, pch + 1, sizeof(liface)); | 1226 | liface = strdup(pch + 1); |
1241 | liface[sizeof(liface) - 1] = '\0'; | ||
1242 | } else { | 1227 | } else { |
1243 | strncpy(liface, iface, sizeof(liface)); | 1228 | liface = strdup(iface); |
1244 | liface[sizeof(liface) - 1] = '\0'; | ||
1245 | } | 1229 | } |
1230 | |||
1246 | if (!force) { | 1231 | if (!force) { |
1247 | int already_up = lookfor_iface(state, n_state, iface);; | 1232 | const llist_t *iface_state = find_iface_state(state_list, iface); |
1248 | 1233 | ||
1249 | if (cmds == iface_up) { | 1234 | if (cmds == iface_up) { |
1250 | /* ifup */ | 1235 | /* ifup */ |
1251 | if (already_up != -1) { | 1236 | if (iface_state) { |
1252 | error_msg("interface %s already configured", iface); | 1237 | error_msg("interface %s already configured", iface); |
1253 | continue; | 1238 | continue; |
1254 | } | 1239 | } |
1255 | } else { | 1240 | } else { |
1256 | /* ifdown */ | 1241 | /* ifdown */ |
1257 | if (already_up == -1) { | 1242 | if (iface_state == NULL) { |
1258 | error_msg("interface %s not configured", iface); | 1243 | error_msg("interface %s not configured", iface); |
1259 | continue; | 1244 | continue; |
1260 | } | 1245 | } |
1261 | strncpy(liface, strchr(state[already_up], '=') + 1, 80); | 1246 | pch = strchr(iface_state->data, '='); |
1262 | liface[79] = 0; | 1247 | liface = strdup(pch + 1); |
1263 | } | 1248 | } |
1264 | } | 1249 | } |
1250 | |||
1265 | #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING | 1251 | #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING |
1266 | if ((cmds == iface_up) && run_mappings) { | 1252 | if ((cmds == iface_up) && run_mappings) { |
1267 | mapping_defn_t *currmap; | 1253 | mapping_defn_t *currmap; |
@@ -1286,13 +1272,13 @@ extern int ifupdown_main(int argc, char **argv) | |||
1286 | char *oldiface = currif->iface; | 1272 | char *oldiface = currif->iface; |
1287 | 1273 | ||
1288 | okay = 1; | 1274 | okay = 1; |
1289 | |||
1290 | currif->iface = iface; | 1275 | currif->iface = iface; |
1291 | 1276 | ||
1292 | if (verbose) { | 1277 | if (verbose) { |
1293 | error_msg("Configuring interface %s=%s (%s)", iface, liface, currif->address_family->name); | 1278 | error_msg("Configuring interface %s=%s (%s)", iface, liface, currif->address_family->name); |
1294 | } | 1279 | } |
1295 | 1280 | ||
1281 | /* Call the cmds function pointer, does either iface_up() or iface_down() */ | ||
1296 | if (cmds(currif) == -1) { | 1282 | if (cmds(currif) == -1) { |
1297 | printf | 1283 | printf |
1298 | ("Don't seem to be have all the variables for %s/%s.\n", | 1284 | ("Don't seem to be have all the variables for %s/%s.\n", |
@@ -1306,39 +1292,54 @@ extern int ifupdown_main(int argc, char **argv) | |||
1306 | if (!okay && !force) { | 1292 | if (!okay && !force) { |
1307 | error_msg("Ignoring unknown interface %s=%s.", iface, liface); | 1293 | error_msg("Ignoring unknown interface %s=%s.", iface, liface); |
1308 | } else { | 1294 | } else { |
1309 | int already_up = lookfor_iface(state, n_state, iface); | 1295 | llist_t *iface_state = find_iface_state(state_list, iface); |
1310 | 1296 | ||
1311 | if (cmds == iface_up) { | 1297 | if (cmds == iface_up) { |
1312 | char *newiface = xmalloc(xstrlen(iface) + 1 + xstrlen(liface) + 1); | 1298 | char *newiface = xmalloc(xstrlen(iface) + 1 + xstrlen(liface) + 1); |
1313 | sprintf(newiface, "%s=%s", iface, liface); | 1299 | sprintf(newiface, "%s=%s", iface, liface); |
1314 | if (already_up == -1) { | 1300 | if (iface_state == NULL) { |
1315 | add_to_state(&state, &n_state, &max_state, newiface); | 1301 | state_list = llist_add_to(state_list, newiface); |
1316 | } else { | 1302 | } else { |
1317 | free(state[already_up]); | 1303 | free(iface_state->data); |
1318 | state[already_up] = newiface; | 1304 | iface_state->data = newiface; |
1319 | } | 1305 | } |
1320 | } else if (cmds == iface_down) { | 1306 | } else if (cmds == iface_down) { |
1321 | if (already_up != -1) { | 1307 | /* Remove an interface from the linked list */ |
1322 | state[already_up] = state[--n_state]; | 1308 | if (iface_state) { |
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; | ||
1315 | } else { | ||
1316 | iface_state->data = NULL; | ||
1317 | iface_state->link = NULL; | ||
1318 | } | ||
1323 | } | 1319 | } |
1324 | } | 1320 | } |
1325 | } | 1321 | } |
1326 | if (state_fp != NULL && !no_act) { | 1322 | } |
1327 | unsigned short j; | ||
1328 | 1323 | ||
1329 | if (ftruncate(fileno(state_fp), 0) < 0) { | 1324 | /* Actually write the new state */ |
1330 | error_msg_and_die("failed to truncate statefile %s: %s", statefile, strerror(errno)); | 1325 | if (state_fp != NULL && !no_act) { |
1331 | } | 1326 | if (ftruncate(fileno(state_fp), 0) < 0) { |
1327 | error_msg_and_die("failed to truncate statefile %s: %s", statefile, strerror(errno)); | ||
1328 | } | ||
1329 | |||
1330 | rewind(state_fp); | ||
1332 | 1331 | ||
1333 | rewind(state_fp); | 1332 | while (state_list) { |
1334 | for (j = 0; j < n_state; j++) { | 1333 | if (state_list->data) { |
1335 | fputs(state[i], state_fp); | 1334 | fputs(state_list->data, state_fp); |
1336 | fputc('\n', state_fp); | 1335 | fputc('\n', state_fp); |
1337 | } | 1336 | } |
1338 | fflush(state_fp); | 1337 | state_list = state_list->link; |
1339 | } | 1338 | } |
1339 | fflush(state_fp); | ||
1340 | } | 1340 | } |
1341 | 1341 | ||
1342 | /* Cleanup */ | ||
1342 | if (state_fp != NULL) { | 1343 | if (state_fp != NULL) { |
1343 | fclose(state_fp); | 1344 | fclose(state_fp); |
1344 | state_fp = NULL; | 1345 | state_fp = NULL; |