pex-msg.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
  4. */
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/un.h>
  8. #include <arpa/inet.h>
  9. #include <errno.h>
  10. #include <fcntl.h>
  11. #include <libubox/list.h>
  12. #include <libubox/uloop.h>
  13. #include <libubox/usock.h>
  14. #include "pex-msg.h"
  15. #include "chacha20.h"
  16. #include "auth-data.h"
  17. static char pex_tx_buf[PEX_BUF_SIZE];
  18. static FILE *pex_urandom;
  19. static struct uloop_fd pex_fd, pex_unix_fd;
  20. static LIST_HEAD(requests);
  21. static struct uloop_timeout gc_timer;
  22. static int pex_raw_v4_fd = -1, pex_raw_v6_fd = -1;
  23. static pex_recv_cb_t pex_recv_cb;
  24. static pex_recv_control_cb_t pex_control_cb;
  25. static int pex_unix_tx_fd = -1;
  26. int pex_socket(void)
  27. {
  28. return pex_fd.fd;
  29. }
  30. int pex_raw_socket(int family)
  31. {
  32. return family == AF_INET ? pex_raw_v4_fd : pex_raw_v6_fd;
  33. }
  34. static const void *
  35. get_mapped_sockaddr(const void *addr)
  36. {
  37. static struct sockaddr_in6 sin6;
  38. const struct sockaddr_in *sin = addr;
  39. if (!sin || sin->sin_family != AF_INET)
  40. return addr;
  41. memset(&sin6, 0, sizeof(sin6));
  42. sin6.sin6_family = AF_INET6;
  43. sin6.sin6_addr.s6_addr[10] = 0xff;
  44. sin6.sin6_addr.s6_addr[11] = 0xff;
  45. memcpy(&sin6.sin6_addr.s6_addr[12], &sin->sin_addr, sizeof(struct in_addr));
  46. sin6.sin6_port = sin->sin_port;
  47. return &sin6;
  48. }
  49. struct pex_msg_update_recv_ctx {
  50. struct list_head list;
  51. union network_endpoint addr;
  52. uint8_t priv_key[CURVE25519_KEY_SIZE];
  53. uint8_t auth_key[CURVE25519_KEY_SIZE];
  54. uint8_t e_key[CURVE25519_KEY_SIZE];
  55. uint64_t req_id;
  56. void *data;
  57. int data_len;
  58. int data_ofs;
  59. int idle;
  60. };
  61. uint64_t pex_network_hash(const uint8_t *auth_key, uint64_t req_id)
  62. {
  63. siphash_key_t key = {
  64. .key = {
  65. be64_to_cpu(req_id),
  66. be64_to_cpu(req_id)
  67. }
  68. };
  69. uint64_t hash;
  70. siphash_to_be64(&hash, auth_key, CURVE25519_KEY_SIZE, &key);
  71. return hash;
  72. }
  73. struct pex_hdr *__pex_msg_init(const uint8_t *pubkey, uint8_t opcode)
  74. {
  75. struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
  76. hdr->version = 0;
  77. hdr->opcode = opcode;
  78. hdr->len = 0;
  79. memcpy(hdr->id, pubkey, sizeof(hdr->id));
  80. return hdr;
  81. }
  82. struct pex_hdr *__pex_msg_init_ext(const uint8_t *pubkey, const uint8_t *auth_key,
  83. uint8_t opcode, bool ext)
  84. {
  85. struct pex_hdr *hdr = __pex_msg_init(pubkey, opcode);
  86. struct pex_ext_hdr *ehdr = (struct pex_ext_hdr *)(hdr + 1);
  87. uint64_t hash;
  88. if (!ext)
  89. return hdr;
  90. hdr->len = sizeof(*ehdr);
  91. if (fread(&ehdr->nonce, sizeof(ehdr->nonce), 1, pex_urandom) != 1)
  92. return NULL;
  93. hash = pex_network_hash(auth_key, ehdr->nonce);
  94. *(uint64_t *)hdr->id ^= hash;
  95. memcpy(ehdr->auth_id, auth_key, sizeof(ehdr->auth_id));
  96. return hdr;
  97. }
  98. void *pex_msg_append(size_t len)
  99. {
  100. struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
  101. int ofs = hdr->len + sizeof(struct pex_hdr);
  102. void *buf = &pex_tx_buf[ofs];
  103. if (sizeof(pex_tx_buf) - ofs < len)
  104. return NULL;
  105. hdr->len += len;
  106. memset(buf, 0, len);
  107. return buf;
  108. }
  109. static void
  110. pex_fd_cb(struct uloop_fd *fd, unsigned int events)
  111. {
  112. static struct sockaddr_in6 sin6;
  113. static char buf[PEX_RX_BUF_SIZE];
  114. ssize_t len;
  115. while (1) {
  116. static struct iovec iov[2] = {
  117. { .iov_base = &sin6 },
  118. { .iov_base = buf },
  119. };
  120. static struct msghdr msg = {
  121. .msg_iov = iov,
  122. .msg_iovlen = ARRAY_SIZE(iov),
  123. };
  124. socklen_t slen = sizeof(sin6);
  125. len = recvfrom(fd->fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6, &slen);
  126. if (len < 0) {
  127. if (errno == EINTR)
  128. continue;
  129. if (errno == EAGAIN)
  130. break;
  131. pex_close();
  132. return;
  133. }
  134. if (!len)
  135. continue;
  136. if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
  137. struct sockaddr_in *sin = (struct sockaddr_in *)&sin6;
  138. struct in_addr in = *(struct in_addr *)&sin6.sin6_addr.s6_addr[12];
  139. int port = sin6.sin6_port;
  140. memset(&sin6, 0, sizeof(sin6));
  141. sin->sin_port = port;
  142. sin->sin_family = AF_INET;
  143. sin->sin_addr = in;
  144. slen = sizeof(*sin);
  145. }
  146. retry:
  147. if (pex_unix_tx_fd >= 0) {
  148. iov[0].iov_len = slen;
  149. iov[1].iov_len = len;
  150. if (sendmsg(pex_unix_tx_fd, &msg, 0) < 0) {
  151. switch (errno) {
  152. case EINTR:
  153. goto retry;
  154. case EMSGSIZE:
  155. case ENOBUFS:
  156. case EAGAIN:
  157. continue;
  158. default:
  159. perror("sendmsg");
  160. close(pex_unix_tx_fd);
  161. pex_unix_tx_fd = -1;
  162. break;
  163. }
  164. }
  165. }
  166. pex_recv_cb(buf, len, &sin6);
  167. }
  168. }
  169. static void
  170. pex_unix_cb(struct uloop_fd *fd, unsigned int events)
  171. {
  172. static char buf[PEX_RX_BUF_SIZE];
  173. static struct iovec iov = {
  174. .iov_base = buf,
  175. .iov_len = sizeof(buf),
  176. };
  177. ssize_t len;
  178. while (1) {
  179. const struct sockaddr *sa = (struct sockaddr *)buf;
  180. uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
  181. struct msghdr msg = {
  182. .msg_iov = &iov,
  183. .msg_iovlen = 1,
  184. .msg_control = fd_buf,
  185. .msg_controllen = CMSG_LEN(sizeof(int)),
  186. };
  187. struct cmsghdr *cmsg;
  188. socklen_t slen;
  189. int *pfd;
  190. cmsg = CMSG_FIRSTHDR(&msg);
  191. cmsg->cmsg_type = SCM_RIGHTS;
  192. cmsg->cmsg_level = SOL_SOCKET;
  193. cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  194. pfd = (int *)CMSG_DATA(cmsg);
  195. *pfd = -1;
  196. len = recvmsg(fd->fd, &msg, 0);
  197. if (len < 0) {
  198. if (errno == EINTR)
  199. continue;
  200. if (errno == EAGAIN)
  201. break;
  202. pex_close();
  203. return;
  204. }
  205. if (*pfd >= 0) {
  206. if (pex_unix_tx_fd >= 0)
  207. close(pex_unix_tx_fd);
  208. pex_unix_tx_fd = *pfd;
  209. }
  210. if (!len)
  211. continue;
  212. if (len < sizeof(*sa))
  213. continue;
  214. if (sa->sa_family == AF_LOCAL) {
  215. slen = sizeof(struct sockaddr);
  216. len -= slen;
  217. if (len < sizeof(struct pex_msg_local_control))
  218. continue;
  219. if (pex_control_cb)
  220. pex_control_cb((struct pex_msg_local_control *)&buf[slen], len);
  221. continue;
  222. }
  223. if (sa->sa_family == AF_INET)
  224. slen = sizeof(struct sockaddr_in);
  225. else if (sa->sa_family == AF_INET6)
  226. slen = sizeof(struct sockaddr_in6);
  227. else
  228. continue;
  229. sa = get_mapped_sockaddr(sa);
  230. sendto(pex_fd.fd, buf + slen, len - slen, 0, sa, sizeof(struct sockaddr_in6));
  231. }
  232. }
  233. int __pex_msg_send(int fd, const void *addr, void *ip_hdr, size_t ip_hdrlen)
  234. {
  235. struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
  236. const struct sockaddr *sa = addr;
  237. size_t tx_len = sizeof(*hdr) + hdr->len;
  238. uint16_t orig_len = hdr->len;
  239. int ret;
  240. if (fd < 0) {
  241. hdr->len -= sizeof(struct pex_ext_hdr);
  242. if (ip_hdrlen)
  243. fd = pex_raw_socket(sa->sa_family);
  244. else {
  245. fd = pex_fd.fd;
  246. sa = addr = get_mapped_sockaddr(addr);
  247. }
  248. if (fd < 0)
  249. return -1;
  250. }
  251. hdr->len = htons(hdr->len);
  252. if (ip_hdr) {
  253. ret = sendto_rawudp(fd, addr, ip_hdr, ip_hdrlen, pex_tx_buf, tx_len);
  254. } else if (addr) {
  255. socklen_t addr_len;
  256. if (sa->sa_family == AF_INET6)
  257. addr_len = sizeof(struct sockaddr_in6);
  258. else
  259. addr_len = sizeof(struct sockaddr_in);
  260. ret = sendto(fd, pex_tx_buf, tx_len, 0, addr, addr_len);
  261. } else {
  262. ret = send(fd, pex_tx_buf, tx_len, 0);
  263. }
  264. hdr->len = orig_len;
  265. return ret;
  266. }
  267. static void
  268. pex_msg_update_response_fill(struct pex_msg_update_send_ctx *ctx)
  269. {
  270. struct pex_hdr *hdr = (struct pex_hdr *)pex_tx_buf;
  271. int ofs = hdr->len + sizeof(struct pex_hdr);
  272. int cur_len = ctx->rem;
  273. if (cur_len > PEX_BUF_SIZE - ofs)
  274. cur_len = PEX_BUF_SIZE - ofs;
  275. memcpy(pex_msg_append(cur_len), ctx->cur, cur_len);
  276. ctx->cur += cur_len;
  277. ctx->rem -= cur_len;
  278. }
  279. void pex_msg_update_response_init(struct pex_msg_update_send_ctx *ctx,
  280. const uint8_t *pubkey, const uint8_t *auth_key,
  281. const uint8_t *peer_key, bool ext,
  282. struct pex_update_request *req,
  283. const void *data, int len)
  284. {
  285. uint8_t e_key_priv[CURVE25519_KEY_SIZE];
  286. uint8_t enc_key[CURVE25519_KEY_SIZE];
  287. struct pex_update_response *res;
  288. ctx->pubkey = pubkey;
  289. ctx->auth_key = auth_key;
  290. ctx->ext = ext;
  291. ctx->req_id = req->req_id;
  292. if (!__pex_msg_init_ext(pubkey, auth_key, PEX_MSG_UPDATE_RESPONSE, ext))
  293. return;
  294. res = pex_msg_append(sizeof(*res));
  295. res->req_id = req->req_id;
  296. res->data_len = cpu_to_be32(len);
  297. if (!fread(e_key_priv, sizeof(e_key_priv), 1, pex_urandom))
  298. return;
  299. curve25519_clamp_secret(e_key_priv);
  300. curve25519_generate_public(res->e_key, e_key_priv);
  301. curve25519(enc_key, e_key_priv, peer_key);
  302. ctx->data = ctx->cur = malloc(len);
  303. ctx->rem = len;
  304. memcpy(ctx->data, data, len);
  305. chacha20_encrypt_msg(ctx->data, len, &req->req_id, enc_key);
  306. pex_msg_update_response_fill(ctx);
  307. }
  308. bool pex_msg_update_response_continue(struct pex_msg_update_send_ctx *ctx)
  309. {
  310. struct pex_update_response_data *res_ext;
  311. if (ctx->rem <= 0) {
  312. free(ctx->data);
  313. ctx->data = NULL;
  314. return false;
  315. }
  316. if (!__pex_msg_init_ext(ctx->pubkey, ctx->auth_key,
  317. PEX_MSG_UPDATE_RESPONSE_DATA, ctx->ext))
  318. return false;
  319. res_ext = pex_msg_append(sizeof(*res_ext));
  320. res_ext->req_id = ctx->req_id;
  321. res_ext->offset = cpu_to_be32(ctx->cur - ctx->data);
  322. pex_msg_update_response_fill(ctx);
  323. return true;
  324. }
  325. struct pex_update_request *
  326. pex_msg_update_request_init(const uint8_t *pubkey, const uint8_t *priv_key,
  327. const uint8_t *auth_key, union network_endpoint *addr,
  328. uint64_t cur_version, bool ext)
  329. {
  330. struct pex_update_request *req;
  331. struct pex_msg_update_recv_ctx *ctx;
  332. list_for_each_entry(ctx, &requests, list) {
  333. if (!memcmp(&ctx->addr, addr, sizeof(ctx->addr)))
  334. return NULL;
  335. }
  336. ctx = calloc(1, sizeof(*ctx));
  337. memcpy(&ctx->addr, addr, sizeof(ctx->addr));
  338. memcpy(ctx->auth_key, auth_key, sizeof(ctx->auth_key));
  339. memcpy(ctx->priv_key, priv_key, sizeof(ctx->priv_key));
  340. if (!fread(&ctx->req_id, sizeof(ctx->req_id), 1, pex_urandom)) {
  341. free(ctx);
  342. return NULL;
  343. }
  344. list_add_tail(&ctx->list, &requests);
  345. if (!gc_timer.pending)
  346. uloop_timeout_set(&gc_timer, 1000);
  347. if (!__pex_msg_init_ext(pubkey, auth_key, PEX_MSG_UPDATE_REQUEST, ext)) {
  348. free(ctx);
  349. return NULL;
  350. }
  351. req = pex_msg_append(sizeof(*req));
  352. req->cur_version = cpu_to_be64(cur_version);
  353. req->req_id = ctx->req_id;
  354. return req;
  355. }
  356. static struct pex_msg_update_recv_ctx *
  357. pex_msg_update_recv_ctx_get(uint64_t req_id)
  358. {
  359. struct pex_msg_update_recv_ctx *ctx;
  360. list_for_each_entry(ctx, &requests, list) {
  361. if (ctx->req_id == req_id) {
  362. ctx->idle = 0;
  363. return ctx;
  364. }
  365. }
  366. return NULL;
  367. }
  368. static void pex_msg_update_ctx_free(struct pex_msg_update_recv_ctx *ctx)
  369. {
  370. list_del(&ctx->list);
  371. free(ctx->data);
  372. free(ctx);
  373. }
  374. void *pex_msg_update_response_recv(const void *data, int len, enum pex_opcode op,
  375. int *data_len, uint64_t *timestamp)
  376. {
  377. struct pex_msg_update_recv_ctx *ctx;
  378. uint8_t enc_key[CURVE25519_KEY_SIZE];
  379. void *ret;
  380. *data_len = 0;
  381. if (op == PEX_MSG_UPDATE_RESPONSE) {
  382. const struct pex_update_response *res = data;
  383. if (len < sizeof(*res))
  384. return NULL;
  385. ctx = pex_msg_update_recv_ctx_get(res->req_id);
  386. if (!ctx || ctx->data_len || !res->data_len ||
  387. be32_to_cpu(res->data_len) > UNETD_NET_DATA_SIZE_MAX)
  388. return NULL;
  389. data += sizeof(*res);
  390. len -= sizeof(*res);
  391. ctx->data_len = be32_to_cpu(res->data_len);
  392. memcpy(ctx->e_key, res->e_key, sizeof(ctx->e_key));
  393. ctx->data = malloc(ctx->data_len);
  394. } else if (op == PEX_MSG_UPDATE_RESPONSE_DATA) {
  395. const struct pex_update_response_data *res = data;
  396. if (len <= sizeof(*res))
  397. return NULL;
  398. ctx = pex_msg_update_recv_ctx_get(res->req_id);
  399. if (!ctx || ctx->data_ofs != be32_to_cpu(res->offset))
  400. return NULL;
  401. data += sizeof(*res);
  402. len -= sizeof(*res);
  403. } else if (op == PEX_MSG_UPDATE_RESPONSE_NO_DATA) {
  404. const struct pex_update_response_no_data *res = data;
  405. if (len < sizeof(*res))
  406. return NULL;
  407. ctx = pex_msg_update_recv_ctx_get(res->req_id);
  408. if (!ctx)
  409. return NULL;
  410. goto error;
  411. } else {
  412. return NULL;
  413. }
  414. if (ctx->data_ofs + len > ctx->data_len)
  415. goto error;
  416. memcpy(ctx->data + ctx->data_ofs, data, len);
  417. ctx->data_ofs += len;
  418. if (ctx->data_ofs < ctx->data_len)
  419. return NULL;
  420. curve25519(enc_key, ctx->priv_key, ctx->e_key);
  421. chacha20_encrypt_msg(ctx->data, ctx->data_len, &ctx->req_id, enc_key);
  422. if (unet_auth_data_validate(ctx->auth_key, ctx->data, ctx->data_len, timestamp, NULL))
  423. goto error;
  424. *data_len = ctx->data_len;
  425. ret = ctx->data;
  426. ctx->data = NULL;
  427. pex_msg_update_ctx_free(ctx);
  428. return ret;
  429. error:
  430. pex_msg_update_ctx_free(ctx);
  431. *data_len = -1;
  432. return NULL;
  433. }
  434. struct pex_hdr *pex_rx_accept(void *data, size_t len, bool ext)
  435. {
  436. struct pex_hdr *hdr = data;
  437. uint16_t hdr_len;
  438. size_t min_size;
  439. min_size = sizeof(*hdr);
  440. if (ext)
  441. min_size += sizeof(struct pex_ext_hdr);
  442. if (len < min_size)
  443. return NULL;
  444. hdr_len = ntohs(hdr->len);
  445. if (len < min_size + hdr_len)
  446. return NULL;
  447. hdr->len = hdr_len;
  448. return hdr;
  449. }
  450. static void
  451. pex_gc_cb(struct uloop_timeout *t)
  452. {
  453. struct pex_msg_update_recv_ctx *ctx, *tmp;
  454. list_for_each_entry_safe(ctx, tmp, &requests, list) {
  455. if (++ctx->idle <= 3)
  456. continue;
  457. pex_msg_update_ctx_free(ctx);
  458. }
  459. if (!list_empty(&requests))
  460. uloop_timeout_set(t, 1000);
  461. }
  462. int pex_open(void *addr, size_t addr_len, pex_recv_cb_t cb, bool server)
  463. {
  464. struct sockaddr *sa = addr;
  465. int yes = 1, no = 0;
  466. int fd;
  467. pex_recv_cb = cb;
  468. if (server) {
  469. pex_raw_v4_fd = fd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
  470. if (fd < 0)
  471. return -1;
  472. setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
  473. setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &yes, sizeof(yes));
  474. #ifdef linux
  475. pex_raw_v6_fd = fd = socket(PF_INET6, SOCK_RAW, IPPROTO_UDP);
  476. if (fd < 0)
  477. goto close_raw;
  478. setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
  479. setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
  480. setsockopt(fd, IPPROTO_IPV6, IPV6_HDRINCL, &yes, sizeof(yes));
  481. #endif
  482. }
  483. pex_urandom = fopen("/dev/urandom", "r");
  484. if (!pex_urandom)
  485. goto close_raw;
  486. fd = socket(sa->sa_family == AF_INET ? PF_INET : PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
  487. if (fd < 0)
  488. goto close_urandom;
  489. fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
  490. fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
  491. if (server) {
  492. if (bind(fd, addr, addr_len) < 0) {
  493. perror("bind");
  494. goto close_socket;
  495. }
  496. setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
  497. setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes));
  498. setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
  499. } else {
  500. if (connect(fd, addr, addr_len) < 0) {
  501. perror("connect");
  502. goto close_socket;
  503. }
  504. }
  505. pex_fd.fd = fd;
  506. pex_fd.cb = pex_fd_cb;
  507. uloop_fd_add(&pex_fd, ULOOP_READ);
  508. gc_timer.cb = pex_gc_cb;
  509. return 0;
  510. close_socket:
  511. close(fd);
  512. close_urandom:
  513. fclose(pex_urandom);
  514. close_raw:
  515. if (pex_raw_v4_fd >= 0)
  516. close(pex_raw_v4_fd);
  517. if (pex_raw_v6_fd >= 0)
  518. close(pex_raw_v6_fd);
  519. pex_raw_v4_fd = -1;
  520. pex_raw_v6_fd = -1;
  521. return -1;
  522. }
  523. int pex_unix_open(const char *path, pex_recv_control_cb_t cb)
  524. {
  525. mode_t prev_mask;
  526. int fd;
  527. pex_control_cb = cb;
  528. unlink(path);
  529. prev_mask = umask(0177);
  530. fd = usock(USOCK_UDP | USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, path, NULL);
  531. umask(prev_mask);
  532. if (fd < 0)
  533. return -1;
  534. pex_unix_fd.cb = pex_unix_cb;
  535. pex_unix_fd.fd = fd;
  536. uloop_fd_add(&pex_unix_fd, ULOOP_READ);
  537. return 0;
  538. }
  539. void pex_close(void)
  540. {
  541. if (pex_raw_v4_fd >= 0)
  542. close(pex_raw_v4_fd);
  543. if (pex_raw_v6_fd >= 0)
  544. close(pex_raw_v6_fd);
  545. pex_raw_v4_fd = -1;
  546. pex_raw_v6_fd = -1;
  547. if (pex_urandom)
  548. fclose(pex_urandom);
  549. if (pex_fd.cb) {
  550. uloop_fd_delete(&pex_fd);
  551. close(pex_fd.fd);
  552. }
  553. if (pex_unix_fd.cb) {
  554. uloop_fd_delete(&pex_unix_fd);
  555. close(pex_unix_fd.fd);
  556. }
  557. pex_fd.cb = NULL;
  558. pex_unix_fd.cb = NULL;
  559. pex_urandom = NULL;
  560. }