55f026ac811fba771c9192678c9d673bb803b53e
[sip-router] / test / ifls.c
1 /* $Id$
2  *
3  *
4  * test programs, list all interfaces and their ip address
5  */
6
7
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <sys/ioctl.h>
12 #include <net/if.h>
13 #ifdef __sun__
14 #include <sys/sockio.h>
15 #endif
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <ctype.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <errno.h>
23
24 #define FLAGS 1
25
26
27 static char* version="ifls 0.1";
28 static char* id="$Id$";
29 static char* help_msg="\
30 Usage: ifls [-6hV} [interface...]\n\
31 (if no interface name is specified it will list all the interfaces)\n\
32 Options:\n\
33     -a      list both ipv4 and ipv6 interfaces (default)\n\
34     -4      list only ipv4 interfaces\n\
35     -6      list only ipv6 interfaces\n\
36     -f      show also the interface flags\n\
37     -V      version number\n\
38     -h      this help message\n\
39 ";
40
41
42 #define MAX(a,b) ( ((a)>(b))?(a):(b))
43
44
45
46 void print_sockaddr(struct sockaddr* sa)
47 {
48         unsigned char* buf;
49         int r;
50         
51         switch(sa->sa_family){
52         case AF_INET:
53                 buf=(char*)&(((struct sockaddr_in*)sa)->sin_addr).s_addr;
54                 printf("%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3]);
55                 break;
56         case AF_INET6:
57                 buf=(((struct sockaddr_in6*)sa)->sin6_addr).s6_addr;
58                 for(r=0; r<16; r++) 
59                         printf("%02x%s", buf[r], ((r%2)&&(r!=15))?":":"" );
60                 printf("\n");
61                 break;
62         default:
63                 printf("unknown af %d\n", sa->sa_family);
64 #ifdef __FreeBSD__
65                 for (r=0; r<sa->sa_len; r++) 
66                         printf("%02x ", ((unsigned char*)sa)[r]);
67                 printf("\n");
68 #endif
69         }
70 }
71
72
73
74 int ls_ifflags(char* name, int family , int options)
75 {
76         struct ifreq ifr;
77         int s;
78         
79         memset(&ifr, 0, sizeof(ifr)); /* init to 0 (check if filled)*/
80         s=socket(family, SOCK_DGRAM, 0);
81         strncpy(ifr.ifr_name, name, IFNAMSIZ);
82 #if 0   
83         if (ioctl(s, SIOCGIFADDR, &ifr)==-1){
84                 if(errno==EBADF) return 0; /* invalid descriptor => no address*/
85                 fprintf(stderr, "ls_if: ioctl for %s failed: %s\n", name, 
86                                         strerror(errno));
87                 goto error;
88         };
89         
90         printf("%s:\n", ifr.ifr_name);
91         printf("        dbg: family=%d", ifr.ifr_addr.sa_family);
92 #ifdef __FreeBSD__
93         printf(", len=%d\n", ifr.ifr_addr.sa_len);
94 #else
95         printf("\n");
96 #endif
97         if (ifr.ifr_addr.sa_family==0){
98                 printf("ls_if: OS BUG: SIOCGIFADDR doesn't work!\n");
99                 goto error;
100         }
101         
102         printf("        ");
103         print_sockaddr(&ifr.ifr_addr);
104
105         if (ifr.ifr_addr.sa_family!=family){
106                 printf("ls_if: strange family %d\n", ifr.ifr_addr.sa_family);
107                 /*goto error;*/
108         }
109 #endif
110         if (options & FLAGS){
111                 if (ioctl(s, SIOCGIFFLAGS, &ifr)==-1){
112                         fprintf(stderr, "ls_if: flags ioctl for %s  failed: %s\n",
113                                         name, strerror(errno));
114                         goto error;
115                 }
116                 if (ifr.ifr_flags & IFF_UP) printf ("UP ");
117                 if (ifr.ifr_flags & IFF_BROADCAST) printf ("BROADCAST ");
118                 if (ifr.ifr_flags & IFF_DEBUG) printf ("DEBUG ");
119                 if (ifr.ifr_flags & IFF_LOOPBACK) printf ("LOOPBACK ");
120                 if (ifr.ifr_flags & IFF_POINTOPOINT) printf ("POINTOPOINT ");
121                 if (ifr.ifr_flags & IFF_RUNNING) printf ("RUNNING ");
122                 if (ifr.ifr_flags & IFF_NOARP) printf ("NOARP ");
123                 if (ifr.ifr_flags & IFF_PROMISC) printf ("PROMISC ");
124                 /*if (ifr.ifr_flags & IFF_NOTRAILERS) printf ("NOTRAILERS ");*/
125                 if (ifr.ifr_flags & IFF_ALLMULTI) printf ("ALLMULTI ");
126                 /*if (ifr.ifr_flags & IFF_MASTER) printf ("MASTER ");*/
127                 /*if (ifr.ifr_flags & IFF_SLAVE) printf ("SLAVE ");*/
128                 if (ifr.ifr_flags & IFF_MULTICAST) printf ("MULTICAST ");
129                 /*if (ifr.ifr_flags & IFF_PORTSEL) printf ("PORTSEL ");*/
130                 /*if (ifr.ifr_flags & IFF_AUTOMEDIA) printf ("AUTOMEDIA ");*/
131                 /*if (ifr.ifr_flags & IFF_DYNAMIC ) printf ("DYNAMIC ");*/
132                 printf ("\n");
133         };
134         close(s);
135         return 0;
136 error:
137         close(s);
138         return -1;
139 }
140
141
142
143 int ls_ifs(char* name, int family, int options)
144 {
145         struct ifconf ifc;
146         struct ifreq* ifr;
147         char*  last;
148         int size;
149         int lastlen;
150         int s;
151         
152         /* ipv4 or ipv6 only*/
153         s=socket(family, SOCK_DGRAM, 0);
154         lastlen=0;
155         for (size=2; ; size*=2){
156                 ifc.ifc_len=size*sizeof(struct ifreq);
157                 ifc.ifc_req=(struct ifreq*) malloc(size*sizeof(struct ifreq));
158                 if (ifc.ifc_req==0){
159                         fprintf(stderr, "memory allocation failure\n");
160                         goto error;
161                 }
162                 if (ioctl(s, SIOCGIFCONF, &ifc)==-1){
163                         if(errno==EBADF) return 0; /* invalid descriptor => no such ifs*/
164                         fprintf(stderr, "ioctl failed: %s\n", strerror(errno));
165                         goto error;
166                 }
167                 if  ((lastlen) && (ifc.ifc_len==lastlen)) break; /*success,
168                                                                                                                    len not changed*/
169                 lastlen=ifc.ifc_len;
170                 /* try a bigger array*/
171                 free(ifc.ifc_req);
172         }
173         
174         last=(char*)ifc.ifc_req+ifc.ifc_len;
175         for(ifr=ifc.ifc_req; (char*)ifr<last;
176                         ifr=(struct ifreq*)((char*)ifr+sizeof(ifr->ifr_name)+
177                         #ifdef  __FreeBSD__
178                                 MAX(ifr->ifr_addr.sa_len, sizeof(struct sockaddr))
179                         #else
180                                 ( (ifr->ifr_addr.sa_family==AF_INET)?
181                                         sizeof(struct sockaddr_in):
182                                         ((ifr->ifr_addr.sa_family==AF_INET6)?
183                                                 sizeof(struct sockaddr_in6):sizeof(struct sockaddr)) )
184                         #endif
185                                 )
186                 )
187         {
188 /*
189                 printf("\nls_all dbg: %s family=%d", ifr->ifr_name,
190                                                                                 ifr->ifr_addr.sa_family);
191 #ifdef __FreeBSD__
192                 printf(", len=%d\n", ifr->ifr_addr.sa_len);
193 #else
194                 printf("\n");
195 #endif
196 */
197                 if (ifr->ifr_addr.sa_family!=family){
198                         /*printf("strange family %d skipping...\n",
199                                         ifr->ifr_addr.sa_family);*/
200                         continue;
201                 }
202                 if ((name==0)||
203                         (strncmp(name, ifr->ifr_name, sizeof(ifr->ifr_name))==0)){
204                         printf("%s:\n", ifr->ifr_name);
205                         printf("        ");
206                         print_sockaddr(&(ifr->ifr_addr));
207                         printf("        ");
208                         ls_ifflags(ifr->ifr_name, family, options);
209                         printf("\n");
210                 }
211         }
212         free(ifc.ifc_req); /*clean up*/
213         close(s);
214         return  0;
215 error:
216         close(s);
217         return -1;
218 }
219
220
221 int main(int argc, char**argv)
222 {
223         char** name;
224         int no;
225         int options;
226         int ipv6, ipv4;
227         int r;
228         char c;
229         
230         
231         options=0;
232         ipv6=ipv4=1;
233         name=0;
234         no=0;
235         opterr=0;
236         while((c=getopt(argc, argv, "a46fhV"))!=-1){
237                 switch(c){
238                         case 'a':
239                                 ipv6=ipv4=1;
240                                 break;
241                         case '4':
242                                 ipv6=0;
243                                 ipv4=1;
244                                 break;
245                         case '6':
246                                 ipv4=0;
247                                 ipv6=1;
248                                 break;
249                         case 'f':
250                                 options|=FLAGS;
251                                 break;
252                         case 'V':
253                                 printf("version: %s\n", version);
254                                 printf("%s\n", id);
255                                 exit(0);
256                                 break;
257                         case 'h':
258                                 printf("version: %s\n", version);
259                                 printf("%s", help_msg);
260                                 exit(0);
261                                 break;
262                         case '?':
263                                 if (isprint(optopt))
264                                         fprintf(stderr, "Unknow option `-%c´\n", optopt);
265                                 else
266                                         fprintf(stderr, "Unknown character `\\x%x´\n", optopt);
267                                 goto error;
268                         case ':':
269                                 fprintf(stderr, "Option `-%c´ requires an argument\n",
270                                                 optopt);
271                                 goto error;
272                         default:
273                                 abort();
274                 };
275         };
276         /* check if we have non-options */
277         if( optind < argc){
278                 no=argc-optind;
279                 name=&argv[optind];
280         }
281         
282         if (no==0){
283                 /* list all interfaces */
284                 if (ipv4) ls_ifs(0, AF_INET, options);
285                 if (ipv6) ls_ifs(0, AF_INET6, options);
286         }else{
287                 for(r=0; r<no; r++){
288                         if (ipv4) ls_ifs(name[r], AF_INET, options);
289                         if (ipv6) ls_ifs(name[r], AF_INET6, options);
290                 }
291         };
292         
293         
294         exit(0);
295 error:
296         exit(-1);
297 };