Upgrade to OpenVPN 2.1.0
[tomato.git] / release / src / router / openvpn / ps.c
blob003fb45eaff41bc585e3e213d4c6c9cac9e5481f
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "syshead.h"
27 #if PORT_SHARE
29 #include "event.h"
30 #include "socket.h"
31 #include "fdmisc.h"
32 #include "crypto.h"
33 #include "ps.h"
35 #include "memdbg.h"
37 struct port_share *port_share = NULL; /* GLOBAL */
39 /* size of i/o buffers */
40 #define PROXY_CONNECTION_BUFFER_SIZE 1500
42 /* Command codes for foreground -> background communication */
43 #define COMMAND_REDIRECT 10
44 #define COMMAND_EXIT 11
46 /* Response codes for background -> foreground communication */
47 #define RESPONSE_INIT_SUCCEEDED 20
48 #define RESPONSE_INIT_FAILED 21
51 * Return values for proxy_connection_io functions
54 #define IOSTAT_EAGAIN_ON_READ 0 /* recv returned EAGAIN */
55 #define IOSTAT_EAGAIN_ON_WRITE 1 /* send returned EAGAIN */
56 #define IOSTAT_READ_ERROR 2 /* the other end of our read socket (pc) was closed */
57 #define IOSTAT_WRITE_ERROR 3 /* the other end of our write socket (pc->counterpart) was closed */
58 #define IOSTAT_GOOD 4 /* nothing to report */
61 * A foreign (non-OpenVPN) connection we are proxying,
62 * usually HTTPS
64 struct proxy_connection {
65 bool defined;
66 struct proxy_connection *next;
67 struct proxy_connection *counterpart;
68 struct buffer buf;
69 bool buffer_initial;
70 int rwflags;
71 int sd;
74 #if 0
75 static const char *
76 headc (const struct buffer *buf)
78 static char foo[16];
79 strncpy (foo, BSTR(buf), 15);
80 foo[15] = 0;
81 return foo;
83 #endif
85 static inline void
86 close_socket_if_defined (const socket_descriptor_t sd)
88 if (socket_defined (sd))
89 openvpn_close_socket (sd);
93 * Close most of parent's fds.
94 * Keep stdin/stdout/stderr, plus one
95 * other fd which is presumed to be
96 * our pipe back to parent.
97 * Admittedly, a bit of a kludge,
98 * but posix doesn't give us a kind
99 * of FD_CLOEXEC which will stop
100 * fds from crossing a fork().
102 static void
103 close_fds_except (int keep)
105 socket_descriptor_t i;
106 closelog ();
107 for (i = 3; i <= 100; ++i)
109 if (i != keep)
110 openvpn_close_socket (i);
115 * Usually we ignore signals, because our parent will
116 * deal with them.
118 static void
119 set_signals (void)
121 signal (SIGTERM, SIG_DFL);
123 signal (SIGINT, SIG_IGN);
124 signal (SIGHUP, SIG_IGN);
125 signal (SIGUSR1, SIG_IGN);
126 signal (SIGUSR2, SIG_IGN);
127 signal (SIGPIPE, SIG_IGN);
131 * Socket read/write functions.
134 static int
135 recv_control (const socket_descriptor_t fd)
137 unsigned char c;
138 const ssize_t size = read (fd, &c, sizeof (c));
139 if (size == sizeof (c))
140 return c;
141 else
143 return -1;
147 static int
148 send_control (const socket_descriptor_t fd, int code)
150 unsigned char c = (unsigned char) code;
151 const ssize_t size = write (fd, &c, sizeof (c));
152 if (size == sizeof (c))
153 return (int) size;
154 else
155 return -1;
158 static int
159 cmsg_size ()
161 return CMSG_SPACE(sizeof(socket_descriptor_t));
165 * Send a command (char), data (head), and a file descriptor (sd_send) to a local process
166 * over unix socket sd. Unfortunately, there's no portable way to send file descriptors
167 * to other processes, so this code, as well as its analog (control_message_from_parent below),
168 * is Linux-specific. This function runs in the context of the main process and is used to
169 * send commands, data, and file descriptors to the background process.
171 static void
172 port_share_sendmsg (const socket_descriptor_t sd,
173 const char command,
174 const struct buffer *head,
175 const socket_descriptor_t sd_send)
177 if (socket_defined (sd))
179 struct msghdr mesg;
180 struct cmsghdr* h;
181 struct iovec iov[2];
182 socket_descriptor_t sd_null[2] = { SOCKET_UNDEFINED, SOCKET_UNDEFINED };
183 char cmd;
184 ssize_t status;
186 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE: sendmsg sd=%d len=%d",
187 (int)sd_send,
188 head ? BLEN(head) : -1);
190 CLEAR (mesg);
192 cmd = command;
194 iov[0].iov_base = &cmd;
195 iov[0].iov_len = sizeof (cmd);
196 mesg.msg_iovlen = 1;
198 if (head)
200 iov[1].iov_base = BPTR (head);
201 iov[1].iov_len = BLEN (head);
202 mesg.msg_iovlen = 2;
205 mesg.msg_iov = iov;
207 mesg.msg_controllen = cmsg_size ();
208 mesg.msg_control = (char *) malloc (mesg.msg_controllen);
209 check_malloc_return (mesg.msg_control);
210 mesg.msg_flags = 0;
212 h = CMSG_FIRSTHDR(&mesg);
213 h->cmsg_level = SOL_SOCKET;
214 h->cmsg_type = SCM_RIGHTS;
215 h->cmsg_len = CMSG_LEN(sizeof(socket_descriptor_t));
217 if (socket_defined (sd_send))
219 *((socket_descriptor_t*)CMSG_DATA(h)) = sd_send;
221 else
223 socketpair (PF_UNIX, SOCK_DGRAM, 0, sd_null);
224 *((socket_descriptor_t*)CMSG_DATA(h)) = sd_null[0];
227 status = sendmsg (sd, &mesg, MSG_NOSIGNAL);
228 if (status == -1)
229 msg (M_WARN, "PORT SHARE: sendmsg failed (unable to communicate with background process)");
231 close_socket_if_defined (sd_null[0]);
232 close_socket_if_defined (sd_null[1]);
233 free (mesg.msg_control);
237 static int
238 pc_list_len (struct proxy_connection *pc)
240 int count = 0;
241 while (pc)
243 ++count;
244 pc = pc->next;
246 return count;
249 static void
250 proxy_entry_close_sd (struct proxy_connection *pc, struct event_set *es)
252 if (pc->defined && socket_defined (pc->sd))
254 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: delete sd=%d", (int)pc->sd);
255 if (es)
256 event_del (es, pc->sd);
257 openvpn_close_socket (pc->sd);
258 pc->sd = SOCKET_UNDEFINED;
263 * Mark a proxy entry and its counterpart for close.
265 static void
266 proxy_entry_mark_for_close (struct proxy_connection *pc, struct event_set *es)
268 if (pc->defined)
270 struct proxy_connection *cp = pc->counterpart;
271 proxy_entry_close_sd (pc, es);
272 free_buf (&pc->buf);
273 pc->buffer_initial = false;
274 pc->rwflags = 0;
275 pc->defined = false;
276 if (cp && cp->defined && cp->counterpart == pc)
277 proxy_entry_mark_for_close (cp, es);
282 * Run through the proxy entry list and delete all entries marked
283 * for close.
285 static void
286 proxy_list_housekeeping (struct proxy_connection **list)
288 if (list)
290 struct proxy_connection *prev = NULL;
291 struct proxy_connection *pc = *list;
293 while (pc)
295 struct proxy_connection *next = pc->next;
296 if (!pc->defined)
298 free (pc);
299 if (prev)
300 prev->next = next;
301 else
302 *list = next;
304 else
305 prev = pc;
306 pc = next;
312 * Cleanup function, on proxy process exit.
314 static void
315 proxy_list_close (struct proxy_connection **list)
317 if (list)
319 struct proxy_connection *pc = *list;
320 while (pc)
322 proxy_entry_mark_for_close (pc, NULL);
323 pc = pc->next;
325 proxy_list_housekeeping (list);
329 static void
330 sock_addr_set (struct openvpn_sockaddr *osaddr,
331 const in_addr_t addr,
332 const int port)
334 CLEAR (*osaddr);
335 osaddr->sa.sin_family = AF_INET;
336 osaddr->sa.sin_addr.s_addr = htonl (addr);
337 osaddr->sa.sin_port = htons (port);
340 static inline void
341 proxy_connection_io_requeue (struct proxy_connection *pc, const int rwflags_new, struct event_set *es)
343 if (socket_defined (pc->sd) && pc->rwflags != rwflags_new)
345 /*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: requeue[%d] rwflags=%d", (int)pc->sd, rwflags_new);*/
346 event_ctl (es, pc->sd, rwflags_new, (void*)pc);
347 pc->rwflags = rwflags_new;
352 * Create a new pair of proxy_connection entries, one for each
353 * socket file descriptor involved in the proxy. We are given
354 * the client fd, and we should derive our own server fd by connecting
355 * to the server given by server_addr/server_port. Return true
356 * on success and false on failure to connect to server.
358 static bool
359 proxy_entry_new (struct proxy_connection **list,
360 struct event_set *es,
361 const in_addr_t server_addr,
362 const int server_port,
363 const socket_descriptor_t sd_client,
364 struct buffer *initial_data)
366 struct openvpn_sockaddr osaddr;
367 socket_descriptor_t sd_server;
368 int status;
369 struct proxy_connection *pc;
370 struct proxy_connection *cp;
372 /* connect to port share server */
373 sock_addr_set (&osaddr, server_addr, server_port);
374 sd_server = create_socket_tcp ();
375 status = openvpn_connect (sd_server, &osaddr, 5, NULL);
376 if (status)
378 msg (M_WARN, "PORT SHARE PROXY: connect to port-share server failed");
379 openvpn_close_socket (sd_server);
380 return false;
382 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: connect to port-share server succeeded");
384 set_nonblock (sd_client);
385 set_nonblock (sd_server);
387 /* allocate 2 new proxy_connection objects */
388 ALLOC_OBJ_CLEAR (pc, struct proxy_connection);
389 ALLOC_OBJ_CLEAR (cp, struct proxy_connection);
391 /* client object */
392 pc->defined = true;
393 pc->next = cp;
394 pc->counterpart = cp;
395 pc->buf = *initial_data;
396 pc->buffer_initial = true;
397 pc->rwflags = EVENT_UNDEF;
398 pc->sd = sd_client;
400 /* server object */
401 cp->defined = true;
402 cp->next = *list;
403 cp->counterpart = pc;
404 cp->buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
405 cp->buffer_initial = false;
406 cp->rwflags = EVENT_UNDEF;
407 cp->sd = sd_server;
409 /* add to list */
410 *list = pc;
412 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: NEW CONNECTION [c=%d s=%d]", (int)sd_client, (int)sd_server);
414 /* set initial i/o states */
415 proxy_connection_io_requeue (pc, EVENT_READ, es);
416 proxy_connection_io_requeue (cp, EVENT_READ|EVENT_WRITE, es);
418 return true;
422 * This function runs in the context of the background proxy process.
423 * Receive a control message from the parent (sent by the port_share_sendmsg
424 * function above) and act on it. Return false if the proxy process should
425 * exit, true otherwise.
427 static bool
428 control_message_from_parent (const socket_descriptor_t sd_control,
429 struct proxy_connection **list,
430 struct event_set *es,
431 const in_addr_t server_addr,
432 const int server_port)
434 struct buffer buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
435 struct msghdr mesg;
436 struct cmsghdr* h;
437 struct iovec iov[2];
438 char command = 0;
439 ssize_t status;
440 int ret = true;
442 CLEAR (mesg);
444 iov[0].iov_base = &command;
445 iov[0].iov_len = sizeof (command);
446 iov[1].iov_base = BPTR (&buf);
447 iov[1].iov_len = BCAP (&buf);
448 mesg.msg_iov = iov;
449 mesg.msg_iovlen = 2;
451 mesg.msg_controllen = cmsg_size ();
452 mesg.msg_control = (char *) malloc (mesg.msg_controllen);
453 check_malloc_return (mesg.msg_control);
454 mesg.msg_flags = 0;
456 h = CMSG_FIRSTHDR(&mesg);
457 h->cmsg_len = CMSG_LEN(sizeof(socket_descriptor_t));
458 h->cmsg_level = SOL_SOCKET;
459 h->cmsg_type = SCM_RIGHTS;
460 *((socket_descriptor_t*)CMSG_DATA(h)) = SOCKET_UNDEFINED;
462 status = recvmsg (sd_control, &mesg, MSG_NOSIGNAL);
463 if (status != -1)
465 if ( h == NULL
466 || h->cmsg_len != CMSG_LEN(sizeof(socket_descriptor_t))
467 || h->cmsg_level != SOL_SOCKET
468 || h->cmsg_type != SCM_RIGHTS )
470 ret = false;
472 else
474 const socket_descriptor_t received_fd = *((socket_descriptor_t*)CMSG_DATA(h));
475 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: RECEIVED sd=%d", (int)received_fd);
477 if (status >= 2 && command == COMMAND_REDIRECT)
479 buf.len = status - 1;
480 if (proxy_entry_new (list,
482 server_addr,
483 server_port,
484 received_fd,
485 &buf))
487 CLEAR (buf); /* we gave the buffer to proxy_entry_new */
489 else
491 openvpn_close_socket (received_fd);
494 else if (status >= 1 && command == COMMAND_EXIT)
496 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: RECEIVED COMMAND_EXIT");
497 openvpn_close_socket (received_fd); /* null socket */
498 ret = false;
502 free (mesg.msg_control);
503 free_buf (&buf);
504 return ret;
507 static int
508 proxy_connection_io_recv (struct proxy_connection *pc)
510 /* recv data from socket */
511 const int status = recv (pc->sd, BPTR(&pc->buf), BCAP(&pc->buf), MSG_NOSIGNAL);
512 if (status < 0)
514 return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
516 else
518 if (!status)
519 return IOSTAT_READ_ERROR;
520 pc->buf.len = status;
522 return IOSTAT_GOOD;
525 static int
526 proxy_connection_io_send (struct proxy_connection *pc, int *bytes_sent)
528 const socket_descriptor_t sd = pc->counterpart->sd;
529 const int status = send (sd, BPTR(&pc->buf), BLEN(&pc->buf), MSG_NOSIGNAL);
531 if (status < 0)
533 const int e = errno;
534 return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_WRITE_ERROR;
536 else
538 *bytes_sent += status;
539 if (status != pc->buf.len)
541 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: partial write[%d], tried=%d got=%d", (int)sd, pc->buf.len, status);
542 buf_advance (&pc->buf, status);
543 return IOSTAT_EAGAIN_ON_WRITE;
545 else
547 /*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: wrote[%d] %d", (int)sd, status);*/
548 pc->buf.len = 0;
549 pc->buf.offset = 0;
553 /* realloc send buffer after initial send */
554 if (pc->buffer_initial)
556 free_buf (&pc->buf);
557 pc->buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
558 pc->buffer_initial = false;
560 return IOSTAT_GOOD;
564 * Forward data from pc to pc->counterpart.
567 static int
568 proxy_connection_io_xfer (struct proxy_connection *pc, const int max_transfer)
570 int transferred = 0;
571 while (transferred < max_transfer)
573 if (!BLEN (&pc->buf))
575 const int status = proxy_connection_io_recv (pc);
576 if (status != IOSTAT_GOOD)
577 return status;
580 if (BLEN (&pc->buf))
582 const int status = proxy_connection_io_send (pc, &transferred);
583 if (status != IOSTAT_GOOD)
584 return status;
587 return IOSTAT_EAGAIN_ON_READ;
591 * Decide how the receipt of an EAGAIN status should affect our next IO queueing.
593 static bool
594 proxy_connection_io_status (const int status, int *rwflags_pc, int *rwflags_cp)
596 switch (status)
598 case IOSTAT_EAGAIN_ON_READ:
599 *rwflags_pc |= EVENT_READ;
600 *rwflags_cp &= ~EVENT_WRITE;
601 return true;
602 case IOSTAT_EAGAIN_ON_WRITE:
603 *rwflags_pc &= ~EVENT_READ;
604 *rwflags_cp |= EVENT_WRITE;
605 return true;
606 case IOSTAT_READ_ERROR:
607 return false;
608 case IOSTAT_WRITE_ERROR:
609 return false;
610 default:
611 msg (M_FATAL, "PORT SHARE PROXY: unexpected status=%d", status);
613 return false; /* NOTREACHED */
617 * Dispatch function for forwarding data between the two socket fds involved
618 * in the proxied connection.
620 static int
621 proxy_connection_io_dispatch (struct proxy_connection *pc,
622 const int rwflags,
623 struct event_set *es)
625 const int max_transfer_per_iteration = 10000;
626 struct proxy_connection *cp = pc->counterpart;
627 int rwflags_pc = pc->rwflags;
628 int rwflags_cp = cp->rwflags;
630 if (rwflags & EVENT_READ)
632 const int status = proxy_connection_io_xfer (pc, max_transfer_per_iteration);
633 if (!proxy_connection_io_status (status, &rwflags_pc, &rwflags_cp))
634 goto bad;
636 if (rwflags & EVENT_WRITE)
638 const int status = proxy_connection_io_xfer (cp, max_transfer_per_iteration);
639 if (!proxy_connection_io_status (status, &rwflags_cp, &rwflags_pc))
640 goto bad;
642 proxy_connection_io_requeue (pc, rwflags_pc, es);
643 proxy_connection_io_requeue (cp, rwflags_cp, es);
645 return true;
647 bad:
648 proxy_entry_mark_for_close (pc, es);
649 return false;
653 * This is the main function for the port share proxy background process.
655 static void
656 port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descriptor_t sd_control)
658 if (send_control (sd_control, RESPONSE_INIT_SUCCEEDED) >= 0)
660 void *sd_control_marker = (void *)1;
661 int maxevents = 256;
662 struct event_set *es;
663 struct event_set_return esr[64];
664 struct proxy_connection *list = NULL;
665 time_t last_housekeeping = 0;
667 msg (D_PS_PROXY, "PORT SHARE PROXY: proxy starting");
669 es = event_set_init (&maxevents, 0);
670 event_ctl (es, sd_control, EVENT_READ, sd_control_marker);
671 while (true)
673 int n_events;
674 struct timeval tv;
675 time_t current;
677 tv.tv_sec = 10;
678 tv.tv_usec = 0;
679 n_events = event_wait (es, &tv, esr, SIZE(esr));
680 /*dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: event_wait returned %d", n_events);*/
681 current = time(NULL);
682 if (n_events > 0)
684 int i;
685 for (i = 0; i < n_events; ++i)
687 const struct event_set_return *e = &esr[i];
688 if (e->arg == sd_control_marker)
690 if (!control_message_from_parent (sd_control, &list, es, hostaddr, port))
691 goto done;
693 else
695 struct proxy_connection *pc = (struct proxy_connection *)e->arg;
696 if (pc->defined)
697 proxy_connection_io_dispatch (pc, e->rwflags, es);
701 else if (n_events < 0)
703 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: event_wait failed");
705 if (current > last_housekeeping)
707 proxy_list_housekeeping (&list);
708 last_housekeeping = current;
712 done:
713 proxy_list_close (&list);
714 event_free (es);
716 msg (D_PS_PROXY, "PORT SHARE PROXY: proxy exiting");
720 * Called from the main OpenVPN process to enable the port
721 * share proxy.
723 struct port_share *
724 port_share_open (const char *host, const int port)
726 pid_t pid;
727 socket_descriptor_t fd[2];
728 in_addr_t hostaddr;
729 struct port_share *ps;
731 ALLOC_OBJ_CLEAR (ps, struct port_share);
734 * Get host's IP address
736 hostaddr = getaddr (GETADDR_RESOLVE|GETADDR_HOST_ORDER|GETADDR_FATAL, host, 0, NULL, NULL);
739 * Make a socket for foreground and background processes
740 * to communicate.
742 if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
744 msg (M_WARN, "PORT SHARE: socketpair call failed");
745 goto error;
749 * Fork off background proxy process.
751 pid = fork ();
753 if (pid)
755 int status;
758 * Foreground Process
761 ps->background_pid = pid;
763 /* close our copy of child's socket */
764 openvpn_close_socket (fd[1]);
766 /* don't let future subprocesses inherit child socket */
767 set_cloexec (fd[0]);
769 /* wait for background child process to initialize */
770 status = recv_control (fd[0]);
771 if (status == RESPONSE_INIT_SUCCEEDED)
773 ps->foreground_fd = fd[0];
774 return ps;
777 else
780 * Background Process
783 /* Ignore most signals (the parent will receive them) */
784 set_signals ();
786 /* Let msg know that we forked */
787 msg_forked ();
789 /* close all parent fds except our socket back to parent */
790 close_fds_except (fd[1]);
792 /* no blocking on control channel back to parent */
793 set_nonblock (fd[1]);
795 /* initialize prng */
796 prng_init (NULL, 0);
798 /* execute the event loop */
799 port_share_proxy (hostaddr, port, fd[1]);
801 openvpn_close_socket (fd[1]);
803 exit (0);
804 return 0; /* NOTREACHED */
807 error:
808 port_share_close (ps);
809 return NULL;
812 void
813 port_share_close (struct port_share *ps)
815 if (ps)
817 if (ps->foreground_fd >= 0)
819 /* tell background process to exit */
820 port_share_sendmsg (ps->foreground_fd, COMMAND_EXIT, NULL, SOCKET_UNDEFINED);
822 /* wait for background process to exit */
823 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE: waiting for background process to exit");
824 if (ps->background_pid > 0)
825 waitpid (ps->background_pid, NULL, 0);
826 dmsg (D_PS_PROXY_DEBUG, "PORT SHARE: background process exited");
828 openvpn_close_socket (ps->foreground_fd);
829 ps->foreground_fd = -1;
832 free (ps);
836 void
837 port_share_abort (struct port_share *ps)
839 if (ps)
841 /* tell background process to exit */
842 if (ps->foreground_fd >= 0)
844 send_control (ps->foreground_fd, COMMAND_EXIT);
845 openvpn_close_socket (ps->foreground_fd);
846 ps->foreground_fd = -1;
852 * Given either the first 2 or 3 bytes of an initial client -> server
853 * data payload, return true if the protocol is that of an OpenVPN
854 * client attempting to connect with an OpenVPN server.
856 bool
857 is_openvpn_protocol (const struct buffer *buf)
859 const unsigned char *p = (const unsigned char *) BSTR (buf);
860 const int len = BLEN (buf);
861 if (len >= 3)
863 return p[0] == 0
864 && p[1] >= 14
865 && p[2] == (P_CONTROL_HARD_RESET_CLIENT_V2<<P_OPCODE_SHIFT);
867 else if (len >= 2)
869 return p[0] == 0 && p[1] >= 14;
871 else
872 return true;
876 * Called from the foreground process. Send a message to the background process that it
877 * should proxy the TCP client on sd to the host/port defined in the initial port_share_open
878 * call.
880 void
881 port_share_redirect (struct port_share *ps, const struct buffer *head, socket_descriptor_t sd)
883 if (ps)
884 port_share_sendmsg (ps->foreground_fd, COMMAND_REDIRECT, head, sd);
887 #endif