00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <netinet/in.h>
00040 #include <sys/ioctl.h>
00041 #include <net/if.h>
00042 #ifdef __sun__
00043 #include <sys/sockio.h>
00044 #endif
00045
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <ctype.h>
00049 #include <string.h>
00050 #include <unistd.h>
00051 #include <errno.h>
00052
00053 #define FLAGS 1
00054 #define IF_DOWN 2
00055 #define IF_UP 4
00056
00057
00058 static char* version="ifls 0.1";
00059 static char* id="$Id$";
00060 static char* help_msg="\
00061 Usage: ifls [-6hV} [interface...]\n\
00062 (if no interface name is specified it will list all the interfaces)\n\
00063 Options:\n\
00064 -a list both ipv4 and ipv6 interfaces (default)\n\
00065 -4 list only ipv4 interfaces\n\
00066 -6 list only ipv6 interfaces\n\
00067 -f show also the interface flags\n\
00068 -U brings all the matching interfaces up\n\
00069 -D brings all the matching interfaces down\n\
00070 -V version number\n\
00071 -h this help message\n\
00072 ";
00073
00074
00075 #define MAX(a,b) ( ((a)>(b))?(a):(b))
00076
00077
00078
00079 void print_sockaddr(struct sockaddr* sa)
00080 {
00081 unsigned char* buf;
00082 int r;
00083
00084 switch(sa->sa_family){
00085 case AF_INET:
00086 buf=(char*)&(((struct sockaddr_in*)sa)->sin_addr).s_addr;
00087 printf("%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3]);
00088 break;
00089 case AF_INET6:
00090 buf=(((struct sockaddr_in6*)sa)->sin6_addr).s6_addr;
00091 for(r=0; r<16; r++)
00092 printf("%02x%s", buf[r], ((r%2)&&(r!=15))?":":"" );
00093 printf("\n");
00094 break;
00095 default:
00096 printf("unknown af %d\n", sa->sa_family);
00097 #ifdef __FreeBSD__
00098 for (r=0; r<sa->sa_len; r++)
00099 printf("%02x ", ((unsigned char*)sa)[r]);
00100 printf("\n");
00101 #endif
00102 }
00103 }
00104
00105
00106
00107 int ls_ifflags(char* name, int family , int options)
00108 {
00109 struct ifreq ifr;
00110 int s;
00111
00112 memset(&ifr, 0, sizeof(ifr));
00113 s=socket(family, SOCK_DGRAM, 0);
00114 strncpy(ifr.ifr_name, name, IFNAMSIZ);
00115 #if 0
00116 if (ioctl(s, SIOCGIFADDR, &ifr)==-1){
00117 if(errno==EBADF) return 0;
00118 fprintf(stderr, "ls_if: ioctl for %s failed: %s\n", name,
00119 strerror(errno));
00120 goto error;
00121 };
00122
00123 printf("%s:\n", ifr.ifr_name);
00124 printf(" dbg: family=%d", ifr.ifr_addr.sa_family);
00125 #ifdef __FreeBSD__
00126 printf(", len=%d\n", ifr.ifr_addr.sa_len);
00127 #else
00128 printf("\n");
00129 #endif
00130 if (ifr.ifr_addr.sa_family==0){
00131 printf("ls_if: OS BUG: SIOCGIFADDR doesn't work!\n");
00132 goto error;
00133 }
00134
00135 printf(" ");
00136 print_sockaddr(&ifr.ifr_addr);
00137
00138 if (ifr.ifr_addr.sa_family!=family){
00139 printf("ls_if: strange family %d\n", ifr.ifr_addr.sa_family);
00140
00141 }
00142 #endif
00143 if (options & (FLAGS|IF_DOWN|IF_UP)){
00144 if (ioctl(s, SIOCGIFFLAGS, &ifr)==-1){
00145 fprintf(stderr, "ls_if: flags ioctl for %s failed: %s\n",
00146 name, strerror(errno));
00147 goto error;
00148 }
00149 if (ifr.ifr_flags & IFF_UP) printf ("UP ");
00150 if (ifr.ifr_flags & IFF_BROADCAST) printf ("BROADCAST ");
00151 if (ifr.ifr_flags & IFF_DEBUG) printf ("DEBUG ");
00152 if (ifr.ifr_flags & IFF_LOOPBACK) printf ("LOOPBACK ");
00153 if (ifr.ifr_flags & IFF_POINTOPOINT) printf ("POINTOPOINT ");
00154 if (ifr.ifr_flags & IFF_RUNNING) printf ("RUNNING ");
00155 if (ifr.ifr_flags & IFF_NOARP) printf ("NOARP ");
00156 if (ifr.ifr_flags & IFF_PROMISC) printf ("PROMISC ");
00157
00158 if (ifr.ifr_flags & IFF_ALLMULTI) printf ("ALLMULTI ");
00159
00160
00161 if (ifr.ifr_flags & IFF_MULTICAST) printf ("MULTICAST ");
00162
00163
00164
00165 printf ("\n");
00166 if (options & IF_DOWN){
00167 ifr.ifr_flags &= ~IFF_UP;
00168 }
00169 if (options & IF_UP){
00170 ifr.ifr_flags |= IFF_UP;
00171 }
00172 if (options & (IF_UP|IF_DOWN)){
00173 if (ioctl(s, SIOCSIFFLAGS, &ifr)==-1){
00174 fprintf(stderr, "ls_if: set flags ioctl for %s failed: %s\n",
00175 name, strerror(errno));
00176 goto error;
00177 }
00178 }
00179 };
00180
00181 close(s);
00182 return 0;
00183 error:
00184 close(s);
00185 return -1;
00186 }
00187
00188
00189
00190 int ls_ifs(char* name, int family, int options)
00191 {
00192 struct ifconf ifc;
00193 struct ifreq* ifr;
00194 char* last;
00195 int size;
00196 int lastlen;
00197 int s;
00198
00199
00200 s=socket(family, SOCK_DGRAM, 0);
00201 lastlen=0;
00202 for (size=2; ; size*=2){
00203 ifc.ifc_len=size*sizeof(struct ifreq);
00204 ifc.ifc_req=(struct ifreq*) malloc(size*sizeof(struct ifreq));
00205 if (ifc.ifc_req==0){
00206 fprintf(stderr, "memory allocation failure\n");
00207 goto error;
00208 }
00209 if (ioctl(s, SIOCGIFCONF, &ifc)==-1){
00210 if(errno==EBADF) return 0;
00211 fprintf(stderr, "ioctl failed: %s\n", strerror(errno));
00212 goto error;
00213 }
00214 if ((lastlen) && (ifc.ifc_len==lastlen)) break;
00215
00216 lastlen=ifc.ifc_len;
00217
00218 free(ifc.ifc_req);
00219 }
00220
00221 last=(char*)ifc.ifc_req+ifc.ifc_len;
00222 for(ifr=ifc.ifc_req; (char*)ifr<last;
00223 ifr=(struct ifreq*)((char*)ifr+sizeof(ifr->ifr_name)+
00224 #ifdef __FreeBSD__
00225 MAX(ifr->ifr_addr.sa_len, sizeof(struct sockaddr))
00226 #else
00227 ( (ifr->ifr_addr.sa_family==AF_INET)?
00228 sizeof(struct sockaddr_in):
00229 ((ifr->ifr_addr.sa_family==AF_INET6)?
00230 sizeof(struct sockaddr_in6):sizeof(struct sockaddr)) )
00231 #endif
00232 )
00233 )
00234 {
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 if (ifr->ifr_addr.sa_family!=family){
00245
00246
00247 continue;
00248 }
00249 if ((name==0)||
00250 (strncmp(name, ifr->ifr_name, sizeof(ifr->ifr_name))==0)){
00251 printf("%s:\n", ifr->ifr_name);
00252 printf(" ");
00253 print_sockaddr(&(ifr->ifr_addr));
00254 printf(" ");
00255 ls_ifflags(ifr->ifr_name, family, options);
00256 printf("\n");
00257 }
00258 }
00259 free(ifc.ifc_req);
00260 close(s);
00261 return 0;
00262 error:
00263 close(s);
00264 return -1;
00265 }
00266
00267
00268 int main(int argc, char**argv)
00269 {
00270 char** name;
00271 int no;
00272 int options;
00273 int ipv6, ipv4;
00274 int r;
00275 char c;
00276
00277
00278 options=0;
00279 ipv6=ipv4=1;
00280 name=0;
00281 no=0;
00282 opterr=0;
00283 while((c=getopt(argc, argv, "a46fhVUD"))!=-1){
00284 switch(c){
00285 case 'a':
00286 ipv6=ipv4=1;
00287 break;
00288 case '4':
00289 ipv6=0;
00290 ipv4=1;
00291 break;
00292 case '6':
00293 ipv4=0;
00294 ipv6=1;
00295 break;
00296 case 'f':
00297 options|=FLAGS;
00298 break;
00299 case 'V':
00300 printf("version: %s\n", version);
00301 printf("%s\n", id);
00302 exit(0);
00303 break;
00304 case 'D':
00305 options|=IF_DOWN;
00306 break;
00307 case 'U':
00308 options|=IF_UP;
00309 break;
00310 case 'h':
00311 printf("version: %s\n", version);
00312 printf("%s", help_msg);
00313 exit(0);
00314 break;
00315 case '?':
00316 if (isprint(optopt))
00317 fprintf(stderr, "Unknown option `-%c´\n", optopt);
00318 else
00319 fprintf(stderr, "Unknown character `\\x%x´\n", optopt);
00320 goto error;
00321 case ':':
00322 fprintf(stderr, "Option `-%c´ requires an argument\n",
00323 optopt);
00324 goto error;
00325 default:
00326 abort();
00327 };
00328 };
00329
00330 if( optind < argc){
00331 no=argc-optind;
00332 name=&argv[optind];
00333 }
00334
00335 if (no==0){
00336
00337 if (ipv4) ls_ifs(0, AF_INET, options);
00338 if (ipv6) ls_ifs(0, AF_INET6, options);
00339 }else{
00340 for(r=0; r<no; r++){
00341 if (ipv4) ls_ifs(name[r], AF_INET, options);
00342 if (ipv6) ls_ifs(name[r], AF_INET6, options);
00343 }
00344 };
00345
00346
00347 exit(0);
00348 error:
00349 exit(-1);
00350 };