39struct port_share *port_share = NULL;
42#define PROXY_CONNECTION_BUFFER_SIZE 1500
45#define COMMAND_REDIRECT 10
46#define COMMAND_EXIT 11
49#define RESPONSE_INIT_SUCCEEDED 20
50#define RESPONSE_INIT_FAILED 21
56#define IOSTAT_EAGAIN_ON_READ 0
57#define IOSTAT_EAGAIN_ON_WRITE 1
58#define IOSTAT_READ_ERROR 2
59#define IOSTAT_WRITE_ERROR 3
66struct 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))
199 head ?
BLEN(head) : -1);
205 iov[0].iov_base = &cmd;
206 iov[0].iov_len =
sizeof(cmd);
211 iov[1].iov_base =
BPTR(head);
212 iov[1].iov_len =
BLENZ(head);
218 mesg.msg_controllen = cmsg_size();
219 mesg.msg_control = (
char *)malloc(mesg.msg_controllen);
223 h = CMSG_FIRSTHDR(&mesg);
224 h->cmsg_level = SOL_SOCKET;
225 h->cmsg_type = SCM_RIGHTS;
230 memcpy(CMSG_DATA(h), &sd_send,
sizeof(sd_send));
234 socketpair(PF_UNIX, SOCK_DGRAM, 0, sd_null);
235 memcpy(CMSG_DATA(h), &sd_null[0],
sizeof(sd_null[0]));
242 "PORT SHARE: sendmsg failed -- unable to communicate with background process (%d,%d,%d,%d)",
243 sd, sd_send, sd_null[0], sd_null[1]);
246 close_socket_if_defined(sd_null[0]);
247 close_socket_if_defined(sd_null[1]);
248 free(mesg.msg_control);
253proxy_entry_close_sd(
struct proxy_connection *pc,
struct event_set *
es)
271proxy_entry_mark_for_close(
struct proxy_connection *pc,
struct event_set *
es)
275 struct proxy_connection *cp = pc->counterpart;
276 proxy_entry_close_sd(pc,
es);
278 pc->buffer_initial =
false;
287 if (cp && cp->defined && cp->counterpart == pc)
289 proxy_entry_mark_for_close(cp,
es);
299proxy_list_housekeeping(
struct proxy_connection **list)
303 struct proxy_connection *prev = NULL;
304 struct proxy_connection *pc = *list;
308 struct proxy_connection *next = pc->next;
330#if defined(__GNUC__) || defined(__clang__)
331#pragma GCC diagnostic push
332#pragma GCC diagnostic ignored "-Wsign-compare"
340journal_add(
const char *journal_dir,
struct proxy_connection *pc,
struct proxy_connection *cp)
344 socklen_t slen =
sizeof(from.addr);
345 socklen_t dlen =
sizeof(to.addr);
346 if (!getpeername(pc->sd, (
struct sockaddr *)&from.addr.sa, &slen)
347 && !getsockname(cp->sd, (
struct sockaddr *)&to.addr.sa, &dlen))
352 size_t fnlen = strlen(journal_dir) + strlen(t) + 2;
353 char *jfn = (
char *)malloc(fnlen);
355 snprintf(jfn, fnlen,
"%s/%s", journal_dir, t);
357 int fd =
platform_open(jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
360 if (
write(fd, f, strlen(f)) != strlen(f))
362 msg(
M_WARN,
"PORT SHARE: writing to journal file (%s) failed", jfn);
369 msg(
M_WARN |
M_ERRNO,
"PORT SHARE: unable to write journal file in %s", jfn);
376#if defined(__GNUC__) || defined(__clang__)
377#pragma GCC diagnostic pop
384proxy_list_close(
struct proxy_connection **
list)
388 struct proxy_connection *pc = *list;
391 proxy_entry_mark_for_close(pc, NULL);
394 proxy_list_housekeeping(list);
399proxy_connection_io_requeue(
struct proxy_connection *pc,
const unsigned int rwflags_new,
407 pc->rwflags = rwflags_new;
419proxy_entry_new(
struct proxy_connection **list,
struct event_set *
es,
421 struct buffer *initial_data,
const char *journal_dir)
425 struct proxy_connection *pc;
426 struct proxy_connection *cp;
429 if ((sd_server = socket(server_addr.
addr.
sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0)
437 msg(
M_WARN,
"PORT SHARE PROXY: connect to port-share server failed");
453 pc->counterpart = cp;
454 pc->buf = *initial_data;
455 pc->buffer_initial =
true;
462 cp->counterpart = pc;
463 cp->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
464 cp->buffer_initial =
false;
474 journal_add(journal_dir, pc, cp);
494control_message_from_parent(
const socket_descriptor_t sd_control,
struct proxy_connection **list,
496 const int max_initial_buf,
const char *journal_dir)
511 iov[0].iov_base = &command;
512 iov[0].iov_len =
sizeof(command);
513 iov[1].iov_base =
BPTR(&buf);
514 iov[1].iov_len =
BCAP(&buf);
518 mesg.msg_controllen = cmsg_size();
519 mesg.msg_control = (
char *)malloc(mesg.msg_controllen);
523 h = CMSG_FIRSTHDR(&mesg);
525 h->cmsg_level = SOL_SOCKET;
526 h->cmsg_type = SCM_RIGHTS;
528 memcpy(CMSG_DATA(h), &socket_undefined,
sizeof(socket_undefined));
534 || h->cmsg_level != SOL_SOCKET || h->cmsg_type != SCM_RIGHTS)
536 msg(
M_WARN,
"PORT SHARE PROXY: received unknown message");
541 memcpy(&received_fd, CMSG_DATA(h),
sizeof(received_fd));
544 if (
status >= 2 && command == COMMAND_REDIRECT)
547 if (proxy_entry_new(list,
es, server_addr, received_fd, &buf, journal_dir))
564 free(mesg.msg_control);
570proxy_connection_io_recv(
struct proxy_connection *pc)
576 return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
582 return IOSTAT_READ_ERROR;
585 pc->buf.len = (int)
status;
591proxy_connection_io_send(
struct proxy_connection *pc,
int *bytes_sent)
599 return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_WRITE_ERROR;
603 *bytes_sent += (int)
status;
604 if (
status != pc->buf.len)
609 return IOSTAT_EAGAIN_ON_WRITE;
620 if (pc->buffer_initial)
623 pc->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
624 pc->buffer_initial =
false;
634proxy_connection_io_xfer(
struct proxy_connection *pc,
const int max_transfer)
637 while (transferred < max_transfer)
641 const int status = proxy_connection_io_recv(pc);
642 if (
status != IOSTAT_GOOD)
650 const int status = proxy_connection_io_send(pc, &transferred);
651 if (
status != IOSTAT_GOOD)
657 return IOSTAT_EAGAIN_ON_READ;
664proxy_connection_io_status(
const int status,
unsigned int *rwflags_pc,
unsigned int *rwflags_cp)
668 case IOSTAT_EAGAIN_ON_READ:
670 *rwflags_cp &= ~EVENT_WRITE;
673 case IOSTAT_EAGAIN_ON_WRITE:
674 *rwflags_pc &= ~EVENT_READ;
678 case IOSTAT_READ_ERROR:
681 case IOSTAT_WRITE_ERROR:
695proxy_connection_io_dispatch(
struct proxy_connection *pc,
const unsigned int rwflags,
698 const int max_transfer_per_iteration = 10000;
699 struct proxy_connection *cp = pc->counterpart;
700 unsigned int rwflags_pc = pc->rwflags;
701 unsigned int rwflags_cp = cp->rwflags;
703 ASSERT(pc->defined && cp->defined && cp->counterpart == pc);
707 const int status = proxy_connection_io_xfer(pc, max_transfer_per_iteration);
708 if (!proxy_connection_io_status(
status, &rwflags_pc, &rwflags_cp))
715 const int status = proxy_connection_io_xfer(cp, max_transfer_per_iteration);
716 if (!proxy_connection_io_status(
status, &rwflags_cp, &rwflags_pc))
721 proxy_connection_io_requeue(pc, rwflags_pc,
es);
722 proxy_connection_io_requeue(cp, rwflags_cp,
es);
727 proxy_entry_mark_for_close(pc,
es);
736 const int max_initial_buf,
const char *journal_dir)
740 void *sd_control_marker = (
void *)1;
744 struct proxy_connection *list = NULL;
745 time_t last_housekeeping = 0;
761 current = time(NULL);
765 for (i = 0; i < n_events; ++i)
768 if (e->
arg == sd_control_marker)
770 if (!control_message_from_parent(sd_control, &list,
es, hostaddr,
771 max_initial_buf, journal_dir))
778 struct proxy_connection *pc = (
struct proxy_connection *)e->
arg;
781 proxy_connection_io_dispatch(pc, e->
rwflags,
es);
786 else if (n_events < 0)
790 if (current > last_housekeeping)
792 proxy_list_housekeeping(&list);
793 last_housekeeping = current;
798 proxy_list_close(&list);
801 msg(
M_INFO,
"PORT SHARE PROXY: proxy exiting");
809port_share_open(
const char *host,
const char *port,
const int max_initial_buf,
810 const char *journal_dir)
814 struct port_share *ps;
817 ps->foreground_fd = -1;
818 ps->background_pid = -1;
825 0, NULL, AF_UNSPEC, &ai);
827 ASSERT(
sizeof(hostaddr.
addr) >= ai->ai_addrlen);
828 memcpy(&hostaddr.
addr.
sa, ai->ai_addr, ai->ai_addrlen);
843 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
865 ps->background_pid = pid;
881 ps->foreground_fd = fd[0];
886 msg(
M_ERR,
"PORT SHARE: unexpected init recv_control status=%d",
status);
901#ifdef ENABLE_MANAGEMENT
913 port_share_proxy(hostaddr, fd[1], max_initial_buf, journal_dir);
922 port_share_close(ps);
927port_share_close(
struct port_share *ps)
931 if (ps->foreground_fd >= 0)
938 if (ps->background_pid > 0)
940 waitpid(ps->background_pid, NULL, 0);
945 ps->foreground_fd = -1;
953port_share_abort(
struct port_share *ps)
958 if (ps->foreground_fd >= 0)
962 ps->foreground_fd = -1;
973is_openvpn_protocol(
const struct buffer *buf)
975 const unsigned char *p = (
const unsigned char *)
BSTR(buf);
976 const int len =
BLEN(buf);
979 int plen = (p[0] << 8) | p[1];
997 return (plen >= 336 && plen < (1024 + 255));
1003 return plen >= 14 && plen <= 255
1009 int plen = (p[0] << 8) | p[1];
1010 return plen >= 14 && plen <= 255;
1028 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, ssize_t 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(msglvl_t flags)
Return true if flags represent an enabled, not muted log level.
int openvpn_connect(socket_descriptor_t sd, const struct sockaddr *remote, int connect_timeout, volatile int *signal_received)
#define openvpn_close_socket(s)
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)
static const char * print_openvpn_sockaddr(const struct openvpn_sockaddr *addr, struct gc_arena *gc)
#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.
struct gc_entry * list
First element of the linked list of gc_entry structures.
union openvpn_sockaddr::@27 addr
SOCKET socket_descriptor_t
static int socket_defined(const socket_descriptor_t sd)