40struct 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
67struct proxy_connection {
69 struct proxy_connection *next;
70 struct proxy_connection *counterpart;
113 for (
i = 3;
i <= 100; ++
i)
147 if (size ==
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);
256proxy_entry_close_sd(
struct proxy_connection *pc,
struct event_set *
es)
274proxy_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);
302proxy_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;
338journal_add(
const char *journal_dir,
struct proxy_connection *pc,
struct proxy_connection *cp)
342 socklen_t slen, dlen;
347 slen =
sizeof(from.addr);
348 dlen =
sizeof(to.addr);
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);
382proxy_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);
397proxy_connection_io_requeue(
struct proxy_connection *pc,
const int rwflags_new,
struct event_set *
es)
403 pc->rwflags = rwflags_new;
415proxy_entry_new(
struct proxy_connection **list,
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(server_addr.
addr.
sa.sa_family, 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,
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);
578proxy_connection_io_recv(
struct proxy_connection *pc)
584 return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
590 return IOSTAT_READ_ERROR;
599proxy_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;
641proxy_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;
671proxy_connection_io_status(
const int status,
int *rwflags_pc,
int *rwflags_cp)
675 case IOSTAT_EAGAIN_ON_READ:
677 *rwflags_cp &= ~EVENT_WRITE;
680 case IOSTAT_EAGAIN_ON_WRITE:
681 *rwflags_pc &= ~EVENT_READ;
685 case IOSTAT_READ_ERROR:
688 case IOSTAT_WRITE_ERROR:
702proxy_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);
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");
818port_share_open(
const char *host,
820 const int max_initial_buf,
821 const char *journal_dir)
826 struct port_share *ps;
831 ps->foreground_fd = -1;
832 ps->background_pid = -1;
839 host, port, 0, NULL, AF_UNSPEC, &ai);
841 ASSERT(
sizeof(hostaddr.
addr) >= ai->ai_addrlen);
842 memcpy(&hostaddr.
addr.
sa, ai->ai_addr, ai->ai_addrlen);
857 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
859 msg(
M_WARN,
"PORT SHARE: socketpair call failed");
876 ps->background_pid = pid;
892 ps->foreground_fd = fd[0];
897 msg(
M_ERR,
"PORT SHARE: unexpected init recv_control status=%d",
status);
912#ifdef ENABLE_MANAGEMENT
924 port_share_proxy(hostaddr, fd[1], max_initial_buf, journal_dir);
933 port_share_close(ps);
938port_share_close(
struct port_share *ps)
942 if (ps->foreground_fd >= 0)
949 if (ps->background_pid > 0)
951 waitpid(ps->background_pid, NULL, 0);
956 ps->foreground_fd = -1;
964port_share_abort(
struct port_share *ps)
969 if (ps->foreground_fd >= 0)
973 ps->foreground_fd = -1;
984is_openvpn_protocol(
const struct buffer *buf)
986 const unsigned char *p = (
const unsigned char *)
BSTR(buf);
987 const int len =
BLEN(buf);
990 int plen = (p[0] << 8) | p[1];
1008 return (plen >= 336 && plen < (1024 + 255));
1014 return plen >= 14 && plen <= 255
1020 int plen = (p[0] << 8) | p[1];
1021 return plen >= 14 && plen <= 255;
1039 port_share_sendmsg(ps->foreground_fd, COMMAND_REDIRECT, head, sd);
static void set_signals(void)
#define RESPONSE_INIT_SUCCEEDED
static int recv_control(int fd)
static int send_control(int fd, int code)
static void close_fds_except(int keep)
void free_buf(struct buffer *buf)
struct buffer alloc_buf(size_t size)
static bool buf_advance(struct buffer *buf, int size)
static void check_malloc_return(void *p)
static void gc_free(struct gc_arena *a)
#define ALLOC_OBJ_CLEAR(dptr, type)
static struct gc_arena gc_new(void)
Data Channel Cryptography Module.
struct event_set * event_set_init(int *maxevents, unsigned int flags)
static void event_free(struct event_set *es)
static void event_del(struct event_set *es, event_t event)
static int event_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
static void event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
void set_nonblock(socket_descriptor_t fd)
void set_cloexec(socket_descriptor_t fd)
static SERVICE_STATUS status
static bool msg_test(unsigned int flags)
Return true if flags represent an enabled, not muted log level.
int openvpn_getaddrinfo(unsigned int flags, const char *hostname, const char *servname, int resolve_retry_seconds, struct signal_info *sig_info, int ai_family, struct addrinfo **res)
int openvpn_connect(socket_descriptor_t sd, const struct sockaddr *remote, int connect_timeout, volatile int *signal_received)
static const char * print_openvpn_sockaddr(const struct openvpn_sockaddr *addr, struct gc_arena *gc)
#define openvpn_close_socket(s)
#define P_CONTROL_HARD_RESET_CLIENT_V2
#define P_CONTROL_HARD_RESET_CLIENT_V3
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Garbage collection arena used to keep track of dynamically allocated memory.
union openvpn_sockaddr::@20 addr
SOCKET socket_descriptor_t
static int socket_defined(const socket_descriptor_t sd)