get.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /* $Id$ */
  2. /*
  3. * Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
  4. * Copyright (c) 2013-2018 Fred Klassen <tcpreplay at appneta dot com> - AppNeta
  5. *
  6. * The Tcpreplay Suite of tools is free software: you can redistribute it
  7. * and/or modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, either version 3 of the
  9. * License, or with the authors permission any later version.
  10. *
  11. * The Tcpreplay Suite is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "config.h"
  20. #include "defines.h"
  21. #include "common.h"
  22. #include "../../lib/sll.h"
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <arpa/inet.h>
  27. #include <ctype.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #ifdef DEBUG
  31. extern int debug;
  32. #endif
  33. #if defined HAVE_PCAP_VERSION && ! defined HAVE_WIN32
  34. extern const char pcap_version[];
  35. #endif
  36. #define JUNIPER_FLAG_NO_L2 0x02 /* L2 header */
  37. #define JUNIPER_FLAG_EXT 0x80 /* Juniper extensions present */
  38. #define JUNIPER_PCAP_MAGIC "MGC"
  39. /**
  40. * Depending on what version of libpcap/WinPcap there are different ways to get
  41. * the version of the libpcap/WinPcap library. This presents a unified way to
  42. * get that information.
  43. */
  44. const char *
  45. get_pcap_version(void)
  46. {
  47. #if defined HAVE_WINPCAP
  48. static char ourver[255];
  49. char *last, *version;
  50. /* WinPcap returns a string like:
  51. * WinPcap version 4.0 (packet.dll version 4.0.0.755), based on libpcap version 0.9.5
  52. */
  53. version = safe_strdup(pcap_lib_version());
  54. strtok_r(version, " ", &last);
  55. strtok_r(NULL, " ", &last);
  56. strlcpy(ourver, strtok_r(NULL, " ", &last), 255);
  57. safe_free(version);
  58. return ourver;
  59. #elif defined HAVE_PCAP_VERSION
  60. return pcap_version;
  61. #else
  62. return pcap_lib_version();
  63. #endif
  64. }
  65. /**
  66. * returns the L2 protocol (IP, ARP, etc)
  67. * or 0 for error
  68. */
  69. uint16_t
  70. get_l2protocol(const u_char *pktdata, const uint32_t datalen, const int datalink)
  71. {
  72. uint16_t eth_hdr_offset = 0;
  73. if (!pktdata || !datalen) {
  74. errx(-1, "invalid l2 parameters: pktdata=0x%p len=%d",
  75. pktdata, datalen);
  76. return 0;
  77. }
  78. switch (datalink) {
  79. case DLT_RAW:
  80. if (datalen < 1)
  81. return 0;
  82. if ((pktdata[0] >> 4) == 4)
  83. return ETHERTYPE_IP;
  84. else if ((pktdata[0] >> 4) == 6)
  85. return ETHERTYPE_IP6;
  86. break;
  87. case DLT_JUNIPER_ETHER:
  88. if (datalen < 4)
  89. return 0;
  90. if (memcmp(pktdata, JUNIPER_PCAP_MAGIC, 3)) {
  91. warnx("No Magic Number found during protocol lookup: %s (0x%x)",
  92. pcap_datalink_val_to_description(datalink), datalink);
  93. return 0;
  94. }
  95. if ((pktdata[3] & JUNIPER_FLAG_EXT) == JUNIPER_FLAG_EXT) {
  96. if (datalen < 6)
  97. return 0; /* datalen too short */
  98. eth_hdr_offset = ntohs(*((uint16_t*)&pktdata[4]));
  99. eth_hdr_offset += 6; /* MGC + flags + ext_total_len */
  100. } else {
  101. eth_hdr_offset = 4; /* MGC + flags (no header extensions) */
  102. }
  103. if ((pktdata[3] & JUNIPER_FLAG_NO_L2) == JUNIPER_FLAG_NO_L2) {
  104. /* no L2 header present - eth_hdr_offset is actually IP offset */
  105. uint32_t ip_hdr_offset = eth_hdr_offset;
  106. if (datalen < ip_hdr_offset + 1)
  107. return 0;
  108. if ((pktdata[ip_hdr_offset] >> 4) == 4)
  109. return ETHERTYPE_IP;
  110. else if ((pktdata[ip_hdr_offset] >> 4) == 6)
  111. return ETHERTYPE_IP6;
  112. else
  113. return 0;
  114. }
  115. /* fall through */
  116. case DLT_EN10MB:
  117. if ((size_t)datalen >= (sizeof(eth_hdr_t) + eth_hdr_offset)) {
  118. eth_hdr_t *eth_hdr = (eth_hdr_t *)(pktdata + eth_hdr_offset);
  119. uint16_t ether_type = ntohs(eth_hdr->ether_type);
  120. uint16_t l2_len = sizeof(*eth_hdr) + eth_hdr_offset;
  121. while (ether_type == ETHERTYPE_VLAN) {
  122. if (datalen < l2_len + sizeof(vlan_hdr_t))
  123. return 0;
  124. vlan_hdr_t *vlan_hdr = (vlan_hdr_t*)(pktdata + l2_len);
  125. ether_type = ntohs(vlan_hdr->vlan_tpid);
  126. l2_len += sizeof(vlan_hdr_t);
  127. }
  128. return ether_type; /* yes, return it in host byte order */
  129. }
  130. break;
  131. case DLT_PPP_SERIAL:
  132. if ((size_t)datalen >= sizeof(struct tcpr_pppserial_hdr)) {
  133. struct tcpr_pppserial_hdr *ppp = (struct tcpr_pppserial_hdr *)pktdata;
  134. if (ntohs(ppp->protocol) == 0x0021)
  135. return htons(ETHERTYPE_IP);
  136. else
  137. return ppp->protocol;
  138. }
  139. break;
  140. case DLT_C_HDLC:
  141. if ((size_t)datalen >= sizeof(hdlc_hdr_t)) {
  142. hdlc_hdr_t *hdlc_hdr = (hdlc_hdr_t *)pktdata;
  143. return hdlc_hdr->protocol;
  144. }
  145. break;
  146. case DLT_LINUX_SLL:
  147. if ((size_t)datalen >= sizeof(sll_hdr_t)) {
  148. sll_hdr_t *sll_hdr = (sll_hdr_t *)pktdata;
  149. return sll_hdr->sll_protocol;
  150. }
  151. break;
  152. default:
  153. errx(-1, "Unable to process unsupported DLT type: %s (0x%x)",
  154. pcap_datalink_val_to_description(datalink), datalink);
  155. }
  156. return 0;
  157. }
  158. /**
  159. * returns the length in number of bytes of the L2 header, or -1 on error
  160. */
  161. int
  162. get_l2len(const u_char *pktdata, const int datalen, const int datalink)
  163. {
  164. int l2_len = 0;
  165. assert(pktdata);
  166. assert(datalen);
  167. switch (datalink) {
  168. case DLT_RAW:
  169. /* pktdata IS the ip header! */
  170. break;
  171. case DLT_JUNIPER_ETHER:
  172. if (datalen < 4) {
  173. l2_len = -1;
  174. break;
  175. }
  176. if (memcmp(pktdata, JUNIPER_PCAP_MAGIC, 3)) {
  177. warnx("No Magic Number found during L2 lookup: %s (0x%x)",
  178. pcap_datalink_val_to_description(datalink), datalink);
  179. l2_len = -1;
  180. break;
  181. }
  182. if ((pktdata[3] & JUNIPER_FLAG_NO_L2) == JUNIPER_FLAG_NO_L2) {
  183. /* no L2 header present */
  184. l2_len = 0;
  185. break;
  186. }
  187. if ((pktdata[3] & JUNIPER_FLAG_EXT) == JUNIPER_FLAG_EXT) {
  188. if (datalen < 6) {
  189. /* datalen too short */
  190. l2_len = -1;
  191. break;
  192. }
  193. l2_len = ntohs(*((uint16_t*)&pktdata[4]));
  194. l2_len += 6; /* MGC + flags + ext_total_len */
  195. } else {
  196. l2_len = 4; /* MGC + flags */
  197. }
  198. /* fall through */
  199. case DLT_EN10MB:
  200. if ((size_t)datalen >= sizeof(eth_hdr_t) + l2_len) {
  201. uint16_t ether_type = ntohs(((eth_hdr_t*)(pktdata + l2_len))->ether_type);
  202. l2_len += sizeof(eth_hdr_t);
  203. while (ether_type == ETHERTYPE_VLAN) {
  204. if ((size_t)datalen < sizeof(vlan_hdr_t) + l2_len) {
  205. l2_len = -1;
  206. break;
  207. }
  208. vlan_hdr_t *vlan_hdr = (vlan_hdr_t *)(pktdata + l2_len);
  209. ether_type = ntohs(vlan_hdr->vlan_tpid);
  210. l2_len += 4;
  211. }
  212. }
  213. if (datalen < l2_len)
  214. l2_len = -1;
  215. break;
  216. case DLT_PPP_SERIAL:
  217. if (datalen >= 4) {
  218. l2_len = 4;
  219. }
  220. break;
  221. case DLT_C_HDLC:
  222. if (datalen >= CISCO_HDLC_LEN) {
  223. l2_len = CISCO_HDLC_LEN;
  224. }
  225. break;
  226. case DLT_LINUX_SLL:
  227. if (datalen >= SLL_HDR_LEN) {
  228. l2_len = SLL_HDR_LEN;
  229. }
  230. break;
  231. default:
  232. errx(-1, "Unable to process unsupported DLT type: %s (0x%x)",
  233. pcap_datalink_val_to_description(datalink), datalink);
  234. return -1; /* we shouldn't get here */
  235. }
  236. return l2_len;
  237. }
  238. /**
  239. * \brief returns a ptr to the ipv4 header + data or NULL if it's not IP
  240. *
  241. * we may use an extra buffer for the IP header (and above)
  242. * on strictly aligned systems where the layer 2 header doesn't
  243. * fall on a 4 byte boundary (like a standard Ethernet header)
  244. *
  245. * Note: you can cast the result as an ip_hdr_t, but you'll be able
  246. * to access data above the header minus any stripped L2 data
  247. */
  248. const u_char *
  249. get_ipv4(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
  250. {
  251. const u_char *ip_hdr = NULL;
  252. int l2_len = 0;
  253. uint16_t proto;
  254. assert(pktdata);
  255. assert(datalen);
  256. assert(*newbuff);
  257. l2_len = get_l2len(pktdata, datalen, datalink);
  258. /* sanity... datalen must be > l2_len + IP header len*/
  259. if (l2_len < 0 || l2_len + TCPR_IPV4_H > datalen) {
  260. dbg(1, "get_ipv4(): Layer 2 len > total packet len, hence no IP header");
  261. return NULL;
  262. }
  263. proto = get_l2protocol(pktdata, datalen, datalink);
  264. if (proto != ETHERTYPE_IP)
  265. return NULL;
  266. #ifdef FORCE_ALIGN
  267. /*
  268. * copy layer 3 and up to our temp packet buffer
  269. * for now on, we have to edit the packetbuff because
  270. * just before we send the packet, we copy the packetbuff
  271. * back onto the pkt.data + l2len buffer
  272. * we do all this work to prevent byte alignment issues
  273. */
  274. if (l2_len % sizeof(long)) {
  275. memcpy(*newbuff, (pktdata + l2_len), (datalen - l2_len));
  276. ip_hdr = *newbuff;
  277. } else {
  278. /* we don't have to do a memcpy if l2_len lands on a boundary */
  279. ip_hdr = (pktdata + l2_len);
  280. }
  281. #else
  282. /*
  283. * on non-strict byte align systems, don't need to memcpy(),
  284. * just point to l2len bytes into the existing buffer
  285. */
  286. ip_hdr = (pktdata + l2_len);
  287. #endif
  288. return ip_hdr;
  289. }
  290. /**
  291. * \brief returns a ptr to the ipv6 header + data or NULL if it's not IP
  292. *
  293. * we may use an extra buffer for the IP header (and above)
  294. * on strictly aligned systems where the layer 2 header doesn't
  295. * fall on a 4 byte boundary (like a standard Ethernet header)
  296. *
  297. * Note: you can cast the result as an ip_hdr_t, but you'll be able
  298. * to access data above the header minus any stripped L2 data
  299. */
  300. const u_char *
  301. get_ipv6(const u_char *pktdata, int datalen, int datalink, u_char **newbuff)
  302. {
  303. const u_char *ip6_hdr = NULL;
  304. int l2_len = 0;
  305. uint16_t proto;
  306. assert(pktdata);
  307. assert(datalen);
  308. assert(*newbuff);
  309. l2_len = get_l2len(pktdata, datalen, datalink);
  310. /* sanity... datalen must be > l2_len + IP header len*/
  311. if (l2_len < 0 || l2_len + TCPR_IPV6_H > datalen) {
  312. dbg(1, "get_ipv6(): Layer 2 len > total packet len, hence no IPv6 header");
  313. return NULL;
  314. }
  315. proto = get_l2protocol(pktdata, datalen, datalink);
  316. if (proto != ETHERTYPE_IP6)
  317. return NULL;
  318. #ifdef FORCE_ALIGN
  319. /*
  320. * copy layer 3 and up to our temp packet buffer
  321. * for now on, we have to edit the packetbuff because
  322. * just before we send the packet, we copy the packetbuff
  323. * back onto the pkt.data + l2len buffer
  324. * we do all this work to prevent byte alignment issues
  325. */
  326. if (l2_len % sizeof(long)) {
  327. memcpy(*newbuff, (pktdata + l2_len), (datalen - l2_len));
  328. ip6_hdr = *newbuff;
  329. } else {
  330. /* we don't have to do a memcpy if l2_len lands on a boundary */
  331. ip6_hdr = (pktdata + l2_len);
  332. }
  333. #else
  334. /*
  335. * on non-strict byte align systems, don't need to memcpy(),
  336. * just point to l2len bytes into the existing buffer
  337. */
  338. ip6_hdr = (pktdata + l2_len);
  339. #endif
  340. return ip6_hdr;
  341. }
  342. /**
  343. * \brief returns a pointer to the layer 4 header which is just beyond the IPv4 header
  344. *
  345. * If the packet is to short, returns NULL
  346. */
  347. void *
  348. get_layer4_v4(const ipv4_hdr_t *ip_hdr, const int l3len)
  349. {
  350. void *ptr;
  351. assert(ip_hdr);
  352. ptr = (u_char *)ip_hdr + (ip_hdr->ip_hl << 2);
  353. /* make sure we don't jump over the end of the buffer */
  354. if ((u_char *)ptr > ((u_char *)ip_hdr + l3len))
  355. return NULL;
  356. return ((void *)ptr);
  357. }
  358. /**
  359. * returns a pointer to the layer 4 header which is just beyond the IPv6 header
  360. * and any extension headers or NULL when there is none as in the case of
  361. * v6 Frag or ESP header. Function is recursive.
  362. */
  363. void *
  364. get_layer4_v6(const ipv6_hdr_t *ip6_hdr, const int l3len)
  365. {
  366. struct tcpr_ipv6_ext_hdr_base *next, *exthdr;
  367. uint8_t proto;
  368. uint32_t maxlen;
  369. int min_len;
  370. assert(ip6_hdr);
  371. min_len = TCPR_IPV6_H + sizeof(struct tcpr_ipv6_ext_hdr_base);
  372. if (l3len < min_len)
  373. return NULL;
  374. /* jump to the end of the IPv6 header */
  375. next = (struct tcpr_ipv6_ext_hdr_base *)((u_char *)ip6_hdr + TCPR_IPV6_H);
  376. proto = ip6_hdr->ip_nh;
  377. while (1) {
  378. dbgx(3, "Processing proto: 0x%hx", (uint16_t)proto);
  379. switch (proto) {
  380. /* recurse due to v6-in-v6, need to recast next as an IPv6 Header */
  381. case TCPR_IPV6_NH_IPV6:
  382. dbg(3, "recursing due to v6-in-v6");
  383. return get_layer4_v6((ipv6_hdr_t *)next, l3len - min_len);
  384. break;
  385. /* loop again */
  386. case TCPR_IPV6_NH_AH:
  387. case TCPR_IPV6_NH_ROUTING:
  388. case TCPR_IPV6_NH_DESTOPTS:
  389. case TCPR_IPV6_NH_HBH:
  390. dbgx(3, "Going deeper due to extension header 0x%02X", proto);
  391. maxlen = l3len - (int)((u_char *)ip6_hdr - (u_char *)next);
  392. exthdr = get_ipv6_next(next, maxlen);
  393. if (exthdr == NULL)
  394. return next;
  395. proto = exthdr->ip_nh;
  396. next = exthdr;
  397. break;
  398. /*
  399. * Can't handle. Unparsable IPv6 fragment/encrypted data
  400. */
  401. case TCPR_IPV6_NH_FRAGMENT:
  402. case TCPR_IPV6_NH_ESP:
  403. return NULL;
  404. break;
  405. /*
  406. * no further processing, either TCP, UDP, ICMP, etc...
  407. */
  408. default:
  409. if (proto != ip6_hdr->ip_nh) {
  410. dbgx(3, "Returning byte offset of this ext header: %u",
  411. IPV6_EXTLEN_TO_BYTES(next->ip_len));
  412. return (void *)((u_char *)next + IPV6_EXTLEN_TO_BYTES(next->ip_len));
  413. } else {
  414. dbgx(3, "%s", "Returning end of IPv6 Header");
  415. return next;
  416. }
  417. break;
  418. } /* switch */
  419. } /* while */
  420. }
  421. /**
  422. * returns the next payload or header of the current extension header
  423. * returns NULL for none/ESP.
  424. */
  425. void *
  426. get_ipv6_next(struct tcpr_ipv6_ext_hdr_base *exthdr, const int len)
  427. {
  428. int extlen = 0;
  429. int maxlen;
  430. void *ptr;
  431. assert(exthdr);
  432. maxlen = *((int*)((u_char *)exthdr + len));
  433. dbgx(3, "Jumping to next IPv6 header. Processing 0x%02x", exthdr->ip_nh);
  434. switch (exthdr->ip_nh) {
  435. /* no further processing */
  436. case TCPR_IPV6_NH_NO_NEXT:
  437. case TCPR_IPV6_NH_ESP:
  438. dbg(3, "No-Next or ESP... can't go any further...");
  439. return NULL;
  440. break;
  441. /*
  442. * fragment header is fixed size
  443. * FIXME: Frag header has further ext headers (has a ip_nh field)
  444. * but I don't support it because there's never a full L4 + payload beyond.
  445. */
  446. case TCPR_IPV6_NH_FRAGMENT:
  447. dbg(3, "Looks like were a fragment header. Returning some frag'd data.");
  448. ptr = (void *)((u_char *)exthdr + sizeof(struct tcpr_ipv6_frag_hdr));
  449. if (*(int*)ptr > maxlen)
  450. return NULL;
  451. return ptr;
  452. break;
  453. /* all the rest require us to go deeper using the ip_len field */
  454. case TCPR_IPV6_NH_IPV6:
  455. case TCPR_IPV6_NH_ROUTING:
  456. case TCPR_IPV6_NH_DESTOPTS:
  457. case TCPR_IPV6_NH_HBH:
  458. case TCPR_IPV6_NH_AH:
  459. extlen = IPV6_EXTLEN_TO_BYTES(exthdr->ip_len);
  460. dbgx(3, "Looks like we're an ext header (0x%hhx). Jumping %u bytes"
  461. " to the next", exthdr->ip_nh, extlen);
  462. ptr = (void *)((u_char *)exthdr + extlen);
  463. if (*(int*)ptr > maxlen)
  464. return NULL;
  465. return ptr;
  466. break;
  467. default:
  468. dbg(3, "Must not be a v6 extension header... returning self");
  469. return (void *)exthdr;
  470. break;
  471. }
  472. }
  473. /**
  474. * returns the protocol of the actual layer4 header by processing through
  475. * the extension headers
  476. */
  477. uint8_t
  478. get_ipv6_l4proto(const ipv6_hdr_t *ip6_hdr, const int l3len)
  479. {
  480. u_char *ptr = (u_char *)ip6_hdr + TCPR_IPV6_H; /* jump to the end of the IPv6 header */
  481. uint8_t proto;
  482. struct tcpr_ipv6_ext_hdr_base *exthdr = NULL;
  483. assert(ip6_hdr);
  484. proto = ip6_hdr->ip_nh;
  485. int l4len = l3len - TCPR_IPV6_H;
  486. if (l4len < 0)
  487. return proto;
  488. while (TRUE) {
  489. dbgx(3, "Processing next proto 0x%02X", proto);
  490. switch (proto) {
  491. /* no further processing for IPV6 types with nothing beyond them */
  492. case TCPR_IPV6_NH_FRAGMENT:
  493. case TCPR_IPV6_NH_ESP:
  494. dbg(3, "No-Next or ESP... can't go any further...");
  495. return proto;
  496. break;
  497. /* recurse */
  498. case TCPR_IPV6_NH_IPV6:
  499. dbg(3, "Recursing due to v6 in v6");
  500. return get_ipv6_l4proto((ipv6_hdr_t *)ptr, l4len);
  501. break;
  502. /* loop again */
  503. case TCPR_IPV6_NH_AH:
  504. case TCPR_IPV6_NH_ROUTING:
  505. case TCPR_IPV6_NH_DESTOPTS:
  506. case TCPR_IPV6_NH_HBH:
  507. dbgx(3, "Jumping to next extension header (0x%hhx)", proto);
  508. exthdr = get_ipv6_next((struct tcpr_ipv6_ext_hdr_base *)ptr,
  509. l4len);
  510. if (exthdr == NULL)
  511. return proto;
  512. proto = exthdr->ip_nh;
  513. l4len -= (u_char *)exthdr - ptr;
  514. ptr = (u_char *)exthdr;
  515. break;
  516. /* should be TCP, UDP or the like */
  517. default:
  518. dbgx(3, "Selecting next L4 Proto as: 0x%02x", proto);
  519. return proto;
  520. } /* switch */
  521. } /* while */
  522. }
  523. /**
  524. * \brief Converts a human readable IPv4 address to a binary one
  525. *
  526. * stolen from LIBNET since I didn't want to have to deal with
  527. * passing a libnet_t around. Returns 0xFFFFFFFF (255.255.255.255)
  528. * on error
  529. */
  530. uint32_t
  531. get_name2addr4(const char *hostname, bool dnslookup)
  532. {
  533. struct in_addr addr;
  534. #if ! defined HAVE_INET_ATON && defined HAVE_INET_ADDR
  535. struct hostent *host_ent;
  536. #endif
  537. if (dnslookup) {
  538. #ifdef HAVE_INET_ATON
  539. if (inet_aton(hostname, &addr) != 1) {
  540. return(0xffffffff);
  541. }
  542. #elif defined HAVE_INET_ADDR
  543. if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
  544. if (!(host_ent = gethostbyname(hostname))) {
  545. warnx("unable to resolve %s: %s", hostname, strerror(errno));
  546. /* this is actually 255.255.255.255 */
  547. return (0xffffffff);
  548. }
  549. /* was: host_ent->h_length); */
  550. memcpy(&addr.s_addr, host_ent->h_addr, sizeof(addr.s_addr));
  551. }
  552. #else
  553. warn("Unable to support get_name2addr4 w/ resolve");
  554. /* call ourselves recursively once w/o resolving the hostname */
  555. return get_name2addr4(hostname, DNS_DONT_RESOLVE);
  556. #endif
  557. /* return in network byte order */
  558. return (addr.s_addr);
  559. } else {
  560. /*
  561. * We only want dots 'n decimals.
  562. */
  563. int i;
  564. uint32_t m;
  565. if (!isdigit(hostname[0])) {
  566. warnx("Expected dotted-quad notation (%s) when DNS lookups are disabled",
  567. hostname);
  568. /* XXX - this is actually 255.255.255.255 */
  569. return (-1);
  570. }
  571. m = 0;
  572. for (i = 0; i < 4; i++) {
  573. u_int val;
  574. m <<= 8;
  575. if (*hostname) {
  576. val = 0;
  577. while (*hostname && *hostname != '.') {
  578. val *= 10;
  579. val += *hostname - '0';
  580. if (val > 255) {
  581. dbgx(4, "value %d > 255 for dotted quad", val);
  582. /* this is actually 255.255.255.255 */
  583. return (-1);
  584. }
  585. hostname++;
  586. }
  587. m |= val;
  588. if (*hostname) {
  589. hostname++;
  590. }
  591. }
  592. }
  593. /* host byte order */
  594. return (ntohl(m));
  595. }
  596. }
  597. /**
  598. * \brief Converts human readable IPv6 address to binary value
  599. *
  600. * Wrapper around inet_pton
  601. * Returns 1 for valid, 0 for not parsable and -1 for system error.
  602. * Does not support DNS.
  603. */
  604. int
  605. get_name2addr6(const char *hostname, bool dnslookup, struct tcpr_in6_addr *addr)
  606. {
  607. (void)dnslookup; /* prevent warning about unused arg */
  608. #ifdef HAVE_INET_PTON
  609. return inet_pton(AF_INET6, hostname, addr);
  610. #else
  611. #error "Unable to support get_name2addr6: Missing inet_pton() support."
  612. #endif
  613. return -1;
  614. }
  615. /**
  616. * \brief Converts binary IPv4 address to a string.
  617. *
  618. * Generic wrapper around inet_ntop() and inet_ntoa() depending on whichever
  619. * is available on your system. Does not support DNS.
  620. */
  621. const char *
  622. get_addr2name4(const uint32_t ip, bool _U_ dnslookup)
  623. {
  624. struct in_addr addr;
  625. static char *new_string = NULL;
  626. if (new_string == NULL)
  627. new_string = (char *)safe_malloc(255);
  628. new_string[0] = '\0';
  629. addr.s_addr = ip;
  630. #ifdef HAVE_INET_NTOP
  631. if (inet_ntop(AF_INET, &addr, new_string, 255) == NULL) {
  632. warnx("Unable to convert 0x%x to a string", ip);
  633. new_string[0] = 0;
  634. }
  635. return new_string;
  636. #elif defined HAVE_INET_NTOA
  637. return inet_ntoa(&addr);
  638. #else
  639. #error "Unable to support get_addr2name4."
  640. #endif
  641. }
  642. /**
  643. * \brief Converts a IPv6 binary address to a string.a
  644. *
  645. * Does not support DNS.
  646. */
  647. const char *
  648. get_addr2name6(const struct tcpr_in6_addr *addr, _U_ bool dnslookup)
  649. {
  650. static char *new_string = NULL;
  651. if (new_string == NULL)
  652. new_string = (char *)safe_malloc(255);
  653. new_string[0] = '\0';
  654. #ifdef HAVE_INET_NTOP
  655. if (inet_ntop(AF_INET6, addr, new_string, 255) == NULL) {
  656. warn("Unable to convert addr to a string");
  657. new_string[0] = 0;
  658. }
  659. return new_string;
  660. #else
  661. #error "Unable to support get_addr2name6."
  662. #endif
  663. }
  664. /**
  665. * \brief Converts the binary network address of a tcpr_cidr_t to a string
  666. */
  667. const char *
  668. get_cidr2name(const tcpr_cidr_t *cidr_ptr, bool dnslookup)
  669. {
  670. if (cidr_ptr->family == AF_INET) {
  671. return get_addr2name4(cidr_ptr->u.network, dnslookup);
  672. } else if (cidr_ptr->family == AF_INET6) {
  673. return get_addr2name6(&cidr_ptr->u.network6, dnslookup);
  674. } else {
  675. return NULL;
  676. }
  677. }