aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/ifupdown.c87
1 files changed, 50 insertions, 37 deletions
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 8843184bf..e9f0a646c 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -104,31 +104,6 @@ static const char *startup_PATH;
104 104
105#if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6 105#if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6
106 106
107#if ENABLE_FEATURE_IFUPDOWN_IP
108
109static unsigned count_bits(unsigned a)
110{
111 unsigned result;
112 result = (a & 0x55) + ((a >> 1) & 0x55);
113 result = (result & 0x33) + ((result >> 2) & 0x33);
114 return (result & 0x0F) + ((result >> 4) & 0x0F);
115}
116
117static int count_netmask_bits(char *dotted_quad)
118{
119 unsigned result, a, b, c, d;
120 /* Found a netmask... Check if it is dotted quad */
121 if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
122 return -1;
123 // FIXME: will be confused by e.g. 255.0.255.0
124 result = count_bits(a);
125 result += count_bits(b);
126 result += count_bits(c);
127 result += count_bits(d);
128 return (int)result;
129}
130#endif
131
132static void addstr(char **bufp, const char *str, size_t str_length) 107static void addstr(char **bufp, const char *str, size_t str_length)
133{ 108{
134 /* xasprintf trick will be smaller, but we are often 109 /* xasprintf trick will be smaller, but we are often
@@ -177,6 +152,39 @@ static char *get_var(const char *id, size_t idlen, struct interface_defn_t *ifd)
177 return NULL; 152 return NULL;
178} 153}
179 154
155#if ENABLE_FEATURE_IFUPDOWN_IP
156static int count_netmask_bits(const char *dotted_quad)
157{
158// int result;
159// unsigned a, b, c, d;
160// /* Found a netmask... Check if it is dotted quad */
161// if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
162// return -1;
163// if ((a|b|c|d) >> 8)
164// return -1; /* one of numbers is >= 256 */
165// d |= (a << 24) | (b << 16) | (c << 8); /* IP */
166// d = ~d; /* 11110000 -> 00001111 */
167
168 /* Shorter version */
169 int result;
170 struct in_addr ip;
171 unsigned d;
172
173 if (inet_aton(dotted_quad, &ip) == 0)
174 return -1; /* malformed dotted IP */
175 d = ntohl(ip.s_addr); /* IP in host order */
176 d = ~d; /* 11110000 -> 00001111 */
177 if (d & (d+1)) /* check that it is in 00001111 form */
178 return -1; /* no it is not */
179 result = 32;
180 while (d) {
181 d >>= 1;
182 result--;
183 }
184 return result;
185}
186#endif
187
180static char *parse(const char *command, struct interface_defn_t *ifd) 188static char *parse(const char *command, struct interface_defn_t *ifd)
181{ 189{
182 size_t old_pos[MAX_OPT_DEPTH] = { 0 }; 190 size_t old_pos[MAX_OPT_DEPTH] = { 0 };
@@ -246,11 +254,14 @@ static char *parse(const char *command, struct interface_defn_t *ifd)
246 if (strncmp(command, "bnmask", 6) == 0) { 254 if (strncmp(command, "bnmask", 6) == 0) {
247 unsigned res; 255 unsigned res;
248 varvalue = get_var("netmask", 7, ifd); 256 varvalue = get_var("netmask", 7, ifd);
249 if (varvalue && (res = count_netmask_bits(varvalue)) > 0) { 257 if (varvalue) {
250 const char *argument = utoa(res); 258 res = count_netmask_bits(varvalue);
251 addstr(&result, argument, strlen(argument)); 259 if (res > 0) {
252 command = nextpercent + 1; 260 const char *argument = utoa(res);
253 break; 261 addstr(&result, argument, strlen(argument));
262 command = nextpercent + 1;
263 break;
264 }
254 } 265 }
255 } 266 }
256#endif 267#endif
@@ -463,7 +474,7 @@ static const struct dhcp_client_t ext_dhcp_clients[] = {
463 }, 474 },
464 { "udhcpc", 475 { "udhcpc",
465 "udhcpc -R -n -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]", 476 "udhcpc -R -n -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]",
466 "kill -TERM `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", 477 "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null",
467 }, 478 },
468}; 479};
469#endif /* ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCPC */ 480#endif /* ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCPC */
@@ -498,10 +509,10 @@ static int dhcp_down(struct interface_defn_t *ifd, execfn *exec)
498 bb_error_msg("no dhcp clients found, using static interface shutdown"); 509 bb_error_msg("no dhcp clients found, using static interface shutdown");
499 return static_down(ifd, exec); 510 return static_down(ifd, exec);
500#elif ENABLE_APP_UDHCPC 511#elif ENABLE_APP_UDHCPC
501 return execute("kill -TERM " 512 return execute("kill "
502 "`cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec); 513 "`cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec);
503#else 514#else
504 return 0; /* no support for dhcp */ 515 return 0; /* no dhcp support */
505#endif 516#endif
506} 517}
507 518
@@ -834,7 +845,8 @@ static struct interfaces_file_t *read_interfaces(const char *filename)
834 free(buf); 845 free(buf);
835 } 846 }
836 if (ferror(f) != 0) { 847 if (ferror(f) != 0) {
837 bb_perror_msg_and_die("%s", filename); 848 /* ferror does NOT set errno! */
849 bb_error_msg_and_die("%s: I/O error", filename);
838 } 850 }
839 fclose(f); 851 fclose(f);
840 852
@@ -884,9 +896,10 @@ static void set_environ(struct interface_defn_t *iface, const char *mode)
884 896
885 for (i = 0; i < iface->n_options; i++) { 897 for (i = 0; i < iface->n_options; i++) {
886 if (strcmp(iface->option[i].name, "up") == 0 898 if (strcmp(iface->option[i].name, "up") == 0
887 || strcmp(iface->option[i].name, "down") == 0 899 || strcmp(iface->option[i].name, "down") == 0
888 || strcmp(iface->option[i].name, "pre-up") == 0 900 || strcmp(iface->option[i].name, "pre-up") == 0
889 || strcmp(iface->option[i].name, "post-down") == 0) { 901 || strcmp(iface->option[i].name, "post-down") == 0
902 ) {
890 continue; 903 continue;
891 } 904 }
892 *(environend++) = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value); 905 *(environend++) = setlocalenv("IF_%s=%s", iface->option[i].name, iface->option[i].value);