2 * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
20 #include <sys/socket.h>
35 #define MIN(a, b) ((a) < (b) ? (a) : (b))
48 struct event sockev[MAXSOCK];
57 struct bufferevent *server;
59 struct bufferevent *client;
64 # define pledge(a, b) (0)
68 copysec(const char *s, char *d, size_t len)
72 if ((c = strchr(s, ':')) == NULL)
74 if ((size_t)(c-s) >= len-1)
86 if ((c = strchr(tohost, ':')) == NULL) {
87 strlcpy(kamihost, tohost, sizeof(kamihost));
88 strlcpy(kamiport, "1337", sizeof(kamiport));
92 if ((c = copysec(tohost, kamihost, sizeof(kamihost))) == NULL)
93 fatalx("hostname too long: %s", tohost);
95 strlcpy(kamiport, c+1, sizeof(kamiport));
99 tls_readcb(int fd, short event, void *d)
101 struct bufferevent *bufev = d;
102 struct conn *conn = bufev->cbarg;
103 char buf[IBUF_READ_SIZE];
104 int what = EVBUFFER_READ;
105 int howmuch = IBUF_READ_SIZE;
109 if (event == EV_TIMEOUT) {
110 what |= EVBUFFER_TIMEOUT;
114 if (bufev->wm_read.high != 0)
115 howmuch = MIN(sizeof(buf), bufev->wm_read.high);
117 switch (ret = tls_read(conn->ctx, buf, howmuch)) {
118 case TLS_WANT_POLLIN:
119 case TLS_WANT_POLLOUT:
122 what |= EVBUFFER_ERROR;
128 what |= EVBUFFER_EOF;
132 if (evbuffer_add(bufev->input, buf, len) == -1) {
133 what |= EVBUFFER_ERROR;
137 event_add(&bufev->ev_read, NULL);
139 len = EVBUFFER_LENGTH(bufev->input);
140 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
142 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
144 * here we could implement some read pressure
149 if (bufev->readcb != NULL)
150 (*bufev->readcb)(bufev, bufev->cbarg);
155 event_add(&bufev->ev_read, NULL);
159 (*bufev->errorcb)(bufev, what, bufev->cbarg);
163 tls_writecb(int fd, short event, void *d)
165 struct bufferevent *bufev = d;
166 struct conn *conn = bufev->cbarg;
169 short what = EVBUFFER_WRITE;
171 if (event == EV_TIMEOUT) {
172 what |= EVBUFFER_TIMEOUT;
176 if (EVBUFFER_LENGTH(bufev->output) != 0) {
177 ret = tls_write(conn->ctx,
178 EVBUFFER_DATA(bufev->output),
179 EVBUFFER_LENGTH(bufev->output));
181 case TLS_WANT_POLLIN:
182 case TLS_WANT_POLLOUT:
185 what |= EVBUFFER_ERROR;
189 evbuffer_drain(bufev->output, len);
192 if (EVBUFFER_LENGTH(bufev->output) != 0)
193 event_add(&bufev->ev_write, NULL);
195 if (bufev->writecb != NULL &&
196 EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
197 (*bufev->writecb)(bufev, bufev->cbarg);
201 event_add(&bufev->ev_write, NULL);
205 (*bufev->errorcb)(bufev, what, bufev->cbarg);
211 struct addrinfo hints, *res, *res0;
212 int v, r, saved_errno;
214 const char *c, *h, *port, *cause;
216 if ((c = strchr(fromhost, ':')) == NULL) {
220 if ((c = copysec(fromhost, host, sizeof(host))) == NULL)
221 fatalx("hostname too long: %s", fromhost);
226 memset(&hints, 0, sizeof(hints));
227 hints.ai_family = AF_UNSPEC;
228 hints.ai_socktype = SOCK_STREAM;
229 hints.ai_flags = AI_PASSIVE;
231 r = getaddrinfo(h, port, &hints, &res0);
233 fatalx("getaddrinfo(%s): %s", fromhost,
236 for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
237 socks[nsock] = socket(res->ai_family, res->ai_socktype,
239 if (socks[nsock] == -1) {
244 if (bind(socks[nsock], res->ai_addr, res->ai_addrlen) == -1) {
253 if (setsockopt(socks[nsock], SOL_SOCKET, SO_REUSEADDR, &v,
255 err(1, "setsockopt(SO_REUSEADDR)");
258 if (setsockopt(socks[nsock], SOL_SOCKET, SO_REUSEPORT, &v,
260 err(1, "setsockopt(SO_REUSEPORT)");
262 listen(socks[nsock], 5);
275 struct addrinfo hints, *res, *res0;
276 int r, saved_errno, sock;
279 memset(&hints, 0, sizeof(hints));
280 hints.ai_family = AF_UNSPEC;
281 hints.ai_socktype = SOCK_STREAM;
283 r = getaddrinfo(kamihost, kamiport, &hints, &res0);
285 log_warnx("getaddrinfo(%s, %s): %s", kamihost, kamiport,
290 for (res = res0; res != NULL; res = res->ai_next) {
291 sock = socket(res->ai_family, res->ai_socktype,
298 if (connect(sock, res->ai_addr, res->ai_addrlen) == -1) {
312 log_warn("%s", cause);
319 copy_to_server(struct bufferevent *bev, void *d)
323 bufferevent_write_buffer(c->server, EVBUFFER_INPUT(bev));
327 copy_to_client(struct bufferevent *bev, void *d)
331 bufferevent_write_buffer(c->client, EVBUFFER_INPUT(bev));
335 nopcb(struct bufferevent *bev, void *d)
341 errcb(struct bufferevent *bev, short ev, void *d)
345 log_debug("closing connection (event=%x / side=%s)", ev,
346 bev == c->server ? "server" : "client");
348 bufferevent_free(c->server);
349 bufferevent_free(c->client);
361 doaccept(int fd, short ev, void *data)
363 struct tls_config *conf;
367 if ((c = calloc(1, sizeof(*c))) == NULL)
370 if ((c->lfd = accept(fd, NULL, 0)) == -1) {
376 if ((c->kfd = servconnect()) == -1) {
382 if ((c->ctx = tls_client()) == NULL)
385 if ((conf = tls_config_new()) == NULL)
386 fatal("tls_config_new");
388 if (tls_config_set_cert_mem(conf, cert, certlen) == -1 ||
389 tls_config_set_key_mem(conf, key, keylen) == -1)
390 fatalx("tls_config_set_{cert,key}: %s", tls_config_error(conf));
391 tls_config_insecure_noverifycert(conf);
393 if (tls_configure(c->ctx, conf) == -1)
394 fatalx("tls_configure");
396 tls_config_free(conf);
398 if (tls_connect_socket(c->ctx, c->kfd, kamihost) == -1)
399 fatal("tls_connect_socket");
401 again: switch (r = tls_handshake(c->ctx)) {
403 log_warnx("tls_handshake: %s", tls_error(c->ctx));
410 case TLS_WANT_POLLIN:
411 case TLS_WANT_POLLOUT:
415 c->server = bufferevent_new(c->kfd, copy_to_client, nopcb, errcb, c);
416 if (c->server == NULL)
417 fatal("bufferevent_new");
419 event_set(&c->server->ev_read, c->kfd, EV_READ, tls_readcb,
421 event_set(&c->server->ev_write, c->kfd, EV_WRITE, tls_writecb,
425 evbuffer_unfreeze(c->server->input, 0);
426 evbuffer_unfreeze(c->server->output, 1);
429 c->client = bufferevent_new(c->lfd, copy_to_server, nopcb, errcb, c);
430 if (c->client == NULL)
431 fatal("bufferevent_new");
433 bufferevent_enable(c->server, EV_READ|EV_WRITE);
434 bufferevent_enable(c->client, EV_READ|EV_WRITE);
441 "usage: %s [-dv] -c host[:port] -l [host:]port -C cert [-K key]\n",
447 main(int argc, char **argv)
450 const char *certf = NULL, *keyf = NULL;
452 log_init(1, LOG_DAEMON);
455 while ((ch = getopt(argc, argv, "C:c:dK:l:v")) != -1) {
484 if (certf == NULL || tohost == NULL || fromhost == NULL)
491 if ((cert = tls_load_file(certf, &certlen, NULL)) == NULL)
492 fatal("can't load %s", certf);
493 if ((key = tls_load_file(keyf, &keylen, NULL)) == NULL)
494 fatal("can't load %s", keyf);
496 log_init(debug, LOG_DAEMON);
497 log_setverbose(verbose);
502 signal(SIGPIPE, SIG_IGN);
507 for (i = 0; i < nsock; ++i) {
508 event_set(&sockev[i], socks[i], EV_READ|EV_PERSIST,
510 event_add(&sockev[i], NULL);
513 if (pledge("stdio dns inet", NULL) == -1)
516 log_info("starting");