bridge.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /* $Id: bridge.c 2423 2010-03-13 07:09:49Z aturner $ */
  2. /*
  3. * Copyright (c) 2001-2010 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 <sys/time.h>
  35. #include <signal.h>
  36. #include <string.h>
  37. #include <netinet/in.h>
  38. #include <time.h>
  39. #include <errno.h>
  40. #include <stdlib.h>
  41. #ifdef HAVE_BPF
  42. #include <sys/select.h> /* necessary for using select() for BPF devices */
  43. #endif
  44. #include "tcpbridge.h"
  45. #include "bridge.h"
  46. #include "send_packets.h"
  47. #include "tcpedit/tcpedit.h"
  48. extern tcpbridge_opt_t options;
  49. extern struct timeval begin, end;
  50. extern COUNTER bytes_sent, failed, pkts_sent;
  51. extern volatile int didsig;
  52. #ifdef DEBUG
  53. extern int debug;
  54. #endif
  55. static int live_callback(struct live_data_t *,
  56. struct pcap_pkthdr *, const u_char *);
  57. /**
  58. * First, prep our RB Tree which tracks where each (source)
  59. * MAC really lives so we don't create really nasty network
  60. * storms.
  61. */
  62. static struct macsrc_t *new_node(void);
  63. RB_HEAD(macsrc_tree, macsrc_t) macsrc_root;
  64. static int
  65. rbmacsrc_comp(struct macsrc_t *a, struct macsrc_t *b)
  66. {
  67. return (memcmp(a->key, b->key, ETHER_ADDR_LEN));
  68. }
  69. RB_PROTOTYPE(macsrc_tree, macsrc_t, node, rbmacsrc_comp)
  70. RB_GENERATE(macsrc_tree, macsrc_t, node, rbmacsrc_comp)
  71. /**
  72. * redblack init
  73. */
  74. void
  75. rbinit(void)
  76. {
  77. RB_INIT(&macsrc_root);
  78. }
  79. /**
  80. * create a new node... Malloc's memory
  81. */
  82. struct macsrc_t *
  83. new_node(void)
  84. {
  85. struct macsrc_t *node;
  86. node = (struct macsrc_t *)safe_malloc(sizeof(struct macsrc_t));
  87. memset(node, '\0', sizeof(struct macsrc_t));
  88. return (node);
  89. }
  90. /**
  91. * main loop for bridging in only one direction
  92. * optimized to not use poll(), but rather libpcap's builtin pcap_loop()
  93. */
  94. static void
  95. do_bridge_unidirectional(tcpbridge_opt_t *options, tcpedit_t *tcpedit)
  96. {
  97. struct live_data_t livedata;
  98. int retcode;
  99. assert(options);
  100. assert(tcpedit);
  101. livedata.tcpedit = tcpedit;
  102. livedata.source = PCAP_INT1;
  103. livedata.pcap = options->pcap1;
  104. livedata.options = options;
  105. if ((retcode = pcap_loop(options->pcap1, options->limit_send,
  106. (pcap_handler)live_callback, (u_char *) &livedata)) < 0) {
  107. warnx("Error in pcap_loop(): %s", pcap_geterr(options->pcap1));
  108. }
  109. }
  110. #ifndef HAVE_BPF
  111. /**
  112. * main loop for bridging in both directions. Since we dealing with two handles
  113. * we need to poll() on them which isn't the most efficent.
  114. *
  115. * Note that this function is only used on systems which do not have a BPF
  116. * device because poll() behaves poorly with /dev/bpf
  117. */
  118. static void
  119. do_bridge_bidirectional(tcpbridge_opt_t *options, tcpedit_t *tcpedit)
  120. {
  121. struct pollfd polls[2]; /* one for left & right pcap */
  122. int pollresult, pollcount, timeout;
  123. struct live_data_t livedata;
  124. assert(options);
  125. assert(tcpedit);
  126. livedata.tcpedit = tcpedit;
  127. livedata.options = options;
  128. /*
  129. * loop until ctrl-C or we've sent enough packets
  130. * note that if -L wasn't specified, limit_send is
  131. * set to 0 so this will loop infinately
  132. */
  133. while ((options->limit_send == 0) || (options->limit_send > pkts_sent)) {
  134. if (didsig)
  135. break;
  136. dbgx(3, "limit_send: " COUNTER_SPEC " \t pkts_sent: " COUNTER_SPEC,
  137. options->limit_send, pkts_sent);
  138. /* reset the result codes */
  139. polls[PCAP_INT1].revents = 0;
  140. polls[PCAP_INT1].events = POLLIN;
  141. polls[PCAP_INT1].fd = pcap_fileno(options->pcap1);
  142. polls[PCAP_INT2].revents = 0;
  143. polls[PCAP_INT2].events = POLLIN;
  144. polls[PCAP_INT2].fd = pcap_fileno(options->pcap2);
  145. timeout = options->poll_timeout;
  146. pollcount = 2;
  147. /* poll for a packet on the two interfaces */
  148. pollresult = poll(polls, pollcount, timeout);
  149. /* poll has returned, process the result */
  150. if (pollresult > 0) {
  151. dbgx(3, "pollresult: %d", pollresult);
  152. /* success, got one or more packets */
  153. if (polls[PCAP_INT1].revents > 0) {
  154. dbg(5, "Processing first interface");
  155. livedata.source = PCAP_INT1;
  156. livedata.pcap = options->pcap1;
  157. pcap_dispatch(options->pcap1, -1, (pcap_handler) live_callback,
  158. (u_char *) &livedata);
  159. }
  160. /* check the other interface?? */
  161. if (polls[PCAP_INT2].revents > 0) {
  162. dbg(5, "Processing second interface");
  163. livedata.source = PCAP_INT2;
  164. livedata.pcap = options->pcap2;
  165. pcap_dispatch(options->pcap2, -1, (pcap_handler) live_callback,
  166. (u_char *) &livedata);
  167. }
  168. }
  169. else if (pollresult == 0) {
  170. dbg(3, "poll timeout exceeded...");
  171. /* do something here? */
  172. }
  173. else {
  174. /* poll error, probably a Ctrl-C */
  175. warnx("poll() error: %s", strerror(errno));
  176. }
  177. /* go back to the top of the loop */
  178. }
  179. } /* do_bridge_bidirectional() */
  180. #elif defined HAVE_BPF && defined HAVE_PCAP_SETNONBLOCK
  181. /**
  182. * main loop for bridging in both directions with BPF. We'll be using
  183. * select() because that works better on older *BSD and OSX
  184. *
  185. * See this for details behind this maddness:
  186. * http://article.gmane.org/gmane.network.tcpdump.devel/3581
  187. */
  188. static void
  189. do_bridge_bidirectional(tcpbridge_opt_t *options, tcpedit_t *tcpedit)
  190. {
  191. fd_set readfds, writefds, errorfds;
  192. struct live_data_t livedata;
  193. int fd, nfds, ret;
  194. struct timeval timeout = { 0, 100 }; /* default to 100ms timeout */
  195. char ebuf[PCAP_ERRBUF_SIZE];
  196. assert(options);
  197. assert(tcpedit);
  198. livedata.tcpedit = tcpedit;
  199. livedata.options = options;
  200. /*
  201. * loop until ctrl-C or we've sent enough packets
  202. * note that if -L wasn't specified, limit_send is
  203. * set to 0 so this will loop infinately
  204. */
  205. while ((options->limit_send == 0) || (options->limit_send > pkts_sent)) {
  206. if (didsig)
  207. break;
  208. dbgx(3, "limit_send: " COUNTER_SPEC " \t pkts_sent: " COUNTER_SPEC,
  209. options->limit_send, pkts_sent);
  210. /* reset the result codes */
  211. FD_ZERO(&readfds);
  212. FD_ZERO(&writefds);
  213. FD_ZERO(&errorfds);
  214. /* set for reading */
  215. #ifdef HAVE_PCAP_GET_SELECTABLE_FD
  216. fd = pcap_get_selectable_fd(options->pcap1);
  217. #else
  218. fd = pcap_fileno(options->pcap1);
  219. #endif
  220. if ((pcap_setnonblock(options->pcap1, 1, ebuf)) < 0)
  221. errx(1, "Unable to set %s into nonblocking mode: %s", options->intf1, ebuf);
  222. FD_SET(fd, &readfds);
  223. #ifdef HAVE_PCAP_GET_SELECTABLE_FD
  224. fd = pcap_get_selectable_fd(options->pcap2);
  225. #else
  226. fd = pcap_fileno(options->pcap2);
  227. #endif
  228. if ((pcap_setnonblock(options->pcap2, 1, ebuf)) < 0)
  229. errx(1, "Unable to set %s into nonblocking mode: %s", options->intf2, ebuf);
  230. FD_SET(fd, &readfds);
  231. nfds = 2;
  232. /* wait for a packet on the two interfaces */
  233. ret = select(nfds, &readfds, &writefds, &errorfds, &timeout);
  234. /*
  235. * There is a problem with OS X and certian *BSD's when using
  236. * select() on a character device like /dev/bpf. Hence we always
  237. * must attempt to read off each fd after the timeout. This is why
  238. * we put the fd's in nonblocking mode above!
  239. */
  240. dbg(5, "Processing first interface");
  241. livedata.source = PCAP_INT1;
  242. livedata.pcap = options->pcap1;
  243. pcap_dispatch(options->pcap1, -1, (pcap_handler) live_callback,
  244. (u_char *) &livedata);
  245. dbg(5, "Processing second interface");
  246. livedata.source = PCAP_INT2;
  247. livedata.pcap = options->pcap2;
  248. pcap_dispatch(options->pcap2, -1, (pcap_handler) live_callback,
  249. (u_char *) &livedata);
  250. /* go back to the top of the loop */
  251. }
  252. }
  253. #else
  254. #error "Your system needs a libpcap with pcap_setnonblock(). Please upgrade libpcap."
  255. #endif
  256. /**
  257. * Main entry point to bridging. Does some initial setup and then calls the
  258. * correct loop (unidirectional or bidirectional)
  259. */
  260. void
  261. do_bridge(tcpbridge_opt_t *options, tcpedit_t *tcpedit)
  262. {
  263. /* do we apply a bpf filter? */
  264. if (options->bpf.filter != NULL) {
  265. /* compile filter */
  266. dbgx(2, "Try to compile pcap bpf filter: %s", options->bpf.filter);
  267. if (pcap_compile(options->pcap1, &options->bpf.program, options->bpf.filter, options->bpf.optimize, 0) != 0) {
  268. errx(-1, "Error compiling BPF filter: %s", pcap_geterr(options->pcap1));
  269. }
  270. /* apply filter */
  271. pcap_setfilter(options->pcap1, &options->bpf.program);
  272. /* same for other interface if applicable */
  273. if (options->unidir == 0) {
  274. /* compile filter */
  275. dbgx(2, "Try to compile pcap bpf filter: %s", options->bpf.filter);
  276. if (pcap_compile(options->pcap2, &options->bpf.program, options->bpf.filter, options->bpf.optimize, 0) != 0) {
  277. errx(-1, "Error compiling BPF filter: %s", pcap_geterr(options->pcap2));
  278. }
  279. /* apply filter */
  280. pcap_setfilter(options->pcap2, &options->bpf.program);
  281. }
  282. }
  283. /* register signals */
  284. didsig = 0;
  285. (void)signal(SIGINT, catcher);
  286. if (options->unidir == 1) {
  287. do_bridge_unidirectional(options, tcpedit);
  288. } else {
  289. do_bridge_bidirectional(options, tcpedit);
  290. }
  291. packet_stats(&begin, &end, bytes_sent, pkts_sent, failed);
  292. }
  293. /**
  294. * This is the callback we use with pcap_dispatch to process
  295. * each packet recieved by libpcap on the two interfaces.
  296. * Need to return > 0 to denote success
  297. */
  298. static int
  299. live_callback(struct live_data_t *livedata, struct pcap_pkthdr *pkthdr,
  300. const u_char * nextpkt)
  301. {
  302. ipv4_hdr_t *ip_hdr = NULL;
  303. ipv6_hdr_t *ip6_hdr = NULL;
  304. pcap_t *send = NULL;
  305. static u_char *pktdata = NULL; /* full packet buffer */
  306. int cache_mode, retcode;
  307. static unsigned long packetnum = 0;
  308. struct macsrc_t *node, finder; /* rb tree nodes */
  309. #ifdef DEBUG
  310. u_char dstmac[ETHER_ADDR_LEN];
  311. #endif
  312. u_int16_t l2proto;
  313. packetnum++;
  314. dbgx(2, "packet %lu caplen %d", packetnum, pkthdr->caplen);
  315. /* only malloc the first time */
  316. if (pktdata == NULL) {
  317. /* create packet buffers */
  318. pktdata = (u_char *)safe_malloc(MAXPACKET);
  319. } else {
  320. /* zero out the old packet info */
  321. memset(pktdata, '\0', MAXPACKET);
  322. }
  323. /* copy the packet to our buffer */
  324. memcpy(pktdata, nextpkt, pkthdr->caplen);
  325. #ifdef ENABLE_VERBOSE
  326. /* decode packet? */
  327. if (livedata->options->verbose)
  328. tcpdump_print(livedata->options->tcpdump, pkthdr, nextpkt);
  329. #endif
  330. /* lookup our source MAC in the tree */
  331. memcpy(&finder.key, &pktdata[ETHER_ADDR_LEN], ETHER_ADDR_LEN);
  332. #ifdef DEBUG
  333. memcpy(&dstmac, pktdata, ETHER_ADDR_LEN);
  334. dbgx(1, "SRC MAC: " MAC_FORMAT "\tDST MAC: " MAC_FORMAT,
  335. MAC_STR(finder.key), MAC_STR(dstmac));
  336. #endif
  337. /* first, is this a packet sent locally? If so, ignore it */
  338. if ((memcmp(livedata->options->intf1_mac, &finder.key, ETHER_ADDR_LEN)) == 0) {
  339. dbgx(1, "Packet matches the MAC of %s, skipping.", livedata->options->intf1);
  340. return (1);
  341. }
  342. else if ((memcmp(livedata->options->intf2_mac, &finder.key, ETHER_ADDR_LEN)) == 0) {
  343. dbgx(1, "Packet matches the MAC of %s, skipping.", livedata->options->intf2);
  344. return (1);
  345. }
  346. node = RB_FIND(macsrc_tree, &macsrc_root, &finder);
  347. /* if we can't find the node, build a new one */
  348. if (node == NULL) {
  349. dbg(1, "Unable to find MAC in the tree");
  350. node = new_node();
  351. node->source = livedata->source;
  352. memcpy(&node->key, &finder.key, ETHER_ADDR_LEN);
  353. RB_INSERT(macsrc_tree, &macsrc_root, node);
  354. }
  355. /* otherwise compare sources */
  356. else if (node->source != livedata->source) {
  357. dbg(1, "Found the dest MAC in the tree and it doesn't match this source NIC... skipping packet");
  358. /*
  359. * IMPORTANT!!!
  360. * Never send a packet out the same interface we sourced it on!
  361. */
  362. return (1);
  363. }
  364. /* what is our cache mode? */
  365. cache_mode = livedata->source == PCAP_INT1 ? TCPR_DIR_C2S : TCPR_DIR_S2C;
  366. l2proto = tcpedit_l3proto(livedata->tcpedit, BEFORE_PROCESS, pktdata, pkthdr->len);
  367. dbgx(2, "Packet protocol: %04hx", l2proto);
  368. /* should we skip this packet based on CIDR match? */
  369. if (l2proto == ETHERTYPE_IP) {
  370. dbg(3, "Packet is IPv4");
  371. ip_hdr = (ipv4_hdr_t *)tcpedit_l3data(livedata->tcpedit, BEFORE_PROCESS, pktdata, pkthdr->len);
  372. /* look for include or exclude CIDR match */
  373. if (livedata->options->xX.cidr != NULL) {
  374. if (!process_xX_by_cidr_ipv4(livedata->options->xX.mode, livedata->options->xX.cidr, ip_hdr)) {
  375. dbg(2, "Skipping IPv4 packet due to CIDR match");
  376. return (1);
  377. }
  378. }
  379. }
  380. else if (l2proto == ETHERTYPE_IP6) {
  381. dbg(3, "Packet is IPv6");
  382. ip6_hdr = (ipv6_hdr_t *)tcpedit_l3data(livedata->tcpedit, BEFORE_PROCESS, pktdata, pkthdr->len);
  383. /* look for include or exclude CIDR match */
  384. if (livedata->options->xX.cidr != NULL) {
  385. if (!process_xX_by_cidr_ipv6(livedata->options->xX.mode, livedata->options->xX.cidr, ip6_hdr)) {
  386. dbg(2, "Skipping IPv6 packet due to CIDR match");
  387. return (1);
  388. }
  389. }
  390. }
  391. if ((retcode = tcpedit_packet(livedata->tcpedit, &pkthdr, &pktdata, cache_mode)) < 0) {
  392. if (retcode == TCPEDIT_SOFT_ERROR) {
  393. return 1;
  394. } else { /* TCPEDIT_ERROR */
  395. return -1;
  396. }
  397. }
  398. /*
  399. * send packets out the OTHER interface
  400. * and update the dst mac if necessary
  401. */
  402. switch(node->source) {
  403. case PCAP_INT1:
  404. dbgx(2, "Packet source was %s... sending out on %s", livedata->options->intf1,
  405. livedata->options->intf2);
  406. send = livedata->options->pcap2;
  407. break;
  408. case PCAP_INT2:
  409. dbgx(2, "Packet source was %s... sending out on %s", livedata->options->intf2,
  410. livedata->options->intf1);
  411. send = livedata->options->pcap1;
  412. break;
  413. default:
  414. errx(-1, "wtf? our node->source != PCAP_INT1 and != PCAP_INT2: %c",
  415. node->source);
  416. }
  417. /*
  418. * write packet out on the network
  419. */
  420. if (pcap_sendpacket(send, pktdata, pkthdr->caplen) < 0)
  421. errx(-1, "Unable to send packet out %s: %s",
  422. send == livedata->options->pcap1 ? livedata->options->intf1 : livedata->options->intf2, pcap_geterr(send));
  423. bytes_sent += pkthdr->caplen;
  424. pkts_sent++;
  425. dbgx(1, "Sent packet " COUNTER_SPEC, pkts_sent);
  426. return (1);
  427. } /* live_callback() */