| /* system/bin/netcfg/netcfg.c | 
 | ** | 
 | ** Copyright 2006, The Android Open Source Project | 
 | ** | 
 | ** Licensed under the Apache License, Version 2.0 (the "License");  | 
 | ** you may not use this file except in compliance with the License.  | 
 | ** You may obtain a copy of the License at  | 
 | ** | 
 | **     http://www.apache.org/licenses/LICENSE-2.0  | 
 | ** | 
 | ** Unless required by applicable law or agreed to in writing, software  | 
 | ** distributed under the License is distributed on an "AS IS" BASIS,  | 
 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
 | ** See the License for the specific language governing permissions and  | 
 | ** limitations under the License. | 
 | */ | 
 |  | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <errno.h> | 
 | #include <dirent.h> | 
 | #include <netinet/ether.h> | 
 | #include <netinet/if_ether.h> | 
 |  | 
 | #include <netutils/ifc.h> | 
 | #include <netutils/dhcp.h> | 
 |  | 
 | static int verbose = 0; | 
 |  | 
 |  | 
 | void die(const char *reason) | 
 | { | 
 |     perror(reason); | 
 |     exit(1); | 
 | } | 
 |  | 
 | const char *ipaddr(in_addr_t addr) | 
 | { | 
 |     struct in_addr in_addr; | 
 |  | 
 |     in_addr.s_addr = addr; | 
 |     return inet_ntoa(in_addr); | 
 | } | 
 |  | 
 | void usage(void) | 
 | { | 
 |     fprintf(stderr,"usage: netcfg [<interface> {dhcp|up|down}]\n"); | 
 |     exit(1); | 
 | } | 
 |  | 
 | int dump_interface(const char *name) | 
 | { | 
 |     unsigned addr, flags; | 
 |     unsigned char hwbuf[ETH_ALEN]; | 
 |     int prefixLength; | 
 |  | 
 |     if(ifc_get_info(name, &addr, &prefixLength, &flags)) { | 
 |         return 0; | 
 |     } | 
 |  | 
 |     printf("%-8s %s  ", name, flags & 1 ? "UP  " : "DOWN"); | 
 |     printf("%40s", ipaddr(addr)); | 
 |     printf("/%-4d", prefixLength); | 
 |     printf("0x%08x ", flags); | 
 |     if (!ifc_get_hwaddr(name, hwbuf)) { | 
 |         int i; | 
 |         for(i=0; i < (ETH_ALEN-1); i++) | 
 |             printf("%02x:", hwbuf[i]); | 
 |         printf("%02x\n", hwbuf[i]); | 
 |     } else { | 
 |         printf("\n"); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int dump_interfaces(void) | 
 | { | 
 |     DIR *d; | 
 |     struct dirent *de; | 
 |  | 
 |     d = opendir("/sys/class/net"); | 
 |     if(d == 0) return -1; | 
 |  | 
 |     while((de = readdir(d))) { | 
 |         if(de->d_name[0] == '.') continue; | 
 |         dump_interface(de->d_name); | 
 |     } | 
 |     closedir(d); | 
 |     return 0; | 
 | } | 
 |  | 
 | int set_hwaddr(const char *name, const char *asc) { | 
 |     struct ether_addr *addr = ether_aton(asc); | 
 |     if (!addr) { | 
 |         printf("Failed to parse '%s'\n", asc); | 
 |         return -1; | 
 |     } | 
 |     return ifc_set_hwaddr(name, addr->ether_addr_octet); | 
 | } | 
 |  | 
 | struct  | 
 | { | 
 |     const char *name; | 
 |     int nargs; | 
 |     void *func; | 
 | } CMDS[] = { | 
 |     { "dhcp",   1, do_dhcp }, | 
 |     { "up",     1, ifc_up }, | 
 |     { "down",   1, ifc_down }, | 
 |     { "flhosts",  1, ifc_remove_host_routes }, | 
 |     { "deldefault", 1, ifc_remove_default_route }, | 
 |     { "hwaddr", 2, set_hwaddr }, | 
 |     { 0, 0, 0 }, | 
 | }; | 
 |  | 
 | static int call_func(void *_func, unsigned nargs, char **args) | 
 | { | 
 |     switch(nargs){ | 
 |     case 1: { | 
 |         int (*func)(char *a0) = _func; | 
 |         return func(args[0]); | 
 |     } | 
 |     case 2: { | 
 |         int (*func)(char *a0, char *a1) = _func; | 
 |         return func(args[0], args[1]); | 
 |     } | 
 |     case 3: { | 
 |         int (*func)(char *a0, char *a1, char *a2) = _func; | 
 |         return func(args[0], args[1], args[2]); | 
 |     } | 
 |     default: | 
 |         return -1; | 
 |     } | 
 | } | 
 |  | 
 | int main(int argc, char **argv) | 
 | { | 
 |     char *iname; | 
 |     int n; | 
 |      | 
 |     if(ifc_init()) { | 
 |         die("Cannot perform requested operation"); | 
 |     } | 
 |  | 
 |     if(argc == 1) { | 
 |         int result = dump_interfaces(); | 
 |         ifc_close(); | 
 |         return result; | 
 |     } | 
 |  | 
 |     if(argc < 3) usage(); | 
 |  | 
 |     iname = argv[1]; | 
 |     if(strlen(iname) > 16) usage(); | 
 |  | 
 |     argc -= 2; | 
 |     argv += 2; | 
 |     while(argc > 0) { | 
 |         for(n = 0; CMDS[n].name; n++){ | 
 |             if(!strcmp(argv[0], CMDS[n].name)) { | 
 |                 char *cmdname = argv[0]; | 
 |                 int nargs = CMDS[n].nargs; | 
 |                  | 
 |                 argv[0] = iname; | 
 |                 if(argc < nargs) { | 
 |                     fprintf(stderr, "not enough arguments for '%s'\n", cmdname); | 
 |                     ifc_close(); | 
 |                     exit(1); | 
 |                 } | 
 |                 if(call_func(CMDS[n].func, nargs, argv)) { | 
 |                     fprintf(stderr, "action '%s' failed (%s)\n", cmdname, strerror(errno)); | 
 |                     ifc_close(); | 
 |                     exit(1); | 
 |                 } | 
 |                 argc -= nargs; | 
 |                 argv += nargs; | 
 |                 goto done; | 
 |             } | 
 |         } | 
 |         fprintf(stderr,"no such action '%s'\n", argv[0]); | 
 |         usage(); | 
 |     done: | 
 |         ; | 
 |     } | 
 |     ifc_close(); | 
 |  | 
 |     return 0; | 
 | } |