static void handler_udp_tun_to_net(int sfd, int dfd, struct curve25519_proto *p, struct curve25519_struct *c, char *buff, size_t len) { char *cbuff; ssize_t rlen, clen; struct ct_proto *hdr; size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes; if (!buff || len <= off) return; memset(buff, 0, len); while ((rlen = read(sfd, buff + off, len - off)) > 0) { hdr = (struct ct_proto *) buff; memset(hdr, 0, sizeof(*hdr)); hdr->flags = 0; clen = curve25519_encode(c, p, (unsigned char *) (buff + off - crypto_box_zerobytes), (rlen + crypto_box_zerobytes), (unsigned char **) &cbuff); if (unlikely(clen <= 0)) goto close; hdr->payload = htons((uint16_t) clen); set_udp_cork(dfd); write_exact(dfd, hdr, sizeof(struct ct_proto), 0); write_exact(dfd, cbuff, clen, 0); set_udp_uncork(dfd); memset(buff, 0, len); } return; close: closed_by_server = 1; }
static int handler_udp_tun_to_net(int fd, const struct worker_struct *ws, char *buff, size_t len) { int dfd, keep = 1; char *cbuff; ssize_t rlen, err, clen; struct ct_proto *hdr; struct curve25519_proto *p; struct sockaddr_storage naddr; socklen_t nlen; size_t off = sizeof(struct ct_proto) + crypto_box_zerobytes; if (!buff || len <= off) return 0; memset(buff, 0, len); while ((rlen = read(fd, buff + off, len - off)) > 0) { dfd = -1; nlen = 0; p = NULL; memset(&naddr, 0, sizeof(naddr)); hdr = (struct ct_proto *) buff; memset(hdr, 0, sizeof(*hdr)); hdr->flags = 0; trie_addr_lookup(buff + off, rlen, ws->parent.ipv4, &dfd, &naddr, (size_t *) &nlen); if (unlikely(dfd < 0 || nlen == 0)) { memset(buff, 0, len); continue; } err = get_user_by_sockaddr(&naddr, nlen, &p); if (unlikely(err || !p)) { memset(buff, 0, len); continue; } clen = curve25519_encode(ws->c, p, (unsigned char *) (buff + off - crypto_box_zerobytes), (rlen + crypto_box_zerobytes), (unsigned char **) &cbuff); if (unlikely(clen <= 0)) { memset(buff, 0, len); continue; } hdr->payload = htons((uint16_t) clen); set_udp_cork(dfd); sendto(dfd, hdr, sizeof(struct ct_proto), 0, (struct sockaddr *) &naddr, nlen); sendto(dfd, cbuff, clen, 0, (struct sockaddr *) &naddr, nlen); set_udp_uncork(dfd); memset(buff, 0, len); } return keep; }