aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-12-08 01:23:39 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-12-08 01:23:39 +0000
commit8e49caa54fd7921dc0cc3b925668c76a16a39414 (patch)
tree27fb1d6413343cc344c09ca8c04381aec6dc7012
parent66125c806518f74a54232206d02e30a39b621232 (diff)
downloadbusybox-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.c207
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
47typedef struct interface_defn_s interface_defn_t; 50typedef struct interface_defn_s interface_defn_t;
48 51
@@ -95,22 +98,13 @@ struct interface_defn_s {
95}; 98};
96 99
97typedef struct interfaces_file_s { 100typedef 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 106static char no_act = 0;
107#define EUNBALBRACK 10001 107static char verbose = 0;
108#define EUNDEFVAR 10002
109#define MAX_VARNAME 32
110#define EUNBALPER 10000
111
112static int no_act = 0;
113static int verbose = 0;
114static char **environ = NULL; 108static char **environ = NULL;
115 109
116static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length) 110static 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
605static 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
611static interfaces_file_t *read_interfaces(char *filename) 616static 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
1098static int lookfor_iface(char **ifaces, int n_ifaces, char *iface) 1091static 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
1113static 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
1123extern int ifupdown_main(int argc, char **argv) 1106extern 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;