1
0

tree.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. /* $Id: tree.c 1368 2005-06-28 05:25:16Z 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 <stdio.h>
  35. #include <stdlib.h>
  36. #include "tree.h"
  37. #include "tcpprep.h"
  38. #include "tcpprep_opts.h"
  39. extern data_tree_t treeroot;
  40. extern tcpprep_opt_t options;
  41. #ifdef DEBUG
  42. extern int debug;
  43. #endif
  44. int checkincidr;
  45. static tree_t *new_tree();
  46. static tree_t *packet2tree(const u_char *);
  47. static void tree_print(data_tree_t *);
  48. static void tree_printnode(const char *, const tree_t *);
  49. static void tree_buildcidr(data_tree_t *, buildcidr_t *);
  50. static void tree_checkincidr(data_tree_t *, buildcidr_t *);
  51. RB_PROTOTYPE(data_tree_s, tree_s, node, tree_comp)
  52. RB_GENERATE(data_tree_s, tree_s, node, tree_comp)
  53. /*
  54. * used with rbwalk to walk a tree and generate cidr_t * cidrdata.
  55. * is smart enough to prevent dupes. void * arg is cast to bulidcidr_t
  56. */
  57. void
  58. tree_buildcidr(data_tree_t *treeroot, buildcidr_t * bcdata)
  59. {
  60. tree_t *node = NULL;
  61. cidr_t *newcidr = NULL;
  62. unsigned long network = 0;
  63. unsigned long mask = ~0; /* turn on all bits */
  64. RB_FOREACH(node, data_tree_s, treeroot) {
  65. /* we only check types that are vaild */
  66. if (bcdata->type != ANY) /* don't check if we're adding ANY */
  67. if (bcdata->type != node->type) /* no match, exit early */
  68. return;
  69. /*
  70. * in cases of leaves and last visit add to cidrdata if
  71. * necessary
  72. */
  73. if (!check_ip_cidr(options.cidrdata, node->ip)) { /* if we exist, abort */
  74. newcidr = new_cidr();
  75. newcidr->masklen = bcdata->masklen;
  76. network = node->ip & (mask >> (32 - bcdata->masklen));
  77. newcidr->network = network;
  78. add_cidr(options.cidrdata, &newcidr);
  79. }
  80. }
  81. }
  82. /*
  83. * uses rbwalk to check to see if a given ip address of a given type in the
  84. * tree is inside any of the cidrdata
  85. *
  86. * since this is void, we return via the global int checkincidr
  87. */
  88. void
  89. tree_checkincidr(data_tree_t *treeroot, buildcidr_t * bcdata)
  90. {
  91. tree_t *node = NULL;
  92. RB_FOREACH(node, data_tree_s, treeroot) {
  93. /* we only check types that are vaild */
  94. if (bcdata->type != ANY) /* don't check if we're adding ANY */
  95. if (bcdata->type != node->type) /* no match, exit early */
  96. return;
  97. /*
  98. * in cases of leaves and last visit add to cidrdata if
  99. * necessary
  100. */
  101. if (check_ip_cidr(options.cidrdata, node->ip)) { /* if we exist, abort */
  102. checkincidr = 1;
  103. }
  104. }
  105. }
  106. /*
  107. * processes the tree using rbwalk / tree2cidr to generate a CIDR
  108. * used for 2nd pass, router mode
  109. *
  110. * returns > 0 for success (the mask len), 0 for fail
  111. */
  112. int
  113. process_tree()
  114. {
  115. int mymask = 0;
  116. buildcidr_t *bcdata;
  117. bcdata = (buildcidr_t *)safe_malloc(sizeof(buildcidr_t));
  118. for (mymask = options.max_mask; mymask <= options.min_mask; mymask++) {
  119. dbg(1, "Current mask: %u", mymask);
  120. /* set starting vals */
  121. bcdata->type = SERVER;
  122. bcdata->masklen = mymask;
  123. /* build cidrdata with servers */
  124. tree_buildcidr(&treeroot, bcdata);
  125. /* calculate types of all IP's */
  126. tree_calculate(&treeroot);
  127. /* try to find clients in cidrdata */
  128. checkincidr = 0;
  129. bcdata->type = CLIENT;
  130. tree_checkincidr(&treeroot, bcdata);
  131. if (checkincidr == 0) { /* didn't find any clients in cidrdata */
  132. return (mymask); /* success! */
  133. }
  134. else {
  135. destroy_cidr(options.cidrdata); /* clean up after our mess */
  136. options.cidrdata = NULL;
  137. }
  138. }
  139. /* we failed to find a vaild cidr list */
  140. return (0);
  141. }
  142. /*
  143. * processes rbdata to bulid cidrdata based upon the
  144. * given type (SERVER, CLIENT, UNKNOWN) using the given masklen
  145. *
  146. * is smart enough to prevent dupes
  147. */
  148. void
  149. tree_to_cidr(const int masklen, const int type)
  150. {
  151. }
  152. /*
  153. * Checks to see if an IP is client or server by finding it in the tree
  154. * returns SERVER or CLIENT.
  155. * if mode = UNKNOWN, then abort on unknowns
  156. * if mode = CLIENT, then unknowns become clients
  157. * if mode = SERVER, then unknowns become servers
  158. */
  159. int
  160. check_ip_tree(const int mode, const unsigned long ip)
  161. {
  162. tree_t *node = NULL, *finder = NULL;
  163. finder = new_tree();
  164. finder->ip = ip;
  165. node = RB_FIND(data_tree_s, &treeroot, finder);
  166. if (node == NULL && mode == UNKNOWN)
  167. errx(1, "%s (%lu) is an unknown system... aborting.!\n"
  168. "Try a different auto mode (-n router|client|server)",
  169. libnet_addr2name4(ip, RESOLVE), ip);
  170. #ifdef DEBUG
  171. if (node->type == SERVER) {
  172. dbg(1, "Server: %s", libnet_addr2name4(ip, RESOLVE));
  173. }
  174. else if (node->type == CLIENT) {
  175. dbg(1, "Client: %s", libnet_addr2name4(ip, RESOLVE));
  176. }
  177. else {
  178. dbg(1, "Unknown: %s", libnet_addr2name4(ip, RESOLVE));
  179. }
  180. #endif
  181. /* return node type if we found the node, else return the default (mode) */
  182. if (node != NULL) {
  183. return (node->type);
  184. }
  185. else {
  186. return mode;
  187. }
  188. }
  189. /*
  190. * adds an entry to the tree (phase 1 of auto mode)
  191. */
  192. void
  193. add_tree(const unsigned long ip, const u_char * data)
  194. {
  195. tree_t *node = NULL, *newnode = NULL;
  196. newnode = packet2tree(data);
  197. if (newnode->type == UNKNOWN) {
  198. /* couldn't figure out if packet was client or server */
  199. dbg(2, "%s (%lu) unknown client/server",
  200. libnet_addr2name4(newnode->ip, RESOLVE), newnode->ip);
  201. }
  202. /* try to find a simular entry in the tree */
  203. node = RB_FIND(data_tree_s, &treeroot, newnode);
  204. #ifdef DEBUG
  205. if (debug > 2)
  206. tree_printnode("add_tree", node);
  207. #endif
  208. /* new entry required */
  209. if (node == NULL) {
  210. /* increment counters */
  211. if (newnode->type == SERVER) {
  212. newnode->server_cnt++;
  213. }
  214. else if (newnode->type == CLIENT) {
  215. newnode->client_cnt++;
  216. }
  217. /* insert it in */
  218. RB_INSERT(data_tree_s, &treeroot, newnode);
  219. }
  220. else {
  221. /* we found something, so update it */
  222. dbg(2, " node: %p\nnewnode: %p", node, newnode);
  223. #ifdef DEBUG
  224. if (debug > 2)
  225. tree_printnode("update node", node);
  226. #endif
  227. /* increment counter */
  228. if (newnode->type == SERVER) {
  229. node->server_cnt++;
  230. }
  231. else if (newnode->type == CLIENT) {
  232. /* temp debug code */
  233. node->client_cnt++;
  234. }
  235. /* didn't insert it, so free it */
  236. free(newnode);
  237. }
  238. dbg(2, "------- START NEXT -------");
  239. #ifdef DEBUG
  240. if (debug > 2)
  241. tree_print(&treeroot);
  242. #endif
  243. }
  244. /*
  245. * calculates wether an IP is a client, server, or unknown for each node in the tree
  246. */
  247. void
  248. tree_calculate(data_tree_t *treeroot)
  249. {
  250. tree_t *node;
  251. RB_FOREACH(node, data_tree_s, treeroot) {
  252. if ((node->server_cnt > 0) || (node->client_cnt > 0)) {
  253. /* type based on: server >= (client*ratio) */
  254. if ((double)node->server_cnt >= (double)node->client_cnt * options.ratio) {
  255. node->type = SERVER;
  256. }
  257. else {
  258. node->type = CLIENT;
  259. }
  260. }
  261. else { /* IP had no client or server connections */
  262. node->type = UNKNOWN;
  263. }
  264. }
  265. }
  266. /*
  267. * tree_comp(), called by rbsearch compares two treees and returns:
  268. * 1 = first > second
  269. * -1 = first < second
  270. * 0 = first = second
  271. * based upon the ip address stored
  272. *
  273. */
  274. int
  275. tree_comp(tree_t *t1, tree_t *t2)
  276. {
  277. if (t1->ip > t2->ip) {
  278. dbg(2, "%s > %s", libnet_addr2name4(t1->ip, RESOLVE),
  279. libnet_addr2name4(t2->ip, RESOLVE));
  280. return 1;
  281. }
  282. if (t1->ip < t2->ip) {
  283. dbg(2, "%s < %s", libnet_addr2name4(t1->ip, RESOLVE),
  284. libnet_addr2name4(t2->ip, RESOLVE));
  285. return -1;
  286. }
  287. dbg(2, "%s = %s", libnet_addr2name4(t1->ip, RESOLVE),
  288. libnet_addr2name4(t2->ip, RESOLVE));
  289. return 0;
  290. }
  291. /*
  292. * creates a new TREE * with reasonable defaults
  293. */
  294. static tree_t *
  295. new_tree()
  296. {
  297. tree_t *node;
  298. node = (tree_t *)safe_malloc(sizeof(tree_t));
  299. memset(node, '\0', sizeof(tree_t));
  300. node->server_cnt = 0;
  301. node->client_cnt = 0;
  302. node->type = UNKNOWN;
  303. node->masklen = -1;
  304. node->ip = 0;
  305. return (node);
  306. }
  307. /*
  308. * returns a struct of TREE * from a packet header
  309. * and sets the type to be SERVER or CLIENT or UNKNOWN
  310. * if it's an undefined packet, we return -1 for the type
  311. * the u_char * data should be the data that is passed by pcap_dispatch()
  312. */
  313. tree_t *
  314. packet2tree(const u_char * data)
  315. {
  316. tree_t *node = NULL;
  317. eth_hdr_t *eth_hdr = NULL;
  318. ip_hdr_t ip_hdr;
  319. tcp_hdr_t tcp_hdr;
  320. udp_hdr_t udp_hdr;
  321. icmp_hdr_t icmp_hdr;
  322. dns_hdr_t dns_hdr;
  323. node = new_tree();
  324. eth_hdr = (eth_hdr_t *) (data);
  325. /* prevent issues with byte alignment, must memcpy */
  326. memcpy(&ip_hdr, (data + LIBNET_ETH_H), LIBNET_IP_H);
  327. /* copy over the source mac */
  328. strncpy((char *)node->mac, (char *)eth_hdr->ether_shost, 6);
  329. /* copy over the source ip */
  330. node->ip = ip_hdr.ip_src.s_addr;
  331. /*
  332. * TCP
  333. */
  334. if (ip_hdr.ip_p == IPPROTO_TCP) {
  335. dbg(1, "%s uses TCP... ",
  336. libnet_addr2name4(ip_hdr.ip_src.s_addr, RESOLVE));
  337. /* memcpy it over to prevent alignment issues */
  338. memcpy(&tcp_hdr, (data + LIBNET_ETH_H + (ip_hdr.ip_hl * 4)),
  339. LIBNET_TCP_H);
  340. /* ftp-data is going to skew our results so we ignore it */
  341. if (tcp_hdr.th_sport == 20) {
  342. return (node);
  343. }
  344. /* set TREE->type based on TCP flags */
  345. if (tcp_hdr.th_flags == TH_SYN) {
  346. node->type = CLIENT;
  347. dbg(1, "is a client");
  348. }
  349. else if (tcp_hdr.th_flags == (TH_SYN | TH_ACK)) {
  350. node->type = SERVER;
  351. dbg(1, "is a server");
  352. }
  353. else {
  354. dbg(1, "is an unknown");
  355. }
  356. /*
  357. * UDP
  358. */
  359. }
  360. else if (ip_hdr.ip_p == IPPROTO_UDP) {
  361. /* memcpy over to prevent alignment issues */
  362. memcpy(&udp_hdr, (data + LIBNET_ETH_H + (ip_hdr.ip_hl * 4)),
  363. LIBNET_UDP_H);
  364. dbg(1, "%s uses UDP... ",
  365. libnet_addr2name4(ip_hdr.ip_src.s_addr, RESOLVE));
  366. switch (ntohs(udp_hdr.uh_dport)) {
  367. case 0x0035: /* dns */
  368. /* prevent memory alignment issues */
  369. memcpy(&dns_hdr,
  370. (data + LIBNET_ETH_H + (ip_hdr.ip_hl * 4) + LIBNET_UDP_H),
  371. LIBNET_DNS_H);
  372. if (dns_hdr.flags & DNS_QUERY_FLAG) {
  373. /* bit set, response */
  374. node->type = SERVER;
  375. dbg(1, "is a dns server");
  376. }
  377. else {
  378. /* bit not set, query */
  379. node->type = CLIENT;
  380. dbg(1, "is a dns client");
  381. }
  382. return (node);
  383. break;
  384. default:
  385. break;
  386. }
  387. switch (ntohs(udp_hdr.uh_sport)) {
  388. case 0x0035: /* dns */
  389. /* prevent memory alignment issues */
  390. memcpy(&dns_hdr,
  391. (data + LIBNET_ETH_H + (ip_hdr.ip_hl * 4) + LIBNET_UDP_H),
  392. LIBNET_DNS_H);
  393. if (dns_hdr.flags & DNS_QUERY_FLAG) {
  394. /* bit set, response */
  395. node->type = SERVER;
  396. dbg(1, "is a dns server");
  397. }
  398. else {
  399. /* bit not set, query */
  400. node->type = CLIENT;
  401. dbg(1, "is a dns client");
  402. }
  403. return (node);
  404. break;
  405. default:
  406. dbg(1, "unknown UDP protocol: %hu->%hu", udp_hdr.uh_sport,
  407. udp_hdr.uh_dport);
  408. break;
  409. }
  410. /*
  411. * ICMP
  412. */
  413. }
  414. else if (ip_hdr.ip_p == IPPROTO_ICMP) {
  415. /* prevent alignment issues */
  416. memcpy(&icmp_hdr, (data + LIBNET_ETH_H + (ip_hdr.ip_hl * 4)),
  417. LIBNET_ICMP_H);
  418. dbg(1, "%s uses ICMP... ",
  419. libnet_addr2name4(ip_hdr.ip_src.s_addr, RESOLVE));
  420. /*
  421. * if port unreachable, then source == server, dst == client
  422. */
  423. if ((icmp_hdr.icmp_type == ICMP_UNREACH) &&
  424. (icmp_hdr.icmp_code == ICMP_UNREACH_PORT)) {
  425. node->type = SERVER;
  426. dbg(1, "is a server with a closed port");
  427. }
  428. }
  429. return (node);
  430. }
  431. /*
  432. * prints out a node of the tree to stderr
  433. */
  434. static void
  435. tree_printnode(const char *name, const tree_t *node)
  436. {
  437. if (node == NULL) {
  438. fprintf(stderr, "%s node is null\n", name);
  439. }
  440. else {
  441. fprintf(stderr, "-- %s: %p\nIP: %s\nMask: %d\nSrvr: %d\nClnt: %d\n",
  442. name, (void *)node, libnet_addr2name4(node->ip, RESOLVE),
  443. node->masklen, node->server_cnt, node->client_cnt);
  444. if (node->type == SERVER) {
  445. fprintf(stderr, "Type: Server\n--\n");
  446. }
  447. else {
  448. fprintf(stderr, "Type: Client\n--\n");
  449. }
  450. }
  451. }
  452. /*
  453. * prints out the entire tree
  454. */
  455. static void
  456. tree_print(data_tree_t *treeroot)
  457. {
  458. tree_t *node = NULL;
  459. RB_FOREACH(node, data_tree_s, treeroot) {
  460. tree_printnode("my node", node);
  461. }
  462. return;
  463. }
  464. /*
  465. Local Variables:
  466. mode:c
  467. indent-tabs-mode:nil
  468. c-basic-offset:4
  469. End:
  470. */