get.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /* $Id: get.c 2096 2009-01-04 20:48:34Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2005 Aaron Turner.
  4. * 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. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the names of the copyright owners nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  20. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  27. * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "config.h"
  32. #include "defines.h"
  33. #include "common.h"
  34. #include "../../lib/sll.h"
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <arpa/inet.h>
  39. #include <ctype.h>
  40. #include <string.h>
  41. #include <stdlib.h>
  42. #ifdef DEBUG
  43. extern int debug;
  44. #endif
  45. #if defined HAVE_PCAP_VERSION && ! defined HAVE_WIN32
  46. extern const char pcap_version[];
  47. #endif
  48. /**
  49. * Depending on what version of libpcap/WinPcap there are different ways to get the
  50. * version of the libpcap/WinPcap library. This presents a unified way to get that
  51. * information.
  52. */
  53. const char *
  54. get_pcap_version(void)
  55. {
  56. #if defined HAVE_WINPCAP
  57. static char ourver[255];
  58. char *last, *version;
  59. /* WinPcap returns a string like:
  60. * WinPcap version 4.0 (packet.dll version 4.0.0.755), based on libpcap version 0.9.5
  61. */
  62. version = safe_strdup(pcap_lib_version());
  63. strtok_r(version, " ", &last);
  64. strtok_r(NULL, " ", &last);
  65. strlcpy(ourver, strtok_r(NULL, " ", &last), 255);
  66. safe_free(version);
  67. return ourver;
  68. #elif defined HAVE_PCAP_VERSION
  69. return pcap_version;
  70. #else
  71. return pcap_lib_version();
  72. #endif
  73. }
  74. /**
  75. * returns the L2 protocol (IP, ARP, etc)
  76. * or 0 for error
  77. */
  78. u_int16_t
  79. get_l2protocol(const u_char *pktdata, const int datalen, const int datalink)
  80. {
  81. eth_hdr_t *eth_hdr;
  82. vlan_hdr_t *vlan_hdr;
  83. hdlc_hdr_t *hdlc_hdr;
  84. sll_hdr_t *sll_hdr;
  85. u_int16_t ether_type;
  86. assert(pktdata);
  87. assert(datalen);
  88. switch (datalink) {
  89. case DLT_RAW:
  90. return ETHERTYPE_IP;
  91. break;
  92. case DLT_EN10MB:
  93. eth_hdr = (eth_hdr_t *)pktdata;
  94. ether_type = ntohs(eth_hdr->ether_type);
  95. switch (ether_type) {
  96. case ETHERTYPE_VLAN: /* 802.1q */
  97. vlan_hdr = (vlan_hdr_t *)pktdata;
  98. return ntohs(vlan_hdr->vlan_len);
  99. default:
  100. return ether_type; /* yes, return it in host byte order */
  101. }
  102. break;
  103. case DLT_C_HDLC:
  104. hdlc_hdr = (hdlc_hdr_t *)pktdata;
  105. return hdlc_hdr->protocol;
  106. break;
  107. case DLT_LINUX_SLL:
  108. sll_hdr = (sll_hdr_t *)pktdata;
  109. return sll_hdr->sll_protocol;
  110. break;
  111. default:
  112. errx(-1, "Unable to process unsupported DLT type: %s (0x%x)",
  113. pcap_datalink_val_to_description(datalink), datalink);
  114. }
  115. return 0;
  116. }
  117. /**
  118. * returns the length in number of bytes of the L2 header, or -1 on error
  119. */
  120. int
  121. get_l2len(const u_char *pktdata, const int datalen, const int datalink)
  122. {
  123. eth_hdr_t *eth_hdr;
  124. assert(pktdata);
  125. assert(datalen);
  126. switch (datalink) {
  127. case DLT_RAW:
  128. /* pktdata IS the ip header! */
  129. return 0;
  130. break;
  131. case DLT_EN10MB:
  132. eth_hdr = (struct tcpr_ethernet_hdr *)pktdata;
  133. switch (ntohs(eth_hdr->ether_type)) {
  134. case ETHERTYPE_VLAN:
  135. return 18;
  136. break;
  137. default:
  138. return 14;
  139. break;
  140. }
  141. break;
  142. case DLT_C_HDLC:
  143. return CISCO_HDLC_LEN;
  144. break;
  145. case DLT_LINUX_SLL:
  146. return SLL_HDR_LEN;
  147. break;
  148. default:
  149. errx(-1, "Unable to process unsupported DLT type: %s (0x%x)",
  150. pcap_datalink_val_to_description(datalink), datalink);
  151. break;
  152. }
  153. return -1; /* we shouldn't get here */
  154. }
  155. /**
  156. * returns a ptr to the ip header + data or NULL if it's not IP
  157. * we may use an extra buffer for the ip header (and above)
  158. * on stricly aligned systems where the layer 2 header doesn't
  159. * fall on a 4 byte boundry (like a standard ethernet header)
  160. *
  161. * Note: you can cast the result as an ip_hdr_t, but you'll be able
  162. * to access data above the header minus any stripped L2 data
  163. */
  164. const u_char *
  165. get_ipv4(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
  166. {
  167. const u_char *ip_hdr = NULL;
  168. int l2_len = 0;
  169. u_int16_t proto;
  170. assert(pktdata);
  171. assert(datalen);
  172. assert(*newbuff);
  173. l2_len = get_l2len(pktdata, datalen, datalink);
  174. /* sanity... datalen must be > l2_len + IP header len*/
  175. if (l2_len + TCPR_IPV4_H > datalen) {
  176. dbg(1, "get_ipv4(): Layer 2 len > total packet len, hence no IP header");
  177. return NULL;
  178. }
  179. proto = get_l2protocol(pktdata, datalen, datalink);
  180. if (proto != ETHERTYPE_IP)
  181. return NULL;
  182. #ifdef FORCE_ALIGN
  183. /*
  184. * copy layer 3 and up to our temp packet buffer
  185. * for now on, we have to edit the packetbuff because
  186. * just before we send the packet, we copy the packetbuff
  187. * back onto the pkt.data + l2len buffer
  188. * we do all this work to prevent byte alignment issues
  189. */
  190. if (l2_len % 4) {
  191. ip_hdr = *newbuff;
  192. memcpy(ip_hdr, (pktdata + l2_len), (datalen - l2_len));
  193. } else {
  194. /* we don't have to do a memcpy if l2_len lands on a boundry */
  195. ip_hdr = (pktdata + l2_len);
  196. }
  197. #else
  198. /*
  199. * on non-strict byte align systems, don't need to memcpy(),
  200. * just point to l2len bytes into the existing buffer
  201. */
  202. ip_hdr = (pktdata + l2_len);
  203. #endif
  204. return ip_hdr;
  205. }
  206. /**
  207. * returns a pointer to the layer 4 header which is just beyond the IP header
  208. */
  209. void *
  210. get_layer4(const ipv4_hdr_t * ip_hdr)
  211. {
  212. void *ptr;
  213. assert(ip_hdr);
  214. ptr = (u_int32_t *) ip_hdr + ip_hdr->ip_hl;
  215. return ((void *)ptr);
  216. }
  217. /**
  218. * get_name2addr4()
  219. * stolen from LIBNET since I didn't want to have to deal with
  220. * passing a libnet_t around. Returns 0xFFFFFFFF (255.255.255.255)
  221. * on error
  222. */
  223. u_int32_t
  224. get_name2addr4(const char *hostname, u_int8_t dnslookup)
  225. {
  226. struct in_addr addr;
  227. #if ! defined HAVE_INET_ATON && defined HAVE_INET_ADDR
  228. struct hostent *host_ent;
  229. #endif
  230. u_int32_t m;
  231. u_int val;
  232. int i;
  233. if (dnslookup == DNS_RESOLVE) {
  234. #ifdef HAVE_INET_ATON
  235. if (inet_aton(hostname, &addr) != 1) {
  236. return(0xffffffff);
  237. }
  238. #elif defined HAVE_INET_ADDR
  239. if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
  240. if (!(host_ent = gethostbyname(hostname))) {
  241. warnx("unable to resolve %s: %s", hostname, strerror(errno));
  242. /* XXX - this is actually 255.255.255.255 */
  243. return (0xffffffff);
  244. }
  245. /* was: host_ent->h_length); */
  246. memcpy(&addr.s_addr, host_ent->h_addr, sizeof(addr.s_addr));
  247. }
  248. #else
  249. warn("Unable to support get_name2addr4 w/ resolve");
  250. /* call ourselves recursively once w/o resolving the hostname */
  251. return get_name2addr4(hostname, DNS_DONT_RESOLVE);
  252. #endif
  253. /* return in network byte order */
  254. return (addr.s_addr);
  255. } else {
  256. /*
  257. * We only want dots 'n decimals.
  258. */
  259. if (!isdigit(hostname[0])) {
  260. warnx("Expected dotted-quad notation (%s) when DNS lookups are disabled", hostname);
  261. /* XXX - this is actually 255.255.255.255 */
  262. return (-1);
  263. }
  264. m = 0;
  265. for (i = 0; i < 4; i++) {
  266. m <<= 8;
  267. if (*hostname) {
  268. val = 0;
  269. while (*hostname && *hostname != '.') {
  270. val *= 10;
  271. val += *hostname - '0';
  272. if (val > 255) {
  273. dbgx(4, "value %d > 255 for dotted quad", val);
  274. /* XXX - this is actually 255.255.255.255 */
  275. return (-1);
  276. }
  277. hostname++;
  278. }
  279. m |= val;
  280. if (*hostname) {
  281. hostname++;
  282. }
  283. }
  284. }
  285. /* host byte order */
  286. return (ntohl(m));
  287. }
  288. }
  289. /**
  290. * Generic wrapper around inet_ntop() and inet_ntoa() depending on whichever
  291. * is available on your system
  292. */
  293. const char *
  294. get_addr2name4(const u_int32_t ip, u_int8_t dnslookup)
  295. {
  296. struct in_addr addr;
  297. static char *new_string = NULL;
  298. if (new_string == NULL)
  299. new_string = (char *)safe_malloc(255);
  300. new_string[0] = '\0';
  301. addr.s_addr = ip;
  302. #ifdef HAVE_INET_NTOP
  303. if (inet_ntop(AF_INET, &addr, new_string, 255) == NULL) {
  304. warnx("Unable to convert 0x%x to a string", ip);
  305. strlcpy(new_string, "", sizeof(new_string));
  306. }
  307. return new_string;
  308. #elif defined HAVE_INET_NTOA
  309. return inet_pton(&addr);
  310. #else
  311. #error "Unable to support get_addr2name4."
  312. #endif
  313. if (dnslookup != DNS_DONT_RESOLVE) {
  314. warn("Sorry, we don't support name resolution.");
  315. }
  316. return new_string;
  317. }
  318. /*
  319. Local Variables:
  320. mode:c
  321. indent-tabs-mode:nil
  322. c-basic-offset:4
  323. End:
  324. */