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