40 struct port_share *port_share = NULL;
43 #define PROXY_CONNECTION_BUFFER_SIZE 1500
46 #define COMMAND_REDIRECT 10
47 #define COMMAND_EXIT 11
50 #define RESPONSE_INIT_SUCCEEDED 20
51 #define RESPONSE_INIT_FAILED 21
57 #define IOSTAT_EAGAIN_ON_READ 0
58 #define IOSTAT_EAGAIN_ON_WRITE 1
59 #define IOSTAT_READ_ERROR 2
60 #define IOSTAT_WRITE_ERROR 3
67 struct proxy_connection {
69 struct proxy_connection *next;
70 struct proxy_connection *counterpart;
80 headc(
const struct buffer *buf)
83 strncpy(foo,
BSTR(buf), 15);
113 for (i = 3; i <= 100; ++i)
129 signal(SIGTERM, SIG_DFL);
131 signal(SIGINT, SIG_IGN);
132 signal(SIGHUP, SIG_IGN);
133 signal(SIGUSR1, SIG_IGN);
134 signal(SIGUSR2, SIG_IGN);
135 signal(SIGPIPE, SIG_IGN);
146 const ssize_t size =
read(fd, &c,
sizeof(c));
147 if (size ==
sizeof(c))
160 unsigned char c = (
unsigned char) code;
161 const ssize_t size =
write(fd, &c,
sizeof(c));
162 if (size ==
sizeof(c))
188 const struct buffer *head,
202 head ?
BLEN(head) : -1);
208 iov[0].iov_base = &cmd;
209 iov[0].iov_len =
sizeof(cmd);
214 iov[1].iov_base =
BPTR(head);
215 iov[1].iov_len =
BLEN(head);
221 mesg.msg_controllen = cmsg_size();
222 mesg.msg_control = (
char *) malloc(mesg.msg_controllen);
226 h = CMSG_FIRSTHDR(&mesg);
227 h->cmsg_level = SOL_SOCKET;
228 h->cmsg_type = SCM_RIGHTS;
233 memcpy(CMSG_DATA(h), &sd_send,
sizeof(sd_send));
237 socketpair(PF_UNIX, SOCK_DGRAM, 0, sd_null);
238 memcpy(CMSG_DATA(h), &sd_null[0],
sizeof(sd_null[0]));
244 msg(
M_WARN|
M_ERRNO,
"PORT SHARE: sendmsg failed -- unable to communicate with background process (%d,%d,%d,%d)",
245 sd, sd_send, sd_null[0], sd_null[1]
249 close_socket_if_defined(sd_null[0]);
250 close_socket_if_defined(sd_null[1]);
251 free(mesg.msg_control);
256 proxy_entry_close_sd(
struct proxy_connection *pc,
struct event_set *
es)
274 proxy_entry_mark_for_close(
struct proxy_connection *pc,
struct event_set *
es)
278 struct proxy_connection *cp = pc->counterpart;
279 proxy_entry_close_sd(pc,
es);
281 pc->buffer_initial =
false;
290 if (cp && cp->defined && cp->counterpart == pc)
292 proxy_entry_mark_for_close(cp,
es);
302 proxy_list_housekeeping(
struct proxy_connection **list)
306 struct proxy_connection *prev = NULL;
307 struct proxy_connection *pc = *list;
311 struct proxy_connection *next = pc->next;
338 journal_add(
const char *journal_dir,
struct proxy_connection *pc,
struct proxy_connection *cp)
342 socklen_t slen, dlen;
347 slen =
sizeof(from.addr.sa);
348 dlen =
sizeof(to.addr.sa);
349 if (!getpeername(pc->sd, (
struct sockaddr *) &from.addr.sa, &slen)
350 && !getsockname(cp->sd, (
struct sockaddr *) &to.addr.sa, &dlen))
354 fnlen = strlen(journal_dir) + strlen(t) + 2;
355 jfn = (
char *) malloc(fnlen);
357 snprintf(jfn, fnlen,
"%s/%s", journal_dir, t);
359 fd =
platform_open(jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
362 if (
write(fd,
f, strlen(
f)) != strlen(
f))
364 msg(
M_WARN,
"PORT SHARE: writing to journal file (%s) failed", jfn);
382 proxy_list_close(
struct proxy_connection **list)
386 struct proxy_connection *pc = *list;
389 proxy_entry_mark_for_close(pc, NULL);
392 proxy_list_housekeeping(list);
397 proxy_connection_io_requeue(
struct proxy_connection *pc,
const int rwflags_new,
struct event_set *
es)
403 pc->rwflags = rwflags_new;
415 proxy_entry_new(
struct proxy_connection **list,
417 const struct sockaddr_in server_addr,
419 struct buffer *initial_data,
420 const char *journal_dir)
424 struct proxy_connection *pc;
425 struct proxy_connection *cp;
428 if ((sd_server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
436 msg(
M_WARN,
"PORT SHARE PROXY: connect to port-share server failed");
452 pc->counterpart = cp;
453 pc->buf = *initial_data;
454 pc->buffer_initial =
true;
461 cp->counterpart = pc;
462 cp->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
463 cp->buffer_initial =
false;
473 journal_add(journal_dir, pc, cp);
476 dmsg(
D_PS_PROXY_DEBUG,
"PORT SHARE PROXY: NEW CONNECTION [c=%d s=%d]", (
int)sd_client, (
int)sd_server);
493 struct proxy_connection **list,
495 const struct sockaddr_in server_addr,
496 const int max_initial_buf,
497 const char *journal_dir)
512 iov[0].iov_base = &command;
513 iov[0].iov_len =
sizeof(command);
514 iov[1].iov_base =
BPTR(&buf);
515 iov[1].iov_len =
BCAP(&buf);
519 mesg.msg_controllen = cmsg_size();
520 mesg.msg_control = (
char *) malloc(mesg.msg_controllen);
524 h = CMSG_FIRSTHDR(&mesg);
526 h->cmsg_level = SOL_SOCKET;
527 h->cmsg_type = SCM_RIGHTS;
529 memcpy(CMSG_DATA(h), &socket_undefined,
sizeof(socket_undefined));
536 || h->cmsg_level != SOL_SOCKET
537 || h->cmsg_type != SCM_RIGHTS)
539 msg(
M_WARN,
"PORT SHARE PROXY: received unknown message");
544 memcpy(&received_fd, CMSG_DATA(h),
sizeof(received_fd));
547 if (
status >= 2 && command == COMMAND_REDIRECT)
550 if (proxy_entry_new(list,
572 free(mesg.msg_control);
578 proxy_connection_io_recv(
struct proxy_connection *pc)
584 return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
590 return IOSTAT_READ_ERROR;
599 proxy_connection_io_send(
struct proxy_connection *pc,
int *bytes_sent)
607 return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_WRITE_ERROR;
612 if (
status != pc->buf.len)
616 return IOSTAT_EAGAIN_ON_WRITE;
627 if (pc->buffer_initial)
630 pc->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
631 pc->buffer_initial =
false;
641 proxy_connection_io_xfer(
struct proxy_connection *pc,
const int max_transfer)
644 while (transferred < max_transfer)
648 const int status = proxy_connection_io_recv(pc);
649 if (
status != IOSTAT_GOOD)
657 const int status = proxy_connection_io_send(pc, &transferred);
658 if (
status != IOSTAT_GOOD)
664 return IOSTAT_EAGAIN_ON_READ;
671 proxy_connection_io_status(
const int status,
int *rwflags_pc,
int *rwflags_cp)
675 case IOSTAT_EAGAIN_ON_READ:
680 case IOSTAT_EAGAIN_ON_WRITE:
685 case IOSTAT_READ_ERROR:
688 case IOSTAT_WRITE_ERROR:
702 proxy_connection_io_dispatch(
struct proxy_connection *pc,
706 const int max_transfer_per_iteration = 10000;
707 struct proxy_connection *cp = pc->counterpart;
708 int rwflags_pc = pc->rwflags;
709 int rwflags_cp = cp->rwflags;
711 ASSERT(pc->defined && cp->defined && cp->counterpart == pc);
715 const int status = proxy_connection_io_xfer(pc, max_transfer_per_iteration);
716 if (!proxy_connection_io_status(
status, &rwflags_pc, &rwflags_cp))
723 const int status = proxy_connection_io_xfer(cp, max_transfer_per_iteration);
724 if (!proxy_connection_io_status(
status, &rwflags_cp, &rwflags_pc))
729 proxy_connection_io_requeue(pc, rwflags_pc,
es);
730 proxy_connection_io_requeue(cp, rwflags_cp,
es);
735 proxy_entry_mark_for_close(pc,
es);
743 port_share_proxy(
const struct sockaddr_in hostaddr,
745 const int max_initial_buf,
746 const char *journal_dir)
750 void *sd_control_marker = (
void *)1;
754 struct proxy_connection *list = NULL;
755 time_t last_housekeeping = 0;
771 current = time(NULL);
775 for (i = 0; i < n_events; ++i)
778 if (e->
arg == sd_control_marker)
780 if (!control_message_from_parent(sd_control, &list,
es, hostaddr, max_initial_buf, journal_dir))
787 struct proxy_connection *pc = (
struct proxy_connection *)e->
arg;
790 proxy_connection_io_dispatch(pc, e->
rwflags,
es);
795 else if (n_events < 0)
799 if (current > last_housekeeping)
801 proxy_list_housekeeping(&list);
802 last_housekeeping = current;
807 proxy_list_close(&list);
810 msg(
M_INFO,
"PORT SHARE PROXY: proxy exiting");
818 port_share_open(
const char *host,
820 const int max_initial_buf,
821 const char *journal_dir)
825 struct sockaddr_in hostaddr;
826 struct port_share *ps;
831 ps->foreground_fd = -1;
832 ps->background_pid = -1;
839 host, port, 0, NULL, AF_INET, &ai);
841 hostaddr = *((
struct sockaddr_in *) ai->ai_addr);
848 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
850 msg(
M_WARN,
"PORT SHARE: socketpair call failed");
867 ps->background_pid = pid;
883 ps->foreground_fd = fd[0];
888 msg(
M_ERR,
"PORT SHARE: unexpected init recv_control status=%d",
status);
903 #ifdef ENABLE_MANAGEMENT
915 port_share_proxy(hostaddr, fd[1], max_initial_buf, journal_dir);
924 port_share_close(ps);
929 port_share_close(
struct port_share *ps)
933 if (ps->foreground_fd >= 0)
940 if (ps->background_pid > 0)
942 waitpid(ps->background_pid, NULL, 0);
947 ps->foreground_fd = -1;
955 port_share_abort(
struct port_share *ps)
960 if (ps->foreground_fd >= 0)
964 ps->foreground_fd = -1;
975 is_openvpn_protocol(
const struct buffer *buf)
977 const unsigned char *p = (
const unsigned char *)
BSTR(buf);
978 const int len =
BLEN(buf);
981 int plen = (p[0] << 8) | p[1];
999 return (plen >= 336 && plen < (1024 + 255));
1005 return plen >= 14 && plen <= 255
1011 int plen = (p[0] << 8) | p[1];
1012 return plen >= 14 && plen <= 255;
1030 port_share_sendmsg(ps->foreground_fd, COMMAND_REDIRECT, head, sd);