~ubuntu-branches/ubuntu/trusty/openvpn/trusty-security

« back to all changes in this revision

Viewing changes to .pc/jjo-ipv6-support.patch/mtcp.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 TCP/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 P2MP_SERVER
 
28
 
 
29
#include "multi.h"
 
30
#include "forward-inline.h"
 
31
 
 
32
#include "memdbg.h"
 
33
 
 
34
/*
 
35
 * TCP States
 
36
 */
 
37
#define TA_UNDEF                 0
 
38
#define TA_SOCKET_READ           1
 
39
#define TA_SOCKET_READ_RESIDUAL  2
 
40
#define TA_SOCKET_WRITE          3
 
41
#define TA_SOCKET_WRITE_READY    4
 
42
#define TA_SOCKET_WRITE_DEFERRED 5
 
43
#define TA_TUN_READ              6
 
44
#define TA_TUN_WRITE             7
 
45
#define TA_INITIAL               8
 
46
#define TA_TIMEOUT               9
 
47
#define TA_TUN_WRITE_TIMEOUT     10
 
48
 
 
49
/*
 
50
 * Special tags passed to event.[ch] functions
 
51
 */
 
52
#define MTCP_SOCKET      ((void*)1)
 
53
#define MTCP_TUN         ((void*)2)
 
54
#define MTCP_SIG         ((void*)3) /* Only on Windows */
 
55
#ifdef ENABLE_MANAGEMENT
 
56
# define MTCP_MANAGEMENT ((void*)4)
 
57
#endif
 
58
 
 
59
#define MTCP_N           ((void*)16) /* upper bound on MTCP_x */
 
60
 
 
61
struct ta_iow_flags
 
62
{
 
63
  unsigned int flags;
 
64
  unsigned int ret;
 
65
  unsigned int tun;
 
66
  unsigned int sock;
 
67
};
 
68
 
 
69
static const char *
 
70
pract (int action)
 
71
{
 
72
  switch (action)
 
73
    {
 
74
    case TA_UNDEF:
 
75
      return "TA_UNDEF";
 
76
    case TA_SOCKET_READ:
 
77
      return "TA_SOCKET_READ";
 
78
    case TA_SOCKET_READ_RESIDUAL:
 
79
      return "TA_SOCKET_READ_RESIDUAL";
 
80
    case TA_SOCKET_WRITE:
 
81
      return "TA_SOCKET_WRITE";
 
82
    case TA_SOCKET_WRITE_READY:
 
83
      return "TA_SOCKET_WRITE_READY";
 
84
    case TA_SOCKET_WRITE_DEFERRED:
 
85
      return "TA_SOCKET_WRITE_DEFERRED";
 
86
    case TA_TUN_READ:
 
87
      return "TA_TUN_READ";
 
88
    case TA_TUN_WRITE:
 
89
      return "TA_TUN_WRITE";
 
90
    case TA_INITIAL:
 
91
      return "TA_INITIAL";
 
92
    case TA_TIMEOUT:
 
93
      return "TA_TIMEOUT";
 
94
    case TA_TUN_WRITE_TIMEOUT:
 
95
      return "TA_TUN_WRITE_TIMEOUT";
 
96
    default:
 
97
      return "?";
 
98
    }
 
99
}
 
100
 
 
101
static struct multi_instance *
 
102
multi_create_instance_tcp (struct multi_context *m)
 
103
{
 
104
  struct gc_arena gc = gc_new ();
 
105
  struct multi_instance *mi = NULL;
 
106
  struct hash *hash = m->hash;
 
107
 
 
108
  mi = multi_create_instance (m, NULL);
 
109
  if (mi)
 
110
    {
 
111
      struct hash_element *he;
 
112
      const uint32_t hv = hash_value (hash, &mi->real);
 
113
      struct hash_bucket *bucket = hash_bucket (hash, hv);
 
114
  
 
115
      hash_bucket_lock (bucket);
 
116
      he = hash_lookup_fast (hash, bucket, &mi->real, hv);
 
117
 
 
118
      if (he)
 
119
        {
 
120
          struct multi_instance *oldmi = (struct multi_instance *) he->value;
 
121
          msg (D_MULTI_LOW, "MULTI TCP: new incoming client address matches existing client address -- new client takes precedence");
 
122
          oldmi->did_real_hash = false;
 
123
          multi_close_instance (m, oldmi, false);
 
124
          he->key = &mi->real;
 
125
          he->value = mi;
 
126
        }
 
127
      else
 
128
        hash_add_fast (hash, bucket, &mi->real, hv, mi);
 
129
 
 
130
      mi->did_real_hash = true;
 
131
 
 
132
      hash_bucket_unlock (bucket);
 
133
    }
 
134
 
 
135
#ifdef ENABLE_DEBUG
 
136
  if (mi)
 
137
    dmsg (D_MULTI_DEBUG, "MULTI TCP: instance added: %s", mroute_addr_print (&mi->real, &gc));
 
138
  else
 
139
    dmsg (D_MULTI_DEBUG, "MULTI TCP: new client instance failed");
 
140
#endif
 
141
 
 
142
  gc_free (&gc);
 
143
  ASSERT (!(mi && mi->halt));
 
144
  return mi;
 
145
}
 
146
 
 
147
bool
 
148
multi_tcp_instance_specific_init (struct multi_context *m, struct multi_instance *mi)
 
149
{
 
150
  /* buffer for queued TCP socket output packets */
 
151
  mi->tcp_link_out_deferred = mbuf_init (m->top.options.n_bcast_buf);
 
152
 
 
153
  ASSERT (mi->context.c2.link_socket);
 
154
  ASSERT (mi->context.c2.link_socket->info.lsa);
 
155
  ASSERT (mi->context.c2.link_socket->mode == LS_MODE_TCP_ACCEPT_FROM);
 
156
  if (!mroute_extract_openvpn_sockaddr (&mi->real, &mi->context.c2.link_socket->info.lsa->actual.dest, true))
 
157
    {
 
158
      msg (D_MULTI_ERRORS, "MULTI TCP: TCP client address is undefined");
 
159
      return false;
 
160
    }
 
161
  return true;
 
162
}
 
163
 
 
164
void
 
165
multi_tcp_instance_specific_free (struct multi_instance *mi)
 
166
{
 
167
  mbuf_free (mi->tcp_link_out_deferred);
 
168
}
 
169
 
 
170
struct multi_tcp *
 
171
multi_tcp_init (int maxevents, int *maxclients)
 
172
{
 
173
  struct multi_tcp *mtcp;
 
174
  const int extra_events = BASE_N_EVENTS;
 
175
 
 
176
  ASSERT (maxevents >= 1);
 
177
  ASSERT (maxclients);
 
178
 
 
179
  ALLOC_OBJ_CLEAR (mtcp, struct multi_tcp);
 
180
  mtcp->maxevents = maxevents + extra_events;
 
181
  mtcp->es = event_set_init (&mtcp->maxevents, 0);
 
182
  wait_signal (mtcp->es, MTCP_SIG);
 
183
  ALLOC_ARRAY (mtcp->esr, struct event_set_return, mtcp->maxevents);
 
184
  *maxclients = max_int (min_int (mtcp->maxevents - extra_events, *maxclients), 1);
 
185
  msg (D_MULTI_LOW, "MULTI: TCP INIT maxclients=%d maxevents=%d", *maxclients, mtcp->maxevents);
 
186
  return mtcp;
 
187
}
 
188
 
 
189
void
 
190
multi_tcp_delete_event (struct multi_tcp *mtcp, event_t event)
 
191
{
 
192
  if (mtcp && mtcp->es)
 
193
    event_del (mtcp->es, event);
 
194
}
 
195
 
 
196
void
 
197
multi_tcp_free (struct multi_tcp *mtcp)
 
198
{
 
199
  if (mtcp)
 
200
    {
 
201
      event_free (mtcp->es);
 
202
      if (mtcp->esr)
 
203
        free (mtcp->esr);
 
204
      free (mtcp);
 
205
    }
 
206
}
 
207
 
 
208
void
 
209
multi_tcp_dereference_instance (struct multi_tcp *mtcp, struct multi_instance *mi)
 
210
{
 
211
  struct link_socket *ls = mi->context.c2.link_socket;
 
212
  if (ls && mi->socket_set_called)
 
213
    event_del (mtcp->es, socket_event_handle (ls));
 
214
  mtcp->n_esr = 0;
 
215
}
 
216
 
 
217
static inline void
 
218
multi_tcp_set_global_rw_flags (struct multi_context *m, struct multi_instance *mi)
 
219
{
 
220
  if (mi)
 
221
    {
 
222
      mi->socket_set_called = true;
 
223
      socket_set (mi->context.c2.link_socket,
 
224
                  m->mtcp->es,
 
225
                  mbuf_defined (mi->tcp_link_out_deferred) ? EVENT_WRITE : EVENT_READ,
 
226
                  mi,
 
227
                  &mi->tcp_rwflags);
 
228
    }
 
229
}
 
230
 
 
231
static inline int
 
232
multi_tcp_wait (const struct context *c,
 
233
                struct multi_tcp *mtcp)
 
234
{
 
235
  int status;
 
236
  socket_set_listen_persistent (c->c2.link_socket, mtcp->es, MTCP_SOCKET);
 
237
  tun_set (c->c1.tuntap, mtcp->es, EVENT_READ, MTCP_TUN, &mtcp->tun_rwflags);
 
238
#ifdef ENABLE_MANAGEMENT
 
239
  if (management)
 
240
    management_socket_set (management, mtcp->es, MTCP_MANAGEMENT, &mtcp->management_persist_flags);
 
241
#endif
 
242
  status = event_wait (mtcp->es, &c->c2.timeval, mtcp->esr, mtcp->maxevents);
 
243
  update_time ();
 
244
  mtcp->n_esr = 0;
 
245
  if (status > 0)
 
246
    mtcp->n_esr = status;
 
247
  return status;
 
248
}
 
249
 
 
250
static inline struct context *
 
251
multi_tcp_context (struct multi_context *m, struct multi_instance *mi)
 
252
{
 
253
  if (mi)
 
254
    return &mi->context;
 
255
  else
 
256
    return &m->top;
 
257
}
 
258
 
 
259
static bool
 
260
multi_tcp_process_outgoing_link_ready (struct multi_context *m, struct multi_instance *mi, const unsigned int mpp_flags)
 
261
{
 
262
  struct mbuf_item item;
 
263
  bool ret = true;
 
264
  ASSERT (mi);
 
265
 
 
266
  /* extract from queue */
 
267
  if (mbuf_extract_item (mi->tcp_link_out_deferred, &item, true)) /* ciphertext IP packet */
 
268
    {
 
269
      dmsg (D_MULTI_TCP, "MULTI TCP: transmitting previously deferred packet");
 
270
 
 
271
      ASSERT (mi == item.instance);
 
272
      mi->context.c2.to_link = item.buffer->buf;
 
273
      ret = multi_process_outgoing_link_dowork (m, mi, mpp_flags);
 
274
      if (!ret)
 
275
        mi = NULL;
 
276
      mbuf_free_buf (item.buffer);
 
277
    }
 
278
  return ret;
 
279
}
 
280
 
 
281
static bool
 
282
multi_tcp_process_outgoing_link (struct multi_context *m, bool defer, const unsigned int mpp_flags)
 
283
{
 
284
  struct multi_instance *mi = multi_process_outgoing_link_pre (m);
 
285
  bool ret = true;
 
286
 
 
287
  if (mi)
 
288
    {
 
289
      if (defer || mbuf_defined (mi->tcp_link_out_deferred))
 
290
        {
 
291
          /* save to queue */
 
292
          struct buffer *buf = &mi->context.c2.to_link;
 
293
          if (BLEN (buf) > 0)
 
294
            {
 
295
              struct mbuf_buffer *mb = mbuf_alloc_buf (buf);
 
296
              struct mbuf_item item;
 
297
 
 
298
              set_prefix (mi);
 
299
              dmsg (D_MULTI_TCP, "MULTI TCP: queuing deferred packet");
 
300
              item.buffer = mb;
 
301
              item.instance = mi;
 
302
              mbuf_add_item (mi->tcp_link_out_deferred, &item);
 
303
              mbuf_free_buf (mb);
 
304
              buf_reset (buf);
 
305
              ret = multi_process_post (m, mi, mpp_flags);
 
306
              if (!ret)
 
307
                mi = NULL;
 
308
              clear_prefix ();
 
309
            }
 
310
        }
 
311
      else
 
312
        {
 
313
          ret = multi_process_outgoing_link_dowork (m, mi, mpp_flags);
 
314
          if (!ret)
 
315
            mi = NULL;
 
316
        }
 
317
    }
 
318
  return ret;
 
319
}
 
320
 
 
321
static int
 
322
multi_tcp_wait_lite (struct multi_context *m, struct multi_instance *mi, const int action, bool *tun_input_pending)
 
323
{
 
324
  struct context *c = multi_tcp_context (m, mi);
 
325
  unsigned int looking_for = 0;
 
326
 
 
327
  dmsg (D_MULTI_DEBUG, "MULTI TCP: multi_tcp_wait_lite a=%s mi=" ptr_format,
 
328
       pract(action),
 
329
       (ptr_type)mi);
 
330
 
 
331
  tv_clear (&c->c2.timeval); /* ZERO-TIMEOUT */
 
332
 
 
333
  switch (action)
 
334
    {
 
335
      case TA_TUN_READ:
 
336
        looking_for = TUN_READ;
 
337
        tun_input_pending = NULL;
 
338
        io_wait (c, IOW_READ_TUN);
 
339
        break;
 
340
      case TA_SOCKET_READ:
 
341
        looking_for = SOCKET_READ;
 
342
        tun_input_pending = NULL;
 
343
        io_wait (c, IOW_READ_LINK);
 
344
        break;
 
345
      case TA_TUN_WRITE:
 
346
        looking_for = TUN_WRITE;
 
347
        tun_input_pending = NULL;
 
348
        c->c2.timeval.tv_sec = 1; /* For some reason, the Linux 2.2 TUN/TAP driver hits this timeout */
 
349
        perf_push (PERF_PROC_OUT_TUN_MTCP);
 
350
        io_wait (c, IOW_TO_TUN);
 
351
        perf_pop ();
 
352
        break;
 
353
      case TA_SOCKET_WRITE:
 
354
        looking_for = SOCKET_WRITE;
 
355
        io_wait (c, IOW_TO_LINK|IOW_READ_TUN_FORCE);
 
356
        break;
 
357
      default:
 
358
        msg (M_FATAL, "MULTI TCP: multi_tcp_wait_lite, unhandled action=%d", action);
 
359
    }
 
360
 
 
361
  if (tun_input_pending && (c->c2.event_set_status & TUN_READ))
 
362
    *tun_input_pending = true;
 
363
 
 
364
  if (c->c2.event_set_status & looking_for)
 
365
    {
 
366
      return action;
 
367
    }
 
368
  else
 
369
    {
 
370
      switch (action)
 
371
        {
 
372
        /* TCP socket output buffer is full */
 
373
        case TA_SOCKET_WRITE:
 
374
          return TA_SOCKET_WRITE_DEFERRED;
 
375
 
 
376
        /* TUN device timed out on accepting write */
 
377
        case TA_TUN_WRITE:
 
378
          return TA_TUN_WRITE_TIMEOUT;
 
379
        }
 
380
 
 
381
      return TA_UNDEF;
 
382
    }
 
383
}
 
384
 
 
385
static struct multi_instance *
 
386
multi_tcp_dispatch (struct multi_context *m, struct multi_instance *mi, const int action)
 
387
{
 
388
  const unsigned int mpp_flags = MPP_PRE_SELECT|MPP_RECORD_TOUCH;
 
389
  struct multi_instance *touched = mi;
 
390
  m->mpp_touched = &touched;
 
391
 
 
392
  dmsg (D_MULTI_DEBUG, "MULTI TCP: multi_tcp_dispatch a=%s mi=" ptr_format,
 
393
       pract(action),
 
394
       (ptr_type)mi);
 
395
 
 
396
  switch (action)
 
397
    {
 
398
    case TA_TUN_READ:
 
399
      read_incoming_tun (&m->top);
 
400
      if (!IS_SIG (&m->top))
 
401
        multi_process_incoming_tun (m, mpp_flags);
 
402
      break;
 
403
    case TA_SOCKET_READ:
 
404
    case TA_SOCKET_READ_RESIDUAL:
 
405
      ASSERT (mi);
 
406
      ASSERT (mi->context.c2.link_socket);
 
407
      set_prefix (mi);
 
408
      read_incoming_link (&mi->context);
 
409
      clear_prefix ();
 
410
      if (!IS_SIG (&mi->context))
 
411
        {
 
412
          multi_process_incoming_link (m, mi, mpp_flags);
 
413
          if (!IS_SIG (&mi->context))
 
414
            stream_buf_read_setup (mi->context.c2.link_socket);
 
415
        }
 
416
      break;
 
417
    case TA_TIMEOUT:
 
418
      multi_process_timeout (m, mpp_flags);
 
419
      break;
 
420
    case TA_TUN_WRITE:
 
421
      multi_process_outgoing_tun (m, mpp_flags);
 
422
      break;
 
423
    case TA_TUN_WRITE_TIMEOUT:
 
424
      multi_process_drop_outgoing_tun (m, mpp_flags);      
 
425
      break;
 
426
    case TA_SOCKET_WRITE_READY:
 
427
      ASSERT (mi);
 
428
      multi_tcp_process_outgoing_link_ready (m, mi, mpp_flags);
 
429
      break;
 
430
    case TA_SOCKET_WRITE:
 
431
      multi_tcp_process_outgoing_link (m, false, mpp_flags);
 
432
      break;
 
433
    case TA_SOCKET_WRITE_DEFERRED:
 
434
      multi_tcp_process_outgoing_link (m, true, mpp_flags);
 
435
      break;
 
436
    case TA_INITIAL:
 
437
      ASSERT (mi);
 
438
      multi_tcp_set_global_rw_flags (m, mi);
 
439
      multi_process_post (m, mi, mpp_flags);
 
440
      break;
 
441
    default:
 
442
      msg (M_FATAL, "MULTI TCP: multi_tcp_dispatch, unhandled action=%d", action);
 
443
    }
 
444
 
 
445
  m->mpp_touched = NULL;
 
446
  return touched;
 
447
}
 
448
 
 
449
int
 
450
multi_tcp_post (struct multi_context *m, struct multi_instance *mi, const int action)
 
451
{
 
452
  struct context *c = multi_tcp_context (m, mi);
 
453
  int newaction = TA_UNDEF;
 
454
 
 
455
# define MTP_NONE         0
 
456
# define MTP_TUN_OUT      (1<<0)
 
457
# define MTP_LINK_OUT     (1<<1)
 
458
  unsigned int flags = MTP_NONE;
 
459
 
 
460
  if (TUN_OUT(c))
 
461
    flags |= MTP_TUN_OUT;
 
462
  if (LINK_OUT(c))
 
463
    flags |= MTP_LINK_OUT;
 
464
 
 
465
  switch (flags)
 
466
    {
 
467
    case MTP_TUN_OUT|MTP_LINK_OUT:
 
468
    case MTP_TUN_OUT:
 
469
      newaction = TA_TUN_WRITE;
 
470
      break;
 
471
    case MTP_LINK_OUT:
 
472
      newaction = TA_SOCKET_WRITE;
 
473
      break;
 
474
    case MTP_NONE:
 
475
      if (mi && socket_read_residual (c->c2.link_socket))
 
476
        newaction = TA_SOCKET_READ_RESIDUAL;
 
477
      else
 
478
        multi_tcp_set_global_rw_flags (m, mi);
 
479
      break;
 
480
    default:
 
481
      {
 
482
        struct gc_arena gc = gc_new ();
 
483
        msg (M_FATAL, "MULTI TCP: multi_tcp_post bad state, mi=%s flags=%d",
 
484
             multi_instance_string (mi, false, &gc),
 
485
             flags);
 
486
        gc_free (&gc);
 
487
        break;
 
488
      }
 
489
    }
 
490
 
 
491
  dmsg (D_MULTI_DEBUG, "MULTI TCP: multi_tcp_post %s -> %s",
 
492
       pract(action),
 
493
       pract(newaction));
 
494
 
 
495
  return newaction;
 
496
}
 
497
 
 
498
static void
 
499
multi_tcp_action (struct multi_context *m, struct multi_instance *mi, int action, bool poll)
 
500
{
 
501
  bool tun_input_pending = false;
 
502
 
 
503
  do {
 
504
    dmsg (D_MULTI_DEBUG, "MULTI TCP: multi_tcp_action a=%s p=%d",
 
505
         pract(action),
 
506
         poll);
 
507
 
 
508
    /*
 
509
     * If TA_SOCKET_READ_RESIDUAL, it means we still have pending
 
510
     * input packets which were read by a prior TCP recv.
 
511
     *
 
512
     * Otherwise do a "lite" wait, which means we wait with 0 timeout
 
513
     * on I/O events only related to the current instance, not
 
514
     * the big list of events.
 
515
     *
 
516
     * On our first pass, poll will be false because we already know
 
517
     * that input is available, and to call io_wait would be redundant.
 
518
     */
 
519
    if (poll && action != TA_SOCKET_READ_RESIDUAL)
 
520
      {
 
521
        const int orig_action = action;
 
522
        action = multi_tcp_wait_lite (m, mi, action, &tun_input_pending);
 
523
        if (action == TA_UNDEF)
 
524
          msg (M_FATAL, "MULTI TCP: I/O wait required blocking in multi_tcp_action, action=%d", orig_action);
 
525
      }
 
526
 
 
527
    /*
 
528
     * Dispatch the action
 
529
     */
 
530
    {
 
531
      struct multi_instance *touched = multi_tcp_dispatch (m, mi, action);
 
532
 
 
533
      /*
 
534
       * Signal received or TCP connection
 
535
       * reset by peer?
 
536
       */
 
537
      if (touched && IS_SIG (&touched->context))
 
538
        {
 
539
          if (mi == touched)
 
540
            mi = NULL;
 
541
          multi_close_instance_on_signal (m, touched);
 
542
        }
 
543
    }
 
544
 
 
545
    /*
 
546
     * If dispatch produced any pending output
 
547
     * for a particular instance, point to
 
548
     * that instance.
 
549
     */
 
550
    if (m->pending)
 
551
      mi = m->pending;
 
552
 
 
553
    /*
 
554
     * Based on the effects of the action,
 
555
     * such as generating pending output,
 
556
     * possibly transition to a new action state.
 
557
     */
 
558
    action = multi_tcp_post (m, mi, action);
 
559
 
 
560
    /*
 
561
     * If we are finished processing the original action,
 
562
     * check if we have any TUN input.  If so, transition
 
563
     * our action state to processing this input.
 
564
     */
 
565
    if (tun_input_pending && action == TA_UNDEF)
 
566
      {
 
567
        action = TA_TUN_READ;
 
568
        mi = NULL;
 
569
        tun_input_pending = false;
 
570
        poll = false;
 
571
      }
 
572
    else
 
573
      poll = true;
 
574
 
 
575
  } while (action != TA_UNDEF);
 
576
}
 
577
 
 
578
static void
 
579
multi_tcp_process_io (struct multi_context *m)
 
580
{
 
581
  struct multi_tcp *mtcp = m->mtcp;
 
582
  int i;
 
583
 
 
584
  for (i = 0; i < mtcp->n_esr; ++i)
 
585
    {
 
586
      struct event_set_return *e = &mtcp->esr[i];
 
587
 
 
588
      /* incoming data for instance? */
 
589
      if (e->arg >= MTCP_N)
 
590
        {
 
591
          struct multi_instance *mi = (struct multi_instance *) e->arg;
 
592
          if (mi)
 
593
            {
 
594
              if (e->rwflags & EVENT_WRITE)
 
595
                multi_tcp_action (m, mi, TA_SOCKET_WRITE_READY, false);
 
596
              else if (e->rwflags & EVENT_READ)
 
597
                multi_tcp_action (m, mi, TA_SOCKET_READ, false);
 
598
            }
 
599
        }
 
600
      else
 
601
        {
 
602
#ifdef ENABLE_MANAGEMENT
 
603
          if (e->arg == MTCP_MANAGEMENT)
 
604
            {
 
605
              ASSERT (management);
 
606
              management_io (management);
 
607
            }
 
608
          else
 
609
#endif
 
610
          /* incoming data on TUN? */
 
611
          if (e->arg == MTCP_TUN)
 
612
            {
 
613
              if (e->rwflags & EVENT_WRITE)
 
614
                multi_tcp_action (m, NULL, TA_TUN_WRITE, false);
 
615
              else if (e->rwflags & EVENT_READ)
 
616
                multi_tcp_action (m, NULL, TA_TUN_READ, false);
 
617
            }
 
618
          /* new incoming TCP client attempting to connect? */
 
619
          else if (e->arg == MTCP_SOCKET)
 
620
            {
 
621
              struct multi_instance *mi;
 
622
              ASSERT (m->top.c2.link_socket);
 
623
              socket_reset_listen_persistent (m->top.c2.link_socket);
 
624
              mi = multi_create_instance_tcp (m);
 
625
              if (mi)
 
626
                multi_tcp_action (m, mi, TA_INITIAL, false);
 
627
            }
 
628
          /* signal received? */
 
629
          else if (e->arg == MTCP_SIG)
 
630
            {
 
631
              get_signal (&m->top.sig->signal_received);
 
632
            }
 
633
        }
 
634
      if (IS_SIG (&m->top))
 
635
        break;
 
636
    }
 
637
  mtcp->n_esr = 0;
 
638
 
 
639
  /*
 
640
   * Process queued mbuf packets destined for TCP socket
 
641
   */
 
642
  {
 
643
    struct multi_instance *mi;
 
644
    while (!IS_SIG (&m->top) && (mi = mbuf_peek (m->mbuf)) != NULL)
 
645
      {
 
646
        multi_tcp_action (m, mi, TA_SOCKET_WRITE, true);
 
647
      }
 
648
  }
 
649
}
 
650
 
 
651
/*
 
652
 * Top level event loop for single-threaded operation.
 
653
 * TCP mode.
 
654
 */
 
655
void
 
656
tunnel_server_tcp (struct context *top)
 
657
{
 
658
  struct multi_context multi;
 
659
  int status;
 
660
 
 
661
  top->mode = CM_TOP;
 
662
  context_clear_2 (top);
 
663
 
 
664
  /* initialize top-tunnel instance */
 
665
  init_instance_handle_signals (top, top->es, CC_HARD_USR1_TO_HUP);
 
666
  if (IS_SIG (top))
 
667
    return;
 
668
  
 
669
  /* initialize global multi_context object */
 
670
  multi_init (&multi, top, true, MC_SINGLE_THREADED);
 
671
 
 
672
  /* initialize our cloned top object */
 
673
  multi_top_init (&multi, top, true);
 
674
 
 
675
  /* initialize management interface */
 
676
  init_management_callback_multi (&multi);
 
677
 
 
678
  /* finished with initialization */
 
679
  initialization_sequence_completed (top, ISC_SERVER); /* --mode server --proto tcp-server */
 
680
 
 
681
  /* per-packet event loop */
 
682
  while (true)
 
683
    {
 
684
      perf_push (PERF_EVENT_LOOP);
 
685
 
 
686
      /* wait on tun/socket list */
 
687
      multi_get_timeout (&multi, &multi.top.c2.timeval);
 
688
      status = multi_tcp_wait (&multi.top, multi.mtcp);
 
689
      MULTI_CHECK_SIG (&multi);
 
690
 
 
691
      /* check on status of coarse timers */
 
692
      multi_process_per_second_timers (&multi);
 
693
 
 
694
      /* timeout? */
 
695
      if (status > 0)
 
696
        {
 
697
          /* process the I/O which triggered select */
 
698
          multi_tcp_process_io (&multi);
 
699
          MULTI_CHECK_SIG (&multi);
 
700
        }
 
701
      else if (status == 0)
 
702
        {
 
703
          multi_tcp_action (&multi, NULL, TA_TIMEOUT, false);
 
704
        }
 
705
 
 
706
      perf_pop ();
 
707
    }
 
708
 
 
709
  /* shut down management interface */
 
710
  uninit_management_callback_multi (&multi);
 
711
 
 
712
  /* save ifconfig-pool */
 
713
  multi_ifconfig_pool_persist (&multi, true);
 
714
 
 
715
  /* tear down tunnel instance (unless --persist-tun) */
 
716
  multi_uninit (&multi);
 
717
  multi_top_free (&multi);
 
718
  close_instance (top);
 
719
}
 
720
 
 
721
#endif