~ubuntu-branches/ubuntu/saucy/openvpn/saucy

« back to all changes in this revision

Viewing changes to .pc/jjo-ipv6-support.patch/ps.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2010-05-05 03:06:19 UTC
  • mfrom: (10.2.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100505030619-cwre0snhgx1mql53
Tags: 2.1.0-2ubuntu1
* Merge from debian unstable.  Remaining changes:
  + debian/openvpn.init.d:
    - Do not use start-stop-daemon and use </dev/null to avoid blocking boot
    - Show per-VPN result messages
    - Add "--script-security 2" by default for backwards compatablitiy
   + debian/control: Add lsb-base >= 3.2-14 to allow status_of_proc() 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
7
 *
 
8
 *  Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
 
9
 *
 
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.
 
13
 *
 
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.
 
18
 *
 
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
 
23
 */
 
24
 
 
25
#include "syshead.h"
 
26
 
 
27
#if PORT_SHARE
 
28
 
 
29
#include "event.h"
 
30
#include "socket.h"
 
31
#include "fdmisc.h"
 
32
#include "crypto.h"
 
33
#include "ps.h"
 
34
 
 
35
#include "memdbg.h"
 
36
 
 
37
struct port_share *port_share = NULL; /* GLOBAL */
 
38
 
 
39
/* size of i/o buffers */
 
40
#define PROXY_CONNECTION_BUFFER_SIZE 1500
 
41
 
 
42
/* Command codes for foreground -> background communication */
 
43
#define COMMAND_REDIRECT 10
 
44
#define COMMAND_EXIT     11
 
45
 
 
46
/* Response codes for background -> foreground communication */
 
47
#define RESPONSE_INIT_SUCCEEDED   20
 
48
#define RESPONSE_INIT_FAILED      21
 
49
 
 
50
/*
 
51
 * Return values for proxy_connection_io functions
 
52
 */
 
53
 
 
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 */
 
59
 
 
60
/*
 
61
 * A foreign (non-OpenVPN) connection we are proxying,
 
62
 * usually HTTPS
 
63
 */
 
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;
 
72
};
 
73
 
 
74
#if 0
 
75
static const char *
 
76
headc (const struct buffer *buf)
 
77
{
 
78
  static char foo[16];
 
79
  strncpy (foo, BSTR(buf), 15);
 
80
  foo[15] = 0;
 
81
  return foo;
 
82
}
 
83
#endif
 
84
 
 
85
static inline void
 
86
close_socket_if_defined (const socket_descriptor_t sd)
 
87
{
 
88
  if (socket_defined (sd))
 
89
    openvpn_close_socket (sd);
 
90
}
 
91
 
 
92
/*
 
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().
 
101
 */
 
102
static void
 
103
close_fds_except (int keep)
 
104
{
 
105
  socket_descriptor_t i;
 
106
  closelog ();
 
107
  for (i = 3; i <= 100; ++i)
 
108
    {
 
109
      if (i != keep)
 
110
        openvpn_close_socket (i);
 
111
    }
 
112
}
 
113
 
 
114
/*
 
115
 * Usually we ignore signals, because our parent will
 
116
 * deal with them.
 
117
 */
 
118
static void
 
119
set_signals (void)
 
120
{
 
121
  signal (SIGTERM, SIG_DFL);
 
122
 
 
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);
 
128
}
 
129
 
 
130
/*
 
131
 * Socket read/write functions.
 
132
 */
 
133
 
 
134
static int
 
135
recv_control (const socket_descriptor_t fd)
 
136
{
 
137
  unsigned char c;
 
138
  const ssize_t size = read (fd, &c, sizeof (c));
 
139
  if (size == sizeof (c))
 
140
    return c;
 
141
  else
 
142
    {
 
143
      return -1;
 
144
    }
 
145
}
 
146
 
 
147
static int
 
148
send_control (const socket_descriptor_t fd, int code)
 
149
{
 
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;
 
156
}
 
157
 
 
158
static int
 
159
cmsg_size ()
 
160
{
 
161
  return CMSG_SPACE(sizeof(socket_descriptor_t));
 
162
}
 
163
 
 
164
/*
 
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.
 
170
 */
 
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)
 
176
{
 
177
  if (socket_defined (sd))
 
178
    {
 
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;
 
185
 
 
186
      dmsg (D_PS_PROXY_DEBUG, "PORT SHARE: sendmsg sd=%d len=%d",
 
187
            (int)sd_send,
 
188
            head ? BLEN(head) : -1);
 
189
 
 
190
      CLEAR (mesg);
 
191
 
 
192
      cmd = command;
 
193
 
 
194
      iov[0].iov_base = &cmd;
 
195
      iov[0].iov_len = sizeof (cmd);
 
196
      mesg.msg_iovlen = 1;
 
197
 
 
198
      if (head)
 
199
        {
 
200
          iov[1].iov_base = BPTR (head);
 
201
          iov[1].iov_len = BLEN (head);
 
202
          mesg.msg_iovlen = 2;
 
203
        }
 
204
 
 
205
      mesg.msg_iov = iov;
 
206
 
 
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;
 
211
 
 
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));
 
216
 
 
217
      if (socket_defined (sd_send))
 
218
        {
 
219
          *((socket_descriptor_t*)CMSG_DATA(h)) = sd_send;
 
220
        }
 
221
      else
 
222
        {
 
223
          socketpair (PF_UNIX, SOCK_DGRAM, 0, sd_null);
 
224
          *((socket_descriptor_t*)CMSG_DATA(h)) = sd_null[0];
 
225
        }
 
226
 
 
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)");
 
230
 
 
231
      close_socket_if_defined (sd_null[0]);
 
232
      close_socket_if_defined (sd_null[1]);
 
233
      free (mesg.msg_control);
 
234
    }
 
235
}
 
236
 
 
237
static int
 
238
pc_list_len (struct proxy_connection *pc)
 
239
{
 
240
  int count = 0;
 
241
  while (pc)
 
242
    {
 
243
      ++count;
 
244
      pc = pc->next;
 
245
    }
 
246
  return count;
 
247
}
 
248
 
 
249
static void
 
250
proxy_entry_close_sd (struct proxy_connection *pc, struct event_set *es)
 
251
{
 
252
  if (pc->defined && socket_defined (pc->sd))
 
253
    {
 
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;
 
259
    }
 
260
}
 
261
 
 
262
/*
 
263
 * Mark a proxy entry and its counterpart for close.
 
264
 */
 
265
static void
 
266
proxy_entry_mark_for_close (struct proxy_connection *pc, struct event_set *es)
 
267
{
 
268
  if (pc->defined)
 
269
    {
 
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);
 
278
    }
 
279
}
 
280
 
 
281
/*
 
282
 * Run through the proxy entry list and delete all entries marked
 
283
 * for close.
 
284
 */
 
285
static void
 
286
proxy_list_housekeeping (struct proxy_connection **list)
 
287
{
 
288
  if (list)
 
289
    {
 
290
      struct proxy_connection *prev = NULL;
 
291
      struct proxy_connection *pc = *list;
 
292
 
 
293
      while (pc)
 
294
        {
 
295
          struct proxy_connection *next = pc->next;
 
296
          if (!pc->defined)
 
297
            {
 
298
              free (pc);
 
299
              if (prev)
 
300
                prev->next = next;
 
301
              else
 
302
                *list = next;
 
303
            }
 
304
          else
 
305
            prev = pc;
 
306
          pc = next;
 
307
        }
 
308
    }
 
309
}
 
310
 
 
311
/*
 
312
 * Cleanup function, on proxy process exit.
 
313
 */
 
314
static void
 
315
proxy_list_close (struct proxy_connection **list)
 
316
{
 
317
  if (list)
 
318
    {
 
319
      struct proxy_connection *pc = *list;
 
320
      while (pc)
 
321
        {
 
322
          proxy_entry_mark_for_close (pc, NULL);
 
323
          pc = pc->next;
 
324
        }
 
325
      proxy_list_housekeeping (list);
 
326
    }
 
327
}
 
328
 
 
329
static void
 
330
sock_addr_set (struct openvpn_sockaddr *osaddr,
 
331
               const in_addr_t addr,
 
332
               const int port)
 
333
{
 
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);
 
338
}
 
339
 
 
340
static inline void
 
341
proxy_connection_io_requeue (struct proxy_connection *pc, const int rwflags_new, struct event_set *es)
 
342
{
 
343
  if (socket_defined (pc->sd) && pc->rwflags != rwflags_new)
 
344
    {
 
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;
 
348
    }
 
349
}
 
350
 
 
351
/*
 
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.
 
357
 */
 
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)
 
365
{
 
366
  struct openvpn_sockaddr osaddr;
 
367
  socket_descriptor_t sd_server;
 
368
  int status;
 
369
  struct proxy_connection *pc;
 
370
  struct proxy_connection *cp;
 
371
 
 
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)
 
377
    {
 
378
      msg (M_WARN, "PORT SHARE PROXY: connect to port-share server failed");
 
379
      openvpn_close_socket (sd_server);
 
380
      return false;
 
381
    }
 
382
  dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: connect to port-share server succeeded");
 
383
 
 
384
  set_nonblock (sd_client);
 
385
  set_nonblock (sd_server);
 
386
 
 
387
  /* allocate 2 new proxy_connection objects */
 
388
  ALLOC_OBJ_CLEAR (pc, struct proxy_connection);
 
389
  ALLOC_OBJ_CLEAR (cp, struct proxy_connection);
 
390
 
 
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;
 
399
 
 
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;
 
408
 
 
409
  /* add to list */
 
410
  *list = pc;
 
411
  
 
412
  dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: NEW CONNECTION [c=%d s=%d]", (int)sd_client, (int)sd_server);
 
413
 
 
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);
 
417
  
 
418
  return true;
 
419
}
 
420
 
 
421
/*
 
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.
 
426
 */
 
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)
 
433
{
 
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;
 
441
 
 
442
  CLEAR (mesg);
 
443
 
 
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;
 
450
 
 
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;
 
455
 
 
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;
 
461
 
 
462
  status = recvmsg (sd_control, &mesg, MSG_NOSIGNAL);
 
463
  if (status != -1)
 
464
    {
 
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 )
 
469
        {
 
470
          ret = false;
 
471
        }
 
472
      else
 
473
        {
 
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);
 
476
 
 
477
          if (status >= 2 && command == COMMAND_REDIRECT)
 
478
            {
 
479
              buf.len = status - 1;
 
480
              if (proxy_entry_new (list,
 
481
                                   es,
 
482
                                   server_addr,
 
483
                                   server_port,
 
484
                                   received_fd,
 
485
                                   &buf))
 
486
                {
 
487
                  CLEAR (buf); /* we gave the buffer to proxy_entry_new */
 
488
                }
 
489
              else
 
490
                {
 
491
                  openvpn_close_socket (received_fd);
 
492
                }
 
493
            }
 
494
          else if (status >= 1 && command == COMMAND_EXIT)
 
495
            {
 
496
              dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: RECEIVED COMMAND_EXIT");
 
497
              openvpn_close_socket (received_fd); /* null socket */
 
498
              ret = false;
 
499
            }
 
500
        }
 
501
    }
 
502
  free (mesg.msg_control);
 
503
  free_buf (&buf);
 
504
  return ret;
 
505
}
 
506
 
 
507
static int
 
508
proxy_connection_io_recv (struct proxy_connection *pc)
 
509
{
 
510
  /* recv data from socket */
 
511
  const int status = recv (pc->sd, BPTR(&pc->buf), BCAP(&pc->buf), MSG_NOSIGNAL);
 
512
  if (status < 0)
 
513
    {
 
514
      return (errno == EAGAIN) ? IOSTAT_EAGAIN_ON_READ : IOSTAT_READ_ERROR;
 
515
    }
 
516
  else
 
517
    {
 
518
      if (!status)
 
519
        return IOSTAT_READ_ERROR;
 
520
      pc->buf.len = status;
 
521
    }
 
522
  return IOSTAT_GOOD;
 
523
}
 
524
 
 
525
static int
 
526
proxy_connection_io_send (struct proxy_connection *pc, int *bytes_sent)
 
527
{
 
528
  const socket_descriptor_t sd = pc->counterpart->sd;
 
529
  const int status = send (sd, BPTR(&pc->buf), BLEN(&pc->buf), MSG_NOSIGNAL);
 
530
 
 
531
  if (status < 0)
 
532
    {
 
533
      const int e = errno;
 
534
      return (e == EAGAIN) ? IOSTAT_EAGAIN_ON_WRITE : IOSTAT_WRITE_ERROR;
 
535
    }
 
536
  else
 
537
    {
 
538
      *bytes_sent += status;
 
539
      if (status != pc->buf.len)
 
540
        {
 
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;
 
544
        }
 
545
      else
 
546
        {
 
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;
 
550
        }
 
551
    }
 
552
 
 
553
  /* realloc send buffer after initial send */
 
554
  if (pc->buffer_initial)
 
555
    {
 
556
      free_buf (&pc->buf);
 
557
      pc->buf = alloc_buf (PROXY_CONNECTION_BUFFER_SIZE);
 
558
      pc->buffer_initial = false;
 
559
    }
 
560
  return IOSTAT_GOOD;
 
561
}
 
562
 
 
563
/*
 
564
 * Forward data from pc to pc->counterpart.
 
565
 */
 
566
 
 
567
static int
 
568
proxy_connection_io_xfer (struct proxy_connection *pc, const int max_transfer)
 
569
{
 
570
  int transferred = 0;
 
571
  while (transferred < max_transfer)
 
572
    {
 
573
      if (!BLEN (&pc->buf))
 
574
        {
 
575
          const int status = proxy_connection_io_recv (pc);
 
576
          if (status != IOSTAT_GOOD)
 
577
            return status;
 
578
        }
 
579
 
 
580
      if (BLEN (&pc->buf))
 
581
        {
 
582
          const int status = proxy_connection_io_send (pc, &transferred);
 
583
          if (status != IOSTAT_GOOD)
 
584
            return status;
 
585
        }
 
586
    }
 
587
  return IOSTAT_EAGAIN_ON_READ;
 
588
}
 
589
 
 
590
/*
 
591
 * Decide how the receipt of an EAGAIN status should affect our next IO queueing.
 
592
 */
 
593
static bool
 
594
proxy_connection_io_status (const int status, int *rwflags_pc, int *rwflags_cp)
 
595
{
 
596
  switch (status)
 
597
    {
 
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);
 
612
    }
 
613
  return false; /* NOTREACHED */
 
614
}
 
615
 
 
616
/*
 
617
 * Dispatch function for forwarding data between the two socket fds involved
 
618
 * in the proxied connection.
 
619
 */
 
620
static int
 
621
proxy_connection_io_dispatch (struct proxy_connection *pc,
 
622
                              const int rwflags,
 
623
                              struct event_set *es)
 
624
{
 
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;
 
629
 
 
630
  if (rwflags & EVENT_READ)
 
631
    {
 
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;
 
635
    }
 
636
  if (rwflags & EVENT_WRITE)
 
637
    {
 
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;
 
641
    }
 
642
  proxy_connection_io_requeue (pc, rwflags_pc, es);
 
643
  proxy_connection_io_requeue (cp, rwflags_cp, es);
 
644
 
 
645
  return true;
 
646
 
 
647
 bad:
 
648
  proxy_entry_mark_for_close (pc, es);
 
649
  return false;
 
650
}
 
651
 
 
652
/*
 
653
 * This is the main function for the port share proxy background process.
 
654
 */
 
655
static void
 
656
port_share_proxy (const in_addr_t hostaddr, const int port, const socket_descriptor_t sd_control)
 
657
{
 
658
  if (send_control (sd_control, RESPONSE_INIT_SUCCEEDED) >= 0)
 
659
    {
 
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;
 
666
 
 
667
      msg (D_PS_PROXY, "PORT SHARE PROXY: proxy starting");
 
668
 
 
669
      es = event_set_init (&maxevents, 0);
 
670
      event_ctl (es, sd_control, EVENT_READ, sd_control_marker);
 
671
      while (true)
 
672
        {
 
673
          int n_events;
 
674
          struct timeval tv;
 
675
          time_t current;
 
676
 
 
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)
 
683
            {
 
684
              int i;
 
685
              for (i = 0; i < n_events; ++i)
 
686
                {
 
687
                  const struct event_set_return *e = &esr[i];
 
688
                  if (e->arg == sd_control_marker)
 
689
                    {
 
690
                      if (!control_message_from_parent (sd_control, &list, es, hostaddr, port))
 
691
                        goto done;
 
692
                    }
 
693
                  else
 
694
                    {
 
695
                      struct proxy_connection *pc = (struct proxy_connection *)e->arg;
 
696
                      if (pc->defined)
 
697
                        proxy_connection_io_dispatch (pc, e->rwflags, es);
 
698
                    }
 
699
                }
 
700
            }
 
701
          else if (n_events < 0)
 
702
            {
 
703
              dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: event_wait failed");
 
704
            }
 
705
          if (current > last_housekeeping)
 
706
            {
 
707
              proxy_list_housekeeping (&list);
 
708
              last_housekeeping = current;
 
709
            }
 
710
        }
 
711
 
 
712
    done:
 
713
      proxy_list_close (&list);
 
714
      event_free (es);
 
715
    }
 
716
  msg (D_PS_PROXY, "PORT SHARE PROXY: proxy exiting");
 
717
}
 
718
 
 
719
/*
 
720
 * Called from the main OpenVPN process to enable the port
 
721
 * share proxy.
 
722
 */
 
723
struct port_share *
 
724
port_share_open (const char *host, const int port)
 
725
{
 
726
  pid_t pid;
 
727
  socket_descriptor_t fd[2];
 
728
  in_addr_t hostaddr;
 
729
  struct port_share *ps;
 
730
 
 
731
  ALLOC_OBJ_CLEAR (ps, struct port_share);
 
732
 
 
733
  /*
 
734
   * Get host's IP address
 
735
   */
 
736
  hostaddr = getaddr (GETADDR_RESOLVE|GETADDR_HOST_ORDER|GETADDR_FATAL, host, 0, NULL, NULL);
 
737
 
 
738
  /*
 
739
   * Make a socket for foreground and background processes
 
740
   * to communicate.
 
741
   */
 
742
  if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
 
743
    {
 
744
      msg (M_WARN, "PORT SHARE: socketpair call failed");
 
745
      goto error;
 
746
    }
 
747
 
 
748
  /*
 
749
   * Fork off background proxy process.
 
750
   */
 
751
  pid = fork ();
 
752
 
 
753
  if (pid)
 
754
    {
 
755
      int status;
 
756
 
 
757
      /*
 
758
       * Foreground Process
 
759
       */
 
760
 
 
761
      ps->background_pid = pid;
 
762
 
 
763
      /* close our copy of child's socket */
 
764
      openvpn_close_socket (fd[1]);
 
765
 
 
766
      /* don't let future subprocesses inherit child socket */
 
767
      set_cloexec (fd[0]);
 
768
 
 
769
      /* wait for background child process to initialize */
 
770
      status = recv_control (fd[0]);
 
771
      if (status == RESPONSE_INIT_SUCCEEDED)
 
772
        {
 
773
          ps->foreground_fd = fd[0];
 
774
          return ps;
 
775
        }
 
776
    }
 
777
  else
 
778
    {
 
779
      /*
 
780
       * Background Process
 
781
       */
 
782
 
 
783
      /* Ignore most signals (the parent will receive them) */
 
784
      set_signals ();
 
785
 
 
786
      /* Let msg know that we forked */
 
787
      msg_forked ();
 
788
 
 
789
      /* close all parent fds except our socket back to parent */
 
790
      close_fds_except (fd[1]);
 
791
 
 
792
      /* no blocking on control channel back to parent */
 
793
      set_nonblock (fd[1]);
 
794
 
 
795
      /* initialize prng */
 
796
      prng_init (NULL, 0);
 
797
 
 
798
      /* execute the event loop */
 
799
      port_share_proxy (hostaddr, port, fd[1]);
 
800
 
 
801
      openvpn_close_socket (fd[1]);
 
802
 
 
803
      exit (0);
 
804
      return 0; /* NOTREACHED */
 
805
    }
 
806
 
 
807
 error:
 
808
  port_share_close (ps);
 
809
  return NULL;
 
810
}
 
811
 
 
812
void
 
813
port_share_close (struct port_share *ps)
 
814
{
 
815
  if (ps)
 
816
    {
 
817
      if (ps->foreground_fd >= 0)
 
818
        {
 
819
          /* tell background process to exit */
 
820
          port_share_sendmsg (ps->foreground_fd, COMMAND_EXIT, NULL, SOCKET_UNDEFINED);
 
821
 
 
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");
 
827
 
 
828
          openvpn_close_socket (ps->foreground_fd);
 
829
          ps->foreground_fd = -1;
 
830
        }
 
831
 
 
832
      free (ps);
 
833
    }
 
834
}
 
835
 
 
836
void
 
837
port_share_abort (struct port_share *ps)
 
838
{
 
839
  if (ps)
 
840
    {
 
841
      /* tell background process to exit */
 
842
      if (ps->foreground_fd >= 0)
 
843
        {
 
844
          send_control (ps->foreground_fd, COMMAND_EXIT);
 
845
          openvpn_close_socket (ps->foreground_fd);
 
846
          ps->foreground_fd = -1;
 
847
        }
 
848
    }
 
849
}
 
850
 
 
851
/*
 
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.
 
855
 */
 
856
bool
 
857
is_openvpn_protocol (const struct buffer *buf)
 
858
{
 
859
  const unsigned char *p = (const unsigned char *) BSTR (buf);
 
860
  const int len = BLEN (buf);
 
861
  if (len >= 3)
 
862
    {
 
863
      return p[0] == 0
 
864
        && p[1] >= 14
 
865
        && p[2] == (P_CONTROL_HARD_RESET_CLIENT_V2<<P_OPCODE_SHIFT);
 
866
    }
 
867
  else if (len >= 2)
 
868
    {
 
869
      return p[0] == 0 && p[1] >= 14;
 
870
    }
 
871
  else
 
872
    return true;
 
873
}
 
874
 
 
875
/*
 
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.
 
879
 */
 
880
void
 
881
port_share_redirect (struct port_share *ps, const struct buffer *head, socket_descriptor_t sd)
 
882
{
 
883
  if (ps)
 
884
    port_share_sendmsg (ps->foreground_fd, COMMAND_REDIRECT, head, sd);
 
885
}
 
886
 
 
887
#endif