fad-glifc.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
  2. /*
  3. * Copyright (c) 1994, 1995, 1996, 1997, 1998
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. All advertising materials mentioning features or use of this software
  15. * must display the following acknowledgement:
  16. * This product includes software developed by the Computer Systems
  17. * Engineering Group at Lawrence Berkeley Laboratory.
  18. * 4. Neither the name of the University nor of the Laboratory may be used
  19. * to endorse or promote products derived from this software without
  20. * specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. */
  34. #ifdef HAVE_CONFIG_H
  35. #include <config.h>
  36. #endif
  37. #include <sys/param.h>
  38. #include <sys/file.h>
  39. #include <sys/ioctl.h>
  40. #include <sys/socket.h>
  41. #ifdef HAVE_SYS_SOCKIO_H
  42. #include <sys/sockio.h>
  43. #endif
  44. #include <sys/time.h> /* concession to AIX */
  45. struct mbuf; /* Squelch compiler warnings on some platforms for */
  46. struct rtentry; /* declarations in <net/if.h> */
  47. #include <net/if.h>
  48. #include <netinet/in.h>
  49. #include <ctype.h>
  50. #include <errno.h>
  51. #include <memory.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <unistd.h>
  56. #include "pcap-int.h"
  57. #ifdef HAVE_OS_PROTO_H
  58. #include "os-proto.h"
  59. #endif
  60. /*
  61. * Get a list of all interfaces that are up and that we can open.
  62. * Returns -1 on error, 0 otherwise.
  63. * The list, as returned through "alldevsp", may be null if no interfaces
  64. * were up and could be opened.
  65. *
  66. * This is the implementation used on platforms that have SIOCGLIFCONF
  67. * but don't have "getifaddrs()". (Solaris 8 and later; we use
  68. * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
  69. */
  70. int
  71. pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
  72. int (*check_usable)(const char *), get_if_flags_func get_flags_func)
  73. {
  74. register int fd4, fd6, fd;
  75. register struct lifreq *ifrp, *ifend;
  76. struct lifnum ifn;
  77. struct lifconf ifc;
  78. char *buf = NULL;
  79. unsigned buf_size;
  80. #ifdef HAVE_SOLARIS
  81. char *p, *q;
  82. #endif
  83. struct lifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
  84. struct sockaddr *netmask, *broadaddr, *dstaddr;
  85. int ret = 0;
  86. /*
  87. * Create a socket from which to fetch the list of interfaces,
  88. * and from which to fetch IPv4 information.
  89. */
  90. fd4 = socket(AF_INET, SOCK_DGRAM, 0);
  91. if (fd4 < 0) {
  92. pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  93. errno, "socket: AF_INET");
  94. return (-1);
  95. }
  96. /*
  97. * Create a socket from which to fetch IPv6 information.
  98. */
  99. fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
  100. if (fd6 < 0) {
  101. pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  102. errno, "socket: AF_INET6");
  103. (void)close(fd4);
  104. return (-1);
  105. }
  106. /*
  107. * How many entries will SIOCGLIFCONF return?
  108. */
  109. ifn.lifn_family = AF_UNSPEC;
  110. ifn.lifn_flags = 0;
  111. ifn.lifn_count = 0;
  112. if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) {
  113. pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  114. errno, "SIOCGLIFNUM");
  115. (void)close(fd6);
  116. (void)close(fd4);
  117. return (-1);
  118. }
  119. /*
  120. * Allocate a buffer for those entries.
  121. */
  122. buf_size = ifn.lifn_count * sizeof (struct lifreq);
  123. buf = malloc(buf_size);
  124. if (buf == NULL) {
  125. pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  126. errno, "malloc");
  127. (void)close(fd6);
  128. (void)close(fd4);
  129. return (-1);
  130. }
  131. /*
  132. * Get the entries.
  133. */
  134. ifc.lifc_len = buf_size;
  135. ifc.lifc_buf = buf;
  136. ifc.lifc_family = AF_UNSPEC;
  137. ifc.lifc_flags = 0;
  138. memset(buf, 0, buf_size);
  139. if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) {
  140. pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  141. errno, "SIOCGLIFCONF");
  142. (void)close(fd6);
  143. (void)close(fd4);
  144. free(buf);
  145. return (-1);
  146. }
  147. /*
  148. * Loop over the entries.
  149. */
  150. ifrp = (struct lifreq *)buf;
  151. ifend = (struct lifreq *)(buf + ifc.lifc_len);
  152. for (; ifrp < ifend; ifrp++) {
  153. /*
  154. * Skip entries that begin with "dummy".
  155. * XXX - what are these? Is this Linux-specific?
  156. * Are there platforms on which we shouldn't do this?
  157. */
  158. if (strncmp(ifrp->lifr_name, "dummy", 5) == 0)
  159. continue;
  160. /*
  161. * Can we capture on this device?
  162. */
  163. if (!(*check_usable)(ifrp->lifr_name)) {
  164. /*
  165. * No.
  166. */
  167. continue;
  168. }
  169. /*
  170. * IPv6 or not?
  171. */
  172. if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
  173. fd = fd6;
  174. else
  175. fd = fd4;
  176. /*
  177. * Get the flags for this interface.
  178. */
  179. strncpy(ifrflags.lifr_name, ifrp->lifr_name,
  180. sizeof(ifrflags.lifr_name));
  181. if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
  182. if (errno == ENXIO)
  183. continue;
  184. pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  185. errno, "SIOCGLIFFLAGS: %.*s",
  186. (int)sizeof(ifrflags.lifr_name),
  187. ifrflags.lifr_name);
  188. ret = -1;
  189. break;
  190. }
  191. /*
  192. * Get the netmask for this address on this interface.
  193. */
  194. strncpy(ifrnetmask.lifr_name, ifrp->lifr_name,
  195. sizeof(ifrnetmask.lifr_name));
  196. memcpy(&ifrnetmask.lifr_addr, &ifrp->lifr_addr,
  197. sizeof(ifrnetmask.lifr_addr));
  198. if (ioctl(fd, SIOCGLIFNETMASK, (char *)&ifrnetmask) < 0) {
  199. if (errno == EADDRNOTAVAIL) {
  200. /*
  201. * Not available.
  202. */
  203. netmask = NULL;
  204. } else {
  205. pcap_fmt_errmsg_for_errno(errbuf,
  206. PCAP_ERRBUF_SIZE, errno,
  207. "SIOCGLIFNETMASK: %.*s",
  208. (int)sizeof(ifrnetmask.lifr_name),
  209. ifrnetmask.lifr_name);
  210. ret = -1;
  211. break;
  212. }
  213. } else
  214. netmask = (struct sockaddr *)&ifrnetmask.lifr_addr;
  215. /*
  216. * Get the broadcast address for this address on this
  217. * interface (if any).
  218. */
  219. if (ifrflags.lifr_flags & IFF_BROADCAST) {
  220. strncpy(ifrbroadaddr.lifr_name, ifrp->lifr_name,
  221. sizeof(ifrbroadaddr.lifr_name));
  222. memcpy(&ifrbroadaddr.lifr_addr, &ifrp->lifr_addr,
  223. sizeof(ifrbroadaddr.lifr_addr));
  224. if (ioctl(fd, SIOCGLIFBRDADDR,
  225. (char *)&ifrbroadaddr) < 0) {
  226. if (errno == EADDRNOTAVAIL) {
  227. /*
  228. * Not available.
  229. */
  230. broadaddr = NULL;
  231. } else {
  232. pcap_fmt_errmsg_for_errno(errbuf,
  233. PCAP_ERRBUF_SIZE, errno,
  234. "SIOCGLIFBRDADDR: %.*s",
  235. (int)sizeof(ifrbroadaddr.lifr_name),
  236. ifrbroadaddr.lifr_name);
  237. ret = -1;
  238. break;
  239. }
  240. } else
  241. broadaddr = (struct sockaddr *)&ifrbroadaddr.lifr_broadaddr;
  242. } else {
  243. /*
  244. * Not a broadcast interface, so no broadcast
  245. * address.
  246. */
  247. broadaddr = NULL;
  248. }
  249. /*
  250. * Get the destination address for this address on this
  251. * interface (if any).
  252. */
  253. if (ifrflags.lifr_flags & IFF_POINTOPOINT) {
  254. strncpy(ifrdstaddr.lifr_name, ifrp->lifr_name,
  255. sizeof(ifrdstaddr.lifr_name));
  256. memcpy(&ifrdstaddr.lifr_addr, &ifrp->lifr_addr,
  257. sizeof(ifrdstaddr.lifr_addr));
  258. if (ioctl(fd, SIOCGLIFDSTADDR,
  259. (char *)&ifrdstaddr) < 0) {
  260. if (errno == EADDRNOTAVAIL) {
  261. /*
  262. * Not available.
  263. */
  264. dstaddr = NULL;
  265. } else {
  266. pcap_fmt_errmsg_for_errno(errbuf,
  267. PCAP_ERRBUF_SIZE, errno,
  268. "SIOCGLIFDSTADDR: %.*s",
  269. (int)sizeof(ifrdstaddr.lifr_name),
  270. ifrdstaddr.lifr_name);
  271. ret = -1;
  272. break;
  273. }
  274. } else
  275. dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr;
  276. } else
  277. dstaddr = NULL;
  278. #ifdef HAVE_SOLARIS
  279. /*
  280. * If this entry has a colon followed by a number at
  281. * the end, it's a logical interface. Those are just
  282. * the way you assign multiple IP addresses to a real
  283. * interface, so an entry for a logical interface should
  284. * be treated like the entry for the real interface;
  285. * we do that by stripping off the ":" and the number.
  286. */
  287. p = strchr(ifrp->lifr_name, ':');
  288. if (p != NULL) {
  289. /*
  290. * We have a ":"; is it followed by a number?
  291. */
  292. q = p + 1;
  293. while (isdigit((unsigned char)*q))
  294. q++;
  295. if (*q == '\0') {
  296. /*
  297. * All digits after the ":" until the end.
  298. * Strip off the ":" and everything after
  299. * it.
  300. */
  301. *p = '\0';
  302. }
  303. }
  304. #endif
  305. /*
  306. * Add information for this address to the list.
  307. */
  308. if (add_addr_to_if(devlistp, ifrp->lifr_name,
  309. ifrflags.lifr_flags, get_flags_func,
  310. (struct sockaddr *)&ifrp->lifr_addr,
  311. sizeof (struct sockaddr_storage),
  312. netmask, sizeof (struct sockaddr_storage),
  313. broadaddr, sizeof (struct sockaddr_storage),
  314. dstaddr, sizeof (struct sockaddr_storage), errbuf) < 0) {
  315. ret = -1;
  316. break;
  317. }
  318. }
  319. free(buf);
  320. (void)close(fd6);
  321. (void)close(fd4);
  322. return (ret);
  323. }