aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/ifconfig.c143
1 files changed, 85 insertions, 58 deletions
diff --git a/networking/ifconfig.c b/networking/ifconfig.c
index d0ee4c3a5..4c1185899 100644
--- a/networking/ifconfig.c
+++ b/networking/ifconfig.c
@@ -15,7 +15,7 @@
15 * Foundation; either version 2 of the License, or (at 15 * Foundation; either version 2 of the License, or (at
16 * your option) any later version. 16 * your option) any later version.
17 * 17 *
18 * $Id: ifconfig.c,v 1.20 2002/11/26 09:02:05 bug1 Exp $ 18 * $Id: ifconfig.c,v 1.21 2002/12/27 17:42:01 mjn3 Exp $
19 * 19 *
20 */ 20 */
21 21
@@ -119,6 +119,13 @@ struct in6_ifreq {
119#define A_NETMASK 0x20 /* Set if netmask (check for multiple sets). */ 119#define A_NETMASK 0x20 /* Set if netmask (check for multiple sets). */
120#define A_SET_AFTER 0x40 /* Set a flag at the end. */ 120#define A_SET_AFTER 0x40 /* Set a flag at the end. */
121#define A_COLON_CHK 0x80 /* Is this needed? See below. */ 121#define A_COLON_CHK 0x80 /* Is this needed? See below. */
122#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
123#define A_HOSTNAME 0x100 /* Set if it is ip addr. */
124#define A_BROADCAST 0x200 /* Set if it is broadcast addr. */
125#else
126#define A_HOSTNAME 0
127#define A_BROADCAST 0
128#endif
122 129
123/* 130/*
124 * These defines are for dealing with the A_CAST_TYPE field. 131 * These defines are for dealing with the A_CAST_TYPE field.
@@ -148,12 +155,12 @@ struct in6_ifreq {
148#define ARG_IRQ (A_ARG_REQ | A_MAP_UCHAR) 155#define ARG_IRQ (A_ARG_REQ | A_MAP_UCHAR)
149#define ARG_DSTADDR (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE) 156#define ARG_DSTADDR (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE)
150#define ARG_NETMASK (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_NETMASK) 157#define ARG_NETMASK (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_NETMASK)
151#define ARG_BROADCAST (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER) 158#define ARG_BROADCAST (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_BROADCAST)
152#define ARG_HW (A_ARG_REQ | A_CAST_HOST_COPY_IN_ETHER) 159#define ARG_HW (A_ARG_REQ | A_CAST_HOST_COPY_IN_ETHER)
153#define ARG_POINTOPOINT (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER) 160#define ARG_POINTOPOINT (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
154#define ARG_KEEPALIVE (A_ARG_REQ | A_CAST_CHAR_PTR) 161#define ARG_KEEPALIVE (A_ARG_REQ | A_CAST_CHAR_PTR)
155#define ARG_OUTFILL (A_ARG_REQ | A_CAST_CHAR_PTR) 162#define ARG_OUTFILL (A_ARG_REQ | A_CAST_CHAR_PTR)
156#define ARG_HOSTNAME (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_COLON_CHK) 163#define ARG_HOSTNAME (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_COLON_CHK | A_HOSTNAME)
157#define ARG_ADD_DEL (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER) 164#define ARG_ADD_DEL (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
158 165
159 166
@@ -169,78 +176,83 @@ struct arg1opt {
169 176
170struct options { 177struct options {
171 const char *name; 178 const char *name;
179#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
180 const unsigned int flags:6;
181 const unsigned int arg_flags:10;
182#else
172 const unsigned char flags; 183 const unsigned char flags;
173 const unsigned char arg_flags; 184 const unsigned char arg_flags;
185#endif
174 const unsigned short selector; 186 const unsigned short selector;
175}; 187};
176 188
177#define ifreq_offsetof(x) offsetof(struct ifreq, x) 189#define ifreq_offsetof(x) offsetof(struct ifreq, x)
178 190
179static const struct arg1opt Arg1Opt[] = { 191static const struct arg1opt Arg1Opt[] = {
180 {"SIOCSIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric)}, 192 {"SIOCSIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric)},
181 {"SIOCSIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu)}, 193 {"SIOCSIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu)},
182 {"SIOCSIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen)}, 194 {"SIOCSIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen)},
183 {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, 195 {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
184 {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)}, 196 {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)},
185 {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)}, 197 {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)},
186#ifdef CONFIG_FEATURE_IFCONFIG_HW 198#ifdef CONFIG_FEATURE_IFCONFIG_HW
187 {"SIOCSIFHWADDR", SIOCSIFHWADDR, ifreq_offsetof(ifr_hwaddr)}, 199 {"SIOCSIFHWADDR", SIOCSIFHWADDR, ifreq_offsetof(ifr_hwaddr)},
188#endif 200#endif
189 {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)}, 201 {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
190#ifdef SIOCSKEEPALIVE 202#ifdef SIOCSKEEPALIVE
191 {"SIOCSKEEPALIVE", SIOCSKEEPALIVE, ifreq_offsetof(ifr_data)}, 203 {"SIOCSKEEPALIVE", SIOCSKEEPALIVE, ifreq_offsetof(ifr_data)},
192#endif 204#endif
193#ifdef SIOCSOUTFILL 205#ifdef SIOCSOUTFILL
194 {"SIOCSOUTFILL", SIOCSOUTFILL, ifreq_offsetof(ifr_data)}, 206 {"SIOCSOUTFILL", SIOCSOUTFILL, ifreq_offsetof(ifr_data)},
195#endif 207#endif
196#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ 208#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
197 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.mem_start)}, 209 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.mem_start)},
198 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr)}, 210 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr)},
199 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq)}, 211 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq)},
200#endif 212#endif
201 /* Last entry if for unmatched (possibly hostname) arg. */ 213 /* Last entry if for unmatched (possibly hostname) arg. */
202#ifdef CONFIG_FEATURE_IPV6 214#ifdef CONFIG_FEATURE_IPV6
203 {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */ 215 {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */
204 {"SIOCDIFADDR", SIOCDIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */ 216 {"SIOCDIFADDR", SIOCDIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */
205#endif 217#endif
206 {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)}, 218 {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)},
207}; 219};
208 220
209static const struct options OptArray[] = { 221static const struct options OptArray[] = {
210 {"metric", N_ARG, ARG_METRIC, 0}, 222 {"metric", N_ARG, ARG_METRIC, 0},
211 {"mtu", N_ARG, ARG_MTU, 0}, 223 {"mtu", N_ARG, ARG_MTU, 0},
212 {"txqueuelen", N_ARG, ARG_TXQUEUELEN, 0}, 224 {"txqueuelen", N_ARG, ARG_TXQUEUELEN, 0},
213 {"dstaddr", N_ARG, ARG_DSTADDR, 0}, 225 {"dstaddr", N_ARG, ARG_DSTADDR, 0},
214 {"netmask", N_ARG, ARG_NETMASK, 0}, 226 {"netmask", N_ARG, ARG_NETMASK, 0},
215 {"broadcast", N_ARG | M_CLR, ARG_BROADCAST, IFF_BROADCAST}, 227 {"broadcast", N_ARG | M_CLR, ARG_BROADCAST, IFF_BROADCAST},
216#ifdef CONFIG_FEATURE_IFCONFIG_HW 228#ifdef CONFIG_FEATURE_IFCONFIG_HW
217 {"hw", N_ARG, ARG_HW, 0}, 229 {"hw", N_ARG, ARG_HW, 0},
218#endif 230#endif
219 {"pointopoint", N_ARG | M_CLR, ARG_POINTOPOINT, IFF_POINTOPOINT}, 231 {"pointopoint", N_ARG | M_CLR, ARG_POINTOPOINT, IFF_POINTOPOINT},
220#ifdef SIOCSKEEPALIVE 232#ifdef SIOCSKEEPALIVE
221 {"keepalive", N_ARG, ARG_KEEPALIVE, 0}, 233 {"keepalive", N_ARG, ARG_KEEPALIVE, 0},
222#endif 234#endif
223#ifdef SIOCSOUTFILL 235#ifdef SIOCSOUTFILL
224 {"outfill", N_ARG, ARG_OUTFILL, 0}, 236 {"outfill", N_ARG, ARG_OUTFILL, 0},
225#endif 237#endif
226#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ 238#ifdef CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
227 {"mem_start", N_ARG, ARG_MEM_START, 0}, 239 {"mem_start", N_ARG, ARG_MEM_START, 0},
228 {"io_addr", N_ARG, ARG_IO_ADDR, 0}, 240 {"io_addr", N_ARG, ARG_IO_ADDR, 0},
229 {"irq", N_ARG, ARG_IRQ, 0}, 241 {"irq", N_ARG, ARG_IRQ, 0},
230#endif 242#endif
231#ifdef CONFIG_FEATURE_IPV6 243#ifdef CONFIG_FEATURE_IPV6
232 {"add", N_ARG, ARG_ADD_DEL, 0}, 244 {"add", N_ARG, ARG_ADD_DEL, 0},
233 {"del", N_ARG, ARG_ADD_DEL, 0}, 245 {"del", N_ARG, ARG_ADD_DEL, 0},
234#endif 246#endif
235 {"arp", N_CLR | M_SET, 0, IFF_NOARP}, 247 {"arp", N_CLR | M_SET, 0, IFF_NOARP},
236 {"trailers", N_CLR | M_SET, 0, IFF_NOTRAILERS}, 248 {"trailers", N_CLR | M_SET, 0, IFF_NOTRAILERS},
237 {"promisc", N_SET | M_CLR, 0, IFF_PROMISC}, 249 {"promisc", N_SET | M_CLR, 0, IFF_PROMISC},
238 {"multicast", N_SET | M_CLR, 0, IFF_MULTICAST}, 250 {"multicast", N_SET | M_CLR, 0, IFF_MULTICAST},
239 {"allmulti", N_SET | M_CLR, 0, IFF_ALLMULTI}, 251 {"allmulti", N_SET | M_CLR, 0, IFF_ALLMULTI},
240 {"dynamic", N_SET | M_CLR, 0, IFF_DYNAMIC}, 252 {"dynamic", N_SET | M_CLR, 0, IFF_DYNAMIC},
241 {"up", N_SET, 0, (IFF_UP | IFF_RUNNING)}, 253 {"up", N_SET, 0, (IFF_UP | IFF_RUNNING)},
242 {"down", N_CLR, 0, IFF_UP}, 254 {"down", N_CLR, 0, IFF_UP},
243 {NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING)} 255 {NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING)}
244}; 256};
245 257
246/* 258/*
@@ -264,7 +276,6 @@ int ifconfig_main(int argc, char **argv)
264{ 276{
265 struct ifreq ifr; 277 struct ifreq ifr;
266 struct sockaddr_in sai; 278 struct sockaddr_in sai;
267
268#ifdef CONFIG_FEATURE_IPV6 279#ifdef CONFIG_FEATURE_IPV6
269 struct sockaddr_in6 sai6; 280 struct sockaddr_in6 sai6;
270#endif 281#endif
@@ -276,10 +287,16 @@ int ifconfig_main(int argc, char **argv)
276 int sockfd; /* socket fd we use to manipulate stuff with */ 287 int sockfd; /* socket fd we use to manipulate stuff with */
277 int goterr; 288 int goterr;
278 int selector; 289 int selector;
279 char *p; 290#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
280 char host[128]; 291 unsigned int mask;
292 unsigned int did_flags;
293 in_addr_t sai_hostname, sai_netmask;
294#else
281 unsigned char mask; 295 unsigned char mask;
282 unsigned char did_flags; 296 unsigned char did_flags;
297#endif
298 char *p;
299 char host[128];
283 300
284 goterr = 0; 301 goterr = 0;
285 did_flags = 0; 302 did_flags = 0;
@@ -289,7 +306,7 @@ int ifconfig_main(int argc, char **argv)
289 --argc; 306 --argc;
290 307
291#ifdef CONFIG_FEATURE_IFCONFIG_STATUS 308#ifdef CONFIG_FEATURE_IFCONFIG_STATUS
292 if ((argc > 0) && (strcmp(*argv, "-a") == 0)) { 309 if ((argc > 0) && (((*argv)[0] == '-') && ((*argv)[1] == 'a') && !(*argv)[2])) {
293 interface_opt_a = 1; 310 interface_opt_a = 1;
294 --argc; 311 --argc;
295 ++argv; 312 ++argv;
@@ -354,7 +371,7 @@ int ifconfig_main(int argc, char **argv)
354 } 371 }
355 } else { /* got an arg so process it */ 372 } else { /* got an arg so process it */
356 HOSTNAME: 373 HOSTNAME:
357 did_flags |= (mask & A_NETMASK); 374 did_flags |= (mask & (A_NETMASK|A_HOSTNAME));
358 if (mask & A_CAST_HOST_COPY) { 375 if (mask & A_CAST_HOST_COPY) {
359#ifdef CONFIG_FEATURE_IFCONFIG_HW 376#ifdef CONFIG_FEATURE_IFCONFIG_HW
360 if (mask & A_CAST_RESOLVE) { 377 if (mask & A_CAST_RESOLVE) {
@@ -381,10 +398,14 @@ int ifconfig_main(int argc, char **argv)
381 if (!strcmp(host, bb_INET_default)) { 398 if (!strcmp(host, bb_INET_default)) {
382 /* Default is special, meaning 0.0.0.0. */ 399 /* Default is special, meaning 0.0.0.0. */
383 sai.sin_addr.s_addr = INADDR_ANY; 400 sai.sin_addr.s_addr = INADDR_ANY;
401#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
402 } else if (((host[0] == '+') && !host[1]) && (mask & A_BROADCAST) &&
403 (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)) {
404 /* + is special, meaning broadcast is derived. */
405 sai.sin_addr.s_addr = (~sai_netmask) | (sai_hostname & sai_netmask);
406#endif
384#ifdef CONFIG_FEATURE_IPV6 407#ifdef CONFIG_FEATURE_IPV6
385 } else 408 } else if (inet_pton(AF_INET6, host, &sai6.sin6_addr) > 0) {
386 if (inet_pton(AF_INET6, host, &sai6.sin6_addr) >
387 0) {
388 int sockfd6; 409 int sockfd6;
389 struct in6_ifreq ifr6; 410 struct in6_ifreq ifr6;
390 411
@@ -393,8 +414,7 @@ int ifconfig_main(int argc, char **argv)
393 sizeof(struct in6_addr)); 414 sizeof(struct in6_addr));
394 415
395 /* Create a channel to the NET kernel. */ 416 /* Create a channel to the NET kernel. */
396 if ((sockfd6 = 417 if ((sockfd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
397 socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
398 perror_msg_and_die("socket6"); 418 perror_msg_and_die("socket6");
399 } 419 }
400 if (ioctl(sockfd6, SIOGIFINDEX, &ifr) < 0) { 420 if (ioctl(sockfd6, SIOGIFINDEX, &ifr) < 0) {
@@ -415,6 +435,14 @@ int ifconfig_main(int argc, char **argv)
415 ++goterr; 435 ++goterr;
416 continue; 436 continue;
417 } 437 }
438#ifdef CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS
439 if (mask & A_HOSTNAME) {
440 sai_hostname = sai.sin_addr.s_addr;
441 }
442 if (mask & A_NETMASK) {
443 sai_netmask = sai.sin_addr.s_addr;
444 }
445#endif
418 p = (char *) &sai; 446 p = (char *) &sai;
419#ifdef CONFIG_FEATURE_IFCONFIG_HW 447#ifdef CONFIG_FEATURE_IFCONFIG_HW
420 } else { /* A_CAST_HOST_COPY_IN_ETHER */ 448 } else { /* A_CAST_HOST_COPY_IN_ETHER */
@@ -528,22 +556,21 @@ static int in_ether(char *bufp, struct sockaddr *sap)
528 sap->sa_family = ARPHRD_ETHER; 556 sap->sa_family = ARPHRD_ETHER;
529 ptr = sap->sa_data; 557 ptr = sap->sa_data;
530 558
531 for (i = 0; i < ETH_ALEN; i++) { 559 i = 0;
532 val = 0; 560 do {
561 j = val = 0;
533 562
534 /* We might get a semicolon here - not required. */ 563 /* We might get a semicolon here - not required. */
535 if (i && (*bufp == ':')) { 564 if (i && (*bufp == ':')) {
536 bufp++; 565 bufp++;
537 } 566 }
538 567
539 for (j = 0; j < 2; j++) { 568 do {
540 c = *bufp; 569 c = *bufp;
541 if (c >= '0' && c <= '9') { 570 if (((unsigned char)(c - '0')) <= 9) {
542 c -= '0'; 571 c -= '0';
543 } else if (c >= 'a' && c <= 'f') { 572 } else if (((unsigned char)((c|0x20) - 'a')) <= 5) {
544 c -= ('a' - 10); 573 c = (c|0x20) - ('a'-10);
545 } else if (c >= 'A' && c <= 'F') {
546 c -= ('A' - 10);
547 } else if (j && (c == ':' || c == 0)) { 574 } else if (j && (c == ':' || c == 0)) {
548 break; 575 break;
549 } else { 576 } else {
@@ -552,9 +579,9 @@ static int in_ether(char *bufp, struct sockaddr *sap)
552 ++bufp; 579 ++bufp;
553 val <<= 4; 580 val <<= 4;
554 val += c; 581 val += c;
555 } 582 } while (++j < 2);
556 *ptr++ = val; 583 *ptr++ = val;
557 } 584 } while (++i < ETH_ALEN);
558 585
559 return (int) (*bufp); /* Error if we don't end at end of string. */ 586 return (int) (*bufp); /* Error if we don't end at end of string. */
560} 587}