BDatagram_unix.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /**
  2. * @file BDatagram_unix.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #ifndef _GNU_SOURCE
  30. #define _GNU_SOURCE
  31. #endif
  32. #include <stddef.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include <errno.h>
  36. #include <sys/types.h>
  37. #include <sys/socket.h>
  38. #ifdef BADVPN_LINUX
  39. # include <netpacket/packet.h>
  40. # include <net/ethernet.h>
  41. #endif
  42. #include <misc/nonblocking.h>
  43. #include <base/BLog.h>
  44. #include "BDatagram.h"
  45. #include <generated/blog_channel_BDatagram.h>
  46. struct sys_addr {
  47. socklen_t len;
  48. union {
  49. struct sockaddr generic;
  50. struct sockaddr_in ipv4;
  51. struct sockaddr_in6 ipv6;
  52. #ifdef BADVPN_LINUX
  53. struct sockaddr_ll packet;
  54. #endif
  55. } addr;
  56. };
  57. static int family_socket_to_sys (int family);
  58. static void addr_socket_to_sys (struct sys_addr *out, BAddr addr);
  59. static void addr_sys_to_socket (BAddr *out, struct sys_addr addr);
  60. static void set_pktinfo (int fd, int family);
  61. static void report_error (BDatagram *o);
  62. static void do_send (BDatagram *o);
  63. static void do_recv (BDatagram *o);
  64. static void fd_handler (BDatagram *o, int events);
  65. static void send_job_handler (BDatagram *o);
  66. static void recv_job_handler (BDatagram *o);
  67. static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len);
  68. static void recv_if_handler_recv (BDatagram *o, uint8_t *data);
  69. static int family_socket_to_sys (int family)
  70. {
  71. switch (family) {
  72. case BADDR_TYPE_IPV4:
  73. return AF_INET;
  74. case BADDR_TYPE_IPV6:
  75. return AF_INET6;
  76. #ifdef BADVPN_LINUX
  77. case BADDR_TYPE_PACKET:
  78. return AF_PACKET;
  79. #endif
  80. }
  81. ASSERT(0);
  82. return 0;
  83. }
  84. static void addr_socket_to_sys (struct sys_addr *out, BAddr addr)
  85. {
  86. switch (addr.type) {
  87. case BADDR_TYPE_IPV4: {
  88. out->len = sizeof(out->addr.ipv4);
  89. memset(&out->addr.ipv4, 0, sizeof(out->addr.ipv4));
  90. out->addr.ipv4.sin_family = AF_INET;
  91. out->addr.ipv4.sin_port = addr.ipv4.port;
  92. out->addr.ipv4.sin_addr.s_addr = addr.ipv4.ip;
  93. } break;
  94. case BADDR_TYPE_IPV6: {
  95. out->len = sizeof(out->addr.ipv6);
  96. memset(&out->addr.ipv6, 0, sizeof(out->addr.ipv6));
  97. out->addr.ipv6.sin6_family = AF_INET6;
  98. out->addr.ipv6.sin6_port = addr.ipv6.port;
  99. out->addr.ipv6.sin6_flowinfo = 0;
  100. memcpy(out->addr.ipv6.sin6_addr.s6_addr, addr.ipv6.ip, 16);
  101. out->addr.ipv6.sin6_scope_id = 0;
  102. } break;
  103. #ifdef BADVPN_LINUX
  104. case BADDR_TYPE_PACKET: {
  105. ASSERT(addr.packet.header_type == BADDR_PACKET_HEADER_TYPE_ETHERNET)
  106. memset(&out->addr.packet, 0, sizeof(out->addr.packet));
  107. out->len = sizeof(out->addr.packet);
  108. out->addr.packet.sll_family = AF_PACKET;
  109. out->addr.packet.sll_protocol = addr.packet.phys_proto;
  110. out->addr.packet.sll_ifindex = addr.packet.interface_index;
  111. out->addr.packet.sll_hatype = 1; // linux/if_arp.h: #define ARPHRD_ETHER 1
  112. switch (addr.packet.packet_type) {
  113. case BADDR_PACKET_PACKET_TYPE_HOST:
  114. out->addr.packet.sll_pkttype = PACKET_HOST;
  115. break;
  116. case BADDR_PACKET_PACKET_TYPE_BROADCAST:
  117. out->addr.packet.sll_pkttype = PACKET_BROADCAST;
  118. break;
  119. case BADDR_PACKET_PACKET_TYPE_MULTICAST:
  120. out->addr.packet.sll_pkttype = PACKET_MULTICAST;
  121. break;
  122. case BADDR_PACKET_PACKET_TYPE_OTHERHOST:
  123. out->addr.packet.sll_pkttype = PACKET_OTHERHOST;
  124. break;
  125. case BADDR_PACKET_PACKET_TYPE_OUTGOING:
  126. out->addr.packet.sll_pkttype = PACKET_OUTGOING;
  127. break;
  128. default:
  129. ASSERT(0);
  130. }
  131. out->addr.packet.sll_halen = 6;
  132. memcpy(out->addr.packet.sll_addr, addr.packet.phys_addr, 6);
  133. } break;
  134. #endif
  135. default: ASSERT(0);
  136. }
  137. }
  138. static void addr_sys_to_socket (BAddr *out, struct sys_addr addr)
  139. {
  140. switch (addr.addr.generic.sa_family) {
  141. case AF_INET: {
  142. ASSERT(addr.len == sizeof(struct sockaddr_in))
  143. BAddr_InitIPv4(out, addr.addr.ipv4.sin_addr.s_addr, addr.addr.ipv4.sin_port);
  144. } break;
  145. case AF_INET6: {
  146. ASSERT(addr.len == sizeof(struct sockaddr_in6))
  147. BAddr_InitIPv6(out, addr.addr.ipv6.sin6_addr.s6_addr, addr.addr.ipv6.sin6_port);
  148. } break;
  149. #ifdef BADVPN_LINUX
  150. case AF_PACKET: {
  151. if (addr.len < offsetof(struct sockaddr_ll, sll_addr) + 6) {
  152. goto fail;
  153. }
  154. if (addr.addr.packet.sll_hatype != 1) { // linux/if_arp.h: #define ARPHRD_ETHER 1
  155. goto fail;
  156. }
  157. int packet_type;
  158. switch (addr.addr.packet.sll_pkttype) {
  159. case PACKET_HOST:
  160. packet_type = BADDR_PACKET_PACKET_TYPE_HOST;
  161. break;
  162. case PACKET_BROADCAST:
  163. packet_type = BADDR_PACKET_PACKET_TYPE_BROADCAST;
  164. break;
  165. case PACKET_MULTICAST:
  166. packet_type = BADDR_PACKET_PACKET_TYPE_MULTICAST;
  167. break;
  168. case PACKET_OTHERHOST:
  169. packet_type = BADDR_PACKET_PACKET_TYPE_OTHERHOST;
  170. break;
  171. case PACKET_OUTGOING:
  172. packet_type = BADDR_PACKET_PACKET_TYPE_OUTGOING;
  173. break;
  174. default:
  175. goto fail;
  176. }
  177. if (addr.addr.packet.sll_halen != 6) {
  178. goto fail;
  179. }
  180. BAddr_InitPacket(out, addr.addr.packet.sll_protocol, addr.addr.packet.sll_ifindex, BADDR_PACKET_HEADER_TYPE_ETHERNET, packet_type, addr.addr.packet.sll_addr);
  181. } break;
  182. #endif
  183. fail:
  184. default: {
  185. BAddr_InitNone(out);
  186. } break;
  187. }
  188. }
  189. static void set_pktinfo (int fd, int family)
  190. {
  191. int opt = 1;
  192. switch (family) {
  193. case BADDR_TYPE_IPV4: {
  194. #ifdef BADVPN_FREEBSD
  195. if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) < 0) {
  196. BLog(BLOG_ERROR, "setsockopt(IP_RECVDSTADDR) failed");
  197. }
  198. #else
  199. if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) < 0) {
  200. BLog(BLOG_ERROR, "setsockopt(IP_PKTINFO) failed");
  201. }
  202. #endif
  203. } break;
  204. #ifdef IPV6_RECVPKTINFO
  205. case BADDR_TYPE_IPV6: {
  206. if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) < 0) {
  207. BLog(BLOG_ERROR, "setsockopt(IPV6_RECVPKTINFO) failed");
  208. }
  209. } break;
  210. #endif
  211. }
  212. }
  213. static void report_error (BDatagram *o)
  214. {
  215. DebugError_AssertNoError(&o->d_err);
  216. // report error
  217. DEBUGERROR(&o->d_err, o->handler(o->user, BDATAGRAM_EVENT_ERROR));
  218. return;
  219. }
  220. static void do_send (BDatagram *o)
  221. {
  222. DebugError_AssertNoError(&o->d_err);
  223. ASSERT(o->send.inited)
  224. ASSERT(o->send.busy)
  225. ASSERT(o->send.have_addrs)
  226. // limit
  227. if (!BReactorLimit_Increment(&o->send.limit)) {
  228. // wait for fd
  229. o->wait_events |= BREACTOR_WRITE;
  230. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  231. return;
  232. }
  233. // convert destination address
  234. struct sys_addr sysaddr;
  235. addr_socket_to_sys(&sysaddr, o->send.remote_addr);
  236. struct iovec iov;
  237. iov.iov_base = (uint8_t *)o->send.busy_data;
  238. iov.iov_len = o->send.busy_data_len;
  239. union {
  240. #ifdef BADVPN_FREEBSD
  241. char in[CMSG_SPACE(sizeof(struct in_addr))];
  242. #else
  243. char in[CMSG_SPACE(sizeof(struct in_pktinfo))];
  244. #endif
  245. char in6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
  246. } cdata;
  247. struct msghdr msg;
  248. memset(&msg, 0, sizeof(msg));
  249. msg.msg_name = &sysaddr.addr.generic;
  250. msg.msg_namelen = sysaddr.len;
  251. msg.msg_iov = &iov;
  252. msg.msg_iovlen = 1;
  253. msg.msg_control = &cdata;
  254. msg.msg_controllen = sizeof(cdata);
  255. struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
  256. size_t controllen = 0;
  257. switch (o->send.local_addr.type) {
  258. case BADDR_TYPE_IPV4: {
  259. #ifdef BADVPN_FREEBSD
  260. memset(cmsg, 0, CMSG_SPACE(sizeof(struct in_addr)));
  261. cmsg->cmsg_level = IPPROTO_IP;
  262. cmsg->cmsg_type = IP_SENDSRCADDR;
  263. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
  264. struct in_addr *addrinfo = (struct in_addr *)CMSG_DATA(cmsg);
  265. addrinfo->s_addr = o->send.local_addr.ipv4;
  266. controllen += CMSG_SPACE(sizeof(struct in_addr));
  267. #else
  268. memset(cmsg, 0, CMSG_SPACE(sizeof(struct in_pktinfo)));
  269. cmsg->cmsg_level = IPPROTO_IP;
  270. cmsg->cmsg_type = IP_PKTINFO;
  271. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
  272. struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
  273. pktinfo->ipi_spec_dst.s_addr = o->send.local_addr.ipv4;
  274. controllen += CMSG_SPACE(sizeof(struct in_pktinfo));
  275. #endif
  276. } break;
  277. case BADDR_TYPE_IPV6: {
  278. memset(cmsg, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));
  279. cmsg->cmsg_level = IPPROTO_IPV6;
  280. cmsg->cmsg_type = IPV6_PKTINFO;
  281. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  282. struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
  283. memcpy(pktinfo->ipi6_addr.s6_addr, o->send.local_addr.ipv6, 16);
  284. controllen += CMSG_SPACE(sizeof(struct in6_pktinfo));
  285. } break;
  286. }
  287. msg.msg_controllen = controllen;
  288. if (msg.msg_controllen == 0) {
  289. msg.msg_control = NULL;
  290. }
  291. // send
  292. int bytes = sendmsg(o->fd, &msg, 0);
  293. if (bytes < 0) {
  294. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  295. // wait for fd
  296. o->wait_events |= BREACTOR_WRITE;
  297. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  298. return;
  299. }
  300. BLog(BLOG_ERROR, "send failed");
  301. report_error(o);
  302. return;
  303. }
  304. ASSERT(bytes >= 0)
  305. ASSERT(bytes <= o->send.busy_data_len)
  306. if (bytes < o->send.busy_data_len) {
  307. BLog(BLOG_ERROR, "send sent too little");
  308. }
  309. // if recv wasn't started yet, start it
  310. if (!o->recv.started) {
  311. // set recv started
  312. o->recv.started = 1;
  313. // continue receiving
  314. if (o->recv.inited && o->recv.busy) {
  315. BPending_Set(&o->recv.job);
  316. }
  317. }
  318. // set not busy
  319. o->send.busy = 0;
  320. // done
  321. PacketPassInterface_Done(&o->send.iface);
  322. }
  323. static void do_recv (BDatagram *o)
  324. {
  325. DebugError_AssertNoError(&o->d_err);
  326. ASSERT(o->recv.inited)
  327. ASSERT(o->recv.busy)
  328. ASSERT(o->recv.started)
  329. // limit
  330. if (!BReactorLimit_Increment(&o->recv.limit)) {
  331. // wait for fd
  332. o->wait_events |= BREACTOR_READ;
  333. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  334. return;
  335. }
  336. struct sys_addr sysaddr;
  337. struct iovec iov;
  338. iov.iov_base = o->recv.busy_data;
  339. iov.iov_len = o->recv.mtu;
  340. union {
  341. #ifdef BADVPN_FREEBSD
  342. char in[CMSG_SPACE(sizeof(struct in_addr))];
  343. #else
  344. char in[CMSG_SPACE(sizeof(struct in_pktinfo))];
  345. #endif
  346. char in6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
  347. } cdata;
  348. struct msghdr msg;
  349. memset(&msg, 0, sizeof(msg));
  350. msg.msg_name = &sysaddr.addr.generic;
  351. msg.msg_namelen = sizeof(sysaddr.addr);
  352. msg.msg_iov = &iov;
  353. msg.msg_iovlen = 1;
  354. msg.msg_control = &cdata;
  355. msg.msg_controllen = sizeof(cdata);
  356. // recv
  357. int bytes = recvmsg(o->fd, &msg, 0);
  358. if (bytes < 0) {
  359. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  360. // wait for fd
  361. o->wait_events |= BREACTOR_READ;
  362. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  363. return;
  364. }
  365. BLog(BLOG_ERROR, "recv failed");
  366. report_error(o);
  367. return;
  368. }
  369. ASSERT(bytes >= 0)
  370. ASSERT(bytes <= o->recv.mtu)
  371. // read returned address
  372. sysaddr.len = msg.msg_namelen;
  373. addr_sys_to_socket(&o->recv.remote_addr, sysaddr);
  374. // read returned local address
  375. BIPAddr_InitInvalid(&o->recv.local_addr);
  376. for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
  377. #ifdef BADVPN_FREEBSD
  378. if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
  379. struct in_addr *addrinfo = (struct in_addr *)CMSG_DATA(cmsg);
  380. BIPAddr_InitIPv4(&o->recv.local_addr, addrinfo->s_addr);
  381. }
  382. #else
  383. if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
  384. struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
  385. BIPAddr_InitIPv4(&o->recv.local_addr, pktinfo->ipi_addr.s_addr);
  386. }
  387. #endif
  388. else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
  389. struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
  390. BIPAddr_InitIPv6(&o->recv.local_addr, pktinfo->ipi6_addr.s6_addr);
  391. }
  392. }
  393. // set have addresses
  394. o->recv.have_addrs = 1;
  395. // set not busy
  396. o->recv.busy = 0;
  397. // done
  398. PacketRecvInterface_Done(&o->recv.iface, bytes);
  399. }
  400. static void fd_handler (BDatagram *o, int events)
  401. {
  402. DebugObject_Access(&o->d_obj);
  403. DebugError_AssertNoError(&o->d_err);
  404. // clear handled events
  405. o->wait_events &= ~events;
  406. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  407. int have_send = 0;
  408. int have_recv = 0;
  409. if ((events & BREACTOR_WRITE) || ((events & (BREACTOR_ERROR|BREACTOR_HUP)) && o->send.inited && o->send.busy && o->send.have_addrs)) {
  410. ASSERT(o->send.inited)
  411. ASSERT(o->send.busy)
  412. ASSERT(o->send.have_addrs)
  413. have_send = 1;
  414. }
  415. if ((events & BREACTOR_READ) || ((events & (BREACTOR_ERROR|BREACTOR_HUP)) && o->recv.inited && o->recv.busy && o->recv.started)) {
  416. ASSERT(o->recv.inited)
  417. ASSERT(o->recv.busy)
  418. ASSERT(o->recv.started)
  419. have_recv = 1;
  420. }
  421. if (have_send) {
  422. if (have_recv) {
  423. BPending_Set(&o->recv.job);
  424. }
  425. do_send(o);
  426. return;
  427. }
  428. if (have_recv) {
  429. do_recv(o);
  430. return;
  431. }
  432. BLog(BLOG_ERROR, "fd error event");
  433. report_error(o);
  434. return;
  435. }
  436. static void send_job_handler (BDatagram *o)
  437. {
  438. DebugObject_Access(&o->d_obj);
  439. DebugError_AssertNoError(&o->d_err);
  440. ASSERT(o->send.inited)
  441. ASSERT(o->send.busy)
  442. ASSERT(o->send.have_addrs)
  443. do_send(o);
  444. return;
  445. }
  446. static void recv_job_handler (BDatagram *o)
  447. {
  448. DebugObject_Access(&o->d_obj);
  449. DebugError_AssertNoError(&o->d_err);
  450. ASSERT(o->recv.inited)
  451. ASSERT(o->recv.busy)
  452. ASSERT(o->recv.started)
  453. do_recv(o);
  454. return;
  455. }
  456. static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len)
  457. {
  458. DebugObject_Access(&o->d_obj);
  459. DebugError_AssertNoError(&o->d_err);
  460. ASSERT(o->send.inited)
  461. ASSERT(!o->send.busy)
  462. ASSERT(data_len >= 0)
  463. ASSERT(data_len <= o->send.mtu)
  464. // remember data
  465. o->send.busy_data = data;
  466. o->send.busy_data_len = data_len;
  467. // set busy
  468. o->send.busy = 1;
  469. // if have no addresses, wait
  470. if (!o->send.have_addrs) {
  471. return;
  472. }
  473. // set job
  474. BPending_Set(&o->send.job);
  475. }
  476. static void recv_if_handler_recv (BDatagram *o, uint8_t *data)
  477. {
  478. DebugObject_Access(&o->d_obj);
  479. DebugError_AssertNoError(&o->d_err);
  480. ASSERT(o->recv.inited)
  481. ASSERT(!o->recv.busy)
  482. // remember data
  483. o->recv.busy_data = data;
  484. // set busy
  485. o->recv.busy = 1;
  486. // if recv not started yet, wait
  487. if (!o->recv.started) {
  488. return;
  489. }
  490. // set job
  491. BPending_Set(&o->recv.job);
  492. }
  493. int BDatagram_AddressFamilySupported (int family)
  494. {
  495. switch (family) {
  496. case BADDR_TYPE_IPV4:
  497. case BADDR_TYPE_IPV6:
  498. #ifdef BADVPN_LINUX
  499. case BADDR_TYPE_PACKET:
  500. #endif
  501. return 1;
  502. }
  503. return 0;
  504. }
  505. int BDatagram_Init (BDatagram *o, int family, BReactor *reactor, void *user,
  506. BDatagram_handler handler)
  507. {
  508. ASSERT(BDatagram_AddressFamilySupported(family))
  509. ASSERT(handler)
  510. BNetwork_Assert();
  511. // init arguments
  512. o->reactor = reactor;
  513. o->user = user;
  514. o->handler = handler;
  515. // init fd
  516. if ((o->fd = socket(family_socket_to_sys(family), SOCK_DGRAM, 0)) < 0) {
  517. BLog(BLOG_ERROR, "socket failed");
  518. goto fail0;
  519. }
  520. // set fd non-blocking
  521. if (!badvpn_set_nonblocking(o->fd)) {
  522. BLog(BLOG_ERROR, "badvpn_set_nonblocking failed");
  523. goto fail1;
  524. }
  525. // enable receiving pktinfo
  526. set_pktinfo(o->fd, family);
  527. // init BFileDescriptor
  528. BFileDescriptor_Init(&o->bfd, o->fd, (BFileDescriptor_handler)fd_handler, o);
  529. if (!BReactor_AddFileDescriptor(o->reactor, &o->bfd)) {
  530. BLog(BLOG_ERROR, "BReactor_AddFileDescriptor failed");
  531. goto fail1;
  532. }
  533. // set no wait events
  534. o->wait_events = 0;
  535. // init limits
  536. BReactorLimit_Init(&o->send.limit, o->reactor, BDATAGRAM_SEND_LIMIT);
  537. BReactorLimit_Init(&o->recv.limit, o->reactor, BDATAGRAM_RECV_LIMIT);
  538. // set have no send and recv addresses
  539. o->send.have_addrs = 0;
  540. o->recv.have_addrs = 0;
  541. // set recv not started
  542. o->recv.started = 0;
  543. // set send and recv not inited
  544. o->send.inited = 0;
  545. o->recv.inited = 0;
  546. DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
  547. DebugObject_Init(&o->d_obj);
  548. return 1;
  549. fail1:
  550. if (close(o->fd) < 0) {
  551. BLog(BLOG_ERROR, "close failed");
  552. }
  553. fail0:
  554. return 0;
  555. }
  556. void BDatagram_Free (BDatagram *o)
  557. {
  558. DebugObject_Free(&o->d_obj);
  559. DebugError_Free(&o->d_err);
  560. ASSERT(!o->recv.inited)
  561. ASSERT(!o->send.inited)
  562. // free limits
  563. BReactorLimit_Free(&o->recv.limit);
  564. BReactorLimit_Free(&o->send.limit);
  565. // free BFileDescriptor
  566. BReactor_RemoveFileDescriptor(o->reactor, &o->bfd);
  567. // free fd
  568. if (close(o->fd) < 0) {
  569. BLog(BLOG_ERROR, "close failed");
  570. }
  571. }
  572. int BDatagram_Bind (BDatagram *o, BAddr addr)
  573. {
  574. DebugObject_Access(&o->d_obj);
  575. DebugError_AssertNoError(&o->d_err);
  576. ASSERT(BDatagram_AddressFamilySupported(addr.type))
  577. // translate address
  578. struct sys_addr sysaddr;
  579. addr_socket_to_sys(&sysaddr, addr);
  580. // bind
  581. if (bind(o->fd, &sysaddr.addr.generic, sysaddr.len) < 0) {
  582. BLog(BLOG_ERROR, "bind failed");
  583. return 0;
  584. }
  585. // if recv wasn't started yet, start it
  586. if (!o->recv.started) {
  587. // set recv started
  588. o->recv.started = 1;
  589. // continue receiving
  590. if (o->recv.inited && o->recv.busy) {
  591. BPending_Set(&o->recv.job);
  592. }
  593. }
  594. return 1;
  595. }
  596. void BDatagram_SetSendAddrs (BDatagram *o, BAddr remote_addr, BIPAddr local_addr)
  597. {
  598. DebugObject_Access(&o->d_obj);
  599. DebugError_AssertNoError(&o->d_err);
  600. ASSERT(BDatagram_AddressFamilySupported(remote_addr.type))
  601. ASSERT(local_addr.type == BADDR_TYPE_NONE || BDatagram_AddressFamilySupported(local_addr.type))
  602. // set addresses
  603. o->send.remote_addr = remote_addr;
  604. o->send.local_addr = local_addr;
  605. if (!o->send.have_addrs) {
  606. // set have addresses
  607. o->send.have_addrs = 1;
  608. // start sending
  609. if (o->send.inited && o->send.busy) {
  610. BPending_Set(&o->send.job);
  611. }
  612. }
  613. }
  614. int BDatagram_GetLastReceiveAddrs (BDatagram *o, BAddr *remote_addr, BIPAddr *local_addr)
  615. {
  616. DebugObject_Access(&o->d_obj);
  617. if (!o->recv.have_addrs) {
  618. return 0;
  619. }
  620. *remote_addr = o->recv.remote_addr;
  621. *local_addr = o->recv.local_addr;
  622. return 1;
  623. }
  624. int BDatagram_GetFd (BDatagram *o)
  625. {
  626. DebugObject_Access(&o->d_obj);
  627. return o->fd;
  628. }
  629. int BDatagram_SetReuseAddr (BDatagram *o, int reuse)
  630. {
  631. DebugObject_Access(&o->d_obj);
  632. ASSERT(reuse == 0 || reuse == 1)
  633. if (setsockopt(o->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
  634. return 0;
  635. }
  636. return 1;
  637. }
  638. void BDatagram_SendAsync_Init (BDatagram *o, int mtu)
  639. {
  640. DebugObject_Access(&o->d_obj);
  641. DebugError_AssertNoError(&o->d_err);
  642. ASSERT(!o->send.inited)
  643. ASSERT(mtu >= 0)
  644. // init arguments
  645. o->send.mtu = mtu;
  646. // init interface
  647. PacketPassInterface_Init(&o->send.iface, o->send.mtu, (PacketPassInterface_handler_send)send_if_handler_send, o, BReactor_PendingGroup(o->reactor));
  648. // init job
  649. BPending_Init(&o->send.job, BReactor_PendingGroup(o->reactor), (BPending_handler)send_job_handler, o);
  650. // set not busy
  651. o->send.busy = 0;
  652. // set inited
  653. o->send.inited = 1;
  654. }
  655. void BDatagram_SendAsync_Free (BDatagram *o)
  656. {
  657. DebugObject_Access(&o->d_obj);
  658. ASSERT(o->send.inited)
  659. // update events
  660. o->wait_events &= ~BREACTOR_WRITE;
  661. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  662. // free job
  663. BPending_Free(&o->send.job);
  664. // free interface
  665. PacketPassInterface_Free(&o->send.iface);
  666. // set not inited
  667. o->send.inited = 0;
  668. }
  669. PacketPassInterface * BDatagram_SendAsync_GetIf (BDatagram *o)
  670. {
  671. DebugObject_Access(&o->d_obj);
  672. ASSERT(o->send.inited)
  673. return &o->send.iface;
  674. }
  675. void BDatagram_RecvAsync_Init (BDatagram *o, int mtu)
  676. {
  677. DebugObject_Access(&o->d_obj);
  678. DebugError_AssertNoError(&o->d_err);
  679. ASSERT(!o->recv.inited)
  680. ASSERT(mtu >= 0)
  681. // init arguments
  682. o->recv.mtu = mtu;
  683. // init interface
  684. PacketRecvInterface_Init(&o->recv.iface, o->recv.mtu, (PacketRecvInterface_handler_recv)recv_if_handler_recv, o, BReactor_PendingGroup(o->reactor));
  685. // init job
  686. BPending_Init(&o->recv.job, BReactor_PendingGroup(o->reactor), (BPending_handler)recv_job_handler, o);
  687. // set not busy
  688. o->recv.busy = 0;
  689. // set inited
  690. o->recv.inited = 1;
  691. }
  692. void BDatagram_RecvAsync_Free (BDatagram *o)
  693. {
  694. DebugObject_Access(&o->d_obj);
  695. ASSERT(o->recv.inited)
  696. // update events
  697. o->wait_events &= ~BREACTOR_READ;
  698. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  699. // free job
  700. BPending_Free(&o->recv.job);
  701. // free interface
  702. PacketRecvInterface_Free(&o->recv.iface);
  703. // set not inited
  704. o->recv.inited = 0;
  705. }
  706. PacketRecvInterface * BDatagram_RecvAsync_GetIf (BDatagram *o)
  707. {
  708. DebugObject_Access(&o->d_obj);
  709. ASSERT(o->recv.inited)
  710. return &o->recv.iface;
  711. }