tree.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. /* $Id: tree.c 2447 2010-03-30 18:51:12Z 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 <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include "tree.h"
  38. #include "tcpprep.h"
  39. #include "tcpprep_opts.h"
  40. extern tcpr_data_tree_t treeroot;
  41. extern tcpprep_opt_t options;
  42. #ifdef DEBUG
  43. extern int debug;
  44. #endif
  45. /* static buffer used by tree_print*() functions */
  46. char tree_print_buff[TREEPRINTBUFFLEN];
  47. static tcpr_tree_t *new_tree();
  48. static tcpr_tree_t *packet2tree(const u_char *);
  49. static char *tree_print(tcpr_data_tree_t *);
  50. static char *tree_printnode(const char *, const tcpr_tree_t *);
  51. static void tree_buildcidr(tcpr_data_tree_t *, tcpr_buildcidr_t *);
  52. static int tree_checkincidr(tcpr_data_tree_t *, tcpr_buildcidr_t *);
  53. static int ipv6_cmp(const struct tcpr_in6_addr *a, const struct tcpr_in6_addr *b);
  54. RB_PROTOTYPE(tcpr_data_tree_s, tcpr_tree_s, node, tree_comp)
  55. RB_GENERATE(tcpr_data_tree_s, tcpr_tree_s, node, tree_comp)
  56. /**
  57. * used with rbwalk to walk a tree and generate cidr_t * cidrdata.
  58. * is smart enough to prevent dupes. void * arg is cast to bulidcidr_t
  59. */
  60. void
  61. tree_buildcidr(tcpr_data_tree_t *treeroot, tcpr_buildcidr_t * bcdata)
  62. {
  63. tcpr_tree_t *node = NULL;
  64. tcpr_cidr_t *newcidr = NULL;
  65. unsigned long network = 0;
  66. struct tcpr_in6_addr network6;
  67. unsigned long mask = ~0; /* turn on all bits */
  68. int i, j, k;
  69. dbg(1, "Running: tree_buildcidr()");
  70. RB_FOREACH(node, tcpr_data_tree_s, treeroot) {
  71. /* we only check types that are vaild */
  72. if (bcdata->type != DIR_ANY) /* don't check if we're adding ANY */
  73. if (bcdata->type != node->type) /* no match, exit early */
  74. return;
  75. /*
  76. * in cases of leaves and last visit add to cidrdata if
  77. * necessary. First check IPv4
  78. */
  79. dbgx(4, "Checking if %s exists in cidrdata...", get_addr2name4(node->u.ip, RESOLVE));
  80. if (node->family == AF_INET) {
  81. if (! check_ip_cidr(options.cidrdata, node->u.ip)) { /* if we exist, abort */
  82. dbgx(3, "Node %s doesn't exist... creating.",
  83. get_addr2name4(node->u.ip, RESOLVE));
  84. newcidr = new_cidr();
  85. newcidr->masklen = bcdata->masklen;
  86. network = node->u.ip & (mask << (32 - bcdata->masklen));
  87. dbgx(3, "Using network: %s", get_addr2name4(network, RESOLVE));
  88. newcidr->u.network = network;
  89. add_cidr(&options.cidrdata, &newcidr);
  90. }
  91. }
  92. /* Check IPv6 Address */
  93. else if (node->family == AF_INET6) {
  94. if (! check_ip6_cidr(options.cidrdata, &node->u.ip6)) { /* if we exist, abort */
  95. dbgx(3, "Node %s doesn't exist... creating.",
  96. get_addr2name6(&node->u.ip6, RESOLVE));
  97. newcidr = new_cidr();
  98. newcidr->masklen = bcdata->masklen;
  99. /* init each 4 quads to zero */
  100. for (i = 0; i < 4; i++)
  101. network6.tcpr_s6_addr32[i] = 0;
  102. /* Build our mask */
  103. j = bcdata->masklen / 8;
  104. for (i = 0; i < j; i++)
  105. network6.tcpr_s6_addr[i] = node->u.ip6.tcpr_s6_addr[i];
  106. if ((k = bcdata->masklen % 8) != 0) {
  107. k = ~0 << (8 - k);
  108. network6.tcpr_s6_addr[j] = node->u.ip6.tcpr_s6_addr[i] & k;
  109. }
  110. dbgx(3, "Using network: %s", get_addr2name6(&network6, RESOLVE));
  111. newcidr->u.network6 = network6;
  112. add_cidr(&options.cidrdata, &newcidr);
  113. }
  114. }
  115. }
  116. }
  117. /**
  118. * uses rbwalk to check to see if a given ip address of a given type in the
  119. * tree is inside any of the cidrdata
  120. */
  121. static int
  122. tree_checkincidr(tcpr_data_tree_t *treeroot, tcpr_buildcidr_t * bcdata)
  123. {
  124. tcpr_tree_t *node = NULL;
  125. RB_FOREACH(node, tcpr_data_tree_s, treeroot) {
  126. /* we only check types that are vaild */
  127. if (bcdata->type != DIR_ANY) /* don't check if we're adding ANY */
  128. if (bcdata->type != node->type) /* no match, exit early */
  129. return 0;
  130. /*
  131. * in cases of leaves and last visit add to cidrdata if
  132. * necessary
  133. */
  134. if (node->family == AF_INET && check_ip_cidr(options.cidrdata, node->u.ip)) /* if we exist, abort */
  135. return 1;
  136. if (node->family == AF_INET6 && check_ip6_cidr(options.cidrdata, &node->u.ip6))
  137. return 1;
  138. }
  139. return 0;
  140. }
  141. /**
  142. * processes the tree using rbwalk / tree2cidr to generate a CIDR
  143. * used for 2nd pass, router mode
  144. *
  145. * returns > 0 for success (the mask len), 0 for fail
  146. */
  147. int
  148. process_tree(void)
  149. {
  150. int mymask = 0;
  151. tcpr_buildcidr_t *bcdata;
  152. dbg(1, "Running: process_tree()");
  153. bcdata = (tcpr_buildcidr_t *)safe_malloc(sizeof(tcpr_buildcidr_t));
  154. for (mymask = options.max_mask; mymask <= options.min_mask; mymask++) {
  155. dbgx(1, "Current mask: %u", mymask);
  156. /* set starting vals */
  157. bcdata->type = DIR_SERVER;
  158. bcdata->masklen = mymask;
  159. /* build cidrdata with servers */
  160. tree_buildcidr(&treeroot, bcdata);
  161. /* calculate types of all IP's */
  162. tree_calculate(&treeroot);
  163. /* try to find clients in cidrdata */
  164. bcdata->type = DIR_CLIENT;
  165. if (! tree_checkincidr(&treeroot, bcdata)) { /* didn't find any clients in cidrdata */
  166. safe_free(bcdata);
  167. return (mymask); /* success! */
  168. }
  169. else {
  170. destroy_cidr(options.cidrdata); /* clean up after our mess */
  171. options.cidrdata = NULL;
  172. }
  173. }
  174. safe_free(bcdata);
  175. /* we failed to find a vaild cidr list */
  176. notice("Unable to determine any IP addresses as a clients.");
  177. notice("Perhaps you should change the --ratio, --minmask/maxmask settings, or try another mode?");
  178. return (0);
  179. }
  180. /*
  181. * processes rbdata to bulid cidrdata based upon the
  182. * given type (SERVER, CLIENT, UNKNOWN) using the given masklen
  183. *
  184. * is smart enough to prevent dupes
  185. void
  186. tcpr_tree_to_cidr(const int masklen, const int type)
  187. {
  188. }
  189. */
  190. /**
  191. * Checks to see if an IP is client or server by finding it in the tree
  192. * returns TCPR_DIR_C2S or TCPR_DIR_S2C or -1 on error
  193. * if mode = UNKNOWN, then abort on unknowns
  194. * if mode = CLIENT, then unknowns become clients
  195. * if mode = SERVER, then unknowns become servers
  196. */
  197. tcpr_dir_t
  198. check_ip_tree(const int mode, const unsigned long ip)
  199. {
  200. tcpr_tree_t *node = NULL, *finder = NULL;
  201. finder = new_tree();
  202. finder->family = AF_INET;
  203. finder->u.ip = ip;
  204. node = RB_FIND(tcpr_data_tree_s, &treeroot, finder);
  205. if (node == NULL && mode == DIR_UNKNOWN)
  206. errx(-1, "%s (%lu) is an unknown system... aborting.!\n"
  207. "Try a different auto mode (-n router|client|server)",
  208. get_addr2name4(ip, RESOLVE), ip);
  209. #ifdef DEBUG
  210. switch (node->type) {
  211. case DIR_SERVER:
  212. dbgx(1, "DIR_SERVER: %s", get_addr2name4(ip, RESOLVE));
  213. break;
  214. case DIR_CLIENT:
  215. dbgx(1, "DIR_CLIENT: %s", get_addr2name4(ip, RESOLVE));
  216. break;
  217. case DIR_UNKNOWN:
  218. dbgx(1, "DIR_UNKNOWN: %s", get_addr2name4(ip, RESOLVE));
  219. break;
  220. case DIR_ANY:
  221. dbgx(1, "DIR_ANY: %s", get_addr2name4(ip, RESOLVE));
  222. break;
  223. }
  224. #endif
  225. /*
  226. * FIXME: Is this logic correct? I think this might be backwards :(
  227. */
  228. /* return node type if we found the node, else return the default (mode) */
  229. if (node != NULL) {
  230. switch (node->type) {
  231. case DIR_SERVER:
  232. return TCPR_DIR_C2S;
  233. break;
  234. case DIR_CLIENT:
  235. return TCPR_DIR_S2C;
  236. break;
  237. case DIR_UNKNOWN:
  238. case DIR_ANY:
  239. /* use our current mode to determine return code */
  240. goto return_unknown;
  241. default:
  242. errx(-1, "Node for %s has invalid type: %d", get_addr2name4(ip, RESOLVE), node->type);
  243. }
  244. }
  245. return_unknown:
  246. switch (mode) {
  247. case DIR_SERVER:
  248. return TCPR_DIR_C2S;
  249. break;
  250. case DIR_CLIENT:
  251. return TCPR_DIR_S2C;
  252. break;
  253. default:
  254. return -1;
  255. }
  256. }
  257. tcpr_dir_t
  258. check_ip6_tree(const int mode, const struct tcpr_in6_addr *addr)
  259. {
  260. tcpr_tree_t *node = NULL, *finder = NULL;
  261. finder = new_tree();
  262. finder->family = AF_INET6;
  263. finder->u.ip6 = *addr;
  264. node = RB_FIND(tcpr_data_tree_s, &treeroot, finder);
  265. if (node == NULL && mode == DIR_UNKNOWN)
  266. errx(-1, "%s is an unknown system... aborting.!\n"
  267. "Try a different auto mode (-n router|client|server)",
  268. get_addr2name6(addr, RESOLVE));
  269. #ifdef DEBUG
  270. switch (node->type) {
  271. case DIR_SERVER:
  272. dbgx(1, "DIR_SERVER: %s", get_addr2name6(addr, RESOLVE));
  273. break;
  274. case DIR_CLIENT:
  275. dbgx(1, "DIR_CLIENT: %s", get_addr2name6(addr, RESOLVE));
  276. break;
  277. case DIR_UNKNOWN:
  278. dbgx(1, "DIR_UNKNOWN: %s", get_addr2name6(addr, RESOLVE));
  279. break;
  280. case DIR_ANY:
  281. dbgx(1, "DIR_ANY: %s", get_addr2name6(addr, RESOLVE));
  282. break;
  283. }
  284. #endif
  285. /*
  286. * FIXME: Is this logic correct? I think this might be backwards :(
  287. */
  288. /* return node type if we found the node, else return the default (mode) */
  289. if (node != NULL) {
  290. switch (node->type) {
  291. case DIR_SERVER:
  292. return TCPR_DIR_C2S;
  293. break;
  294. case DIR_CLIENT:
  295. return TCPR_DIR_S2C;
  296. break;
  297. case DIR_UNKNOWN:
  298. case DIR_ANY:
  299. /* use our current mode to determine return code */
  300. goto return_unknown;
  301. default:
  302. errx(-1, "Node for %s has invalid type: %d", get_addr2name6(addr, RESOLVE), node->type);
  303. }
  304. }
  305. return_unknown:
  306. switch (mode) {
  307. case DIR_SERVER:
  308. return TCPR_DIR_C2S;
  309. break;
  310. case DIR_CLIENT:
  311. return TCPR_DIR_S2C;
  312. break;
  313. default:
  314. return -1;
  315. }
  316. }
  317. /**
  318. * Parses the IP header of the given packet (data) to get the SRC/DST IP
  319. * addresses. If the SRC IP doesn't exist in the TREE, we add it as a
  320. * client, if the DST IP doesn't exist in the TREE, we add it as a server
  321. */
  322. void
  323. add_tree_first_ipv4(const u_char *data)
  324. {
  325. tcpr_tree_t *newnode = NULL, *findnode;
  326. eth_hdr_t *eth_hdr = NULL;
  327. ipv4_hdr_t ip_hdr;
  328. assert(data);
  329. /*
  330. * first add/find the source IP/client
  331. */
  332. newnode = new_tree();
  333. eth_hdr = (eth_hdr_t *) (data);
  334. /* prevent issues with byte alignment, must memcpy */
  335. memcpy(&ip_hdr, (data + TCPR_ETH_H), TCPR_IPV4_H);
  336. /* copy over the source ip, and values to gurantee this a client */
  337. newnode->family = AF_INET;
  338. newnode->u.ip = ip_hdr.ip_src.s_addr;
  339. newnode->type = DIR_CLIENT;
  340. newnode->client_cnt = 1000;
  341. findnode = RB_FIND(tcpr_data_tree_s, &treeroot, newnode);
  342. /* if we didn't find it, add it to the tree, else free it */
  343. if (findnode == NULL) {
  344. RB_INSERT(tcpr_data_tree_s, &treeroot, newnode);
  345. } else {
  346. safe_free(newnode);
  347. }
  348. /*
  349. * now add/find the destination IP/server
  350. */
  351. newnode = new_tree();
  352. eth_hdr = (eth_hdr_t *) (data);
  353. memcpy(&ip_hdr, (data + TCPR_ETH_H), TCPR_IPV4_H);
  354. newnode->family = AF_INET;
  355. newnode->u.ip = ip_hdr.ip_dst.s_addr;
  356. newnode->type = DIR_SERVER;
  357. newnode->server_cnt = 1000;
  358. findnode = RB_FIND(tcpr_data_tree_s, &treeroot, newnode);
  359. if (findnode == NULL) {
  360. RB_INSERT(tcpr_data_tree_s, &treeroot, newnode);
  361. } else {
  362. safe_free(newnode);
  363. }
  364. }
  365. void
  366. add_tree_first_ipv6(const u_char *data)
  367. {
  368. tcpr_tree_t *newnode = NULL, *findnode;
  369. eth_hdr_t *eth_hdr = NULL;
  370. ipv6_hdr_t ip6_hdr;
  371. assert(data);
  372. /*
  373. * first add/find the source IP/client
  374. */
  375. newnode = new_tree();
  376. eth_hdr = (eth_hdr_t *) (data);
  377. /* prevent issues with byte alignment, must memcpy */
  378. memcpy(&ip6_hdr, (data + TCPR_ETH_H), TCPR_IPV6_H);
  379. /* copy over the source ip, and values to gurantee this a client */
  380. newnode->family = AF_INET6;
  381. newnode->u.ip6 = ip6_hdr.ip_src;
  382. newnode->type = DIR_CLIENT;
  383. newnode->client_cnt = 1000;
  384. findnode = RB_FIND(tcpr_data_tree_s, &treeroot, newnode);
  385. /* if we didn't find it, add it to the tree, else free it */
  386. if (findnode == NULL) {
  387. RB_INSERT(tcpr_data_tree_s, &treeroot, newnode);
  388. } else {
  389. safe_free(newnode);
  390. }
  391. /*
  392. * now add/find the destination IP/server
  393. */
  394. newnode = new_tree();
  395. eth_hdr = (eth_hdr_t *) (data);
  396. memcpy(&ip6_hdr, (data + TCPR_ETH_H), TCPR_IPV6_H);
  397. newnode->family = AF_INET6;
  398. newnode->u.ip6 = ip6_hdr.ip_dst;
  399. newnode->type = DIR_SERVER;
  400. newnode->server_cnt = 1000;
  401. findnode = RB_FIND(tcpr_data_tree_s, &treeroot, newnode);
  402. if (findnode == NULL) {
  403. RB_INSERT(tcpr_data_tree_s, &treeroot, newnode);
  404. } else {
  405. safe_free(newnode);
  406. }
  407. }
  408. static void
  409. add_tree_node(tcpr_tree_t *newnode)
  410. {
  411. tcpr_tree_t *node;
  412. /* try to find a simular entry in the tree */
  413. node = RB_FIND(tcpr_data_tree_s, &treeroot, newnode);
  414. dbgx(3, "%s", tree_printnode("add_tree", node));
  415. /* new entry required */
  416. if (node == NULL) {
  417. /* increment counters */
  418. if (newnode->type == DIR_SERVER) {
  419. newnode->server_cnt++;
  420. }
  421. else if (newnode->type == DIR_CLIENT) {
  422. newnode->client_cnt++;
  423. }
  424. /* insert it in */
  425. RB_INSERT(tcpr_data_tree_s, &treeroot, newnode);
  426. }
  427. else {
  428. /* we found something, so update it */
  429. dbgx(2, " node: %p\nnewnode: %p", node, newnode);
  430. dbgx(3, "%s", tree_printnode("update node", node));
  431. /* increment counter */
  432. if (newnode->type == DIR_SERVER) {
  433. node->server_cnt++;
  434. }
  435. else if (newnode->type == DIR_CLIENT) {
  436. /* temp debug code */
  437. node->client_cnt++;
  438. }
  439. /* didn't insert it, so free it */
  440. safe_free(newnode);
  441. }
  442. dbg(2, "------- START NEXT -------");
  443. dbgx(3, "%s", tree_print(&treeroot));
  444. }
  445. /**
  446. * adds an entry to the tree (phase 1 of auto mode). We add each host
  447. * to the tree if it doesn't yet exist. We go through and track:
  448. * - number of times each host acts as a client or server
  449. * - the way the host acted the first time we saw it (client or server)
  450. */
  451. void
  452. add_tree_ipv4(const unsigned long ip, const u_char * data)
  453. {
  454. tcpr_tree_t *newnode = NULL;
  455. assert(data);
  456. newnode = packet2tree(data);
  457. assert(ip == newnode->u.ip);
  458. if (newnode->type == DIR_UNKNOWN) {
  459. /* couldn't figure out if packet was client or server */
  460. dbgx(2, "%s (%lu) unknown client/server",
  461. get_addr2name4(newnode->u.ip, RESOLVE), newnode->u.ip);
  462. }
  463. add_tree_node(newnode);
  464. }
  465. void
  466. add_tree_ipv6(const struct tcpr_in6_addr * addr, const u_char * data)
  467. {
  468. tcpr_tree_t *newnode = NULL;
  469. assert(data);
  470. newnode = packet2tree(data);
  471. assert(ipv6_cmp(addr, &newnode->u.ip6) == 0);
  472. if (newnode->type == DIR_UNKNOWN) {
  473. /* couldn't figure out if packet was client or server */
  474. dbgx(2, "%s unknown client/server",
  475. get_addr2name6(&newnode->u.ip6, RESOLVE));
  476. }
  477. add_tree_node(newnode);
  478. }
  479. /**
  480. * calculates wether each node in the tree is a client, server, or unknown for each node in the tree
  481. */
  482. void
  483. tree_calculate(tcpr_data_tree_t *treeroot)
  484. {
  485. tcpr_tree_t *node;
  486. dbg(1, "Running tree_calculate()");
  487. RB_FOREACH(node, tcpr_data_tree_s, treeroot) {
  488. dbgx(4, "Processing %s", get_addr2name4(node->u.ip, RESOLVE));
  489. if ((node->server_cnt > 0) || (node->client_cnt > 0)) {
  490. /* type based on: server >= (client*ratio) */
  491. if ((double)node->server_cnt >= (double)node->client_cnt * options.ratio) {
  492. node->type = DIR_SERVER;
  493. dbgx(3, "Setting %s to server",
  494. get_addr2name4(node->u.ip, RESOLVE));
  495. }
  496. else {
  497. node->type = DIR_CLIENT;
  498. dbgx(3, "Setting %s to client",
  499. get_addr2name4(node->u.ip, RESOLVE));
  500. }
  501. }
  502. else { /* IP had no client or server connections */
  503. node->type = DIR_UNKNOWN;
  504. dbgx(3, "Setting %s to unknown",
  505. get_addr2name4(node->u.ip, RESOLVE));
  506. }
  507. }
  508. }
  509. static int
  510. ipv6_cmp(const struct tcpr_in6_addr *a, const struct tcpr_in6_addr *b)
  511. {
  512. int i, k;
  513. for (i = 0; i < 4; i++) {
  514. if ((k = (a->tcpr_s6_addr32[i] - b->tcpr_s6_addr32[i]))) {
  515. return (k > 0) ? 1 : -1;
  516. }
  517. }
  518. return 0;
  519. }
  520. /**
  521. * tree_comp(), called by rbsearch compares two treees and returns:
  522. * 1 = first > second
  523. * -1 = first < second
  524. * 0 = first = second
  525. * based upon the ip address stored
  526. *
  527. */
  528. int
  529. tree_comp(tcpr_tree_t *t1, tcpr_tree_t *t2)
  530. {
  531. int ret;
  532. if (t1->family > t2->family) {
  533. dbgx(2, "family %d > %d", t1->family, t2->family);
  534. return 1;
  535. }
  536. if (t1->family < t2->family) {
  537. dbgx(2, "family %d < %d", t1->family, t2->family);
  538. return -1;
  539. }
  540. if (t1->family == AF_INET) {
  541. if (t1->u.ip > t2->u.ip) {
  542. dbgx(2, "%s > %s", get_addr2name4(t1->u.ip, RESOLVE),
  543. get_addr2name4(t2->u.ip, RESOLVE));
  544. return 1;
  545. }
  546. if (t1->u.ip < t2->u.ip) {
  547. dbgx(2, "%s < %s", get_addr2name4(t1->u.ip, RESOLVE),
  548. get_addr2name4(t2->u.ip, RESOLVE));
  549. return -1;
  550. }
  551. dbgx(2, "%s = %s", get_addr2name4(t1->u.ip, RESOLVE),
  552. get_addr2name4(t2->u.ip, RESOLVE));
  553. return 0;
  554. }
  555. if (t1->family == AF_INET6) {
  556. ret = ipv6_cmp(&t1->u.ip6, &t1->u.ip6);
  557. dbgx(2, "cmp(%s, %s) = %d", get_addr2name6(&t1->u.ip6, RESOLVE),
  558. get_addr2name6(&t2->u.ip6, RESOLVE), ret);
  559. return ret;
  560. }
  561. return 0;
  562. }
  563. /**
  564. * creates a new TREE * with reasonable defaults
  565. */
  566. static tcpr_tree_t *
  567. new_tree()
  568. {
  569. tcpr_tree_t *node;
  570. node = (tcpr_tree_t *)safe_malloc(sizeof(tcpr_tree_t));
  571. memset(node, '\0', sizeof(tcpr_tree_t));
  572. node->server_cnt = 0;
  573. node->client_cnt = 0;
  574. node->type = DIR_UNKNOWN;
  575. node->masklen = -1;
  576. node->u.ip = 0;
  577. return (node);
  578. }
  579. /**
  580. * returns a struct of TREE * from a packet header
  581. * and sets the type to be SERVER or CLIENT or UNKNOWN
  582. * if it's an undefined packet, we return -1 for the type
  583. * the u_char * data should be the data that is passed by pcap_dispatch()
  584. */
  585. tcpr_tree_t *
  586. packet2tree(const u_char * data)
  587. {
  588. tcpr_tree_t *node = NULL;
  589. eth_hdr_t *eth_hdr = NULL;
  590. ipv4_hdr_t ip_hdr;
  591. ipv6_hdr_t ip6_hdr;
  592. tcp_hdr_t tcp_hdr;
  593. udp_hdr_t udp_hdr;
  594. icmpv4_hdr_t icmp_hdr;
  595. dnsv4_hdr_t dnsv4_hdr;
  596. u_int16_t ether_type;
  597. u_char proto = 0;
  598. int hl = 0;
  599. #ifdef DEBUG
  600. char srcip[INET6_ADDRSTRLEN];
  601. #endif
  602. node = new_tree();
  603. eth_hdr = (eth_hdr_t *) (data);
  604. /* prevent issues with byte alignment, must memcpy */
  605. memcpy(&ether_type, (u_char*)eth_hdr + 12, 2);
  606. /* drop VLAN info if it exists before the IP info */
  607. if (ether_type == htons(ETHERTYPE_VLAN)) {
  608. dbg(4,"Processing as VLAN traffic...");
  609. /* prevent issues with byte alignment, must memcpy */
  610. memcpy(&ether_type, (u_char*)eth_hdr + 16, 2);
  611. hl += 4;
  612. }
  613. if (ether_type == htons(ETHERTYPE_IP)) {
  614. memcpy(&ip_hdr, (data + TCPR_ETH_H + hl), TCPR_IPV4_H);
  615. node->family = AF_INET;
  616. node->u.ip = ip_hdr.ip_src.s_addr;
  617. proto = ip_hdr.ip_p;
  618. hl += ip_hdr.ip_hl * 4;
  619. #ifdef DEBUG
  620. strlcpy(srcip, get_addr2name4(ip_hdr.ip_src.s_addr,
  621. RESOLVE), 16);
  622. #endif
  623. } else if (ether_type == htons(ETHERTYPE_IP6)) {
  624. memcpy(&ip6_hdr, (data + TCPR_ETH_H + hl), TCPR_IPV6_H);
  625. node->family = AF_INET6;
  626. node->u.ip6 = ip6_hdr.ip_src;
  627. proto = ip6_hdr.ip_nh;
  628. hl += TCPR_IPV6_H;
  629. #ifdef DEBUG
  630. strlcpy(srcip, get_addr2name6(&ip6_hdr.ip_src, RESOLVE), INET6_ADDRSTRLEN);
  631. #endif
  632. } else {
  633. dbgx(2,"Unrecognized ether_type (%x)", ether_type);
  634. }
  635. /* copy over the source mac */
  636. strncpy((char *)node->mac, (char *)eth_hdr->ether_shost, 6);
  637. /*
  638. * TCP
  639. */
  640. if (proto == IPPROTO_TCP) {
  641. dbgx(3, "%s uses TCP... ", srcip);
  642. /* memcpy it over to prevent alignment issues */
  643. memcpy(&tcp_hdr, (data + TCPR_ETH_H + hl), TCPR_TCP_H);
  644. /* ftp-data is going to skew our results so we ignore it */
  645. if (tcp_hdr.th_sport == 20)
  646. return (node);
  647. /* set TREE->type based on TCP flags */
  648. if (tcp_hdr.th_flags == TH_SYN) {
  649. node->type = DIR_CLIENT;
  650. dbg(3, "is a client");
  651. }
  652. else if (tcp_hdr.th_flags == (TH_SYN | TH_ACK)) {
  653. node->type = DIR_SERVER;
  654. dbg(3, "is a server");
  655. }
  656. else {
  657. dbg(3, "is an unknown");
  658. }
  659. }
  660. /*
  661. * UDP
  662. */
  663. else if (proto == IPPROTO_UDP) {
  664. /* memcpy over to prevent alignment issues */
  665. memcpy(&udp_hdr, (data + TCPR_ETH_H + hl), TCPR_UDP_H);
  666. dbgx(3, "%s uses UDP... ", srcip);
  667. switch (ntohs(udp_hdr.uh_dport)) {
  668. case 0x0035: /* dns */
  669. /* prevent memory alignment issues */
  670. memcpy(&dnsv4_hdr,
  671. (data + TCPR_ETH_H + hl + TCPR_UDP_H), TCPR_DNS_H);
  672. if (dnsv4_hdr.flags & DNS_QUERY_FLAG) {
  673. /* bit set, response */
  674. node->type = DIR_SERVER;
  675. dbg(3, "is a dns server");
  676. }
  677. else {
  678. /* bit not set, query */
  679. node->type = DIR_CLIENT;
  680. dbg(3, "is a dns client");
  681. }
  682. return (node);
  683. break;
  684. default:
  685. break;
  686. }
  687. switch (ntohs(udp_hdr.uh_sport)) {
  688. case 0x0035: /* dns */
  689. /* prevent memory alignment issues */
  690. memcpy(&dnsv4_hdr,
  691. (data + TCPR_ETH_H + hl + TCPR_UDP_H),
  692. TCPR_DNS_H);
  693. if ((dnsv4_hdr.flags & 0x7FFFF) ^ DNS_QUERY_FLAG) {
  694. /* bit set, response */
  695. node->type = DIR_SERVER;
  696. dbg(3, "is a dns server");
  697. }
  698. else {
  699. /* bit not set, query */
  700. node->type = DIR_CLIENT;
  701. dbg(3, "is a dns client");
  702. }
  703. return (node);
  704. break;
  705. default:
  706. dbgx(3, "unknown UDP protocol: %hu->%hu", udp_hdr.uh_sport,
  707. udp_hdr.uh_dport);
  708. break;
  709. }
  710. }
  711. /*
  712. * ICMP
  713. */
  714. else if (proto == IPPROTO_ICMP) {
  715. /* prevent alignment issues */
  716. memcpy(&icmp_hdr, (data + TCPR_ETH_H + hl), TCPR_ICMPV4_H);
  717. dbgx(3, "%s uses ICMP... ", srcip);
  718. /*
  719. * if port unreachable, then source == server, dst == client
  720. */
  721. if ((icmp_hdr.icmp_type == ICMP_UNREACH) &&
  722. (icmp_hdr.icmp_code == ICMP_UNREACH_PORT)) {
  723. node->type = DIR_SERVER;
  724. dbg(3, "is a server with a closed port");
  725. }
  726. }
  727. return (node);
  728. }
  729. /**
  730. * prints out a node of the tree to stderr
  731. */
  732. static char *
  733. tree_printnode(const char *name, const tcpr_tree_t *node)
  734. {
  735. memset(&tree_print_buff, '\0', TREEPRINTBUFFLEN);
  736. if (node == NULL) {
  737. snprintf(tree_print_buff, TREEPRINTBUFFLEN, "%s node is null", name);
  738. }
  739. else {
  740. snprintf(tree_print_buff, TREEPRINTBUFFLEN,
  741. "-- %s: %p\nIP: %s\nMask: %d\nSrvr: %d\nClnt: %d\n",
  742. name, (void *)node, node->family == AF_INET ?
  743. get_addr2name4(node->u.ip, RESOLVE) :
  744. get_addr2name6(&node->u.ip6, RESOLVE),
  745. node->masklen, node->server_cnt, node->client_cnt);
  746. if (node->type == DIR_SERVER) {
  747. strlcat(tree_print_buff, "Type: Server\n--\n", TREEPRINTBUFFLEN);
  748. }
  749. else {
  750. strlcat(tree_print_buff, "Type: Client\n--", TREEPRINTBUFFLEN);
  751. }
  752. }
  753. return (tree_print_buff);
  754. }
  755. /**
  756. * prints out the entire tree
  757. */
  758. static char *
  759. tree_print(tcpr_data_tree_t *treeroot)
  760. {
  761. tcpr_tree_t *node = NULL;
  762. memset(&tree_print_buff, '\0', TREEPRINTBUFFLEN);
  763. RB_FOREACH(node, tcpr_data_tree_s, treeroot) {
  764. tree_printnode("my node", node);
  765. }
  766. return (tree_print_buff);
  767. }