get.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /* $Id: get.c 1991 2008-04-26 22:22:05Z 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. u_int16_t ether_type;
  125. assert(pktdata);
  126. assert(datalen);
  127. switch (datalink) {
  128. case DLT_RAW:
  129. /* pktdata IS the ip header! */
  130. return 0;
  131. break;
  132. case DLT_EN10MB:
  133. eth_hdr = (struct tcpr_ethernet_hdr *)pktdata;
  134. switch (ntohs(eth_hdr->ether_type)) {
  135. case ETHERTYPE_VLAN:
  136. return 18;
  137. break;
  138. default:
  139. return 14;
  140. break;
  141. }
  142. break;
  143. case DLT_C_HDLC:
  144. return CISCO_HDLC_LEN;
  145. break;
  146. case DLT_LINUX_SLL:
  147. return SLL_HDR_LEN;
  148. break;
  149. default:
  150. errx(1, "Unable to process unsupported DLT type: %s (0x%x)",
  151. pcap_datalink_val_to_description(datalink), datalink);
  152. break;
  153. }
  154. return -1; /* we shouldn't get here */
  155. }
  156. /**
  157. * returns a ptr to the ip header + data or NULL if it's not IP
  158. * we may use an extra buffer for the ip header (and above)
  159. * on stricly aligned systems where the layer 2 header doesn't
  160. * fall on a 4 byte boundry (like a standard ethernet header)
  161. *
  162. * Note: you can cast the result as an ip_hdr_t, but you'll be able
  163. * to access data above the header minus any stripped L2 data
  164. */
  165. const u_char *
  166. get_ipv4(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
  167. {
  168. const u_char *ip_hdr = NULL;
  169. int l2_len = 0;
  170. u_int16_t proto;
  171. assert(pktdata);
  172. assert(datalen);
  173. assert(*newbuff);
  174. l2_len = get_l2len(pktdata, datalen, datalink);
  175. /* sanity... datalen must be > l2_len + IP header len*/
  176. if (l2_len + TCPR_IPV4_H > datalen) {
  177. dbg(1, "get_ipv4(): Layer 2 len > total packet len, hence no IP header");
  178. return NULL;
  179. }
  180. proto = get_l2protocol(pktdata, datalen, datalink);
  181. if (proto != ETHERTYPE_IP)
  182. return NULL;
  183. #ifdef FORCE_ALIGN
  184. /*
  185. * copy layer 3 and up to our temp packet buffer
  186. * for now on, we have to edit the packetbuff because
  187. * just before we send the packet, we copy the packetbuff
  188. * back onto the pkt.data + l2len buffer
  189. * we do all this work to prevent byte alignment issues
  190. */
  191. if (l2_len % 4) {
  192. ip_hdr = *newbuff;
  193. memcpy(ip_hdr, (pktdata + l2_len), (datalen - l2_len));
  194. } else {
  195. /* we don't have to do a memcpy if l2_len lands on a boundry */
  196. ip_hdr = (pktdata + l2_len);
  197. }
  198. #else
  199. /*
  200. * on non-strict byte align systems, don't need to memcpy(),
  201. * just point to l2len bytes into the existing buffer
  202. */
  203. ip_hdr = (pktdata + l2_len);
  204. #endif
  205. return ip_hdr;
  206. }
  207. /**
  208. * returns a pointer to the layer 4 header which is just beyond the IP header
  209. */
  210. void *
  211. get_layer4(const ipv4_hdr_t * ip_hdr)
  212. {
  213. void *ptr;
  214. assert(ip_hdr);
  215. ptr = (u_int32_t *) ip_hdr + ip_hdr->ip_hl;
  216. return ((void *)ptr);
  217. }
  218. /**
  219. * get_name2addr4()
  220. * stolen from LIBNET since I didn't want to have to deal with
  221. * passing a libnet_t around. Returns 0xFFFFFFFF (255.255.255.255)
  222. * on error
  223. */
  224. u_int32_t
  225. get_name2addr4(const char *hostname, u_int8_t dnslookup)
  226. {
  227. struct in_addr addr;
  228. #if ! defined HAVE_INET_ATON && defined HAVE_INET_ADDR
  229. struct hostent *host_ent;
  230. #endif
  231. u_int32_t m;
  232. u_int val;
  233. int i;
  234. if (dnslookup == DNS_RESOLVE) {
  235. #ifdef HAVE_INET_ATON
  236. if (inet_aton(hostname, &addr) != 1) {
  237. return(0xffffffff);
  238. }
  239. #elif defined HAVE_INET_ADDR
  240. if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
  241. if (!(host_ent = gethostbyname(hostname))) {
  242. warnx("unable to resolve %s: %s", hostname, strerror(errno));
  243. /* XXX - this is actually 255.255.255.255 */
  244. return (0xffffffff);
  245. }
  246. /* was: host_ent->h_length); */
  247. memcpy(&addr.s_addr, host_ent->h_addr, sizeof(addr.s_addr));
  248. }
  249. #else
  250. warn("Unable to support get_name2addr4 w/ resolve");
  251. /* call ourselves recursively once w/o resolving the hostname */
  252. return get_name2addr4(hostname, DNS_DONT_RESOLVE);
  253. #endif
  254. /* return in network byte order */
  255. return (addr.s_addr);
  256. } else {
  257. /*
  258. * We only want dots 'n decimals.
  259. */
  260. if (!isdigit(hostname[0])) {
  261. warnx("Expected dotted-quad notation (%s) when DNS lookups are disabled", hostname);
  262. /* XXX - this is actually 255.255.255.255 */
  263. return (-1);
  264. }
  265. m = 0;
  266. for (i = 0; i < 4; i++) {
  267. m <<= 8;
  268. if (*hostname) {
  269. val = 0;
  270. while (*hostname && *hostname != '.') {
  271. val *= 10;
  272. val += *hostname - '0';
  273. if (val > 255) {
  274. dbgx(4, "value %d > 255 for dotted quad", val);
  275. /* XXX - this is actually 255.255.255.255 */
  276. return (-1);
  277. }
  278. hostname++;
  279. }
  280. m |= val;
  281. if (*hostname) {
  282. hostname++;
  283. }
  284. }
  285. }
  286. /* host byte order */
  287. return (ntohl(m));
  288. }
  289. }
  290. /**
  291. * Generic wrapper around inet_ntop() and inet_ntoa() depending on whichever
  292. * is available on your system
  293. */
  294. const char *
  295. get_addr2name4(const u_int32_t ip, u_int8_t dnslookup)
  296. {
  297. struct in_addr addr;
  298. static char *new_string = NULL;
  299. if (new_string == NULL)
  300. new_string = (char *)safe_malloc(255);
  301. new_string[0] = '\0';
  302. addr.s_addr = ip;
  303. #ifdef HAVE_INET_NTOP
  304. if (inet_ntop(AF_INET, &addr, new_string, 255) == NULL) {
  305. warnx("Unable to convert 0x%x to a string", ip);
  306. strlcpy(new_string, "", sizeof(new_string));
  307. }
  308. return new_string;
  309. #elif defined HAVE_INET_NTOA
  310. return inet_pton(&addr);
  311. #else
  312. #error "Unable to support get_addr2name4."
  313. #endif
  314. if (dnslookup != DNS_DONT_RESOLVE) {
  315. warn("Sorry, we don't support name resolution.");
  316. }
  317. return new_string;
  318. }
  319. /*
  320. Local Variables:
  321. mode:c
  322. indent-tabs-mode:nil
  323. c-basic-offset:4
  324. End:
  325. */