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
70 struct proxy_connection *next;
71 struct proxy_connection *counterpart;
103 for (i = 3; i <= 100; ++i)
125 signal(SIGPIPE, SIG_IGN);
136 const ssize_t size =
read(fd, &c,
sizeof(c));
137 if (size ==
sizeof(c))
150 unsigned char c = (
unsigned char)code;
151 const ssize_t size =
write(fd, &c,
sizeof(c));
152 if (size ==
sizeof(c))
189 head ?
BLEN(head) : -1);
195 iov[0].iov_base = &cmd;
196 iov[0].iov_len =
sizeof(cmd);
203 iov[1].iov_base = (
char *)
CBPTR(head);
204 iov[1].iov_len =
BLENZ(head);
210 mesg.msg_controllen = cmsg_size();
211 mesg.msg_control = (
char *)malloc(mesg.msg_controllen);
215 h = CMSG_FIRSTHDR(&mesg);
216 h->cmsg_level = SOL_SOCKET;
217 h->cmsg_type = SCM_RIGHTS;
222 memcpy(CMSG_DATA(h), &sd_send,
sizeof(sd_send));
226 socketpair(PF_UNIX, SOCK_DGRAM, 0, sd_null);
227 memcpy(CMSG_DATA(h), &sd_null[0],
sizeof(sd_null[0]));
234 "PORT SHARE: sendmsg failed -- unable to communicate with background process (%d,%d,%d,%d)",
235 sd, sd_send, sd_null[0], sd_null[1]);
238 close_socket_if_defined(sd_null[0]);
239 close_socket_if_defined(sd_null[1]);
240 free(mesg.msg_control);
245proxy_entry_close_sd(
struct proxy_connection *pc,
struct event_set *es)
263proxy_entry_mark_for_close(
struct proxy_connection *pc,
struct event_set *es)
267 struct proxy_connection *cp = pc->counterpart;
268 proxy_entry_close_sd(pc, es);
270 pc->buffer_initial =
false;
279 if (cp && cp->defined && cp->counterpart == pc)
281 proxy_entry_mark_for_close(cp, es);
291proxy_list_housekeeping(
struct proxy_connection **list)
295 struct proxy_connection *prev = NULL;
296 struct proxy_connection *pc = *list;
300 struct proxy_connection *next = pc->next;
327journal_add(
const char *journal_dir,
const struct proxy_connection *pc,
struct proxy_connection *cp)
331 socklen_t slen =
sizeof(from.addr);
332 socklen_t dlen =
sizeof(to.addr);
333 if (!getpeername(pc->sd, (
struct sockaddr *)&from.addr.sa, &slen)
334 && !getsockname(cp->sd, (
struct sockaddr *)&to.addr.sa, &dlen))
339 size_t fnlen = strlen(journal_dir) + strlen(t) + 2;
340 char *jfn = (
char *)malloc(fnlen);
342 snprintf(jfn, fnlen,
"%s/%s", journal_dir, t);
344 int fd =
platform_open(jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
347 ssize_t write_len = strlen(f);
348 if (
write(fd, f, write_len) != write_len)
350 msg(
M_WARN,
"PORT SHARE: writing to journal file (%s) failed", jfn);
357 msg(
M_WARN |
M_ERRNO,
"PORT SHARE: unable to write journal file in %s", jfn);
368proxy_list_close(
struct proxy_connection **
list)
372 struct proxy_connection *pc = *list;
375 proxy_entry_mark_for_close(pc, NULL);
378 proxy_list_housekeeping(list);
383proxy_connection_io_requeue(
struct proxy_connection *pc,
const unsigned int rwflags_new,
390 event_ctl(es, pc->sd, rwflags_new, (
void *)pc);
391 pc->rwflags = rwflags_new;
403proxy_entry_new(
struct proxy_connection **list,
struct event_set *es,
405 const struct buffer *initial_data,
const char *journal_dir)
409 struct proxy_connection *pc;
410 struct proxy_connection *cp;
413 if ((sd_server = socket(server_addr.
addr.
sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0)
421 msg(
M_WARN,
"PORT SHARE PROXY: connect to port-share server failed");
437 pc->counterpart = cp;
438 pc->buf = *initial_data;
439 pc->buffer_initial =
true;
446 cp->counterpart = pc;
447 cp->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
448 cp->buffer_initial =
false;
458 journal_add(journal_dir, pc, cp);
465 proxy_connection_io_requeue(pc,
EVENT_READ, es);
478control_message_from_parent(
const socket_descriptor_t sd_control,
struct proxy_connection **list,
480 const int max_initial_buf,
const char *journal_dir)
495 iov[0].iov_base = &command;
496 iov[0].iov_len =
sizeof(command);
497 iov[1].iov_base =
BPTR(&buf);
498 iov[1].iov_len =
BCAP(&buf);
502 mesg.msg_controllen = cmsg_size();
503 mesg.msg_control = (
char *)malloc(mesg.msg_controllen);
507 h = CMSG_FIRSTHDR(&mesg);
509 h->cmsg_level = SOL_SOCKET;
510 h->cmsg_type = SCM_RIGHTS;
512 memcpy(CMSG_DATA(h), &socket_undefined,
sizeof(socket_undefined));
518 || h->cmsg_level != SOL_SOCKET || h->cmsg_type != SCM_RIGHTS)
520 msg(
M_WARN,
"PORT SHARE PROXY: received unknown message");
525 memcpy(&received_fd, CMSG_DATA(h),
sizeof(received_fd));
528 if (
status >= 2 && command == COMMAND_REDIRECT)
531 if (proxy_entry_new(list, es, server_addr, received_fd, &buf, journal_dir))
548 free(mesg.msg_control);
554proxy_connection_io_recv(
struct proxy_connection *pc)
560 return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
566 return IOSTAT_READ_ERROR;
569 pc->buf.len = (int)
status;
575proxy_connection_io_send(
struct proxy_connection *pc,
int *bytes_sent)
583 return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_WRITE_ERROR;
587 *bytes_sent += (int)
status;
588 if (
status != pc->buf.len)
593 return IOSTAT_EAGAIN_ON_WRITE;
604 if (pc->buffer_initial)
607 pc->buf =
alloc_buf(PROXY_CONNECTION_BUFFER_SIZE);
608 pc->buffer_initial =
false;
618proxy_connection_io_xfer(
struct proxy_connection *pc,
const int max_transfer)
621 while (transferred < max_transfer)
625 const int status = proxy_connection_io_recv(pc);
626 if (
status != IOSTAT_GOOD)
634 const int status = proxy_connection_io_send(pc, &transferred);
635 if (
status != IOSTAT_GOOD)
641 return IOSTAT_EAGAIN_ON_READ;
648proxy_connection_io_status(
const int status,
unsigned int *rwflags_pc,
unsigned int *rwflags_cp)
652 case IOSTAT_EAGAIN_ON_READ:
657 case IOSTAT_EAGAIN_ON_WRITE:
662 case IOSTAT_READ_ERROR:
665 case IOSTAT_WRITE_ERROR:
679proxy_connection_io_dispatch(
struct proxy_connection *pc,
const unsigned int rwflags,
682 const int max_transfer_per_iteration = 10000;
683 struct proxy_connection *cp = pc->counterpart;
684 unsigned int rwflags_pc = pc->rwflags;
685 unsigned int rwflags_cp = cp->rwflags;
687 ASSERT(pc->defined && cp->defined && cp->counterpart == pc);
691 const int status = proxy_connection_io_xfer(pc, max_transfer_per_iteration);
692 if (!proxy_connection_io_status(
status, &rwflags_pc, &rwflags_cp))
699 const int status = proxy_connection_io_xfer(cp, max_transfer_per_iteration);
700 if (!proxy_connection_io_status(
status, &rwflags_cp, &rwflags_pc))
705 proxy_connection_io_requeue(pc, rwflags_pc, es);
706 proxy_connection_io_requeue(cp, rwflags_cp, es);
711 proxy_entry_mark_for_close(pc, es);
720 const int max_initial_buf,
const char *journal_dir)
724 void *sd_control_marker = (
void *)1;
728 struct proxy_connection *list = NULL;
729 time_t last_housekeeping = 0;
745 current = time(NULL);
749 for (i = 0; i < n_events; ++i)
752 if (e->
arg == sd_control_marker)
754 if (!control_message_from_parent(sd_control, &list, es, hostaddr,
755 max_initial_buf, journal_dir))
762 struct proxy_connection *pc = (
struct proxy_connection *)e->
arg;
765 proxy_connection_io_dispatch(pc, e->
rwflags, es);
770 else if (n_events < 0)
774 if (current > last_housekeeping)
776 proxy_list_housekeeping(&list);
777 last_housekeeping = current;
782 proxy_list_close(&list);
785 msg(
M_INFO,
"PORT SHARE PROXY: proxy exiting");
793port_share_open(
const char *host,
const char *port,
const int max_initial_buf,
794 const char *journal_dir)
798 struct port_share *ps;
801 ps->foreground_fd = -1;
802 ps->background_pid = -1;
809 0, NULL, AF_UNSPEC, &ai);
811 ASSERT(
sizeof(hostaddr.
addr) >= ai->ai_addrlen);
812 memcpy(&hostaddr.
addr.
sa, ai->ai_addr, ai->ai_addrlen);
827 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
849 ps->background_pid = pid;
865 ps->foreground_fd = fd[0];
870 msg(
M_ERR,
"PORT SHARE: unexpected init recv_control status=%d", recv_status);
885#ifdef ENABLE_MANAGEMENT
897 port_share_proxy(hostaddr, fd[1], max_initial_buf, journal_dir);
906 port_share_close(ps);
911port_share_close(
struct port_share *ps)
915 if (ps->foreground_fd >= 0)
922 if (ps->background_pid > 0)
924 waitpid(ps->background_pid, NULL, 0);
929 ps->foreground_fd = -1;
937port_share_abort(
struct port_share *ps)
942 if (ps->foreground_fd >= 0)
946 ps->foreground_fd = -1;
957is_openvpn_protocol(
const struct buffer *buf)
959 const unsigned char *p = (
const unsigned char *)
CBSTR(buf);
960 const int len =
BLEN(buf);
963 int plen = (p[0] << 8) | p[1];
981 return (plen >= 336 && plen < (1024 + 255));
987 return plen >= 14 && plen <= 255
993 int plen = (p[0] << 8) | p[1];
994 return plen >= 14 && plen <= 255;
1012 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 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_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)
#define openvpn_close_socket(s)
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::@051240265251124304325377241125360350250341115171 addr
SOCKET socket_descriptor_t
static int socket_defined(const socket_descriptor_t sd)