bool buffer_initial;
int rwflags;
int sd;
+ char *jfn;
};
#if 0
status = sendmsg (sd, &mesg, MSG_NOSIGNAL);
if (status == -1)
- msg (M_WARN, "PORT SHARE: sendmsg failed (unable to communicate with background process)");
+ msg (M_WARN|M_ERRNO_SOCK, "PORT SHARE: sendmsg failed (unable to communicate with background process)");
close_socket_if_defined (sd_null[0]);
close_socket_if_defined (sd_null[1]);
pc->buffer_initial = false;
pc->rwflags = 0;
pc->defined = false;
+ if (pc->jfn)
+ {
+ unlink (pc->jfn);
+ free (pc->jfn);
+ pc->jfn = NULL;
+ }
if (cp && cp->defined && cp->counterpart == pc)
proxy_entry_mark_for_close (cp, es);
}
}
}
+/*
+ * Record IP/port of client in filesystem, so that server receiving
+ * the proxy can determine true client origin.
+ */
+static void
+journal_add (const char *journal_dir, struct proxy_connection *pc, struct proxy_connection *cp)
+{
+ struct gc_arena gc = gc_new ();
+ struct openvpn_sockaddr from, to;
+ socklen_t slen, dlen;
+ int fnlen;
+ char *jfn;
+ int fd;
+
+ slen = sizeof(from.sa);
+ dlen = sizeof(to.sa);
+ if (!getpeername (pc->sd, (struct sockaddr *) &from.sa, &slen)
+ && !getsockname (cp->sd, (struct sockaddr *) &to.sa, &dlen))
+ {
+ const char *f = print_sockaddr_ex (&from, ":", PS_SHOW_PORT, &gc);
+ const char *t = print_sockaddr_ex (&to, ":", PS_SHOW_PORT, &gc);
+ fnlen = strlen(journal_dir) + strlen(t) + 2;
+ jfn = (char *) malloc(fnlen);
+ check_malloc_return (jfn);
+ openvpn_snprintf (jfn, fnlen, "%s/%s", journal_dir, t);
+ dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: client origin %s -> %s", jfn, f);
+ fd = open (jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
+ if (fd != -1)
+ {
+ write(fd, f, strlen(f));
+ close (fd);
+ cp->jfn = jfn;
+ }
+ else
+ {
+ msg (M_WARN|M_ERRNO, "PORT SHARE: unable to write journal file in %s", jfn);
+ free (jfn);
+ }
+ }
+ gc_free (&gc);
+}
+
/*
* Cleanup function, on proxy process exit.
*/
const in_addr_t server_addr,
const int server_port,
const socket_descriptor_t sd_client,
- struct buffer *initial_data)
+ struct buffer *initial_data,
+ const char *journal_dir)
{
struct openvpn_sockaddr osaddr;
socket_descriptor_t sd_server;
/* connect to port share server */
sock_addr_set (&osaddr, server_addr, server_port);
- sd_server = create_socket_tcp ();
+ if ((sd_server = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ {
+ msg (M_WARN|M_ERRNO_SOCK, "PORT SHARE PROXY: cannot create socket");
+ return false;
+ }
status = openvpn_connect (sd_server, &osaddr, 5, NULL);
if (status)
{
/* add to list */
*list = pc;
+
+ /* add journal entry */
+ if (journal_dir)
+ journal_add (journal_dir, pc, cp);
dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: NEW CONNECTION [c=%d s=%d]", (int)sd_client, (int)sd_server);
struct proxy_connection **list,
struct event_set *es,
const in_addr_t server_addr,
- const int server_port)
+ const int server_port,
+ const int max_initial_buf,
+ const char *journal_dir)
{
- struct buffer buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
+ /* this buffer needs to be large enough to handle the largest buffer
+ that might be returned by the link_socket_read call in read_incoming_link. */
+ struct buffer buf = alloc_buf (max_initial_buf);
+
struct msghdr mesg;
struct cmsghdr* h;
struct iovec iov[2];
|| h->cmsg_level != SOL_SOCKET
|| h->cmsg_type != SCM_RIGHTS )
{
- ret = false;
+ msg (M_WARN, "PORT SHARE PROXY: received unknown message");
}
else
{
server_addr,
server_port,
received_fd,
- &buf))
+ &buf,
+ journal_dir))
{
CLEAR (buf); /* we gave the buffer to proxy_entry_new */
}
{
if (!status)
return IOSTAT_READ_ERROR;
+ dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: read[%d] %d", (int)pc->sd, status);
pc->buf.len = status;
}
return IOSTAT_GOOD;
}
else
{
- /*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: wrote[%d] %d", (int)sd, status);*/
+ dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: wrote[%d] %d", (int)sd, status);
pc->buf.len = 0;
pc->buf.offset = 0;
}
int rwflags_pc = pc->rwflags;
int rwflags_cp = cp->rwflags;
+ ASSERT(pc->defined && cp->defined && cp->counterpart == pc);
+
if (rwflags & EVENT_READ)
{
const int status = proxy_connection_io_xfer (pc, max_transfer_per_iteration);
* This is the main function for the port share proxy background process.
*/
static void
-port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descriptor_t sd_control)
+port_share_proxy (const in_addr_t hostaddr,
+ const int port,
+ const socket_descriptor_t sd_control,
+ const int max_initial_buf,
+ const char *journal_dir)
{
if (send_control (sd_control, RESPONSE_INIT_SUCCEEDED) >= 0)
{
const struct event_set_return *e = &esr[i];
if (e->arg == sd_control_marker)
{
- if (!control_message_from_parent (sd_control, &list, es, hostaddr, port))
+ if (!control_message_from_parent (sd_control, &list, es, hostaddr, port, max_initial_buf, journal_dir))
goto done;
}
else
proxy_list_close (&list);
event_free (es);
}
- msg (D_PS_PROXY, "PORT SHARE PROXY: proxy exiting");
+ msg (M_INFO, "PORT SHARE PROXY: proxy exiting");
}
/*
* share proxy.
*/
struct port_share *
-port_share_open (const char *host, const int port)
+port_share_open (const char *host,
+ const int port,
+ const int max_initial_buf,
+ const char *journal_dir)
{
pid_t pid;
socket_descriptor_t fd[2];
/* don't let future subprocesses inherit child socket */
set_cloexec (fd[0]);
+ /* note that this will cause possible EAGAIN when writing to
+ control socket if proxy process is backlogged */
+ set_nonblock (fd[0]);
+
/* wait for background child process to initialize */
status = recv_control (fd[0]);
if (status == RESPONSE_INIT_SUCCEEDED)
prng_init (NULL, 0);
/* execute the event loop */
- port_share_proxy (hostaddr, port, fd[1]);
+ port_share_proxy (hostaddr, port, fd[1], max_initial_buf, journal_dir);
openvpn_close_socket (fd[1]);