Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/networking/ifupdown.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/networking/ifupdown.c
r821 r1770 11 11 * Remove checks for kernel version, assume kernel version 2.2.0 or better. 12 12 * Lines in the interfaces file cannot wrap. 13 * To adhere to the FHS, the default state file is /var/run/ifstate. 13 * To adhere to the FHS, the default state file is /var/run/ifstate 14 * (defined via CONFIG_IFUPDOWN_IFSTATE_PATH) and can be overridden by build 15 * configuration. 14 16 * 15 17 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 16 18 */ 17 19 18 /* TODO: standardise execute() return codes to return 0 for success and 1 for failure */19 20 #include <sys/stat.h>21 20 #include <sys/utsname.h> 22 #include <sys/wait.h>23 24 #include <ctype.h>25 #include <errno.h>26 #include <fcntl.h>27 21 #include <fnmatch.h> 28 22 #include <getopt.h> 29 #include <stdarg.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include "busybox.h" 23 24 #include "libbb.h" 36 25 37 26 #define MAX_OPT_DEPTH 10 … … 40 29 #define EUNBALPER 10000 41 30 42 #if def CONFIG_FEATURE_IFUPDOWN_MAPPING31 #if ENABLE_FEATURE_IFUPDOWN_MAPPING 43 32 #define MAX_INTERFACE_LENGTH 10 44 33 #endif 45 34 46 #if 0 47 #define debug_noise(fmt, args...) printf(fmt, ## args) 48 #else 49 #define debug_noise(fmt, args...) 50 #endif 35 #define debug_noise(args...) /*fprintf(stderr, args)*/ 51 36 52 37 /* Forward declaration */ 53 38 struct interface_defn_t; 54 39 55 typedef int (execfn)(char *command); 56 57 struct method_t 58 { 59 char *name; 40 typedef int execfn(char *command); 41 42 struct method_t { 43 const char *name; 60 44 int (*up)(struct interface_defn_t *ifd, execfn *e); 61 45 int (*down)(struct interface_defn_t *ifd, execfn *e); 62 46 }; 63 47 64 struct address_family_t 65 { 66 char *name; 48 struct address_family_t { 49 const char *name; 67 50 int n_methods; 68 struct method_t *method;51 const struct method_t *method; 69 52 }; 70 53 71 struct mapping_defn_t 72 { 54 struct mapping_defn_t { 73 55 struct mapping_defn_t *next; 74 56 … … 84 66 }; 85 67 86 struct variable_t 87 { 68 struct variable_t { 88 69 char *name; 89 70 char *value; 90 71 }; 91 72 92 struct interface_defn_t 93 { 94 struct address_family_t *address_family; 95 struct method_t *method; 73 struct interface_defn_t { 74 const struct address_family_t *address_family; 75 const struct method_t *method; 96 76 97 77 char *iface; … … 101 81 }; 102 82 103 struct interfaces_file_t 104 { 83 struct interfaces_file_t { 105 84 llist_t *autointerfaces; 106 85 llist_t *ifaces; … … 108 87 }; 109 88 110 static char no_act = 0; 111 static char verbose = 0; 112 static char **__myenviron = NULL; 89 #define OPTION_STR "anvf" USE_FEATURE_IFUPDOWN_MAPPING("m") "i:" 90 enum { 91 OPT_do_all = 0x1, 92 OPT_no_act = 0x2, 93 OPT_verbose = 0x4, 94 OPT_force = 0x8, 95 OPT_no_mappings = 0x10, 96 }; 97 #define DO_ALL (option_mask32 & OPT_do_all) 98 #define NO_ACT (option_mask32 & OPT_no_act) 99 #define VERBOSE (option_mask32 & OPT_verbose) 100 #define FORCE (option_mask32 & OPT_force) 101 #define NO_MAPPINGS (option_mask32 & OPT_no_mappings) 102 103 static char **my_environ; 104 105 static const char *startup_PATH; 113 106 114 107 #if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6 115 108 116 #ifdef CONFIG_FEATURE_IFUPDOWN_IP 117 118 static unsigned int count_bits(unsigned int a) 119 { 120 unsigned int result; 121 result = (a & 0x55) + ((a >> 1) & 0x55); 122 result = (result & 0x33) + ((result >> 2) & 0x33); 123 return((result & 0x0F) + ((result >> 4) & 0x0F)); 124 } 125 126 static int count_netmask_bits(char *dotted_quad) 127 { 128 unsigned int result, a, b, c, d; 129 /* Found a netmask... Check if it is dotted quad */ 130 if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) 131 return -1; 132 result = count_bits(a); 133 result += count_bits(b); 134 result += count_bits(c); 135 result += count_bits(d); 136 return ((int)result); 137 } 138 #endif 139 140 static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length) 141 { 142 if (*pos + str_length >= *len) { 143 char *newbuf; 144 145 newbuf = xrealloc(*buf, *len * 2 + str_length + 1); 146 *buf = newbuf; 147 *len = *len * 2 + str_length + 1; 148 } 149 150 while (str_length-- >= 1) { 151 (*buf)[(*pos)++] = *str; 152 str++; 153 } 154 (*buf)[*pos] = '\0'; 155 } 156 157 static int strncmpz(char *l, char *r, size_t llen) 109 static void addstr(char **bufp, const char *str, size_t str_length) 110 { 111 /* xasprintf trick will be smaller, but we are often 112 * called with str_length == 1 - don't want to have 113 * THAT much of malloc/freeing! */ 114 char *buf = *bufp; 115 int len = (buf ? strlen(buf) : 0); 116 str_length++; 117 buf = xrealloc(buf, len + str_length); 118 /* copies at most str_length-1 chars! */ 119 safe_strncpy(buf + len, str, str_length); 120 *bufp = buf; 121 } 122 123 static int strncmpz(const char *l, const char *r, size_t llen) 158 124 { 159 125 int i = strncmp(l, r, llen); 160 126 161 if (i == 0) { 162 return(-r[llen]); 163 } else { 164 return(i); 165 } 166 } 167 168 static char *get_var(char *id, size_t idlen, struct interface_defn_t *ifd) 127 if (i == 0) 128 return -r[llen]; 129 return i; 130 } 131 132 static char *get_var(const char *id, size_t idlen, struct interface_defn_t *ifd) 169 133 { 170 134 int i; … … 173 137 char *result; 174 138 static char label_buf[20]; 175 strncpy(label_buf, ifd->iface, 19); 176 label_buf[19]=0; 139 safe_strncpy(label_buf, ifd->iface, sizeof(label_buf)); 177 140 result = strchr(label_buf, ':'); 178 141 if (result) { 179 *result=0; 180 } 181 return( label_buf); 182 } else if (strncmpz(id, "label", idlen) == 0) { 183 return (ifd->iface); 184 } else { 185 for (i = 0; i < ifd->n_options; i++) { 186 if (strncmpz(id, ifd->option[i].name, idlen) == 0) { 187 return (ifd->option[i].value); 188 } 189 } 190 } 191 192 return(NULL); 193 } 194 195 static char *parse(char *command, struct interface_defn_t *ifd) 196 { 197 198 char *result = NULL; 199 size_t pos = 0, len = 0; 142 *result = '\0'; 143 } 144 return label_buf; 145 } 146 if (strncmpz(id, "label", idlen) == 0) { 147 return ifd->iface; 148 } 149 for (i = 0; i < ifd->n_options; i++) { 150 if (strncmpz(id, ifd->option[i].name, idlen) == 0) { 151 return ifd->option[i].value; 152 } 153 } 154 return NULL; 155 } 156 157 #if ENABLE_FEATURE_IFUPDOWN_IP 158 static int count_netmask_bits(const char *dotted_quad) 159 { 160 // int result; 161 // unsigned a, b, c, d; 162 // /* Found a netmask... Check if it is dotted quad */ 163 // if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) 164 // return -1; 165 // if ((a|b|c|d) >> 8) 166 // return -1; /* one of numbers is >= 256 */ 167 // d |= (a << 24) | (b << 16) | (c << 8); /* IP */ 168 // d = ~d; /* 11110000 -> 00001111 */ 169 170 /* Shorter version */ 171 int result; 172 struct in_addr ip; 173 unsigned d; 174 175 if (inet_aton(dotted_quad, &ip) == 0) 176 return -1; /* malformed dotted IP */ 177 d = ntohl(ip.s_addr); /* IP in host order */ 178 d = ~d; /* 11110000 -> 00001111 */ 179 if (d & (d+1)) /* check that it is in 00001111 form */ 180 return -1; /* no it is not */ 181 result = 32; 182 while (d) { 183 d >>= 1; 184 result--; 185 } 186 return result; 187 } 188 #endif 189 190 static char *parse(const char *command, struct interface_defn_t *ifd) 191 { 200 192 size_t old_pos[MAX_OPT_DEPTH] = { 0 }; 201 193 int okay[MAX_OPT_DEPTH] = { 1 }; 202 194 int opt_depth = 1; 195 char *result = NULL; 203 196 204 197 while (*command) { 205 198 switch (*command) { 206 207 default: 208 addstr(&result, &len, &pos, command, 1); 199 default: 200 addstr(&result, command, 1); 201 command++; 202 break; 203 case '\\': 204 if (command[1]) { 205 addstr(&result, command + 1, 1); 206 command += 2; 207 } else { 208 addstr(&result, command, 1); 209 209 command++; 210 break; 211 case '\\': 212 if (command[1]) { 213 addstr(&result, &len, &pos, command + 1, 1); 214 command += 2; 210 } 211 break; 212 case '[': 213 if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) { 214 old_pos[opt_depth] = result ? strlen(result) : 0; 215 okay[opt_depth] = 1; 216 opt_depth++; 217 command += 2; 218 } else { 219 addstr(&result, "[", 1); 220 command++; 221 } 222 break; 223 case ']': 224 if (command[1] == ']' && opt_depth > 1) { 225 opt_depth--; 226 if (!okay[opt_depth]) { 227 result[old_pos[opt_depth]] = '\0'; 228 } 229 command += 2; 230 } else { 231 addstr(&result, "]", 1); 232 command++; 233 } 234 break; 235 case '%': 236 { 237 char *nextpercent; 238 char *varvalue; 239 240 command++; 241 nextpercent = strchr(command, '%'); 242 if (!nextpercent) { 243 errno = EUNBALPER; 244 free(result); 245 return NULL; 246 } 247 248 varvalue = get_var(command, nextpercent - command, ifd); 249 250 if (varvalue) { 251 addstr(&result, varvalue, strlen(varvalue)); 215 252 } else { 216 addstr(&result, &len, &pos, command, 1); 217 command++; 218 } 219 break; 220 case '[': 221 if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) { 222 old_pos[opt_depth] = pos; 223 okay[opt_depth] = 1; 224 opt_depth++; 225 command += 2; 226 } else { 227 addstr(&result, &len, &pos, "[", 1); 228 command++; 229 } 230 break; 231 case ']': 232 if (command[1] == ']' && opt_depth > 1) { 233 opt_depth--; 234 if (!okay[opt_depth]) { 235 pos = old_pos[opt_depth]; 236 result[pos] = '\0'; 237 } 238 command += 2; 239 } else { 240 addstr(&result, &len, &pos, "]", 1); 241 command++; 242 } 243 break; 244 case '%': 245 { 246 char *nextpercent; 247 char *varvalue; 248 249 command++; 250 nextpercent = strchr(command, '%'); 251 if (!nextpercent) { 252 errno = EUNBALPER; 253 free(result); 254 return (NULL); 255 } 256 257 varvalue = get_var(command, nextpercent - command, ifd); 258 259 if (varvalue) { 260 addstr(&result, &len, &pos, varvalue, strlen(varvalue)); 261 } else { 262 #ifdef CONFIG_FEATURE_IFUPDOWN_IP 263 /* Sigh... Add a special case for 'ip' to convert from 264 * dotted quad to bit count style netmasks. */ 265 if (strncmp(command, "bnmask", 6)==0) { 266 int res; 267 varvalue = get_var("netmask", 7, ifd); 268 if (varvalue && (res=count_netmask_bits(varvalue)) > 0) { 269 char argument[255]; 270 sprintf(argument, "%d", res); 271 addstr(&result, &len, &pos, argument, strlen(argument)); 253 #if ENABLE_FEATURE_IFUPDOWN_IP 254 /* Sigh... Add a special case for 'ip' to convert from 255 * dotted quad to bit count style netmasks. */ 256 if (strncmp(command, "bnmask", 6) == 0) { 257 unsigned res; 258 varvalue = get_var("netmask", 7, ifd); 259 if (varvalue) { 260 res = count_netmask_bits(varvalue); 261 if (res > 0) { 262 const char *argument = utoa(res); 263 addstr(&result, argument, strlen(argument)); 272 264 command = nextpercent + 1; 273 265 break; 274 266 } 275 267 } 276 #endif277 okay[opt_depth - 1] = 0;278 268 } 279 280 command = nextpercent + 1; 281 } 282 break; 269 #endif 270 okay[opt_depth - 1] = 0; 271 } 272 273 command = nextpercent + 1; 274 } 275 break; 283 276 } 284 277 } … … 287 280 errno = EUNBALBRACK; 288 281 free(result); 289 return (NULL);282 return NULL; 290 283 } 291 284 … … 293 286 errno = EUNDEFVAR; 294 287 free(result); 295 return(NULL); 296 } 297 298 return(result); 299 } 300 301 static int execute(char *command, struct interface_defn_t *ifd, execfn *exec) 288 return NULL; 289 } 290 291 return result; 292 } 293 294 /* execute() returns 1 for success and 0 for failure */ 295 static int execute(const char *command, struct interface_defn_t *ifd, execfn *exec) 302 296 { 303 297 char *out; … … 306 300 out = parse(command, ifd); 307 301 if (!out) { 308 return(0); 309 } 310 ret = (*exec) (out); 302 /* parse error? */ 303 return 0; 304 } 305 /* out == "": parsed ok but not all needed variables known, skip */ 306 ret = out[0] ? (*exec)(out) : 1; 311 307 312 308 free(out); 313 309 if (ret != 1) { 314 return (0);315 } 316 return (1);317 } 318 #endif 319 320 #if def CONFIG_FEATURE_IFUPDOWN_IPV6310 return 0; 311 } 312 return 1; 313 } 314 #endif 315 316 #if ENABLE_FEATURE_IFUPDOWN_IPV6 321 317 static int loopback_up6(struct interface_defn_t *ifd, execfn *exec) 322 318 { 323 #if def CONFIG_FEATURE_IFUPDOWN_IP319 #if ENABLE_FEATURE_IFUPDOWN_IP 324 320 int result; 325 result = execute("ip addr add ::1 dev %iface%", ifd, exec);321 result = execute("ip addr add ::1 dev %iface%", ifd, exec); 326 322 result += execute("ip link set %iface% up", ifd, exec); 327 323 return ((result == 2) ? 2 : 0); 328 324 #else 329 return ( execute("ifconfig %iface% add ::1", ifd, exec));325 return execute("ifconfig %iface% add ::1", ifd, exec); 330 326 #endif 331 327 } … … 333 329 static int loopback_down6(struct interface_defn_t *ifd, execfn *exec) 334 330 { 335 #if def CONFIG_FEATURE_IFUPDOWN_IP336 return (execute("ip link set %iface% down", ifd, exec));331 #if ENABLE_FEATURE_IFUPDOWN_IP 332 return execute("ip link set %iface% down", ifd, exec); 337 333 #else 338 return (execute("ifconfig %iface% del ::1", ifd, exec));334 return execute("ifconfig %iface% del ::1", ifd, exec); 339 335 #endif 340 336 } … … 343 339 { 344 340 int result; 345 #ifdef CONFIG_FEATURE_IFUPDOWN_IP 346 result = execute("ip addr add %address%/%netmask% dev %iface% [[label %label%]]", ifd, exec); 347 result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec); 348 result += execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec); 341 #if ENABLE_FEATURE_IFUPDOWN_IP 342 result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec); 343 result += execute("ip link set[[ mtu %mtu%]][[ address %hwaddress%]] %iface% up", ifd, exec); 344 /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */ 345 result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec); 349 346 #else 350 result = execute("ifconfig %iface% [[media %media%]] [[hw %hwaddress%]] [[mtu %mtu%]] up", ifd, exec);347 result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec); 351 348 result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec); 352 result += execute("[[ route -A inet6 add ::/0 gw %gateway%]]", ifd, exec);349 result += execute("[[route -A inet6 add ::/0 gw %gateway%]]", ifd, exec); 353 350 #endif 354 351 return ((result == 3) ? 3 : 0); … … 357 354 static int static_down6(struct interface_defn_t *ifd, execfn *exec) 358 355 { 359 #if def CONFIG_FEATURE_IFUPDOWN_IP360 return (execute("ip link set %iface% down", ifd, exec));356 #if ENABLE_FEATURE_IFUPDOWN_IP 357 return execute("ip link set %iface% down", ifd, exec); 361 358 #else 362 return (execute("ifconfig %iface% down", ifd, exec));363 #endif 364 } 365 366 #if def CONFIG_FEATURE_IFUPDOWN_IP359 return execute("ifconfig %iface% down", ifd, exec); 360 #endif 361 } 362 363 #if ENABLE_FEATURE_IFUPDOWN_IP 367 364 static int v4tunnel_up(struct interface_defn_t *ifd, execfn *exec) 368 365 { 369 366 int result; 370 367 result = execute("ip tunnel add %iface% mode sit remote " 371 "%endpoint% [[local %local%]] [[ttl %ttl%]]", ifd, exec);368 "%endpoint%[[ local %local%]][[ ttl %ttl%]]", ifd, exec); 372 369 result += execute("ip link set %iface% up", ifd, exec); 373 370 result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec); 374 result += execute("[[ ip route add ::/0 via %gateway%]]", ifd, exec);371 result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec); 375 372 return ((result == 4) ? 4 : 0); 376 373 } … … 378 375 static int v4tunnel_down(struct interface_defn_t * ifd, execfn * exec) 379 376 { 380 return ( execute("ip tunnel del %iface%", ifd, exec));381 } 382 #endif 383 384 static struct method_t methods6[] = {385 #if def CONFIG_FEATURE_IFUPDOWN_IP377 return execute("ip tunnel del %iface%", ifd, exec); 378 } 379 #endif 380 381 static const struct method_t methods6[] = { 382 #if ENABLE_FEATURE_IFUPDOWN_IP 386 383 { "v4tunnel", v4tunnel_up, v4tunnel_down, }, 387 384 #endif … … 390 387 }; 391 388 392 static struct address_family_t addr_inet6 = {389 static const struct address_family_t addr_inet6 = { 393 390 "inet6", 394 sizeof(methods6) / sizeof(struct method_t),391 ARRAY_SIZE(methods6), 395 392 methods6 396 393 }; 397 #endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */398 399 #if def CONFIG_FEATURE_IFUPDOWN_IPV4394 #endif /* FEATURE_IFUPDOWN_IPV6 */ 395 396 #if ENABLE_FEATURE_IFUPDOWN_IPV4 400 397 static int loopback_up(struct interface_defn_t *ifd, execfn *exec) 401 398 { 402 #if def CONFIG_FEATURE_IFUPDOWN_IP399 #if ENABLE_FEATURE_IFUPDOWN_IP 403 400 int result; 404 401 result = execute("ip addr add 127.0.0.1/8 dev %iface%", ifd, exec); … … 406 403 return ((result == 2) ? 2 : 0); 407 404 #else 408 return ( execute("ifconfig %iface% 127.0.0.1 up", ifd, exec));405 return execute("ifconfig %iface% 127.0.0.1 up", ifd, exec); 409 406 #endif 410 407 } … … 412 409 static int loopback_down(struct interface_defn_t *ifd, execfn *exec) 413 410 { 414 #if def CONFIG_FEATURE_IFUPDOWN_IP411 #if ENABLE_FEATURE_IFUPDOWN_IP 415 412 int result; 416 413 result = execute("ip addr flush dev %iface%", ifd, exec); … … 418 415 return ((result == 2) ? 2 : 0); 419 416 #else 420 return ( execute("ifconfig %iface% 127.0.0.1 down", ifd, exec));417 return execute("ifconfig %iface% 127.0.0.1 down", ifd, exec); 421 418 #endif 422 419 } … … 425 422 { 426 423 int result; 427 #if def CONFIG_FEATURE_IFUPDOWN_IP428 result = execute("ip addr add %address%/%bnmask% [[broadcast %broadcast%]] "429 "dev %iface% [[peer %pointopoint%]] [[label %label%]]", ifd, exec);430 result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec);431 result += execute("[[ ip route add default via %gateway% dev %iface%]]", ifd, exec);424 #if ENABLE_FEATURE_IFUPDOWN_IP 425 result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] " 426 "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec); 427 result += execute("ip link set[[ mtu %mtu%]][[ address %hwaddress%]] %iface% up", ifd, exec); 428 result += execute("[[ip route add default via %gateway% dev %iface%]]", ifd, exec); 432 429 return ((result == 3) ? 3 : 0); 433 430 #else 434 result = execute("ifconfig %iface% %address% netmask %netmask% "435 "[[broadcast %broadcast%]] [[pointopoint %pointopoint%]] "436 "[[media %media%]] [[mtu %mtu%]] [[hw %hwaddress%]] up",431 /* ifconfig said to set iface up before it processes hw %hwaddress%, 432 * which then of course fails. Thus we run two separate ifconfig */ 433 result = execute("ifconfig %iface%[[ hw %hwaddress%]][[ media %media%]][[ mtu %mtu%]] up", 437 434 ifd, exec); 438 result += execute("[[ route add default gw %gateway% %iface% ]]", ifd, exec); 439 return ((result == 2) ? 2 : 0); 435 result += execute("ifconfig %iface% %address% netmask %netmask%" 436 "[[ broadcast %broadcast%]][[ pointopoint %pointopoint%]] ", 437 ifd, exec); 438 result += execute("[[route add default gw %gateway% %iface%]]", ifd, exec); 439 return ((result == 3) ? 3 : 0); 440 440 #endif 441 441 } … … 444 444 { 445 445 int result; 446 #if def CONFIG_FEATURE_IFUPDOWN_IP446 #if ENABLE_FEATURE_IFUPDOWN_IP 447 447 result = execute("ip addr flush dev %iface%", ifd, exec); 448 448 result += execute("ip link set %iface% down", ifd, exec); 449 449 #else 450 result = execute("[[ route del default gw %gateway% %iface%]]", ifd, exec);450 result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec); 451 451 result += execute("ifconfig %iface% down", ifd, exec); 452 452 #endif … … 454 454 } 455 455 456 static int execable(char *program) 457 { 458 struct stat buf; 459 if (0 == stat(program, &buf)) { 460 if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode)) { 461 return(1); 462 } 463 } 464 return(0); 465 } 456 #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP 457 struct dhcp_client_t 458 { 459 const char *name; 460 const char *startcmd; 461 const char *stopcmd; 462 }; 463 464 static const struct dhcp_client_t ext_dhcp_clients[] = { 465 { "dhcpcd", 466 "dhcpcd[[ -h %hostname%]][[ -i %vendor%]][[ -I %clientid%]][[ -l %leasetime%]] %iface%", 467 "dhcpcd -k %iface%", 468 }, 469 { "dhclient", 470 "dhclient -pf /var/run/dhclient.%iface%.pid %iface%", 471 "kill -9 `cat /var/run/dhclient.%iface%.pid` 2>/dev/null", 472 }, 473 { "pump", 474 "pump -i %iface%[[ -h %hostname%]][[ -l %leasehours%]]", 475 "pump -i %iface% -k", 476 }, 477 { "udhcpc", 478 "udhcpc -R -n -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]", 479 "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", 480 }, 481 }; 482 #endif /* ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCPC */ 466 483 467 484 static int dhcp_up(struct interface_defn_t *ifd, execfn *exec) 468 485 { 469 if (execable("/sbin/udhcpc")) { 470 return( execute("udhcpc -n -p /var/run/udhcpc.%iface%.pid -i " 471 "%iface% [[-H %hostname%]] [[-c %clientid%]]", ifd, exec)); 472 } else if (execable("/sbin/pump")) { 473 return( execute("pump -i %iface% [[-h %hostname%]] [[-l %leasehours%]]", ifd, exec)); 474 } else if (execable("/sbin/dhclient")) { 475 return( execute("dhclient -pf /var/run/dhclient.%iface%.pid %iface%", ifd, exec)); 476 } else if (execable("/sbin/dhcpcd")) { 477 return( execute("dhcpcd [[-h %hostname%]] [[-i %vendor%]] [[-I %clientid%]] " 478 "[[-l %leasetime%]] %iface%", ifd, exec)); 479 } 480 return(0); 486 #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP 487 int i; 488 #if ENABLE_FEATURE_IFUPDOWN_IP 489 /* ip doesn't up iface when it configures it (unlike ifconfig) */ 490 if (!execute("ip link set %iface% up", ifd, exec)) 491 return 0; 492 #endif 493 for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) { 494 if (exists_execable(ext_dhcp_clients[i].name)) 495 return execute(ext_dhcp_clients[i].startcmd, ifd, exec); 496 } 497 bb_error_msg("no dhcp clients found"); 498 return 0; 499 #elif ENABLE_APP_UDHCPC 500 #if ENABLE_FEATURE_IFUPDOWN_IP 501 /* ip doesn't up iface when it configures it (unlike ifconfig) */ 502 if (!execute("ip link set %iface% up", ifd, exec)) 503 return 0; 504 #endif 505 return execute("udhcpc -R -n -p /var/run/udhcpc.%iface%.pid " 506 "-i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]", 507 ifd, exec); 508 #else 509 return 0; /* no dhcp support */ 510 #endif 481 511 } 482 512 483 513 static int dhcp_down(struct interface_defn_t *ifd, execfn *exec) 484 514 { 485 int result = 0; 486 if (execable("/sbin/udhcpc")) { 487 /* SIGUSR2 forces udhcpc to release the current lease and go inactive, 488 * and SIGTERM causes udhcpc to exit. Signals are queued and processed 489 * sequentially so we don't need to sleep */ 490 result = execute("kill -USR2 `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec); 491 result += execute("kill -TERM `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec); 492 } else if (execable("/sbin/pump")) { 493 result = execute("pump -i %iface% -k", ifd, exec); 494 } else if (execable("/sbin/dhclient")) { 495 result = execute("kill -9 `cat /var/run/dhclient.%iface%.pid` 2>/dev/null", ifd, exec); 496 } else if (execable("/sbin/dhcpcd")) { 497 result = execute("dhcpcd -k %iface%", ifd, exec); 498 } 499 return (result || static_down(ifd, exec)); 515 #if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP 516 int i; 517 for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) { 518 if (exists_execable(ext_dhcp_clients[i].name)) 519 return execute(ext_dhcp_clients[i].stopcmd, ifd, exec); 520 } 521 bb_error_msg("no dhcp clients found, using static interface shutdown"); 522 return static_down(ifd, exec); 523 #elif ENABLE_APP_UDHCPC 524 return execute("kill " 525 "`cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec); 526 #else 527 return 0; /* no dhcp support */ 528 #endif 529 } 530 531 static int manual_up_down(struct interface_defn_t *ifd, execfn *exec) 532 { 533 return 1; 500 534 } 501 535 502 536 static int bootp_up(struct interface_defn_t *ifd, execfn *exec) 503 537 { 504 return ( execute("bootpc [[--bootfile %bootfile%]] --dev %iface%"505 "[[--server %server%]] [[--hwaddr %hwaddr%]]"506 "--returniffail --serverbcast", ifd, exec));538 return execute("bootpc[[ --bootfile %bootfile%]] --dev %iface%" 539 "[[ --server %server%]][[ --hwaddr %hwaddr%]]" 540 " --returniffail --serverbcast", ifd, exec); 507 541 } 508 542 509 543 static int ppp_up(struct interface_defn_t *ifd, execfn *exec) 510 544 { 511 return ( execute("pon [[%provider%]]", ifd, exec));545 return execute("pon[[ %provider%]]", ifd, exec); 512 546 } 513 547 514 548 static int ppp_down(struct interface_defn_t *ifd, execfn *exec) 515 549 { 516 return ( execute("poff [[%provider%]]", ifd, exec));550 return execute("poff[[ %provider%]]", ifd, exec); 517 551 } 518 552 519 553 static int wvdial_up(struct interface_defn_t *ifd, execfn *exec) 520 554 { 521 return ( execute("/sbin/start-stop-daemon --start -x /usr/bin/wvdial "522 "-p /var/run/wvdial.%iface% -b -m -- [[ %provider% ]]", ifd, exec));555 return execute("start-stop-daemon --start -x wvdial " 556 "-p /var/run/wvdial.%iface% -b -m --[[ %provider%]]", ifd, exec); 523 557 } 524 558 525 559 static int wvdial_down(struct interface_defn_t *ifd, execfn *exec) 526 560 { 527 return ( execute("/sbin/start-stop-daemon --stop -x /usr/bin/wvdial "528 "-p /var/run/wvdial.%iface% -s 2", ifd, exec));529 } 530 531 static struct method_t methods[] =532 { 561 return execute("start-stop-daemon --stop -x wvdial " 562 "-p /var/run/wvdial.%iface% -s 2", ifd, exec); 563 } 564 565 static const struct method_t methods[] = { 566 { "manual", manual_up_down, manual_up_down, }, 533 567 { "wvdial", wvdial_up, wvdial_down, }, 534 568 { "ppp", ppp_up, ppp_down, }, … … 539 573 }; 540 574 541 static struct address_family_t addr_inet = 542 { 575 static const struct address_family_t addr_inet = { 543 576 "inet", 544 sizeof(methods) / sizeof(struct method_t),577 ARRAY_SIZE(methods), 545 578 methods 546 579 }; 547 580 548 #endif /* if def CONFIG_FEATURE_IFUPDOWN_IPV4 */581 #endif /* if ENABLE_FEATURE_IFUPDOWN_IPV4 */ 549 582 550 583 static char *next_word(char **buf) … … 553 586 char *word; 554 587 555 if ( (buf == NULL) || (*buf == NULL) || (**buf == '\0')) {588 if (!buf || !*buf || !**buf) { 556 589 return NULL; 557 590 } 558 591 559 592 /* Skip over leading whitespace */ 560 word = *buf; 561 while (isspace(*word)) { 562 ++word; 563 } 593 word = skip_whitespace(*buf); 564 594 565 595 /* Skip over comments */ 566 596 if (*word == '#') { 567 return (NULL);597 return NULL; 568 598 } 569 599 … … 571 601 length = strcspn(word, " \t\n"); 572 602 if (length == 0) { 573 return (NULL);603 return NULL; 574 604 } 575 605 *buf = word + length; … … 583 613 } 584 614 585 static struct address_family_t *get_address_family(struct address_family_t *af[], char *name)615 static const struct address_family_t *get_address_family(const struct address_family_t *const af[], char *name) 586 616 { 587 617 int i; 618 619 if (!name) 620 return NULL; 588 621 589 622 for (i = 0; af[i]; i++) { … … 595 628 } 596 629 597 static struct method_t *get_method(struct address_family_t *af, char *name)630 static const struct method_t *get_method(const struct address_family_t *af, char *name) 598 631 { 599 632 int i; 633 634 if (!name) 635 return NULL; 600 636 601 637 for (i = 0; i < af->n_methods; i++) { … … 604 640 } 605 641 } 606 return (NULL);642 return NULL; 607 643 } 608 644 609 645 static const llist_t *find_list_string(const llist_t *list, const char *string) 610 646 { 647 if (string == NULL) 648 return NULL; 649 611 650 while (list) { 612 651 if (strcmp(list->data, string) == 0) { 613 return (list);652 return list; 614 653 } 615 654 list = list->link; 616 655 } 617 return (NULL);656 return NULL; 618 657 } 619 658 620 659 static struct interfaces_file_t *read_interfaces(const char *filename) 621 660 { 622 #if def CONFIG_FEATURE_IFUPDOWN_MAPPING661 #if ENABLE_FEATURE_IFUPDOWN_MAPPING 623 662 struct mapping_defn_t *currmap = NULL; 624 663 #endif … … 633 672 defn = xzalloc(sizeof(struct interfaces_file_t)); 634 673 635 f = bb_xfopen(filename, "r");636 637 while ((buf = bb_get_chomped_line_from_file(f)) != NULL) {674 f = xfopen(filename, "r"); 675 676 while ((buf = xmalloc_getline(f)) != NULL) { 638 677 char *buf_ptr = buf; 639 678 … … 645 684 646 685 if (strcmp(firstword, "mapping") == 0) { 647 #if def CONFIG_FEATURE_IFUPDOWN_MAPPING686 #if ENABLE_FEATURE_IFUPDOWN_MAPPING 648 687 currmap = xzalloc(sizeof(struct mapping_defn_t)); 649 688 … … 654 693 } 655 694 656 currmap->match[currmap->n_matches++] = bb_xstrdup(firstword);695 currmap->match[currmap->n_matches++] = xstrdup(firstword); 657 696 } 658 697 currmap->max_mappings = 0; … … 672 711 currently_processing = MAPPING; 673 712 } else if (strcmp(firstword, "iface") == 0) { 674 { 675 char *iface_name; 676 char *address_family_name; 677 char *method_name; 678 struct address_family_t *addr_fams[] = { 679 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV4 680 &addr_inet, 681 #endif 682 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV6 683 &addr_inet6, 684 #endif 685 NULL 686 }; 687 688 currif = xzalloc(sizeof(struct interface_defn_t)); 689 iface_name = next_word(&buf_ptr); 690 address_family_name = next_word(&buf_ptr); 691 method_name = next_word(&buf_ptr); 692 693 if (buf_ptr == NULL) { 694 bb_error_msg("too few parameters for line \"%s\"", buf); 713 static const struct address_family_t *const addr_fams[] = { 714 #if ENABLE_FEATURE_IFUPDOWN_IPV4 715 &addr_inet, 716 #endif 717 #if ENABLE_FEATURE_IFUPDOWN_IPV6 718 &addr_inet6, 719 #endif 720 NULL 721 }; 722 723 char *iface_name; 724 char *address_family_name; 725 char *method_name; 726 llist_t *iface_list; 727 728 currif = xzalloc(sizeof(struct interface_defn_t)); 729 iface_name = next_word(&buf_ptr); 730 address_family_name = next_word(&buf_ptr); 731 method_name = next_word(&buf_ptr); 732 733 if (buf_ptr == NULL) { 734 bb_error_msg("too few parameters for line \"%s\"", buf); 735 return NULL; 736 } 737 738 /* ship any trailing whitespace */ 739 buf_ptr = skip_whitespace(buf_ptr); 740 741 if (buf_ptr[0] != '\0') { 742 bb_error_msg("too many parameters \"%s\"", buf); 743 return NULL; 744 } 745 746 currif->iface = xstrdup(iface_name); 747 748 currif->address_family = get_address_family(addr_fams, address_family_name); 749 if (!currif->address_family) { 750 bb_error_msg("unknown address type \"%s\"", address_family_name); 751 return NULL; 752 } 753 754 currif->method = get_method(currif->address_family, method_name); 755 if (!currif->method) { 756 bb_error_msg("unknown method \"%s\"", method_name); 757 return NULL; 758 } 759 760 for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) { 761 struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data; 762 if ((strcmp(tmp->iface, currif->iface) == 0) && 763 (tmp->address_family == currif->address_family)) { 764 bb_error_msg("duplicate interface \"%s\"", tmp->iface); 695 765 return NULL; 696 766 } 697 698 /* ship any trailing whitespace */ 699 while (isspace(*buf_ptr)) { 700 ++buf_ptr; 701 } 702 703 if (buf_ptr[0] != '\0') { 704 bb_error_msg("too many parameters \"%s\"", buf); 705 return NULL; 706 } 707 708 currif->iface = bb_xstrdup(iface_name); 709 710 currif->address_family = get_address_family(addr_fams, address_family_name); 711 if (!currif->address_family) { 712 bb_error_msg("unknown address type \"%s\"", address_family_name); 713 return NULL; 714 } 715 716 currif->method = get_method(currif->address_family, method_name); 717 if (!currif->method) { 718 bb_error_msg("unknown method \"%s\"", method_name); 719 return NULL; 720 } 721 722 723 { 724 llist_t *iface_list; 725 for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) { 726 struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data; 727 if ((strcmp(tmp->iface, currif->iface) == 0) && 728 (tmp->address_family == currif->address_family)) { 729 bb_error_msg("duplicate interface \"%s\"", tmp->iface); 730 return NULL; 731 } 732 } 733 734 llist_add_to_end(&(defn->ifaces), (char*)currif); 735 } 736 debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name); 737 } 767 } 768 llist_add_to_end(&(defn->ifaces), (char*)currif); 769 770 debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name); 738 771 currently_processing = IFACE; 739 772 } else if (strcmp(firstword, "auto") == 0) { … … 746 779 747 780 /* Add the interface to the list */ 748 llist_add_to_end(&(defn->autointerfaces), bb_xstrdup(firstword));781 llist_add_to_end(&(defn->autointerfaces), xstrdup(firstword)); 749 782 debug_noise("\nauto %s\n", firstword); 750 783 } … … 752 785 } else { 753 786 switch (currently_processing) { 754 case IFACE: 755 { 756 int i; 757 758 if (strlen(buf_ptr) == 0) { 759 bb_error_msg("option with empty value \"%s\"", buf); 760 return NULL; 761 } 762 763 if (strcmp(firstword, "up") != 0 764 && strcmp(firstword, "down") != 0 765 && strcmp(firstword, "pre-up") != 0 766 && strcmp(firstword, "post-down") != 0) { 767 for (i = 0; i < currif->n_options; i++) { 768 if (strcmp(currif->option[i].name, firstword) == 0) { 769 bb_error_msg("duplicate option \"%s\"", buf); 770 return NULL; 771 } 787 case IFACE: 788 { 789 int i; 790 791 if (strlen(buf_ptr) == 0) { 792 bb_error_msg("option with empty value \"%s\"", buf); 793 return NULL; 794 } 795 796 if (strcmp(firstword, "up") != 0 797 && strcmp(firstword, "down") != 0 798 && strcmp(firstword, "pre-up") != 0 799 && strcmp(firstword, "post-down") != 0) { 800 for (i = 0; i < currif->n_options; i++) { 801 if (strcmp(currif->option[i].name, firstword) == 0) { 802 bb_error_msg("duplicate option \"%s\"", buf); 803 return NULL; 772 804 } 773 805 } 774 806 } 775 if (currif->n_options >= currif->max_options) { 776 struct variable_t *opt; 777 778 currif->max_options = currif->max_options + 10; 779 opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options); 780 currif->option = opt; 807 } 808 if (currif->n_options >= currif->max_options) { 809 struct variable_t *opt; 810 811 currif->max_options = currif->max_options + 10; 812 opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options); 813 currif->option = opt; 814 } 815 currif->option[currif->n_options].name = xstrdup(firstword); 816 currif->option[currif->n_options].value = xstrdup(buf_ptr); 817 if (!currif->option[currif->n_options].name) { 818 perror(filename); 819 return NULL; 820 } 821 if (!currif->option[currif->n_options].value) { 822 perror(filename); 823 return NULL; 824 } 825 debug_noise("\t%s=%s\n", currif->option[currif->n_options].name, 826 currif->option[currif->n_options].value); 827 currif->n_options++; 828 break; 829 case MAPPING: 830 #if ENABLE_FEATURE_IFUPDOWN_MAPPING 831 if (strcmp(firstword, "script") == 0) { 832 if (currmap->script != NULL) { 833 bb_error_msg("duplicate script in mapping \"%s\"", buf); 834 return NULL; 835 } else { 836 currmap->script = xstrdup(next_word(&buf_ptr)); 781 837 } 782 currif->option[currif->n_options].name = bb_xstrdup(firstword); 783 currif->option[currif->n_options].value = bb_xstrdup(buf_ptr); 784 if (!currif->option[currif->n_options].name) { 785 perror(filename); 786 return NULL; 838 } else if (strcmp(firstword, "map") == 0) { 839 if (currmap->max_mappings == currmap->n_mappings) { 840 currmap->max_mappings = currmap->max_mappings * 2 + 1; 841 currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings); 787 842 } 788 if (!currif->option[currif->n_options].value) { 789 perror(filename); 790 return NULL; 791 } 792 debug_noise("\t%s=%s\n", currif->option[currif->n_options].name, 793 currif->option[currif->n_options].value); 794 currif->n_options++; 795 break; 796 case MAPPING: 797 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING 798 if (strcmp(firstword, "script") == 0) { 799 if (currmap->script != NULL) { 800 bb_error_msg("duplicate script in mapping \"%s\"", buf); 801 return NULL; 802 } else { 803 currmap->script = bb_xstrdup(next_word(&buf_ptr)); 804 } 805 } else if (strcmp(firstword, "map") == 0) { 806 if (currmap->max_mappings == currmap->n_mappings) { 807 currmap->max_mappings = currmap->max_mappings * 2 + 1; 808 currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings); 809 } 810 currmap->mapping[currmap->n_mappings] = bb_xstrdup(next_word(&buf_ptr)); 811 currmap->n_mappings++; 812 } else { 813 bb_error_msg("misplaced option \"%s\"", buf); 814 return NULL; 815 } 816 #endif 817 break; 818 case NONE: 819 default: 843 currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&buf_ptr)); 844 currmap->n_mappings++; 845 } else { 820 846 bb_error_msg("misplaced option \"%s\"", buf); 821 847 return NULL; 848 } 849 #endif 850 break; 851 case NONE: 852 default: 853 bb_error_msg("misplaced option \"%s\"", buf); 854 return NULL; 822 855 } 823 856 } … … 825 858 } 826 859 if (ferror(f) != 0) { 827 bb_perror_msg_and_die("%s", filename); 860 /* ferror does NOT set errno! */ 861 bb_error_msg_and_die("%s: I/O error", filename); 828 862 } 829 863 fclose(f); … … 832 866 } 833 867 834 static char *setlocalenv(c har *format, const char *name, const char *value)868 static char *setlocalenv(const char *format, const char *name, const char *value) 835 869 { 836 870 char *result; … … 838 872 char *there; 839 873 840 result = bb_xasprintf(format, name, value);874 result = xasprintf(format, name, value); 841 875 842 876 for (here = there = result; *there != '=' && *there; there++) { … … 863 897 char **ppch; 864 898 865 if ( __myenviron != NULL) {866 for (ppch = __myenviron; *ppch; ppch++) {899 if (my_environ != NULL) { 900 for (ppch = my_environ; *ppch; ppch++) { 867 901 free(*ppch); 868 902 *ppch = NULL; 869 903 } 870 free( __myenviron);871 } 872 __myenviron = xzalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ ));873 environend = __myenviron;904 free(my_environ); 905 } 906 my_environ = xzalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ )); 907 environend = my_environ; 874 908 875 909 for (i = 0; i < iface->n_options; i++) { 876 910 if (strcmp(iface->option[i].name, "up") == 0 877 || strcmp(iface->option[i].name, "down") == 0 878 || strcmp(iface->option[i].name, "pre-up") == 0 879 || strcmp(iface->option[i].name, "post-down") == 0) { 911 || strcmp(iface->option[i].name, "down") == 0 912 || strcmp(iface->option[i].name, "pre-up") == 0 913 || strcmp(iface->option[i].name, "post-down") == 0 914 ) { 880 915 continue; 881 916 } … … 887 922 *(environend++) = setlocalenv("%s=%s", "METHOD", iface->method->name); 888 923 *(environend++) = setlocalenv("%s=%s", "MODE", mode); 889 *(environend++) = setlocalenv("%s=%s", "PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");924 *(environend++) = setlocalenv("%s=%s", "PATH", startup_PATH); 890 925 } 891 926 892 927 static int doit(char *str) 893 928 { 894 if ( verbose || no_act) {895 p rintf("%s\n",str);896 } 897 if (! no_act) {929 if (option_mask32 & (OPT_no_act|OPT_verbose)) { 930 puts(str); 931 } 932 if (!(option_mask32 & OPT_no_act)) { 898 933 pid_t child; 899 934 int status; 900 935 901 936 fflush(NULL); 902 switch (child = fork()) { 903 case -1: /* failure */ 904 return 0; 905 case 0: /* child */ 906 execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, __myenviron); 907 exit(127); 937 child = fork(); 938 switch (child) { 939 case -1: /* failure */ 940 return 0; 941 case 0: /* child */ 942 execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ); 943 exit(127); 908 944 } 909 945 waitpid(child, &status, 0); … … 912 948 } 913 949 } 914 return (1);950 return 1; 915 951 } 916 952 … … 927 963 } 928 964 929 buf = bb_xasprintf("run-parts /etc/network/if-%s.d", opt); 930 if (doit(buf) != 1) { 931 return 0; 932 } 933 return 1; 934 } 935 936 static int check(char *str) { 965 buf = xasprintf("run-parts /etc/network/if-%s.d", opt); 966 /* heh, we don't bother free'ing it */ 967 return doit(buf); 968 } 969 970 static int check(char *str) 971 { 937 972 return str != NULL; 938 973 } … … 940 975 static int iface_up(struct interface_defn_t *iface) 941 976 { 942 if (!iface->method->up(iface, check)) return -1;977 if (!iface->method->up(iface, check)) return -1; 943 978 set_environ(iface, "start"); 944 979 if (!execute_all(iface, "pre-up")) return 0; … … 958 993 } 959 994 960 #if def CONFIG_FEATURE_IFUPDOWN_MAPPING995 #if ENABLE_FEATURE_IFUPDOWN_MAPPING 961 996 static int popen2(FILE **in, FILE **out, char *command, ...) 962 997 { … … 987 1022 fflush(NULL); 988 1023 switch (pid = fork()) { 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 execvp(command, argv);1003 1004 1005 1006 1007 1008 1009 1024 case -1: /* failure */ 1025 close(infd[0]); 1026 close(infd[1]); 1027 close(outfd[0]); 1028 close(outfd[1]); 1029 return 0; 1030 case 0: /* child */ 1031 dup2(infd[0], 0); 1032 dup2(outfd[1], 1); 1033 close(infd[0]); 1034 close(infd[1]); 1035 close(outfd[0]); 1036 close(outfd[1]); 1037 BB_EXECVP(command, argv); 1038 exit(127); 1039 default: /* parent */ 1040 *in = fdopen(infd[1], "w"); 1041 *out = fdopen(outfd[0], "r"); 1042 close(infd[0]); 1043 close(outfd[1]); 1044 return pid; 1010 1045 } 1011 1046 /* unreached */ … … 1018 1053 pid_t pid; 1019 1054 1020 char *logical = bb_xstrdup(physical);1055 char *logical = xstrdup(physical); 1021 1056 1022 1057 /* Run the mapping script. */ … … 1038 1073 * grab a line of output and use that as the name of the 1039 1074 * logical interface. */ 1040 char *new_logical = (char *)xmalloc(MAX_INTERFACE_LENGTH);1075 char *new_logical = xmalloc(MAX_INTERFACE_LENGTH); 1041 1076 1042 1077 if (fgets(new_logical, MAX_INTERFACE_LENGTH, out)) { … … 1062 1097 return logical; 1063 1098 } 1064 #endif /* CONFIG_FEATURE_IFUPDOWN_MAPPING */1099 #endif /* FEATURE_IFUPDOWN_MAPPING */ 1065 1100 1066 1101 static llist_t *find_iface_state(llist_t *state_list, const char *iface) … … 1070 1105 1071 1106 while (search) { 1072 if ((strncmp(search->data, iface, iface_len) == 0) &&1073 1074 return (search);1107 if ((strncmp(search->data, iface, iface_len) == 0) 1108 && (search->data[iface_len] == '=')) { 1109 return search; 1075 1110 } 1076 1111 search = search->link; 1077 1112 } 1078 return(NULL); 1079 } 1080 1113 return NULL; 1114 } 1115 1116 /* read the previous state from the state file */ 1117 static llist_t *read_iface_state(void) 1118 { 1119 llist_t *state_list = NULL; 1120 FILE *state_fp = fopen(CONFIG_IFUPDOWN_IFSTATE_PATH, "r"); 1121 1122 if (state_fp) { 1123 char *start, *end_ptr; 1124 while ((start = xmalloc_fgets(state_fp)) != NULL) { 1125 /* We should only need to check for a single character */ 1126 end_ptr = start + strcspn(start, " \t\n"); 1127 *end_ptr = '\0'; 1128 llist_add_to(&state_list, start); 1129 } 1130 fclose(state_fp); 1131 } 1132 return state_list; 1133 } 1134 1135 1136 int ifupdown_main(int argc, char **argv); 1081 1137 int ifupdown_main(int argc, char **argv) 1082 1138 { 1083 int (*cmds) 1139 int (*cmds)(struct interface_defn_t *) = NULL; 1084 1140 struct interfaces_file_t *defn; 1085 llist_t *state_list = NULL;1086 1141 llist_t *target_list = NULL; 1087 1142 const char *interfaces = "/etc/network/interfaces"; 1088 const char *statefile = "/var/run/ifstate"; 1089 1090 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING 1091 int run_mappings = 1; 1092 #endif 1093 int do_all = 0; 1094 int force = 0; 1095 int any_failures = 0; 1096 int i; 1097 1098 if (bb_applet_name[2] == 'u') { 1143 bool any_failures = 0; 1144 1145 cmds = iface_down; 1146 if (applet_name[2] == 'u') { 1099 1147 /* ifup command */ 1100 1148 cmds = iface_up; 1149 } 1150 1151 getopt32(argv, OPTION_STR, &interfaces); 1152 if (argc - optind > 0) { 1153 if (DO_ALL) bb_show_usage(); 1101 1154 } else { 1102 /* ifdown command */ 1103 cmds = iface_down; 1104 } 1105 1106 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING 1107 while ((i = getopt(argc, argv, "i:hvnamf")) != -1) 1108 #else 1109 while ((i = getopt(argc, argv, "i:hvnaf")) != -1) 1110 #endif 1111 { 1112 switch (i) { 1113 case 'i': /* interfaces */ 1114 interfaces = optarg; 1115 break; 1116 case 'v': /* verbose */ 1117 verbose = 1; 1118 break; 1119 case 'a': /* all */ 1120 do_all = 1; 1121 break; 1122 case 'n': /* no-act */ 1123 no_act = 1; 1124 break; 1125 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING 1126 case 'm': /* no-mappings */ 1127 run_mappings = 0; 1128 break; 1129 #endif 1130 case 'f': /* force */ 1131 force = 1; 1132 break; 1133 default: 1134 bb_show_usage(); 1135 break; 1136 } 1137 } 1138 1139 if (argc - optind > 0) { 1140 if (do_all) { 1141 bb_show_usage(); 1142 } 1143 } else { 1144 if (!do_all) { 1145 bb_show_usage(); 1146 } 1155 if (!DO_ALL) bb_show_usage(); 1147 1156 } 1148 1157 … … 1152 1161 1153 1162 if (!defn) { 1154 exit(EXIT_FAILURE); 1155 } 1163 return EXIT_FAILURE; 1164 } 1165 1166 startup_PATH = getenv("PATH"); 1167 if (!startup_PATH) startup_PATH = ""; 1156 1168 1157 1169 /* Create a list of interfaces to work on */ 1158 if (do_all) { 1159 if (cmds == iface_up) { 1160 target_list = defn->autointerfaces; 1161 } else { 1162 /* iface_down */ 1163 const llist_t *list = state_list; 1164 while (list) { 1165 llist_add_to_end(&target_list, bb_xstrdup(list->data)); 1166 list = list->link; 1167 } 1168 target_list = defn->autointerfaces; 1169 } 1170 if (DO_ALL) { 1171 target_list = defn->autointerfaces; 1170 1172 } else { 1171 1173 llist_add_to_end(&target_list, argv[optind]); 1172 1174 } 1173 1174 1175 1175 1176 /* Update the interfaces */ … … 1180 1181 char *liface; 1181 1182 char *pch; 1182 intokay = 0;1183 intcmds_ret;1184 1185 iface = bb_xstrdup(target_list->data);1183 bool okay = 0; 1184 unsigned cmds_ret; 1185 1186 iface = xstrdup(target_list->data); 1186 1187 target_list = target_list->link; 1187 1188 … … 1189 1190 if (pch) { 1190 1191 *pch = '\0'; 1191 liface = bb_xstrdup(pch + 1);1192 liface = xstrdup(pch + 1); 1192 1193 } else { 1193 liface = bb_xstrdup(iface); 1194 } 1195 1196 if (!force) { 1194 liface = xstrdup(iface); 1195 } 1196 1197 if (!FORCE) { 1198 llist_t *state_list = read_iface_state(); 1197 1199 const llist_t *iface_state = find_iface_state(state_list, iface); 1198 1200 … … 1205 1207 } else { 1206 1208 /* ifdown */ 1207 if ( iface_state) {1209 if (!iface_state) { 1208 1210 bb_error_msg("interface %s not configured", iface); 1209 1211 continue; 1210 1212 } 1211 1213 } 1212 } 1213 1214 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING 1215 if ((cmds == iface_up) && run_mappings) { 1214 llist_free(state_list, free); 1215 } 1216 1217 #if ENABLE_FEATURE_IFUPDOWN_MAPPING 1218 if ((cmds == iface_up) && !NO_MAPPINGS) { 1216 1219 struct mapping_defn_t *currmap; 1217 1220 1218 1221 for (currmap = defn->mappings; currmap; currmap = currmap->next) { 1219 1222 int i; 1220 1223 for (i = 0; i < currmap->n_matches; i++) { 1221 1224 if (fnmatch(currmap->match[i], liface, 0) != 0) 1222 1225 continue; 1223 if ( verbose) {1226 if (VERBOSE) { 1224 1227 printf("Running mapping script %s on %s\n", currmap->script, liface); 1225 1228 } … … 1230 1233 } 1231 1234 #endif 1232 1233 1235 1234 1236 iface_list = defn->ifaces; … … 1246 1248 cmds_ret = cmds(currif); 1247 1249 if (cmds_ret == -1) { 1248 bb_error_msg(" Don't seem to have all the variables for %s/%s.",1250 bb_error_msg("don't seem to have all the variables for %s/%s", 1249 1251 liface, currif->address_family->name); 1250 any_failures += 1;1252 any_failures = 1; 1251 1253 } else if (cmds_ret == 0) { 1252 any_failures += 1;1254 any_failures = 1; 1253 1255 } 1254 1256 … … 1257 1259 iface_list = iface_list->link; 1258 1260 } 1259 if (verbose) { 1260 printf("\n"); 1261 } 1262 1263 if (!okay && !force) { 1264 bb_error_msg("Ignoring unknown interface %s", liface); 1265 any_failures += 1; 1266 } else { 1261 if (VERBOSE) { 1262 puts(""); 1263 } 1264 1265 if (!okay && !FORCE) { 1266 bb_error_msg("ignoring unknown interface %s", liface); 1267 any_failures = 1; 1268 } else if (!NO_ACT) { 1269 /* update the state file */ 1270 FILE *state_fp; 1271 llist_t *state; 1272 llist_t *state_list = read_iface_state(); 1267 1273 llist_t *iface_state = find_iface_state(state_list, iface); 1268 1274 1269 1275 if (cmds == iface_up) { 1270 char * newiface = bb_xasprintf("%s=%s", iface, liface);1276 char * const newiface = xasprintf("%s=%s", iface, liface); 1271 1277 if (iface_state == NULL) { 1272 1278 llist_add_to_end(&state_list, newiface); … … 1276 1282 } 1277 1283 } else { 1278 /* Remove an interface from the linked list */ 1284 /* Remove an interface from state_list */ 1285 llist_unlink(&state_list, iface_state); 1279 1286 free(llist_pop(&iface_state)); 1280 1287 } 1281 } 1282 } 1283 1284 /* Actually write the new state */ 1285 if (!no_act) { 1286 FILE *state_fp = NULL; 1287 1288 state_fp = bb_xfopen(statefile, "w"); 1289 while (state_list) { 1290 if (state_list->data) { 1291 fputs(state_list->data, state_fp); 1292 fputc('\n', state_fp); 1293 } 1294 state_list = state_list->link; 1295 } 1296 fclose(state_fp); 1297 } 1298 1299 if (any_failures) 1300 return 1; 1301 return 0; 1302 } 1288 1289 /* Actually write the new state */ 1290 state_fp = xfopen(CONFIG_IFUPDOWN_IFSTATE_PATH, "w"); 1291 state = state_list; 1292 while (state) { 1293 if (state->data) { 1294 fprintf(state_fp, "%s\n", state->data); 1295 } 1296 state = state->link; 1297 } 1298 fclose(state_fp); 1299 llist_free(state_list, free); 1300 } 1301 } 1302 1303 return any_failures; 1304 }
Note:
See TracChangeset
for help on using the changeset viewer.