enum entry for unarchive to be used by tar
[oweals/busybox.git] / ifconfig.c
index f342ceedefa54033d27789b210971dea6ece0d10..7f3978a4a61917810e688927db7a3f695bca2d9c 100644 (file)
@@ -15,7 +15,7 @@
  * Foundation;  either  version 2 of the License, or  (at
  * your option) any later version.
  *
- * $Id: ifconfig.c,v 1.5 2001/03/08 22:57:00 mjn3 Exp $
+ * $Id: ifconfig.c,v 1.11 2001/07/07 05:19:52 andersen Exp $
  *
  */
 
@@ -26,7 +26,7 @@
  * converting to a table-driven approach.  Added several (optional)
  * args missing from initial port.
  *
- * Still missing:  media.
+ * Still missing:  media, tunnel.
  */
 
 #include <stdio.h>
 #define A_NETMASK        0x20  /* Set if netmask (check for multiple sets). */
 #define A_SET_AFTER      0x40  /* Set a flag at the end. */
 #define A_COLON_CHK      0x80  /* Is this needed?  See below. */
+#define A_HOSTNAME      0x100  /* Set if it is ip addr. */
+#define A_BROADCAST     0x200  /* Set if it is broadcast addr. */
 
 /*
  * These defines are for dealing with the A_CAST_TYPE field.
 #define ARG_IRQ          (A_ARG_REQ | A_MAP_UCHAR)
 #define ARG_DSTADDR      (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE)
 #define ARG_NETMASK      (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_NETMASK)
-#define ARG_BROADCAST    (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
+#define ARG_BROADCAST    (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_BROADCAST)
 #define ARG_HW           (A_ARG_REQ | A_CAST_HOST_COPY_IN_ETHER)
 #define ARG_POINTOPOINT  (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
 #define ARG_KEEPALIVE    (A_ARG_REQ | A_CAST_CHAR_PTR)
 #define ARG_OUTFILL      (A_ARG_REQ | A_CAST_CHAR_PTR)
-#define ARG_HOSTNAME     (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_COLON_CHK)
+#define ARG_HOSTNAME     (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_COLON_CHK | A_HOSTNAME)
 
 
 /*
@@ -160,7 +162,7 @@ struct arg1opt {
 struct options {
        const char *name;
        const unsigned char flags;
-       const unsigned char arg_flags;
+       const unsigned int arg_flags;
        const unsigned short selector;
 };
 
@@ -234,7 +236,8 @@ static int in_ether(char *bufp, struct sockaddr *sap);
 #endif
 
 #ifdef BB_FEATURE_IFCONFIG_STATUS
-extern int display_interfaces(void);
+extern int interface_opt_a;
+extern int display_interfaces(char *ifname);
 #endif
 
 /*
@@ -245,6 +248,7 @@ int ifconfig_main(int argc, char **argv)
 {
        struct ifreq ifr;
        struct sockaddr_in sai;
+       struct sockaddr_in sai_hostname, sai_netmask;
 #ifdef BB_FEATURE_IFCONFIG_HW
        struct sockaddr sa;
 #endif
@@ -255,30 +259,37 @@ int ifconfig_main(int argc, char **argv)
        int selector;
        char *p;
        char host[128];
-       unsigned char mask;
-       unsigned char did_flags;
+       unsigned int mask;
+       unsigned int did_flags;
 
        goterr = 0;
        did_flags = 0;
 
-       if(argc < 2) {
+       /* skip argv[0] */
+       ++argv;
+       --argc;
+
+#ifdef BB_FEATURE_IFCONFIG_STATUS
+       if ((argc > 0) && (strcmp(*argv,"-a") == 0)) {
+               interface_opt_a = 1;
+               --argc;
+               ++argv;
+       }
+#endif
+
+       if(argc <= 1) {
 #ifdef BB_FEATURE_IFCONFIG_STATUS
-               return(display_interfaces());
+               return display_interfaces(argc ? *argv : NULL);
 #else
-               show_usage();
+               error_msg_and_die( "ifconfig was not compiled with interface status display support.");
 #endif
        }
 
        /* Create a channel to the NET kernel. */
        if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               perror("socket");
-               exit(1);
+               perror_msg_and_die("socket");
        }
 
-       /* skip argv[0] */
-       argc--;
-       argv++;
-
        /* get interface name */
        safe_strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
 
@@ -291,7 +302,7 @@ int ifconfig_main(int argc, char **argv)
                        mask = M_MASK;          /*    set the appropriate mask. */
                }
                for (op = OptArray ; op->name ; op++) { /* Find table entry. */
-                       if (!strcmp(p,op->name)) { /* If name matches... */
+                       if (strcmp(p,op->name) == 0) { /* If name matches... */
                                if ((mask &= op->flags)) { /* set the mask and go. */
                                    goto FOUND_ARG;;
                                }
@@ -323,7 +334,7 @@ int ifconfig_main(int argc, char **argv)
                                }
                        } else {                        /* got an arg so process it */
                        HOSTNAME:
-                               did_flags |= (mask & A_NETMASK);
+                               did_flags |= (mask & (A_NETMASK|A_HOSTNAME));
                                if (mask & A_CAST_HOST_COPY) {
 #ifdef BB_FEATURE_IFCONFIG_HW
                                        if (mask & A_CAST_RESOLVE) {
@@ -334,11 +345,20 @@ int ifconfig_main(int argc, char **argv)
                                                if (!strcmp(host, "default")) {
                                                        /* Default is special, meaning 0.0.0.0. */
                                                        sai.sin_addr.s_addr = INADDR_ANY;
+                                               } else if ((!strcmp(host, "+")) && (mask & A_BROADCAST) &&
+                                                                (did_flags & (A_NETMASK|A_HOSTNAME))) {
+                                                       /* + is special, meaning broadcast is derived. */
+                                                       sai.sin_addr.s_addr = (~sai_netmask.sin_addr.s_addr) |
+                                                               (sai_hostname.sin_addr.s_addr & sai_netmask.sin_addr.s_addr);
                                                } else if (inet_aton(host, &sai.sin_addr) == 0) {
                                                        /* It's not a dotted quad. */
                                                        ++goterr;
                                                        continue;
                                                }
+                                               if(mask & A_HOSTNAME)
+                                                       sai_hostname = sai;
+                                               if(mask & A_NETMASK)
+                                                       sai_netmask = sai;
                                                p = (char *) &sai;
 #ifdef BB_FEATURE_IFCONFIG_HW
                                        } else { /* A_CAST_HOST_COPY_IN_ETHER */
@@ -464,9 +484,9 @@ in_ether(char *bufp, struct sockaddr *sap)
                        if (c >= '0' && c <= '9') {
                                c -= '0';
                        } else if (c >= 'a' && c <= 'f') {
-                               c -= ('a' + 10);
+                               c -= ('a' - 10);
                        } else if (c >= 'A' && c <= 'F') {
-                               c -= ('A' + 10);
+                               c -= ('A' - 10);
                        } else if (j && (c == ':' || c == 0)) {
                                break;
                        } else {