You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pkts.c 25KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. /* This file is part of Netsukuku
  2. * (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
  3. *
  4. * This source code is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as published
  6. * by the Free Software Foundation; either version 2 of the License,
  7. * or (at your option) any later version.
  8. *
  9. * This source code is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * Please refer to the GNU Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Public License along with
  15. * this source code; if not, write to:
  16. * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * --
  19. * pkts.c:
  20. * General functions to forge, pack, send, receive, forward and unpack
  21. * packets.
  22. */
  23. #include "includes.h"
  24. #include <zlib.h>
  25. #include "inet.h"
  26. #include "request.h"
  27. #include "endianness.h"
  28. #include "pkts.h"
  29. #include "accept.h"
  30. #include "common.h"
  31. interface cur_ifs[MAX_INTERFACES];
  32. int cur_ifs_n;
  33. /*
  34. * pkts_init:
  35. * Initialize the vital organs of the pkts.c's functions.
  36. * `ifs' is the array which keeps all the the `ifs_n'# network
  37. * interface that will be used.
  38. * If `queue_init' is not 0, the pkt_queue is initialized too.
  39. */
  40. void
  41. pkts_init(interface * ifs, int ifs_n, int queue_init)
  42. {
  43. cur_ifs_n = ifs_n > MAX_INTERFACES ? ifs_n : MAX_INTERFACES;
  44. memcpy(cur_ifs, ifs, sizeof(interface) * cur_ifs_n);
  45. pkt_q_counter = 0;
  46. if (queue_init)
  47. pkt_queue_init();
  48. op_filter_reset(OP_FILTER_ALLOW);
  49. }
  50. /*
  51. * * * Handy functions to build the PACKET * *
  52. */
  53. void
  54. pkt_addfrom(PACKET * pkt, inet_prefix * from)
  55. {
  56. if (!from)
  57. setzero(&pkt->from, sizeof(inet_prefix));
  58. else
  59. inet_copy(&pkt->from, from);
  60. }
  61. void
  62. pkt_addto(PACKET * pkt, inet_prefix * to)
  63. {
  64. if (!to)
  65. setzero(&pkt->to, sizeof(inet_prefix));
  66. else
  67. inet_copy(&pkt->to, to);
  68. }
  69. void
  70. pkt_add_dev(PACKET * pkt, interface * dev, int bind_the_socket)
  71. {
  72. pkt->dev = dev;
  73. if (dev && bind_the_socket)
  74. pkt->pkt_flags |= PKT_BIND_DEV;
  75. }
  76. void
  77. pkt_addsk(PACKET * pkt, int family, int sk, int sk_type)
  78. {
  79. pkt->family = family;
  80. pkt->sk = sk;
  81. pkt->sk_type = sk_type;
  82. }
  83. void
  84. pkt_addport(PACKET * pkt, u_short port)
  85. {
  86. pkt->port = port;
  87. }
  88. void
  89. pkt_addtimeout(PACKET * pkt, u_int timeout, int recv, int send)
  90. {
  91. if ((pkt->timeout = timeout)) {
  92. if (recv)
  93. pkt->pkt_flags |= PKT_RECV_TIMEOUT;
  94. if (send)
  95. pkt->pkt_flags |= PKT_SEND_TIMEOUT;
  96. }
  97. }
  98. void
  99. pkt_addcompress(PACKET * pkt)
  100. {
  101. pkt->pkt_flags |= PKT_COMPRESSED;
  102. }
  103. void
  104. pkt_addlowdelay(PACKET * pkt)
  105. {
  106. pkt->pkt_flags |= PKT_SET_LOWDELAY;
  107. }
  108. void
  109. pkt_addnonblock(PACKET * pkt)
  110. {
  111. pkt->pkt_flags |= PKT_NONBLOCK;
  112. }
  113. void
  114. pkt_addhdr(PACKET * pkt, pkt_hdr * hdr)
  115. {
  116. if (!hdr)
  117. setzero(&pkt->hdr, sizeof(pkt_hdr));
  118. else
  119. memcpy(&pkt->hdr, hdr, sizeof(pkt_hdr));
  120. }
  121. void
  122. pkt_addmsg(PACKET * pkt, char *msg)
  123. {
  124. pkt->msg = msg;
  125. }
  126. /* * * End of handy stupid functions (^_+) * * */
  127. /*
  128. * pkt_clear: blanks the entire PACKET struct, leaving intact only `hdr'
  129. * and `msg'
  130. */
  131. void
  132. pkt_clear(PACKET * pkt)
  133. {
  134. pkt_addfrom(pkt, 0);
  135. pkt_addto(pkt, 0);
  136. pkt_addsk(pkt, 0, 0, 0);
  137. pkt_addport(pkt, 0);
  138. pkt->flags = pkt->pkt_flags = 0;
  139. }
  140. /*
  141. * pkt_copy: Copy the `src' PACKET in `dst'. It xmallocs also a new msg block in
  142. * `dst->msg' of `src->hdr.sz' size and copies in it `src->msg'
  143. */
  144. void
  145. pkt_copy(PACKET * dst, PACKET * src)
  146. {
  147. memcpy(dst, src, sizeof(PACKET));
  148. if (src->hdr.sz && src->msg) {
  149. dst->msg = xmalloc(src->hdr.sz);
  150. memcpy(dst->msg, src->msg, src->hdr.sz);
  151. }
  152. }
  153. void
  154. pkt_free(PACKET * pkt, int close_socket)
  155. {
  156. if (close_socket && pkt->sk)
  157. inet_close(&pkt->sk);
  158. if (pkt->msg) {
  159. xfree(pkt->msg);
  160. pkt->msg = 0;
  161. }
  162. }
  163. /*
  164. * pkt_compress
  165. *
  166. * It compresses `pkt'->msg and stores the result in `dst'.
  167. * `dst_msg' must have at least `newhdr'->sz bytes big.
  168. * It is also assumed that `pkt'->msg is not 0.
  169. *
  170. * The size of the compressed msg is stored in `newhdr'->sz, while
  171. * the size of the orignal one is written in `newhdr'->uncompress_sz.
  172. * If the compression doesn't fail, `newhdr'->sz will be always less than
  173. * `newhdr'->uncompress_sz.
  174. *
  175. * Nothing in `pkt' is modified.
  176. *
  177. * If the packet was compressed 0 is returned and the COMPRESSED_PKT flag is
  178. * set to `newhdr'->.flags.
  179. * On error a negative value is returned.
  180. */
  181. int
  182. pkt_compress(PACKET * pkt, pkt_hdr * newhdr, char *dst_msg)
  183. {
  184. uLongf bound_sz;
  185. int ret;
  186. bound_sz = compressBound(pkt->hdr.sz);
  187. unsigned char dst[bound_sz];
  188. ret = compress2(dst, &bound_sz, (u_char *) pkt->msg, pkt->hdr.sz,
  189. PKT_COMPRESS_LEVEL);
  190. if (ret != Z_OK) {
  191. error(RED(ERROR_MSG) "cannot compress the pkt. "
  192. "It will be sent uncompressed.", ERROR_FUNC);
  193. return -1;
  194. }
  195. if (bound_sz >= pkt->hdr.sz)
  196. /* Disgregard compression, it isn't useful in this case */
  197. return -pkt->hdr.sz;
  198. memcpy(dst_msg, dst, bound_sz);
  199. newhdr->uncompress_sz = pkt->hdr.sz;
  200. newhdr->sz = bound_sz;
  201. newhdr->flags |= COMPRESSED_PKT;
  202. return 0;
  203. }
  204. /*
  205. * pkt_pack
  206. *
  207. * It packs the packet with its `pkt'->header in a single buffer.
  208. * If PKT_COMPRESSED is set in `pkt'->pkt_flags, `pkt'->msg will be compressed
  209. * if its size is > PKT_COMPRESS_THRESHOLD.
  210. */
  211. char *
  212. pkt_pack(PACKET * pkt)
  213. {
  214. char *buf, *buf_hdr, *buf_body;
  215. buf = (char *) xmalloc(PACKET_SZ(pkt->hdr.sz));
  216. buf_hdr = buf;
  217. buf_body = buf + sizeof(pkt_hdr);
  218. /***
  219. * Copy the header
  220. */
  221. memcpy(buf_hdr, &pkt->hdr, sizeof(pkt_hdr));
  222. /* host -> network order */
  223. ints_host_to_network(buf_hdr, pkt_hdr_iinfo);
  224. /***/
  225. if (pkt->hdr.sz) {
  226. /*
  227. * compress the packet if necessary
  228. */
  229. if ((pkt->pkt_flags & PKT_COMPRESSED &&
  230. pkt->hdr.sz >= PKT_COMPRESS_THRESHOLD)) {
  231. if (!pkt_compress(pkt, &pkt->hdr, buf_body)) {
  232. /*
  233. * Re-copy the header in `buf', because
  234. * it has been changed during compression. */
  235. memcpy(buf_hdr, &pkt->hdr, sizeof(pkt_hdr));
  236. ints_host_to_network(buf_hdr, pkt_hdr_iinfo);
  237. }
  238. } else
  239. /* Just copy the body of the packet */
  240. memcpy(buf_body, pkt->msg, pkt->hdr.sz);
  241. /**/}
  242. return buf;
  243. }
  244. /*
  245. * pkt_uncompress
  246. *
  247. * It uncompress the compressed `pkt' and stores the result in `pkt' itself
  248. * On error -1 is returned.
  249. */
  250. int
  251. pkt_uncompress(PACKET * pkt)
  252. {
  253. uLongf dstlen;
  254. int ret = 0;
  255. unsigned char *dst = 0;
  256. dstlen = pkt->hdr.uncompress_sz;
  257. dst = xmalloc(dstlen);
  258. ret = uncompress(dst, &dstlen, (u_char *) pkt->msg, pkt->hdr.sz);
  259. if (ret != Z_OK)
  260. ERROR_FINISH(ret, -1, finish);
  261. else
  262. ret = 0;
  263. /**
  264. * Restore the uncompressed packet
  265. */
  266. xfree(pkt->msg);
  267. pkt->msg = (char *) dst;
  268. pkt->hdr.sz = pkt->hdr.uncompress_sz;
  269. pkt->hdr.uncompress_sz = 0;
  270. pkt->hdr.flags &= ~COMPRESSED_PKT;
  271. /**/ finish:
  272. if (ret && dst)
  273. xfree(dst);
  274. return ret;
  275. }
  276. /*
  277. * pkt_unpack
  278. *
  279. * `pkt' must be already in host order
  280. */
  281. int
  282. pkt_unpack(PACKET * pkt)
  283. {
  284. if (pkt->hdr.sz && pkt->msg && pkt->hdr.flags & COMPRESSED_PKT)
  285. if (pkt_uncompress(pkt))
  286. return -1;
  287. return 0;
  288. }
  289. int
  290. pkt_verify_hdr(PACKET pkt)
  291. {
  292. if (strncmp(pkt.hdr.ntk_id, NETSUKUKU_ID, 3) || pkt.hdr.sz > MAXMSGSZ)
  293. return 1;
  294. if (pkt.hdr.flags & COMPRESSED_PKT &&
  295. (pkt.hdr.sz >= pkt.hdr.uncompress_sz ||
  296. pkt.hdr.uncompress_sz > PKT_MAX_MSG_SZ))
  297. /* Invalid compression */
  298. return 1;
  299. return 0;
  300. }
  301. ssize_t
  302. pkt_send(PACKET * pkt)
  303. {
  304. ssize_t ret = 0;
  305. char *buf = 0;
  306. buf = pkt_pack(pkt);
  307. if (pkt->sk_type == SKT_UDP || pkt->sk_type == SKT_BCAST) {
  308. struct sockaddr_storage saddr_sto;
  309. struct sockaddr *to = (struct sockaddr *) &saddr_sto;
  310. socklen_t tolen;
  311. if (inet_to_sockaddr(&pkt->to, pkt->port, to, &tolen) < 0) {
  312. debug(DBG_NOISE, "Cannot pkt_send(): %d "
  313. "Family not supported", pkt->to.family);
  314. ERROR_FINISH(ret, -1, finish);
  315. }
  316. if (pkt->pkt_flags & PKT_SEND_TIMEOUT)
  317. ret = inet_sendto_timeout(pkt->sk, buf,
  318. PACKET_SZ(pkt->hdr.sz), pkt->flags,
  319. to, tolen, pkt->timeout);
  320. else
  321. ret = inet_sendto(pkt->sk, buf, PACKET_SZ(pkt->hdr.sz),
  322. pkt->flags, to, tolen);
  323. } else if (pkt->sk_type == SKT_TCP) {
  324. if (pkt->pkt_flags & PKT_SEND_TIMEOUT)
  325. ret = inet_send_timeout(pkt->sk, buf, PACKET_SZ(pkt->hdr.sz),
  326. pkt->flags, pkt->timeout);
  327. else
  328. ret = inet_send(pkt->sk, buf, PACKET_SZ(pkt->hdr.sz),
  329. pkt->flags);
  330. } else
  331. fatal("Unkown socket_type. Something's very wrong!! Be aware");
  332. finish:
  333. if (buf)
  334. xfree(buf);
  335. return ret;
  336. }
  337. ssize_t
  338. pkt_recv_udp(PACKET * pkt)
  339. {
  340. ssize_t err = -1;
  341. struct sockaddr from;
  342. socklen_t fromlen;
  343. char buf[MAXMSGSZ];
  344. setzero(buf, MAXMSGSZ);
  345. setzero(&from, sizeof(struct sockaddr));
  346. if (pkt->family == AF_INET)
  347. fromlen = sizeof(struct sockaddr_in);
  348. else if (pkt->family == AF_INET6)
  349. fromlen = sizeof(struct sockaddr_in6);
  350. else {
  351. error("pkt_recv udp: family not set");
  352. return -1;
  353. }
  354. /* we get the whole pkt, */
  355. if (pkt->pkt_flags & PKT_RECV_TIMEOUT)
  356. err = inet_recvfrom_timeout(pkt->sk, buf, PACKET_SZ(MAXMSGSZ),
  357. pkt->flags, &from, &fromlen,
  358. pkt->timeout);
  359. else
  360. err = inet_recvfrom(pkt->sk, buf, PACKET_SZ(MAXMSGSZ),
  361. pkt->flags, &from, &fromlen);
  362. if (err < sizeof(pkt_hdr)) {
  363. debug(DBG_NOISE, "inet_recvfrom() of the hdr aborted!");
  364. return -1;
  365. }
  366. /* then we extract the hdr... and verify it */
  367. memcpy(&pkt->hdr, buf, sizeof(pkt_hdr));
  368. /* network -> host order */
  369. ints_network_to_host(&pkt->hdr, pkt_hdr_iinfo);
  370. if (pkt_verify_hdr(*pkt) || pkt->hdr.sz + sizeof(pkt_hdr) > err) {
  371. debug(DBG_NOISE, RED(ERROR_MSG) "Malformed header", ERROR_POS);
  372. return -1;
  373. }
  374. if (sockaddr_to_inet(&from, &pkt->from, 0) < 0) {
  375. debug(DBG_NOISE, "Cannot pkt_recv(): %d"
  376. " Family not supported", from.sa_family);
  377. return -1;
  378. }
  379. pkt->msg = 0;
  380. if (pkt->hdr.sz) {
  381. /*let's get the body */
  382. pkt->msg = xmalloc(pkt->hdr.sz);
  383. memcpy(pkt->msg, buf + sizeof(pkt_hdr), pkt->hdr.sz);
  384. }
  385. return err;
  386. }
  387. ssize_t
  388. pkt_recv_tcp(PACKET * pkt)
  389. {
  390. ssize_t err = -1;
  391. /* we get the hdr... */
  392. if (pkt->pkt_flags & PKT_RECV_TIMEOUT)
  393. err = inet_recv_timeout(pkt->sk, &pkt->hdr, sizeof(pkt_hdr),
  394. pkt->flags, pkt->timeout);
  395. else
  396. err = inet_recv(pkt->sk, &pkt->hdr, sizeof(pkt_hdr), pkt->flags);
  397. if (err != sizeof(pkt_hdr))
  398. return -1;
  399. /* ...and verify it */
  400. ints_network_to_host(&pkt->hdr, pkt_hdr_iinfo);
  401. if (pkt_verify_hdr(*pkt)) {
  402. debug(DBG_NOISE, RED(ERROR_MSG) "Malformed header", ERROR_POS);
  403. return -1;
  404. }
  405. pkt->msg = 0;
  406. if (pkt->hdr.sz) {
  407. /* let's get the body */
  408. pkt->msg = xmalloc(pkt->hdr.sz);
  409. if (pkt->pkt_flags & PKT_RECV_TIMEOUT)
  410. err = inet_recv_timeout(pkt->sk, pkt->msg, pkt->hdr.sz,
  411. pkt->flags, pkt->timeout);
  412. else
  413. err = inet_recv(pkt->sk, pkt->msg, pkt->hdr.sz, pkt->flags);
  414. if (err != pkt->hdr.sz) {
  415. debug(DBG_NOISE, RED(ERROR_MSG) "Cannot recv the "
  416. "pkt's body", ERROR_FUNC);
  417. return -1;
  418. }
  419. }
  420. return err;
  421. }
  422. ssize_t
  423. pkt_recv(PACKET * pkt)
  424. {
  425. ssize_t err = -1;
  426. switch (pkt->sk_type) {
  427. case SKT_UDP:
  428. case SKT_BCAST:
  429. err = pkt_recv_udp(pkt);
  430. break;
  431. case SKT_TCP:
  432. err = pkt_recv_tcp(pkt);
  433. break;
  434. default:
  435. fatal("Unkown socket_type. Something's very wrong!! Be aware");
  436. break;
  437. }
  438. /* let's finish it */
  439. pkt_unpack(pkt);
  440. return err;
  441. }
  442. int
  443. pkt_tcp_connect(inet_prefix * host, short port, interface * dev)
  444. {
  445. int sk;
  446. PACKET pkt;
  447. const char *ntop;
  448. ssize_t err;
  449. ntop = inet_to_str(*host);
  450. setzero(&pkt, sizeof(PACKET));
  451. if ((sk = new_tcp_conn(host, port, dev ? dev->dev_name : 0)) == -1)
  452. goto finish;
  453. /*
  454. * Now we receive the first pkt from the server.
  455. * It is an ack.
  456. * Let's hope it isn't NEGATIVE (-_+)
  457. */
  458. pkt_addsk(&pkt, host->family, sk, SKT_TCP);
  459. pkt.flags = MSG_WAITALL;
  460. pkt_addport(&pkt, port);
  461. if ((err = pkt_recv(&pkt)) < 0) {
  462. error("Connection to %s failed: it wasn't possible to receive "
  463. "the ACK", ntop);
  464. ERROR_FINISH(sk, -1, finish);
  465. }
  466. /* ...Last famous words */
  467. if (pkt.hdr.op != ACK_AFFERMATIVE) {
  468. u_char err;
  469. memcpy(&err, pkt.msg, pkt.hdr.sz);
  470. error("Cannot connect to %s:%d: %s", ntop, port, rq_strerror(err));
  471. ERROR_FINISH(sk, -1, finish);
  472. }
  473. finish:
  474. pkt_free(&pkt, 0);
  475. return sk;
  476. }
  477. void
  478. pkt_fill_hdr(pkt_hdr * hdr, u_char flags, int id, u_char op, size_t sz)
  479. {
  480. hdr->ntk_id[0] = 'n';
  481. hdr->ntk_id[1] = 't';
  482. hdr->ntk_id[2] = 'k';
  483. hdr->id = !id ? rand() : id;
  484. hdr->flags = flags;
  485. hdr->op = op;
  486. hdr->sz = sz;
  487. }
  488. /*
  489. * add_pkt_op: Add the `exec_f' in the pkt_exec_functions array.
  490. * `op' must be add int the pkt_op_tbl if it is a request that will be
  491. * received or if it is an op that will be sent with send_rq().
  492. */
  493. void
  494. add_pkt_op(u_char op, char sk_type, u_short port,
  495. int (*exec_f) (PACKET pkt))
  496. {
  497. pkt_op_tbl[op].sk_type = sk_type;
  498. pkt_op_tbl[op].port = port;
  499. pkt_op_tbl[op].exec_func = exec_f;
  500. }
  501. /*
  502. * send_rq
  503. *
  504. * This functions send a `rq' request, with an id set to `rq_id', to
  505. * `pkt->to'.
  506. *
  507. * If `pkt->sk' is non zero, it will be used to send the request.
  508. * If `pkt->sk' is 0, it will create a new socket and connection to `pkt->to',
  509. * the new socket is stored in `pkt->sk'.
  510. *
  511. * If `pkt->hdr.sz` is > 0 it includes the `pkt->msg' in the packet otherwise
  512. * it will be NULL.
  513. *
  514. * If `rpkt' is not null it will receive and store the reply pkt in `rpkt'.
  515. *
  516. * If `check_ack' is set, send_rq checks the reply pkt ACK and its id; if the
  517. * test fails it gives an appropriate error message.
  518. *
  519. * If `rpkt' is not null send_rq confronts the OP of the received reply pkt
  520. * with `re'; if the test fails it gives an appropriate error message.
  521. *
  522. * If `pkt'->hdr.flags has the ASYNC_REPLY set, the `rpkt' will be received with
  523. * the pkt_queue, in this case, if `rpkt'->from is set to a valid ip, it will
  524. * be used to check the sender ip of the reply pkt.
  525. *
  526. * If `pkt'->dev is not null and the PKT_BIND_DEV flag is set in
  527. * `pkt'->pkt_flags, it will bind the socket of the outgoing/ingoing packet to
  528. * the device named `pkt'->dev->dev_name.
  529. *
  530. *
  531. * On failure a negative value is returned, otherwise 0.
  532. * The error values are defined in pkts.h.
  533. */
  534. int
  535. send_rq(PACKET * pkt, int pkt_flags, u_char rq, int rq_id, u_char re,
  536. int check_ack, PACKET * rpkt)
  537. {
  538. ssize_t err;
  539. int ret = 0;
  540. const char *ntop = 0;
  541. const u_char *rq_str = 0, *re_str = 0;
  542. inet_prefix *wanted_from = 0;
  543. if (op_verify(rq)) {
  544. error("\"%s\" request/reply is not valid!", rq_str);
  545. return SEND_RQ_ERR_RQ;
  546. }
  547. rq_str = !re_verify(rq) ? re_to_str(rq) : rq_to_str(rq);
  548. if (re && re_verify(re)) {
  549. error("\"%s\" reply is not valid!", re_str);
  550. return SEND_RQ_ERR_RE;
  551. }
  552. ntop = inet_to_str(pkt->to);
  553. /* * * the request building process * * */
  554. if (check_ack)
  555. pkt->hdr.flags |= SEND_ACK;
  556. pkt_fill_hdr(&pkt->hdr, pkt->hdr.flags, rq_id, rq, pkt->hdr.sz);
  557. if (!pkt->hdr.sz)
  558. pkt->msg = 0;
  559. if (!pkt->port) {
  560. if (!pkt_op_tbl[rq].port && !pkt->sk) {
  561. error("send_rq: The rq %s doesn't have an associated "
  562. "port.", rq_str);
  563. ERROR_FINISH(ret, SEND_RQ_ERR_PORT, finish);
  564. }
  565. pkt_addport(pkt, pkt_op_tbl[rq].port);
  566. }
  567. /* If the PKT_BIND_DEV flag is set we can use pkt->dev */
  568. pkt->dev = (pkt->pkt_flags & PKT_BIND_DEV) ? pkt->dev : 0;
  569. if (!pkt->sk_type)
  570. pkt->sk_type = pkt_op_tbl[rq].sk_type;
  571. if (!pkt->sk) {
  572. if (!pkt->to.family || !pkt->to.len) {
  573. error("pkt->to isn't set. I can't create the new connection");
  574. ERROR_FINISH(ret, SEND_RQ_ERR_TO, finish);
  575. }
  576. if (pkt->sk_type == SKT_TCP)
  577. pkt->sk = pkt_tcp_connect(&pkt->to, pkt->port, pkt->dev);
  578. else if (pkt->sk_type == SKT_UDP)
  579. pkt->sk =
  580. new_udp_conn(&pkt->to, pkt->port, pkt->dev->dev_name);
  581. else if (pkt->sk_type == SKT_BCAST) {
  582. if (!pkt->dev)
  583. fatal(RED(ERROR_MSG) "cannot broadcast the packet: "
  584. "device not specified", ERROR_FUNC);
  585. pkt->sk =
  586. new_bcast_conn(&pkt->to, pkt->port, pkt->dev->dev_idx);
  587. } else
  588. fatal("Unkown socket_type. Something's very wrong!! Be aware");
  589. if (pkt->sk == -1) {
  590. error("Couldn't connect to %s to launch the %s request", ntop,
  591. rq_str);
  592. ERROR_FINISH(ret, SEND_RQ_ERR_CONNECT, finish);
  593. }
  594. }
  595. /* Set the LOWDELAY TOS if necessary */
  596. if (pkt->pkt_flags & PKT_SET_LOWDELAY)
  597. set_tos_sk(pkt->sk, 1);
  598. if (pkt->pkt_flags & PKT_NONBLOCK)
  599. set_nonblock_sk(pkt->sk);
  600. /*Let's send the request */
  601. err = pkt_send(pkt);
  602. if (err == -1) {
  603. error("Cannot send the %s request to %s:%d.", rq_str, ntop,
  604. pkt->port);
  605. ERROR_FINISH(ret, SEND_RQ_ERR_SEND, finish);
  606. }
  607. /*
  608. * * * the reply * *
  609. */
  610. if (rpkt) {
  611. if (rpkt->from.data[0] && rpkt->from.len) {
  612. wanted_from = &rpkt->from;
  613. ntop = inet_to_str(rpkt->from);
  614. }
  615. setzero(rpkt, sizeof(PACKET));
  616. pkt_addport(rpkt, pkt->port);
  617. pkt_addsk(rpkt, pkt->to.family, pkt->sk, pkt->sk_type);
  618. rpkt->flags = MSG_WAITALL;
  619. pkt_addtimeout(rpkt, pkt->timeout,
  620. pkt->pkt_flags & PKT_RECV_TIMEOUT,
  621. pkt->pkt_flags & PKT_SEND_TIMEOUT);
  622. if (pkt->pkt_flags & PKT_COMPRESSED)
  623. pkt_addcompress(rpkt);
  624. debug(DBG_NOISE, "Receiving reply for the %s request"
  625. " (id 0x%x)", rq_str, pkt->hdr.id);
  626. if (pkt->hdr.flags & ASYNC_REPLY) {
  627. pkt_queue *pq;
  628. /* Receive the pkt in the async way */
  629. err = pkt_q_wait_recv(pkt->hdr.id, wanted_from, rpkt, &pq);
  630. pkt_q_del(pq, 0);
  631. } else {
  632. if (pkt->sk_type == SKT_UDP) {
  633. inet_copy(&rpkt->from, &pkt->to);
  634. ntop = inet_to_str(rpkt->from);
  635. }
  636. /* Receive the pkt in the standard way */
  637. err = pkt_recv(rpkt);
  638. }
  639. if (err == -1) {
  640. error("Error while receving the reply for the %s request"
  641. " from %s.", rq_str, ntop);
  642. ERROR_FINISH(ret, SEND_RQ_ERR_RECV, finish);
  643. }
  644. if ((rpkt->hdr.op == ACK_NEGATIVE) && check_ack) {
  645. u_char err_ack;
  646. memcpy(&err_ack, rpkt->msg, sizeof(u_char));
  647. error("%s failed. The node %s replied: %s", rq_str, ntop,
  648. rq_strerror(err_ack));
  649. ERROR_FINISH(ret, SEND_RQ_ERR_REPLY, finish);
  650. } else if (rpkt->hdr.op != re && check_ack) {
  651. error("The node %s replied %s but we asked %s!", ntop,
  652. re_to_str(rpkt->hdr.op), re_str);
  653. ERROR_FINISH(ret, SEND_RQ_ERR_RECVOP, finish);
  654. }
  655. if (check_ack && rpkt->hdr.id != pkt->hdr.id) {
  656. error("The id (0x%x) of the reply (%s) doesn't match the"
  657. " id of our request (0x%x)", rpkt->hdr.id,
  658. re_str, pkt->hdr.id);
  659. ERROR_FINISH(ret, SEND_RQ_ERR_RECVID, finish);
  660. }
  661. }
  662. finish:
  663. return ret;
  664. }
  665. /*
  666. * forward_pkt: forwards the received packet `rpkt' to `to'.
  667. */
  668. int
  669. forward_pkt(PACKET rpkt, inet_prefix to)
  670. {
  671. int err;
  672. rpkt.sk = 0; /* create a new connection */
  673. pkt_addto(&rpkt, &to);
  674. err = send_rq(&rpkt, 0, rpkt.hdr.op, rpkt.hdr.id, 0, 0, 0);
  675. if (!err)
  676. inet_close(&rpkt.sk);
  677. return err;
  678. }
  679. /*
  680. * pkt_err: Sends back to "pkt.from" an error pkt, with ACK_NEGATIVE,
  681. * containing the "err" code.
  682. * If `free_pkt' is not 0, `pkt' will be freed.
  683. */
  684. int
  685. pkt_err(PACKET pkt, u_char err, int free_pkt)
  686. {
  687. char *msg;
  688. u_char flags = 0;
  689. pkt_addto(&pkt, &pkt.from);
  690. if (pkt.hdr.flags & ASYNC_REPLY) {
  691. flags |= ASYNC_REPLIED;
  692. pkt.sk = 0;
  693. }
  694. /* It's useless to compress this pkt */
  695. pkt.pkt_flags &= ~PKT_COMPRESSED;
  696. pkt_fill_hdr(&pkt.hdr, flags, pkt.hdr.id, ACK_NEGATIVE,
  697. sizeof(u_char));
  698. pkt.msg = msg = xmalloc(sizeof(u_char));
  699. memcpy(msg, &err, sizeof(u_char));
  700. err = send_rq(&pkt, 0, ACK_NEGATIVE, pkt.hdr.id, 0, 0, 0);
  701. if (pkt.hdr.flags & ASYNC_REPLY)
  702. pkt_free(&pkt, 1);
  703. else
  704. pkt_free(&pkt, 0);
  705. return err;
  706. }
  707. /*
  708. * pkt_exec
  709. *
  710. * It "executes" the received `pkt' passing it to the function which associated
  711. * to `pkt'.hdr.op.
  712. *
  713. * `acpt_idx' is the accept table index of the connection where the pkt was
  714. * received.
  715. */
  716. int
  717. pkt_exec(PACKET pkt, int acpt_idx)
  718. {
  719. const char *ntop;
  720. const u_char *op_str;
  721. int (*exec_f) (PACKET pkt);
  722. int err = 0;
  723. if (!re_verify(pkt.hdr.op))
  724. op_str = re_to_str(pkt.hdr.op);
  725. else if (!rq_verify(pkt.hdr.op))
  726. op_str = rq_to_str(pkt.hdr.op);
  727. else {
  728. debug(DBG_SOFT, "Dropped pkt from %s: bad op value",
  729. inet_to_str(pkt.from));
  730. return -1; /* bad op */
  731. }
  732. if ((err = add_rq(pkt.hdr.op, &accept_tbl[acpt_idx].rqtbl))) {
  733. ntop = inet_to_str(pkt.from);
  734. error("From %s: Cannot process the %s request: %s", ntop,
  735. op_str, rq_strerror(err));
  736. pkt_err(pkt, err, 1);
  737. return -1;
  738. }
  739. if (op_filter_test(pkt.hdr.op)) {
  740. /* Drop the pkt, `pkt.hdr.op' has been filtered */
  741. #ifdef DEBUG
  742. ntop = inet_to_str(pkt.from);
  743. debug(DBG_INSANE, "FILTERED %s from %s, id 0x%x", op_str, ntop,
  744. pkt.hdr.id);
  745. #endif
  746. return err;
  747. }
  748. /* Call the function associated to `pkt.hdr.op' */
  749. exec_f = pkt_op_tbl[pkt.hdr.op].exec_func;
  750. #ifdef DEBUG
  751. if (pkt.hdr.op != ECHO_ME && pkt.hdr.op != ECHO_REPLY) {
  752. ntop = inet_to_str(pkt.from);
  753. debug(DBG_INSANE, "Received %s from %s, id 0x%x", op_str, ntop,
  754. pkt.hdr.id);
  755. }
  756. #endif
  757. if (exec_f)
  758. err = (*exec_f) (pkt);
  759. else if (pkt_q_counter) {
  760. debug(DBG_INSANE, "pkt_exec: %s Async reply, id 0x%x", op_str,
  761. pkt.hdr.id);
  762. /*
  763. * There isn't a function to handle this pkt, so maybe it is
  764. * an async reply
  765. */
  766. pkt_q_add_pkt(pkt);
  767. }
  768. return err;
  769. }
  770. /*
  771. * * * Pkt queue functions * * *
  772. */
  773. pthread_attr_t wait_and_unlock_attr;
  774. void
  775. pkt_queue_init(void)
  776. {
  777. pkt_q = (pkt_queue *) clist_init(&pkt_q_counter);
  778. pthread_attr_init(&wait_and_unlock_attr);
  779. pthread_attr_setdetachstate(&wait_and_unlock_attr,
  780. PTHREAD_CREATE_DETACHED);
  781. }
  782. void
  783. pkt_queue_close(void)
  784. {
  785. pkt_queue *pq = pkt_q, *next;
  786. if (pkt_q_counter)
  787. list_safe_for(pq, next)
  788. pkt_q_del(pq, 1);
  789. pthread_attr_destroy(&wait_and_unlock_attr);
  790. }
  791. /*
  792. * wait_and_unlock
  793. *
  794. * It waits REQUEST_TIMEOUT seconds, then it unlocks `pq'->mtx.
  795. * This prevents the dead lock in pkt_q_wait_recv()
  796. */
  797. void *
  798. wait_and_unlock(void *m)
  799. {
  800. pkt_queue *pq, **pq_ptr;
  801. int i;
  802. pq_ptr = (pkt_queue **) m;
  803. pq = *pq_ptr;
  804. if (!pq)
  805. return 0;
  806. for (i = 0; i < REQUEST_TIMEOUT; i++) {
  807. sleep(1);
  808. if (!(*pq_ptr) || (pq->flags & PKT_Q_PKT_RECEIVED) ||
  809. !(pq->flags & PKT_Q_MTX_LOCKED) ||
  810. pthread_mutex_trylock(&pq->mtx) != EBUSY)
  811. break;
  812. }
  813. if (!(*pq_ptr) || (pq->flags & PKT_Q_PKT_RECEIVED) ||
  814. !(pq->flags & PKT_Q_MTX_LOCKED) ||
  815. pthread_mutex_trylock(&pq->mtx) != EBUSY)
  816. goto finish;
  817. debug(DBG_INSANE, "pq->pkt.hdr.id: 0x%x Timeoutted. mtx: 0x%X",
  818. pq->pkt.hdr.id, &pq->mtx);
  819. pthread_mutex_unlock(&pq->mtx);
  820. pq->flags |= PKT_Q_TIMEOUT;
  821. finish:
  822. if (pq_ptr)
  823. xfree(pq_ptr);
  824. return 0;
  825. }
  826. /*
  827. * pkt_q_wait_recv
  828. *
  829. * adds a new struct in pkt_q and waits REQUEST_TIMEOUT
  830. * seconds until a reply with an id equal to `id' is received.
  831. * If `from' is not null, the sender ip of the reply is considered too.
  832. * The received reply pkt is copied in `rpkt' (if `rpkt' isn't null).
  833. * In `ret_pq' is stored the address of the pkt_queue struct that
  834. * corresponds to `rpkt'.
  835. * After the use of this function pkt_q_del() must be called.
  836. * On error -1 is returned.
  837. */
  838. int
  839. pkt_q_wait_recv(int id, inet_prefix * from, PACKET * rpkt,
  840. pkt_queue ** ret_pq)
  841. {
  842. pthread_t thread;
  843. pkt_queue *pq, **pq_ptr;
  844. pq = xzalloc(sizeof(pkt_queue));
  845. pq_ptr = xmalloc(sizeof(pkt_queue *));
  846. *pq_ptr = pq;
  847. pthread_mutex_init(&pq->mtx, 0);
  848. pq->flags |= PKT_Q_MTX_LOCKED;
  849. *ret_pq = pq;
  850. if (!pkt_q_counter)
  851. pkt_queue_init();
  852. pq->pkt.hdr.id = id;
  853. if (from) {
  854. debug(DBG_INSANE, "0x%x wanted_rfrom %s activated", id,
  855. inet_to_str(*from));
  856. inet_copy(&pq->pkt.from, from);
  857. pq->flags |= PKT_Q_CHECK_FROM;
  858. }
  859. clist_add(&pkt_q, &pkt_q_counter, pq);
  860. /* Be sure to unlock me after the timeout */
  861. pthread_create(&thread, &wait_and_unlock_attr, wait_and_unlock,
  862. (void *) pq_ptr);
  863. if (pq->flags & PKT_Q_MTX_LOCKED) {
  864. debug(DBG_INSANE, "pkt_q_wait_recv: Locking 0x%x!", &pq->mtx);
  865. /* Freeze! */
  866. pthread_mutex_lock(&pq->mtx);
  867. pthread_mutex_lock(&pq->mtx);
  868. }
  869. debug(DBG_INSANE, "We've been unlocked: timeout %d",
  870. (pq->flags & PKT_Q_TIMEOUT));
  871. if (pq->flags & PKT_Q_TIMEOUT)
  872. return -1;
  873. if (rpkt)
  874. pkt_copy(rpkt, &pq->pkt);
  875. /* When *pq_ptr is set to 0, the wait_and_unlock thread exits */
  876. *pq_ptr = 0;
  877. return 0;
  878. }
  879. /*
  880. * pkt_q_add_pkt: Copy the reply pkt in the struct of pkt_q which has the same
  881. * hdr.id, then unlock the mutex of the pkt_q struct.
  882. * If the struct in pkt_q isn't found, -1 is returned.
  883. */
  884. int
  885. pkt_q_add_pkt(PACKET pkt)
  886. {
  887. pkt_queue *pq = pkt_q, *next = 0;
  888. int ret = -1;
  889. list_safe_for(pq, next) {
  890. debug(DBG_INSANE,
  891. "pkt_q_add_pkt: %d == %d. data[0]: %d, async replied: %d",
  892. pq->pkt.hdr.id, pkt.hdr.id, pq->pkt.from.data[0],
  893. (pkt.hdr.flags & ASYNC_REPLIED));
  894. if (pq->pkt.hdr.id == pkt.hdr.id) {
  895. if (pq->pkt.from.data[0] && (pq->flags & PKT_Q_CHECK_FROM) &&
  896. memcmp(pq->pkt.from.data, pkt.from.data, MAX_IP_SZ))
  897. continue; /* The wanted from ip and the
  898. real from ip don't match */
  899. if (!(pkt.hdr.flags & ASYNC_REPLIED))
  900. continue;
  901. pkt_copy(&pq->pkt, &pkt);
  902. /* Now it's possible to read the reply,
  903. * pkt_q_wait_recv() is now hot again */
  904. while (pthread_mutex_trylock(&pq->mtx) != EBUSY)
  905. usleep(5000);
  906. debug(DBG_INSANE, "pkt_q_add_pkt: Unlocking 0x%X ", &pq->mtx);
  907. pq->flags &= ~PKT_Q_MTX_LOCKED & ~PKT_Q_TIMEOUT;
  908. pq->flags |= PKT_Q_PKT_RECEIVED;
  909. pthread_mutex_unlock(&pq->mtx);
  910. pthread_mutex_unlock(&pq->mtx);
  911. ret = 0;
  912. }
  913. }
  914. return ret;
  915. }
  916. /*
  917. * pkt_q_del: Deletes `pq' from the pkt_q llist and frees the `pq' struct. The
  918. * `pq'->pkt is also freed and the pq->pkt.sk socket is closed if `close_socket'
  919. * is non zero.
  920. */
  921. void
  922. pkt_q_del(pkt_queue * pq, int close_socket)
  923. {
  924. pthread_mutex_unlock(&pq->mtx);
  925. pthread_mutex_destroy(&pq->mtx);
  926. pkt_free(&pq->pkt, close_socket);
  927. clist_del(&pkt_q, &pkt_q_counter, pq);
  928. }