get.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /* $Id: get.c 1543 2006-07-29 06:20:25Z 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. #ifdef DEBUG
  41. extern int debug;
  42. #endif
  43. /*
  44. * returns the L2 protocol (IP, ARP, etc)
  45. * or 0 for error
  46. */
  47. u_int16_t
  48. get_l2protocol(const u_char *pktdata, const int datalen, const int datalink)
  49. {
  50. eth_hdr_t *eth_hdr;
  51. vlan_hdr_t *vlan_hdr;
  52. hdlc_hdr_t *hdlc_hdr;
  53. sll_hdr_t *sll_hdr;
  54. u_int16_t ether_type;
  55. assert(pktdata);
  56. assert(datalen);
  57. switch (datalink) {
  58. case DLT_RAW:
  59. return ETHERTYPE_IP;
  60. break;
  61. case DLT_EN10MB:
  62. eth_hdr = (eth_hdr_t *)pktdata;
  63. ether_type = ntohs(eth_hdr->ether_type);
  64. switch (ether_type) {
  65. case ETHERTYPE_VLAN: /* 802.1q */
  66. vlan_hdr = (vlan_hdr_t *)pktdata;
  67. return vlan_hdr->vlan_len;
  68. default:
  69. return ether_type; /* yes, return it in nbo */
  70. }
  71. break;
  72. case DLT_C_HDLC:
  73. hdlc_hdr = (hdlc_hdr_t *)pktdata;
  74. return hdlc_hdr->protocol;
  75. break;
  76. case DLT_LINUX_SLL:
  77. sll_hdr = (sll_hdr_t *)pktdata;
  78. return sll_hdr->sll_protocol;
  79. break;
  80. default:
  81. errx(1, "Unable to process unsupported DLT type: %s (0x%x)",
  82. pcap_datalink_val_to_description(datalink), datalink);
  83. }
  84. return 0;
  85. }
  86. /*
  87. * returns the length in number of bytes of the L2 header, or -1 on error
  88. */
  89. int
  90. get_l2len(const u_char *pktdata, const int datalen, const int datalink)
  91. {
  92. eth_hdr_t *eth_hdr;
  93. u_int16_t ether_type;
  94. assert(pktdata);
  95. assert(datalen);
  96. switch (datalink) {
  97. case DLT_RAW:
  98. /* pktdata IS the ip header! */
  99. return 0;
  100. break;
  101. case DLT_EN10MB:
  102. eth_hdr = (eth_hdr_t *)pktdata;
  103. ether_type = ntohs(eth_hdr->ether_type);
  104. switch (ether_type) {
  105. case ETHERTYPE_VLAN: /* 802.1q */
  106. return TCPR_802_1Q_H;
  107. break;
  108. default: /* ethernet */
  109. return TCPR_ETH_H;
  110. break;
  111. }
  112. break;
  113. case DLT_C_HDLC:
  114. return CISCO_HDLC_LEN;
  115. break;
  116. case DLT_LINUX_SLL:
  117. return SLL_HDR_LEN;
  118. break;
  119. default:
  120. errx(1, "Unable to process unsupported DLT type: %s (0x%x)",
  121. pcap_datalink_val_to_description(datalink), datalink);
  122. break;
  123. }
  124. return -1; /* we shouldn't get here */
  125. }
  126. /*
  127. * returns a ptr to the ip header + data or NULL if it's not IP
  128. * we may use an extra buffer for the ip header (and above)
  129. * on stricly aligned systems where the layer 2 header doesn't
  130. * fall on a 4 byte boundry (like a standard ethernet header)
  131. *
  132. * Note: you can cast the result as an ip_hdr_t, but you'll be able
  133. * to access data above the header minus any stripped L2 data
  134. */
  135. const u_char *
  136. get_ipv4(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
  137. {
  138. const u_char *ip_hdr = NULL;
  139. int l2_len = 0;
  140. u_int16_t proto;
  141. assert(pktdata);
  142. assert(datalen);
  143. assert(*newbuff);
  144. l2_len = get_l2len(pktdata, datalen, datalink);
  145. /* sanity... datalen must be > l2_len + IP header len*/
  146. if (l2_len + TCPR_IPV4_H > datalen) {
  147. dbg(1, "get_ipv4(): Layer 2 len > total packet len, hence no IP header");
  148. return NULL;
  149. }
  150. proto = get_l2protocol(pktdata, datalen, datalink);
  151. if (proto != ETHERTYPE_IP)
  152. return NULL;
  153. #ifdef FORCE_ALIGN
  154. /*
  155. * copy layer 3 and up to our temp packet buffer
  156. * for now on, we have to edit the packetbuff because
  157. * just before we send the packet, we copy the packetbuff
  158. * back onto the pkt.data + l2len buffer
  159. * we do all this work to prevent byte alignment issues
  160. */
  161. if (l2_len % 4) {
  162. ip_hdr = *newbuff;
  163. memcpy(ip_hdr, (pktdata + l2_len), (datalen - l2_len));
  164. } else {
  165. /* we don't have to do a memcpy if l2_len lands on a boundry */
  166. ip_hdr = (pktdata + l2_len);
  167. }
  168. #else
  169. /*
  170. * on non-strict byte align systems, don't need to memcpy(),
  171. * just point to l2len bytes into the existing buffer
  172. */
  173. ip_hdr = (pktdata + l2_len);
  174. #endif
  175. return ip_hdr;
  176. }
  177. /*
  178. * returns a pointer to the layer 4 header which is just beyond the IP header
  179. */
  180. void *
  181. get_layer4(const ipv4_hdr_t * ip_hdr)
  182. {
  183. void *ptr;
  184. assert(ip_hdr);
  185. ptr = (u_int32_t *) ip_hdr + ip_hdr->ip_hl;
  186. return ((void *)ptr);
  187. }
  188. /*
  189. * get_name2addr4()
  190. * stolen from LIBNET since I didn't want to have to deal with
  191. * passing a libnet_t around. Returns 0xFFFFFFFF (255.255.255.255)
  192. * on error
  193. */
  194. u_int32_t
  195. get_name2addr4(const char *hostname, u_int8_t dnslookup)
  196. {
  197. struct in_addr addr;
  198. #ifndef HAVE_INET_ATON && defined HAVE_INET_ADDR
  199. struct hostent *host_ent;
  200. #endif
  201. u_int32_t m;
  202. u_int val;
  203. int i;
  204. if (dnslookup == 1) {
  205. #ifdef HAVE_INET_ATON
  206. if (inet_aton(hostname, &addr) != 1) {
  207. return(0xffffffff);
  208. }
  209. #elif defined HAVE_INET_ADDR
  210. if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
  211. if (!(host_ent = gethostbyname(hostname))) {
  212. warnx("unable to resolve %s: %s", hostname, strerror(errno));
  213. /* XXX - this is actually 255.255.255.255 */
  214. return (0xffffffff);
  215. }
  216. /* was: host_ent->h_length); */
  217. memcpy(&addr.s_addr, host_ent->h_addr, sizeof(addr.s_addr));
  218. }
  219. #else
  220. warn("Unable to support get_name2addr4 w/ resolve");
  221. goto DONT_RESOLVE;
  222. #endif
  223. /* return in network byte order */
  224. return (addr.s_addr);
  225. } else {
  226. DONT_RESOLVE:
  227. /*
  228. * We only want dots 'n decimals.
  229. */
  230. if (!isdigit(hostname[0])) {
  231. warnx("Expected dotted-quad notation (%s) when DNS lookups are disabled", hostname);
  232. /* XXX - this is actually 255.255.255.255 */
  233. return (-1);
  234. }
  235. m = 0;
  236. for (i = 0; i < 4; i++) {
  237. m <<= 8;
  238. if (*hostname) {
  239. val = 0;
  240. while (*hostname && *hostname != '.') {
  241. val *= 10;
  242. val += *hostname - '0';
  243. if (val > 255) {
  244. dbgx(4, "value %d > 255 for dotted quad", val);
  245. /* XXX - this is actually 255.255.255.255 */
  246. return (-1);
  247. }
  248. hostname++;
  249. }
  250. m |= val;
  251. if (*hostname) {
  252. hostname++;
  253. }
  254. }
  255. }
  256. /* host byte order */
  257. return (ntohl(m));
  258. }
  259. }
  260. const char *
  261. get_addr2name4(const u_int32_t ip, u_int8_t dnslookup)
  262. {
  263. struct in_addr addr;
  264. char *new_string = NULL;
  265. if (new_string == NULL)
  266. new_string = (char *)safe_malloc(255);
  267. new_string[0] = '\0';
  268. addr.s_addr = ip;
  269. #ifdef HAVE_INET_NTOP
  270. if (inet_ntop(AF_INET, &addr, new_string, 255) == NULL) {
  271. warnx("Unable to convert 0x%x to a string", ip);
  272. strlcpy(new_string, "", sizeof(new_string));
  273. }
  274. return new_string;
  275. #elif defined HAVE_INET_NTOA
  276. return inet_pton(&addr);
  277. #else
  278. #error "Unable to support get_addr2name4."
  279. #endif
  280. if (dnslookup != DNS_DONT_RESOLVE) {
  281. warn("Sorry, we don't support name resolution.");
  282. }
  283. return new_string;
  284. }
  285. /*
  286. Local Variables:
  287. mode:c
  288. indent-tabs-mode:nil
  289. c-basic-offset:4
  290. End:
  291. */