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);
213 iov[1].iov_base = (
char *)
CBPTR(head);
214 iov[1].iov_len =
BLENZ(head);
220 mesg.msg_controllen = cmsg_size();
221 mesg.msg_control = (
char *)malloc(mesg.msg_controllen);
225 h = CMSG_FIRSTHDR(&mesg);
226 h->cmsg_level = SOL_SOCKET;
227 h->cmsg_type = SCM_RIGHTS;
232 memcpy(CMSG_DATA(h), &sd_send,
sizeof(sd_send));
236 socketpair(PF_UNIX, SOCK_DGRAM, 0, sd_null);
237 memcpy(CMSG_DATA(h), &sd_null[0],
sizeof(sd_null[0]));
244 "PORT SHARE: sendmsg failed -- unable to communicate with background process (%d,%d,%d,%d)",
245 sd, sd_send, sd_null[0], sd_null[1]);
248 close_socket_if_defined(sd_null[0]);
249 close_socket_if_defined(sd_null[1]);
250 free(mesg.msg_control);
255proxy_entry_close_sd(
struct proxy_connection *pc,
struct event_set *es)
273proxy_entry_mark_for_close(
struct proxy_connection *pc,
struct event_set *es)
277 struct proxy_connection *cp = pc->counterpart;
278 proxy_entry_close_sd(pc, es);
280 pc->buffer_initial =
false;
289 if (cp && cp->defined && cp->counterpart == pc)
291 proxy_entry_mark_for_close(cp, es);
301proxy_list_housekeeping(
struct proxy_connection **list)
305 struct proxy_connection *prev = NULL;
306 struct proxy_connection *pc = *list;
310 struct proxy_connection *next = pc->next;
337journal_add(
const char *journal_dir,
struct proxy_connection *pc,
struct proxy_connection *cp)
341 socklen_t slen =
sizeof(from.addr);
342 socklen_t dlen =
sizeof(to.addr);
343 if (!getpeername(pc->sd, (
struct sockaddr *)&from.addr.sa, &slen)
344 && !getsockname(cp->sd, (
struct sockaddr *)&to.addr.sa, &dlen))
349 size_t fnlen = strlen(journal_dir) + strlen(t) + 2;
350 char *jfn = (
char *)malloc(fnlen);
352 snprintf(jfn, fnlen,
"%s/%s", journal_dir, t);
354 int fd =
platform_open(jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
357 ssize_t write_len = strlen(f);
358 if (
write(fd, f, write_len) != write_len)
360 msg(
M_WARN,
"PORT SHARE: writing to journal file (%s) failed", jfn);
367 msg(
M_WARN |
M_ERRNO,
"PORT SHARE: unable to write journal file in %s", jfn);
378proxy_list_close(
struct proxy_connection **
list)
382 struct proxy_connection *pc = *list;
385 proxy_entry_mark_for_close(pc, NULL);
388 proxy_list_housekeeping(list);
393proxy_connection_io_requeue(
struct proxy_connection *pc,
const unsigned int rwflags_new,
400 event_ctl(es, pc->sd, rwflags_new, (
void *)pc);
401 pc->rwflags = rwflags_new;
413proxy_entry_new(
struct proxy_connection **list,
struct event_set *es,
415 struct buffer *initial_data,
const char *journal_dir)
419 struct proxy_connection *pc;
420 struct proxy_connection *cp;
423 if ((sd_server = socket(server_addr.
addr.
sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0)
431 msg(
M_WARN,
"PORT SHARE PROXY: connect to port-share server failed");
447 pc->counterpart = cp;
448 pc->buf = *initial_data;
449 pc->buffer_initial =
true;
456 cp->counterpart = pc;
457 cp->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
458 cp->buffer_initial =
false;
468 journal_add(journal_dir, pc, cp);
475 proxy_connection_io_requeue(pc,
EVENT_READ, es);
488control_message_from_parent(
const socket_descriptor_t sd_control,
struct proxy_connection **list,
490 const int max_initial_buf,
const char *journal_dir)
505 iov[0].iov_base = &command;
506 iov[0].iov_len =
sizeof(command);
507 iov[1].iov_base =
BPTR(&buf);
508 iov[1].iov_len =
BCAP(&buf);
512 mesg.msg_controllen = cmsg_size();
513 mesg.msg_control = (
char *)malloc(mesg.msg_controllen);
517 h = CMSG_FIRSTHDR(&mesg);
519 h->cmsg_level = SOL_SOCKET;
520 h->cmsg_type = SCM_RIGHTS;
522 memcpy(CMSG_DATA(h), &socket_undefined,
sizeof(socket_undefined));
528 || h->cmsg_level != SOL_SOCKET || h->cmsg_type != SCM_RIGHTS)
530 msg(
M_WARN,
"PORT SHARE PROXY: received unknown message");
535 memcpy(&received_fd, CMSG_DATA(h),
sizeof(received_fd));
538 if (
status >= 2 && command == COMMAND_REDIRECT)
541 if (proxy_entry_new(list, es, server_addr, received_fd, &buf, journal_dir))
558 free(mesg.msg_control);
564proxy_connection_io_recv(
struct proxy_connection *pc)
570 return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
576 return IOSTAT_READ_ERROR;
579 pc->buf.len = (int)
status;
585proxy_connection_io_send(
struct proxy_connection *pc,
int *bytes_sent)
593 return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_WRITE_ERROR;
597 *bytes_sent += (int)
status;
598 if (
status != pc->buf.len)
603 return IOSTAT_EAGAIN_ON_WRITE;
614 if (pc->buffer_initial)
617 pc->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
618 pc->buffer_initial =
false;
628proxy_connection_io_xfer(
struct proxy_connection *pc,
const int max_transfer)
631 while (transferred < max_transfer)
635 const int status = proxy_connection_io_recv(pc);
636 if (
status != IOSTAT_GOOD)
644 const int status = proxy_connection_io_send(pc, &transferred);
645 if (
status != IOSTAT_GOOD)
651 return IOSTAT_EAGAIN_ON_READ;
658proxy_connection_io_status(
const int status,
unsigned int *rwflags_pc,
unsigned int *rwflags_cp)
662 case IOSTAT_EAGAIN_ON_READ:
664 *rwflags_cp &= ~EVENT_WRITE;
667 case IOSTAT_EAGAIN_ON_WRITE:
668 *rwflags_pc &= ~EVENT_READ;
672 case IOSTAT_READ_ERROR:
675 case IOSTAT_WRITE_ERROR:
689proxy_connection_io_dispatch(
struct proxy_connection *pc,
const unsigned int rwflags,
692 const int max_transfer_per_iteration = 10000;
693 struct proxy_connection *cp = pc->counterpart;
694 unsigned int rwflags_pc = pc->rwflags;
695 unsigned int rwflags_cp = cp->rwflags;
697 ASSERT(pc->defined && cp->defined && cp->counterpart == pc);
701 const int status = proxy_connection_io_xfer(pc, max_transfer_per_iteration);
702 if (!proxy_connection_io_status(
status, &rwflags_pc, &rwflags_cp))
709 const int status = proxy_connection_io_xfer(cp, max_transfer_per_iteration);
710 if (!proxy_connection_io_status(
status, &rwflags_cp, &rwflags_pc))
715 proxy_connection_io_requeue(pc, rwflags_pc, es);
716 proxy_connection_io_requeue(cp, rwflags_cp, es);
721 proxy_entry_mark_for_close(pc, es);
730 const int max_initial_buf,
const char *journal_dir)
734 void *sd_control_marker = (
void *)1;
738 struct proxy_connection *list = NULL;
739 time_t last_housekeeping = 0;
755 current = time(NULL);
759 for (i = 0; i < n_events; ++i)
762 if (e->
arg == sd_control_marker)
764 if (!control_message_from_parent(sd_control, &list, es, hostaddr,
765 max_initial_buf, journal_dir))
772 struct proxy_connection *pc = (
struct proxy_connection *)e->
arg;
775 proxy_connection_io_dispatch(pc, e->
rwflags, es);
780 else if (n_events < 0)
784 if (current > last_housekeeping)
786 proxy_list_housekeeping(&list);
787 last_housekeeping = current;
792 proxy_list_close(&list);
795 msg(
M_INFO,
"PORT SHARE PROXY: proxy exiting");
803port_share_open(
const char *host,
const char *port,
const int max_initial_buf,
804 const char *journal_dir)
808 struct port_share *ps;
811 ps->foreground_fd = -1;
812 ps->background_pid = -1;
819 0, NULL, AF_UNSPEC, &ai);
821 ASSERT(
sizeof(hostaddr.
addr) >= ai->ai_addrlen);
822 memcpy(&hostaddr.
addr.
sa, ai->ai_addr, ai->ai_addrlen);
837 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
859 ps->background_pid = pid;
875 ps->foreground_fd = fd[0];
880 msg(
M_ERR,
"PORT SHARE: unexpected init recv_control status=%d", recv_status);
895#ifdef ENABLE_MANAGEMENT
907 port_share_proxy(hostaddr, fd[1], max_initial_buf, journal_dir);
916 port_share_close(ps);
921port_share_close(
struct port_share *ps)
925 if (ps->foreground_fd >= 0)
932 if (ps->background_pid > 0)
934 waitpid(ps->background_pid, NULL, 0);
939 ps->foreground_fd = -1;
947port_share_abort(
struct port_share *ps)
952 if (ps->foreground_fd >= 0)
956 ps->foreground_fd = -1;
967is_openvpn_protocol(
const struct buffer *buf)
969 const unsigned char *p = (
const unsigned char *)
CBSTR(buf);
970 const int len =
BLEN(buf);
973 int plen = (p[0] << 8) | p[1];
991 return (plen >= 336 && plen < (1024 + 255));
997 return plen >= 14 && plen <= 255
1003 int plen = (p[0] << 8) | p[1];
1004 return plen >= 14 && plen <= 255;
1022 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)
Free the memory allocated for a buffer.
struct buffer alloc_buf(size_t size)
Allocate a buffer of the given size.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
#define BPTR(buf)
Return a pointer to the start of the buffer content.
#define CBPTR(buf)
Return a const pointer to the start of the buffer content.
static bool buf_advance(struct buffer *buf, ssize_t size)
Advance the content start of a buffer, consuming bytes from the front.
#define BLEN(buf)
Return the length of the buffer content in bytes.
#define BCAP(buf)
Return the number of bytes available for appending to the buffer.
#define BLENZ(buf)
Return the length of the buffer content as a size_t.
static void check_malloc_return(void *p)
Abort if a memory allocation returned NULL.
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
#define CBSTR(buf)
Return the buffer content pointer cast to const char *.
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
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)