fad-getad.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  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/types.h>
  38. #include <sys/socket.h>
  39. #include <netinet/in.h>
  40. #include <net/if.h>
  41. #include <ctype.h>
  42. #include <errno.h>
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #include <ifaddrs.h>
  47. #include "pcap-int.h"
  48. #ifdef HAVE_OS_PROTO_H
  49. #include "os-proto.h"
  50. #endif
  51. /*
  52. * We don't do this on Solaris 11 and later, as it appears there aren't
  53. * any AF_PACKET addresses on interfaces, so we don't need this, and
  54. * we end up including both the OS's <net/bpf.h> and our <pcap/bpf.h>,
  55. * and their definitions of some data structures collide.
  56. */
  57. #if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
  58. # ifdef HAVE_NETPACKET_PACKET_H
  59. /* Linux distributions with newer glibc */
  60. # include <netpacket/packet.h>
  61. # else /* HAVE_NETPACKET_PACKET_H */
  62. /* LynxOS, Linux distributions with older glibc */
  63. # ifdef __Lynx__
  64. /* LynxOS */
  65. # include <netpacket/if_packet.h>
  66. # else /* __Lynx__ */
  67. /* Linux */
  68. # include <linux/types.h>
  69. # include <linux/if_packet.h>
  70. # endif /* __Lynx__ */
  71. # endif /* HAVE_NETPACKET_PACKET_H */
  72. #endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */
  73. /*
  74. * This is fun.
  75. *
  76. * In older BSD systems, socket addresses were fixed-length, and
  77. * "sizeof (struct sockaddr)" gave the size of the structure.
  78. * All addresses fit within a "struct sockaddr".
  79. *
  80. * In newer BSD systems, the socket address is variable-length, and
  81. * there's an "sa_len" field giving the length of the structure;
  82. * this allows socket addresses to be longer than 2 bytes of family
  83. * and 14 bytes of data.
  84. *
  85. * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
  86. * variant of the old BSD scheme (with "struct sockaddr_storage" rather
  87. * than "struct sockaddr"), and some use the new BSD scheme.
  88. *
  89. * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
  90. * macro that determines the size based on the address family. Other
  91. * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
  92. * but not in the final version). On the latter systems, we explicitly
  93. * check the AF_ type to determine the length; we assume that on
  94. * all those systems we have "struct sockaddr_storage".
  95. */
  96. #ifndef SA_LEN
  97. #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
  98. #define SA_LEN(addr) ((addr)->sa_len)
  99. #else /* HAVE_STRUCT_SOCKADDR_SA_LEN */
  100. #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
  101. static size_t
  102. get_sa_len(struct sockaddr *addr)
  103. {
  104. switch (addr->sa_family) {
  105. #ifdef AF_INET
  106. case AF_INET:
  107. return (sizeof (struct sockaddr_in));
  108. #endif
  109. #ifdef AF_INET6
  110. case AF_INET6:
  111. return (sizeof (struct sockaddr_in6));
  112. #endif
  113. #if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
  114. case AF_PACKET:
  115. return (sizeof (struct sockaddr_ll));
  116. #endif
  117. default:
  118. return (sizeof (struct sockaddr));
  119. }
  120. }
  121. #define SA_LEN(addr) (get_sa_len(addr))
  122. #else /* HAVE_STRUCT_SOCKADDR_STORAGE */
  123. #define SA_LEN(addr) (sizeof (struct sockaddr))
  124. #endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
  125. #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
  126. #endif /* SA_LEN */
  127. /*
  128. * Get a list of all interfaces that are up and that we can open.
  129. * Returns -1 on error, 0 otherwise.
  130. * The list, as returned through "alldevsp", may be null if no interfaces
  131. * could be opened.
  132. */
  133. int
  134. pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
  135. int (*check_usable)(const char *), get_if_flags_func get_flags_func)
  136. {
  137. struct ifaddrs *ifap, *ifa;
  138. struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
  139. size_t addr_size, broadaddr_size, dstaddr_size;
  140. int ret = 0;
  141. char *p, *q;
  142. /*
  143. * Get the list of interface addresses.
  144. *
  145. * Note: this won't return information about interfaces
  146. * with no addresses, so, if a platform has interfaces
  147. * with no interfaces on which traffic can be captured,
  148. * we must check for those interfaces as well (see, for
  149. * example, what's done on Linux).
  150. *
  151. * LAN interfaces will probably have link-layer
  152. * addresses; I don't know whether all implementations
  153. * of "getifaddrs()" now, or in the future, will return
  154. * those.
  155. */
  156. if (getifaddrs(&ifap) != 0) {
  157. pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
  158. errno, "getifaddrs");
  159. return (-1);
  160. }
  161. for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
  162. /*
  163. * If this entry has a colon followed by a number at
  164. * the end, we assume it's a logical interface. Those
  165. * are just the way you assign multiple IP addresses to
  166. * a real interface on Linux, so an entry for a logical
  167. * interface should be treated like the entry for the
  168. * real interface; we do that by stripping off the ":"
  169. * and the number.
  170. *
  171. * XXX - should we do this only on Linux?
  172. */
  173. p = strchr(ifa->ifa_name, ':');
  174. if (p != NULL) {
  175. /*
  176. * We have a ":"; is it followed by a number?
  177. */
  178. q = p + 1;
  179. while (isdigit((unsigned char)*q))
  180. q++;
  181. if (*q == '\0') {
  182. /*
  183. * All digits after the ":" until the end.
  184. * Strip off the ":" and everything after
  185. * it.
  186. */
  187. *p = '\0';
  188. }
  189. }
  190. /*
  191. * Can we capture on this device?
  192. */
  193. if (!(*check_usable)(ifa->ifa_name)) {
  194. /*
  195. * No.
  196. */
  197. continue;
  198. }
  199. /*
  200. * "ifa_addr" was apparently null on at least one
  201. * interface on some system. Therefore, we supply
  202. * the address and netmask only if "ifa_addr" is
  203. * non-null (if there's no address, there's obviously
  204. * no netmask).
  205. */
  206. if (ifa->ifa_addr != NULL) {
  207. addr = ifa->ifa_addr;
  208. addr_size = SA_LEN(addr);
  209. netmask = ifa->ifa_netmask;
  210. } else {
  211. addr = NULL;
  212. addr_size = 0;
  213. netmask = NULL;
  214. }
  215. /*
  216. * Note that, on some platforms, ifa_broadaddr and
  217. * ifa_dstaddr could be the same field (true on at
  218. * least some versions of *BSD and macOS), so we
  219. * can't just check whether the broadcast address
  220. * is null and add it if so and check whether the
  221. * destination address is null and add it if so.
  222. *
  223. * Therefore, we must also check the IFF_BROADCAST
  224. * flag, and only add a broadcast address if it's
  225. * set, and check the IFF_POINTTOPOINT flag, and
  226. * only add a destination address if it's set (as
  227. * per man page recommendations on some of those
  228. * platforms).
  229. */
  230. if (ifa->ifa_flags & IFF_BROADCAST &&
  231. ifa->ifa_broadaddr != NULL) {
  232. broadaddr = ifa->ifa_broadaddr;
  233. broadaddr_size = SA_LEN(broadaddr);
  234. } else {
  235. broadaddr = NULL;
  236. broadaddr_size = 0;
  237. }
  238. if (ifa->ifa_flags & IFF_POINTOPOINT &&
  239. ifa->ifa_dstaddr != NULL) {
  240. dstaddr = ifa->ifa_dstaddr;
  241. dstaddr_size = SA_LEN(ifa->ifa_dstaddr);
  242. } else {
  243. dstaddr = NULL;
  244. dstaddr_size = 0;
  245. }
  246. /*
  247. * Add information for this address to the list.
  248. */
  249. if (add_addr_to_if(devlistp, ifa->ifa_name, ifa->ifa_flags,
  250. get_flags_func,
  251. addr, addr_size, netmask, addr_size,
  252. broadaddr, broadaddr_size, dstaddr, dstaddr_size,
  253. errbuf) < 0) {
  254. ret = -1;
  255. break;
  256. }
  257. }
  258. freeifaddrs(ifap);
  259. return (ret);
  260. }