changeset 1193:f6f56a002d9a draft

Add /prefix netmask support to ifconfig, ala "ifconfig eth0 192.168.1.42/28"
author Rob Landley <rob@landley.net>
date Tue, 04 Feb 2014 06:13:13 -0600
parents 3df4da929f8a
children 855b706d10dc
files toys/other/ifconfig.c
diffstat 1 files changed, 24 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/toys/other/ifconfig.c	Sun Feb 02 15:02:15 2014 -0600
+++ b/toys/other/ifconfig.c	Tue Feb 04 06:13:13 2014 -0600
@@ -64,16 +64,20 @@
 };
 
 // Convert hostname to binary address for AF_INET or AF_INET6
-void get_addrinfo(char *host, sa_family_t af, void *addr)
+// return /prefix (or range max if none)
+int get_addrinfo(char *host, sa_family_t af, void *addr)
 {
   struct addrinfo hints, *result, *rp = 0;
   int status, len;
-  char *from;
+  char *from, *slash;
 
   memset(&hints, 0 , sizeof(struct addrinfo));
   hints.ai_family = af;
   hints.ai_socktype = SOCK_STREAM;
 
+  slash = strchr(host, '/');
+  if (slash) *slash = 0;
+
   status = getaddrinfo(host, NULL, &hints, &result);
   if (!status)
     for (rp = result; rp; rp = rp->ai_next)
@@ -89,6 +93,11 @@
   } else len = 4;
   memcpy(addr, from, len);
   freeaddrinfo(result);
+
+  len = -1;
+  if (slash) len = atolx_range(slash+1, 0, (af == AF_INET) ? 128 : 32);
+
+  return len;
 }
 
 static void display_ifconfig(char *name, int always, unsigned long long val[])
@@ -443,21 +452,15 @@
         unsigned prefix;
         int index;
       } ifre6;
-      int plen = 128, fd6 = xsocket(AF_INET6, SOCK_DGRAM, 0);
-      char *prefix;
+      int plen, fd6 = xsocket(AF_INET6, SOCK_DGRAM, 0);
 
       if (!argv[1]) {
         toys.exithelp++;
         error_exit(*argv);
       }
 
-      prefix = strchr(argv[1], '/');
-      if (prefix) {
-        plen = atolx_range(prefix+1, 0, 128);
-        *prefix = 0;
-      }
-
-      get_addrinfo(argv[1], AF_INET6, &ifre6.addr);
+      plen = get_addrinfo(argv[1], AF_INET6, &ifre6.addr);
+      if (plen < 0) plen = 128;
       xioctl(fd6, SIOCGIFINDEX, &ifre);
       ifre6.index = ifre.ifr_ifindex;
       ifre6.prefix = plen;
@@ -491,12 +494,21 @@
             break;
           } else if (t->name || !strchr(ifre.ifr_name, ':')) {
             struct sockaddr_in *si = (struct sockaddr_in *)&ifre.ifr_addr;
+            int mask = -1;
 
             si->sin_family = AF_INET;
 
             if (!strcmp(*argv, "default")) si->sin_addr.s_addr = INADDR_ANY;
-            else get_addrinfo(*argv, AF_INET, &si->sin_addr);
+            else mask = get_addrinfo(*argv, AF_INET, &si->sin_addr);
             xioctl(TT.sockfd, off, &ifre);
+
+            // Handle /netmask
+            if (mask >= 0) {
+              // sin_addr probably isn't unaligned, but just in case...
+              mask = htonl((~0)<<(32-mask));
+              memcpy(&si->sin_addr, &mask, 4);
+              xioctl(TT.sockfd, SIOCSIFNETMASK, &ifre);
+            }
           }
         }
         off = 0;