ifls.c 7.6 KB

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