diff options
| -rw-r--r-- | toys/pending/ifconfig.c | 294 | 
1 files changed, 129 insertions, 165 deletions
diff --git a/toys/pending/ifconfig.c b/toys/pending/ifconfig.c index cffeaf58..2864e3f9 100644 --- a/toys/pending/ifconfig.c +++ b/toys/pending/ifconfig.c @@ -10,7 +10,7 @@ USE_IFCONFIG(NEWTOY(ifconfig, "?a", TOYFLAG_BIN))  config IFCONFIG    bool "ifconfig" -  default n +  default y    help      usage: ifconfig [-a] interface [address] @@ -37,6 +37,8 @@ config IFCONFIG  GLOBALS(    void *if_list; + +  int sockfd;  )  typedef struct sockaddr_with_len { @@ -71,44 +73,6 @@ struct ifreq_inet6 {    int ifrinet6_ifindex;  }; -#ifndef SIOCSKEEPALIVE -# define SIOCSKEEPALIVE  (SIOCDEVPRIVATE)        /* Set keepalive timeout in sec */ -# define SIOCGKEEPALIVE  (SIOCDEVPRIVATE+1)        /* Get keepalive timeout */ -#endif - -#ifndef SIOCSOUTFILL -# define SIOCSOUTFILL  (SIOCDEVPRIVATE+2)        /* Set outfill timeout */ -# define SIOCGOUTFILL  (SIOCDEVPRIVATE+3)        /* Get outfill timeout */ -#endif - -/* - * used to extract the address info from the given host ip - * and update the swl param accordingly. - */ -static int get_socket_stream(char *host, sa_family_t af, sockaddr_with_len **swl) -{ -  struct addrinfo hints, *result, *rp; -  int status; - -  memset(&hints, 0 , sizeof(struct addrinfo)); -  hints.ai_family = af; -  hints.ai_socktype = SOCK_STREAM; - -  status = getaddrinfo(host, NULL, &hints, &result); -  if (status) error_exit("bad address '%s' : %s", host, gai_strerror(status)); - -  for (rp = result; rp; rp = rp->ai_next) { -    if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) { -      *swl = xmalloc(sizeof(struct sockaddr_with_len)); -      (*swl)->socklen = rp->ai_addrlen; -      memcpy(&((*swl)->sock_u.sock), rp->ai_addr, rp->ai_addrlen); -      break; -    } -  } -  freeaddrinfo(result); -  return rp ? 0 : -1; -} -  /*   * use to get the socket address with the given host ip.   */ @@ -116,6 +80,8 @@ sockaddr_with_len *get_sockaddr(char *host, int port, sa_family_t af)  {    sockaddr_with_len *swl = NULL;    in_port_t port_num = htons(port); +  struct addrinfo hints, *result, *rp; +  int status;    char *s;    if (!strncmp(host, "local:", 6)) { @@ -142,7 +108,7 @@ sockaddr_with_len *get_sockaddr(char *host, int port, sa_family_t af)      }    } else {      s = strrchr(host, ':'); -    if (s && strchr(host, ':') != s) s = 0; +    if (strchr(host, ':') != s) s = 0;    }    if (s++) { @@ -152,7 +118,24 @@ sockaddr_with_len *get_sockaddr(char *host, int port, sa_family_t af)      port = p;    } -  if (get_socket_stream(host, af, &swl)) return NULL; +  memset(&hints, 0 , sizeof(struct addrinfo)); +  hints.ai_family = af; +  hints.ai_socktype = SOCK_STREAM; + +  status = getaddrinfo(host, NULL, &hints, &result); +  if (status) error_exit("bad address '%s' : %s", host, gai_strerror(status)); + +  for (rp = result; rp; rp = rp->ai_next) { +    if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) { +      swl = xmalloc(sizeof(struct sockaddr_with_len)); +      swl->socklen = rp->ai_addrlen; +      memcpy(&swl->sock_u.sock, rp->ai_addr, rp->ai_addrlen); +      break; +    } +  } +  freeaddrinfo(result); +  if (!rp) error_exit("bad host name"); +    if(swl->sock_u.sock.sa_family == AF_INET)      swl->sock_u.sock_in.sin_port = port_num; @@ -195,56 +178,22 @@ char *address_to_name(struct sockaddr *sock)    } else return NULL;  } -static void set_ipv6_addr(int sockfd, struct ifreq *ifre, char *ipv6_addr, int request) +static void set_address(char *host_name, struct ifreq *ifre, int request)  { -  char *prefix; -  int plen = 0; +  struct sockaddr_in *sock_in = (struct sockaddr_in *)&ifre->ifr_addr;    sockaddr_with_len *swl = NULL; -  prefix = strchr(ipv6_addr, '/'); -  if(prefix) { -    plen = get_int_value(prefix + 1, 0, 128); -    *prefix = '\0'; -  } -  swl = get_sockaddr(ipv6_addr, 0, AF_INET6); -  if(!swl) error_exit("error in resolving host name"); -    int sockfd6; -    struct ifreq_inet6 ifre6; -    memcpy((char *) &ifre6.ifrinte6_addr, -        (char *) &(swl->sock_u.sock_in6.sin6_addr), -        sizeof(struct in6_addr)); -    //Create a channel to the NET kernel. -    sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0); -    xioctl(sockfd6, SIOGIFINDEX, ifre); -    ifre6.ifrinet6_ifindex = ifre->ifr_ifindex; -    ifre6.ifrinet6_prefixlen = plen; - -    xioctl(sockfd6, request, &ifre6); -    free(swl); -} - -static void set_address(int sockfd, char *host_name, struct ifreq *ifre, int request) -{ -  struct sockaddr_in sock_in; -  sockaddr_with_len *swl = NULL; -  sock_in.sin_family = AF_INET; -  sock_in.sin_port = 0; +  memset(sock_in, 0, sizeof(struct sockaddr_in)); +  sock_in->sin_family = AF_INET;    //Default 0.0.0.0 -  if(strcmp(host_name, "default") == 0) sock_in.sin_addr.s_addr = INADDR_ANY; +  if(strcmp(host_name, "default") == 0) sock_in->sin_addr.s_addr = INADDR_ANY;    else {      swl = get_sockaddr(host_name, 0, AF_INET); -    if(!swl) error_exit("error in resolving host name"); - -    sock_in.sin_addr = swl->sock_u.sock_in.sin_addr; -  } -  memcpy((char *)&ifre->ifr_addr, (char *) &sock_in, sizeof(struct sockaddr)); -  xioctl(sockfd, request, ifre); - -  if(swl != NULL) { +    sock_in->sin_addr = swl->sock_u.sock_in.sin_addr;      free(swl); -    swl = NULL;    } +  xioctl(TT.sockfd, request, ifre);  }  static void add_iface_to_list(struct if_list *newnode) @@ -268,78 +217,34 @@ static void get_device_info(struct if_list *il)  {    struct ifreq ifre;    char *name = il->name; -  int sokfd;    il->txqueuelen = -1; -  sokfd = xsocket(AF_INET, SOCK_DGRAM, 0);    xstrncpy(ifre.ifr_name, name, IFNAMSIZ); -  if (ioctl(sokfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name); +  if (ioctl(TT.sockfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name);    il->flags = ifre.ifr_flags; -  if (ioctl(sokfd, SIOCGIFHWADDR, &ifre) >= 0) +  if (ioctl(TT.sockfd, SIOCGIFHWADDR, &ifre) >= 0)      memcpy(il->hwaddr.sa_data, ifre.ifr_hwaddr.sa_data, sizeof(il->hwaddr.sa_data));    il->hw_type = ifre.ifr_hwaddr.sa_family; -  if (ioctl(sokfd, SIOCGIFMETRIC, &ifre) >= 0) il->metric = ifre.ifr_metric; -  if (ioctl(sokfd, SIOCGIFMTU, &ifre) >= 0) il->mtu = ifre.ifr_mtu; -  if (ioctl(sokfd, SIOCGIFMAP, &ifre) == 0) il->map = ifre.ifr_map; -  if (ioctl(sokfd, SIOCGIFTXQLEN, &ifre) >= 0) il->txqueuelen = ifre.ifr_qlen; +  if (ioctl(TT.sockfd, SIOCGIFMETRIC, &ifre) >= 0) +    il->metric = ifre.ifr_metric; +  if (ioctl(TT.sockfd, SIOCGIFMTU, &ifre) >= 0) il->mtu = ifre.ifr_mtu; +  if (ioctl(TT.sockfd, SIOCGIFMAP, &ifre) == 0) il->map = ifre.ifr_map; +  if (ioctl(TT.sockfd, SIOCGIFTXQLEN, &ifre) >= 0) +    il->txqueuelen = ifre.ifr_qlen;    // If an address is assigned record that.    ifre.ifr_addr.sa_family = AF_INET; -  if (!ioctl(sokfd, SIOCGIFADDR, &ifre)) il->addr = ifre.ifr_addr; -  if (ioctl(sokfd, SIOCGIFDSTADDR, &ifre) >= 0) il->dstaddr = ifre.ifr_dstaddr; -  if (ioctl(sokfd, SIOCGIFBRDADDR, &ifre) >= 0) il->broadaddr = ifre.ifr_broadaddr; -  if (ioctl(sokfd, SIOCGIFNETMASK, &ifre) >= 0) il->netmask = ifre.ifr_netmask; -  close(sokfd); -} - -static void print_ip6_addr(struct if_list *il) -{ -  char iface_name[IFNAMSIZ] = {0,}; -  int plen, scope; -  FILE *fp; - -  if(!(fp = fopen("/proc/net/if_net6", "r"))) return; - -  while(fgets(toybuf, sizeof(toybuf), fp)) { -    int nitems = 0; -    char ipv6_addr[40] = {0,}; -    nitems = sscanf(toybuf, "%32s %*08x %02x %02x %*02x %15s\n", -        ipv6_addr+7, &plen, &scope, iface_name); -    if(nitems != 4) { -      if((nitems < 0) && feof(fp)) break; -      perror_exit("sscanf"); -    } -    if(strcmp(il->name, iface_name) == 0) { -      int i = 0; -      struct sockaddr_in6 sock_in6; -      int len = sizeof(ipv6_addr) / (sizeof ipv6_addr[0]); -      char *ptr = ipv6_addr+7; - -      while((i < len-2) && (*ptr)) { -        ipv6_addr[i++] = *ptr++; -        //put ':' after 4th bit -        if(!((i+1) % 5)) ipv6_addr[i++] = ':'; -      } -      ipv6_addr[i+1] = '\0'; -      if(inet_pton(AF_INET6, ipv6_addr, (struct sockaddr *) &sock_in6.sin6_addr) > 0) { -        sock_in6.sin6_family = AF_INET6; -        if(inet_ntop(AF_INET6, &sock_in6.sin6_addr, toybuf, BUFSIZ)) { -          char *names[] = {"Global","Host","Link","Site","Compat"}, -               *name = "Unknown"; -          int j; - -          for (j=0; j < sizeof(names)/sizeof(*names); j++) -            if (scope == (!!j)<<(j+3)) name = names[j]; -          xprintf("%10cinet6 addr: %s/%d Scope: %s\n", ' ', toybuf, plen, name); -        } -      } -    } -  } -  fclose(fp); +  if (!ioctl(TT.sockfd, SIOCGIFADDR, &ifre)) il->addr = ifre.ifr_addr; +  if (ioctl(TT.sockfd, SIOCGIFDSTADDR, &ifre) >= 0) +    il->dstaddr = ifre.ifr_dstaddr; +  if (ioctl(TT.sockfd, SIOCGIFBRDADDR, &ifre) >= 0) +    il->broadaddr = ifre.ifr_broadaddr; +  if (ioctl(TT.sockfd, SIOCGIFNETMASK, &ifre) >= 0) +    il->netmask = ifre.ifr_netmask;  }  static void display_ifconfig(struct if_list *il) @@ -354,6 +259,7 @@ static void display_ifconfig(struct if_list *il)    };    int i;    char *p; +  FILE *fp;    for (i=0; i < (sizeof(types)/sizeof(*types))-1; i++)      if (il->hw_type == types[i].type) break; @@ -394,7 +300,49 @@ static void display_ifconfig(struct if_list *il)      xputc('\n');    } -  print_ip6_addr(il); +  fp = fopen("/proc/net/if_net6", "r"); +  if (fp) { +    char iface_name[IFNAMSIZ] = {0,}; +    int plen, scope; + +    while(fgets(toybuf, sizeof(toybuf), fp)) { +      int nitems = 0; +      char ipv6_addr[40] = {0,}; +      nitems = sscanf(toybuf, "%32s %*08x %02x %02x %*02x %15s\n", +          ipv6_addr+7, &plen, &scope, iface_name); +      if(nitems != 4) { +        if((nitems < 0) && feof(fp)) break; +        perror_exit("sscanf"); +      } +      if(strcmp(il->name, iface_name) == 0) { +        int i = 0; +        struct sockaddr_in6 sock_in6; +        int len = sizeof(ipv6_addr) / (sizeof ipv6_addr[0]); +        char *ptr = ipv6_addr+7; + +        while((i < len-2) && (*ptr)) { +          ipv6_addr[i++] = *ptr++; +          //put ':' after 4th bit +          if(!((i+1) % 5)) ipv6_addr[i++] = ':'; +        } +        ipv6_addr[i+1] = '\0'; +        if(inet_pton(AF_INET6, ipv6_addr, (struct sockaddr *) &sock_in6.sin6_addr) > 0) { +          sock_in6.sin6_family = AF_INET6; +          if(inet_ntop(AF_INET6, &sock_in6.sin6_addr, toybuf, BUFSIZ)) { +            char *names[] = {"Global","Host","Link","Site","Compat"}, +                 *name = "Unknown"; +            int j; + +            for (j=0; j < sizeof(names)/sizeof(*names); j++) +              if (scope == (!!j)<<(j+3)) name = names[j]; +            xprintf("%10cinet6 addr: %s/%d Scope: %s\n", ' ', toybuf, plen, name); +          } +        } +      } +    } +    fclose(fp); +  } +    xprintf("%10c", ' ');    if (il->flags) { @@ -449,16 +397,14 @@ static void readconf(void)  {    struct ifconf ifcon;    struct ifreq *ifre; -  int num, sokfd; - -  sokfd = xsocket(AF_INET, SOCK_DGRAM, 0); +  int num;    // Loop until buffer's big enough    ifcon.ifc_buf = NULL;    for (num = 30;;num += 10) {      ifcon.ifc_len = sizeof(struct ifreq)*num;      ifcon.ifc_buf = xrealloc(ifcon.ifc_buf, ifcon.ifc_len); -    xioctl(sokfd, SIOCGIFCONF, &ifcon); +    xioctl(TT.sockfd, SIOCGIFCONF, &ifcon);      if (ifcon.ifc_len != sizeof(struct ifreq)*num) break;    } @@ -478,7 +424,6 @@ static void readconf(void)      }    } -  close(sokfd);    free(ifcon.ifc_buf);  } @@ -507,7 +452,6 @@ static void show_iface(char *iface_name)      add_iface_to_list(il);      il->non_virtual_iface = 1; -    errno = 0;      get_device_info(il);    }    fclose(fp); @@ -523,7 +467,6 @@ static void show_iface(char *iface_name)      if(!il) {        il = xzalloc(sizeof(struct if_list));        xstrncpy(il->name, iface_name, IFNAMSIZ); -      errno = 0;        get_device_info(il);        display_ifconfig(il);        free(il); @@ -545,10 +488,11 @@ void ifconfig_main(void)  {    char **argv = toys.optargs;    struct ifreq ifre; -  int i, sockfd = 0; +  int i;    if(*argv && (strcmp(*argv, "--help") == 0)) show_help(); +  TT.sockfd = xsocket(AF_INET, SOCK_DGRAM, 0);    if(toys.optc < 2) {      show_iface(*argv);      return; @@ -557,7 +501,6 @@ void ifconfig_main(void)    // Open interface    memset(&ifre, 0, sizeof(struct ifreq));    xstrncpy(ifre.ifr_name, *argv, IFNAMSIZ); -  sockfd = xsocket(AF_INET, SOCK_DGRAM, 0);    // Perform operations on interface    while(*++argv) { @@ -578,8 +521,8 @@ void ifconfig_main(void)        {"netmask", 0, SIOCSIFNETMASK},        {"dstaddr", 0, SIOCSIFDSTADDR},        {"mtu", IFREQ_OFFSZ(ifr_mtu), SIOCSIFMTU}, -      {"keepalive", IFREQ_OFFSZ(ifr_data), SIOCSKEEPALIVE}, -      {"outfill", IFREQ_OFFSZ(ifr_data), SIOCSOUTFILL}, +      {"keepalive", IFREQ_OFFSZ(ifr_data), SIOCDEVPRIVATE}, // SIOCSKEEPALIVE +      {"outfill", IFREQ_OFFSZ(ifr_data), SIOCDEVPRIVATE+2}, // SIOCSOUTFILL        {"metric", IFREQ_OFFSZ(ifr_metric), SIOCSIFMETRIC},        {"txqueuelen", IFREQ_OFFSZ(ifr_qlen), SIOCSIFTXQLEN},        {"mem_start", IFREQ_OFFSZ(ifr_map.mem_start), SIOCSIFMAP}, @@ -608,22 +551,22 @@ void ifconfig_main(void)            if (on < 0) {              long l = strtoul(*argv, 0, 0); -            if (off == SIOCSIFMAP) xioctl(sockfd, SIOCGIFMAP, &ifre); +            if (off == SIOCSIFMAP) xioctl(TT.sockfd, SIOCGIFMAP, &ifre);              on = -on;              poke((on>>16) + (char *)&ifre, l, on&15); -            xioctl(sockfd, off, &ifre); +            xioctl(TT.sockfd, off, &ifre);              break; -          } else set_address(sockfd, *argv, &ifre, off); +          } else set_address(*argv, &ifre, off);          }          off = 0;        }        // Set flags        if (on || off) { -        xioctl(sockfd, SIOCGIFFLAGS, &ifre); +        xioctl(TT.sockfd, SIOCGIFFLAGS, &ifre);          ifre.ifr_flags &= ~(rev ? on : off);          ifre.ifr_flags |= (rev ? off : on); -        xioctl(sockfd, SIOCSIFFLAGS, &ifre); +        xioctl(TT.sockfd, SIOCSIFFLAGS, &ifre);        }        break; @@ -662,20 +605,41 @@ void ifconfig_main(void)          if ((p-ptr) != count || *hw_addr)            error_exit("bad hw-addr '%s'", hw_addr ? hw_addr : ""); -        xioctl(sockfd, SIOCSIFHWADDR, &ifre); +        xioctl(TT.sockfd, SIOCSIFHWADDR, &ifre); + +      // Add/remove ipv6 address to interface        } else if (!strcmp(*argv, "add") || !strcmp(*argv, "del")) { +        sockaddr_with_len *swl = NULL; +        struct ifreq_inet6 ifre6; +        char *prefix; +        int plen = 0, sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0); +          if (!argv[1]) show_help(); -        set_ipv6_addr(sockfd, &ifre, argv[1], -          **argv=='a' ? SIOCSIFADDR : SIOCDIFADDR); + +        prefix = strchr(argv[1], '/'); +        if (prefix) { +          plen = get_int_value(prefix + 1, 0, 128); +          *prefix = 0; +        } +        swl = get_sockaddr(argv[1], 0, AF_INET6); +        ifre6.ifrinte6_addr = swl->sock_u.sock_in6.sin6_addr; +        xioctl(sockfd6, SIOCGIFINDEX, &ifre); +        ifre6.ifrinet6_ifindex = ifre.ifr_ifindex; +        ifre6.ifrinet6_prefixlen = plen; +        xioctl(sockfd6, **argv=='a' ? SIOCSIFADDR : SIOCDIFADDR, &ifre6); + +        free(swl); +        close(sockfd6); +          argv++;        } else if (isdigit(**argv) || !strcmp(*argv, "default")) { -          set_address(sockfd, *argv, &ifre, SIOCSIFADDR); +          set_address(*argv, &ifre, SIOCSIFADDR);            //if the interface name is not an alias; set the flag and continue.            if(!strchr(ifre.ifr_name, ':')) { -            xioctl(sockfd, SIOCGIFFLAGS, &ifre); +            xioctl(TT.sockfd, SIOCGIFFLAGS, &ifre);              ifre.ifr_flags |= IFF_UP|IFF_RUNNING; -            xioctl(sockfd, SIOCSIFFLAGS, &ifre); +            xioctl(TT.sockfd, SIOCSIFFLAGS, &ifre);            }      } else { @@ -684,5 +648,5 @@ void ifconfig_main(void)        error_exit("bad argument '%s'", *argv);      }    } -  if (CFG_TOYBOX_FREE && sockfd > 0) close(sockfd); +  close(TT.sockfd);  }  | 
