Coverage Report

Created: 2023-09-25 06:44

/src/rtpproxy/src/main.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3
 * Copyright (c) 2006-2007 Sippy Software, Inc., http://www.sippysoft.com
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 */
28
29
#ifdef LINUX_XXX
30
/* Apparently needed for drand48(3) */
31
#define _SVID_SOURCE  1
32
/* Needed for the asprintf(3) */
33
#define _GNU_SOURCE 1
34
#endif
35
36
#include <sys/types.h>
37
#include <sys/resource.h>
38
#include <sys/socket.h>
39
#include <sys/stat.h>
40
#include <fcntl.h>
41
#include <getopt.h>
42
#include <grp.h>
43
#include <limits.h>
44
#include <math.h>
45
#include <netdb.h>
46
#include <pthread.h>
47
#include <pwd.h>
48
#include <stdatomic.h>
49
#include <stdbool.h>
50
#include <stdio.h>
51
#include <stdint.h>
52
#include <stdlib.h>
53
#include <signal.h>
54
#include <string.h>
55
#include <syslog.h>
56
#include <unistd.h>
57
58
#include "config_pp.h"
59
60
#if !defined(NO_ERR_H)
61
#include <err.h>
62
#include "rtpp_util.h"
63
#else
64
#include "rtpp_util.h"
65
#endif
66
67
#ifdef HAVE_SYSTEMD_DAEMON
68
#include <systemd/sd-daemon.h>
69
#endif
70
71
#include <elperiodic.h>
72
73
#include "rtpp_types.h"
74
#include "rtpp_refcnt.h"
75
#include "rtpp_runcreds.h"
76
#include "rtpp_cfile.h"
77
#include "rtpp_log.h"
78
#include "rtpp_log_obj.h"
79
#include "rtpp_cfg.h"
80
#include "rtpp_defines.h"
81
#include "rtpp_command.h"
82
#include "rtpp_controlfd.h"
83
#include "rtpp_genuid_singlet.h"
84
#include "rtpp_hash_table.h"
85
#include "commands/rpcpv1_ver.h"
86
#include "rtpp_command_async.h"
87
#include "rtpp_command_ecodes.h"
88
#include "rtpp_port_table.h"
89
#include "rtpp_proc_async.h"
90
#include "rtpp_proc_servers.h"
91
#include "rtpp_proc_ttl.h"
92
#include "rtpp_bindaddrs.h"
93
#include "rtpp_network.h"
94
#include "rtpp_notify.h"
95
#include "rtpp_math.h"
96
#include "rtpp_mallocs.h"
97
#include "rtpp_list.h"
98
#if ENABLE_MODULE_IF
99
#include "rtpp_module_if.h"
100
#include "rtpp_modman.h"
101
#endif
102
#include "rtpp_stats.h"
103
#include "rtpp_sessinfo.h"
104
#include "rtpp_time.h"
105
#include "rtpp_timed.h"
106
#include "rtpp_timed_task.h"
107
#include "rtpp_tnotify_set.h"
108
#include "rtpp_weakref.h"
109
#include "rtpp_debug.h"
110
#include "rtpp_locking.h"
111
#include "rtpp_nofile.h"
112
#include "advanced/pproc_manager.h"
113
#ifdef RTPP_CHECK_LEAKS
114
#include "libexecinfo/stacktraverse.h"
115
#include "libexecinfo/execinfo.h"
116
#include "rtpp_memdeb_internal.h"
117
#endif
118
#include "rtpp_stacktrace.h"
119
#if defined(LIBRTPPROXY)
120
#include "librtpproxy.h"
121
#include "rtpp_module_if_static.h"
122
#endif
123
124
#ifndef RTPP_DEBUG
125
# define RTPP_DEBUG 0
126
#else
127
# define RTPP_DEBUG 1
128
#endif
129
130
4
#define PRIO_UNSET (PRIO_MIN - 1)
131
132
static void usage(void);
133
134
#ifdef RTPP_CHECK_LEAKS
135
RTPP_MEMDEB_APP_STATIC;
136
#endif
137
138
static void
139
usage(void)
140
0
{
141
142
0
    fprintf(stderr, "usage:\trtpproxy [-2fvFiPaRbD] [-l addr1[/addr2]] "
143
0
      "[-6 addr1[/addr2]] [-s path]\n\t  [-t tos] [-r rdir [-S sdir]] [-T ttl] "
144
0
      "[-L nfiles] [-m port_min]\n\t  [-M port_max] [-u uname[:gname]] [-w sock_mode] "
145
0
      "[-n timeout_socket]\n\t  [-d log_level[:log_facility]] [-p pid_file]\n"
146
0
      "\t  [-c fifo|rr] [-A addr1[/addr2] [-W setup_ttl]\n"
147
0
      "\trtpproxy -V\n");
148
0
    exit(1);
149
0
}
150
151
static struct rtpp_cfg *_sig_cf;
152
153
static void rtpp_exit(int, int) __attribute__ ((noreturn));
154
155
static void
156
rtpp_exit(int memdeb, int rval)
157
0
{
158
0
    int ecode;
159
160
0
    ecode = 0;
161
#ifdef RTPP_CHECK_LEAKS
162
    if (memdeb) {
163
        ecode = rtpp_memdeb_dumpstats(MEMDEB_SYM, 0) == 0 ? 0 : 1;
164
    }
165
#endif
166
0
    exit(rval == 0 ? ecode : rval);
167
0
}
168
169
static void
170
rtpp_glog_fin(void)
171
0
{
172
173
0
    RTPP_OBJ_DECREF(_sig_cf->glog);
174
#ifdef RTPP_CHECK_LEAKS
175
    RTPP_MEMDEB_FIN(rtpproxy);
176
#ifdef RTPP_MEMDEB_STDOUT
177
    fclose(stdout);
178
#endif
179
#endif
180
0
}
181
182
static void
183
fatsignal(int sig)
184
0
{
185
186
0
    RTPP_LOG(_sig_cf->glog, RTPP_LOG_INFO, "got signal %d", sig);
187
0
    if (_sig_cf->fastshutdown == 0) {
188
0
        _sig_cf->fastshutdown = 1;
189
0
        return;
190
0
    }
191
    /*
192
     * Got second signal while already in the fastshutdown mode, something
193
     * probably jammed, do quick exit right from sighandler.
194
     */
195
0
    rtpp_exit(1, 0);
196
0
}
197
198
static void
199
sighup(int sig)
200
0
{
201
202
0
    if (_sig_cf->slowshutdown == 0) {
203
0
        RTPP_LOG(_sig_cf->glog, RTPP_LOG_INFO,
204
0
          "got SIGHUP, initiating deorbiting-burn sequence");
205
0
    }
206
0
    _sig_cf->slowshutdown = 1;
207
0
}
208
209
static void
210
ehandler(void)
211
0
{
212
213
0
    RTPP_DBGCODE(catchtrace) {
214
0
        rtpp_stacktrace_print("Exiting from: ehandler()");
215
0
    }
216
0
    if (_sig_cf->ctrl_socks != NULL)
217
0
        rtpp_controlfd_cleanup(_sig_cf);
218
0
    unlink(_sig_cf->pid_file);
219
0
    RTPP_LOG(_sig_cf->glog, RTPP_LOG_INFO, "rtpproxy ended");
220
0
}
221
222
long long
223
rtpp_rlim_max(const struct rtpp_cfg *cfsp)
224
0
{
225
226
0
    return (long long)(cfsp->nofile->limit->rlim_max);
227
0
}
228
229
6
#define LOPT_DSO      256
230
0
#define LOPT_BRSYM    257
231
0
#define LOPT_NICE     258
232
0
#define LOPT_OVL_PROT 259
233
0
#define LOPT_CONFIG   260
234
0
#define LOPT_FORC_ASM 261
235
236
const static struct option longopts[] = {
237
    { "dso", required_argument, NULL, LOPT_DSO },
238
    { "bridge_symmetric", no_argument, NULL, LOPT_BRSYM },
239
    { "nice", required_argument, NULL, LOPT_NICE },
240
    { "overload_prot", optional_argument, NULL, LOPT_OVL_PROT },
241
    { "config", required_argument, NULL, LOPT_CONFIG },
242
    { "force_asymmetric", no_argument, NULL, LOPT_FORC_ASM },
243
    { NULL,  0,                 NULL, 0 }
244
};
245
246
static void
247
init_config_bail(struct rtpp_cfg *cfsp, int rval, const char *msg, int memdeb)
248
0
{
249
0
    struct rtpp_ctrl_sock *ctrl_sock, *ctrl_sock_next;
250
251
0
    if (msg != NULL) {
252
0
        RTPP_LOG(cfsp->glog, RTPP_LOG_ERR, "%s", msg);
253
0
    }
254
0
    CALL_METHOD(cfsp->bindaddrs_cf, dtor);
255
0
    free(cfsp->locks);
256
0
    CALL_METHOD(cfsp->rtpp_tnset_cf, dtor);
257
0
    CALL_METHOD(cfsp->nofile, dtor);
258
0
    RTPP_OBJ_DECREF(cfsp->sessions_wrt);
259
260
0
    for (ctrl_sock = RTPP_LIST_HEAD(cfsp->ctrl_socks);
261
0
      ctrl_sock != NULL; ctrl_sock = ctrl_sock_next) {
262
0
        ctrl_sock_next = RTPP_ITER_NEXT(ctrl_sock);
263
0
        free(ctrl_sock);
264
0
    }
265
0
    free(cfsp->ctrl_socks);
266
0
    free(cfsp->runcreds);
267
0
    RTPP_OBJ_DECREF(cfsp->modules_cf);
268
0
    rtpp_gen_uid_free();
269
0
    rtpp_exit(memdeb, rval);
270
0
}
271
272
static void
273
init_config(struct rtpp_cfg *cfsp, int argc, char **argv)
274
2
{
275
2
    int ch, i, umode, stdio_mode;
276
2
    char *bh[2], *bh6[2], *cp;
277
2
    const char *errmsg;
278
2
    struct passwd *pp;
279
2
    struct group *gp;
280
2
    struct rtpp_ctrl_sock *ctrl_sock;
281
2
    int option_index, brsym;
282
2
    const struct proto_cap *pcp;
283
2
    struct rtpp_module_if *mif;
284
2
    char mpath[PATH_MAX + 1];
285
2
    struct rtpp_module_conf *mcp;
286
287
2
    bh[0] = bh[1] = bh6[0] = bh6[1] = NULL;
288
289
2
    umode = stdio_mode = 0;
290
291
2
    cfsp->pid_file = PID_FILE;
292
293
2
    cfsp->port_min = PORT_MIN;
294
2
    cfsp->port_max = PORT_MAX;
295
2
    cfsp->port_ctl = 0;
296
297
2
    cfsp->advaddr[0] = NULL;
298
2
    cfsp->advaddr[1] = NULL;
299
300
2
    cfsp->max_ttl = SESSION_TIMEOUT;
301
2
    cfsp->tos = TOS;
302
2
    cfsp->rrtcp = 1;
303
2
    cfsp->runcreds->sock_mode = 0;
304
2
    cfsp->ttl_mode = TTL_UNIFIED;
305
2
    cfsp->log_level = -1;
306
2
    cfsp->log_facility = -1;
307
2
    cfsp->sched_hz = rtpp_get_sched_hz();
308
2
    cfsp->sched_policy = SCHED_OTHER;
309
2
    cfsp->sched_nice = PRIO_UNSET;
310
2
    cfsp->target_pfreq = MIN(POLL_RATE, cfsp->sched_hz);
311
2
    cfsp->slowshutdown = 0;
312
2
    cfsp->fastshutdown = 0;
313
314
2
    cfsp->rtpp_tnset_cf = rtpp_tnotify_set_ctor();
315
2
    if (cfsp->rtpp_tnset_cf == NULL) {
316
0
        err(1, "rtpp_tnotify_set_ctor");
317
0
    }
318
319
2
    cfsp->locks = malloc(sizeof(*cfsp->locks));
320
2
    if (cfsp->locks == NULL) {
321
0
        err(1, "malloc(rtpp_cfg->locks)");
322
0
    }
323
2
    if (pthread_mutex_init(&(cfsp->locks->glob), NULL) != 0) {
324
0
        errx(1, "pthread_mutex_init(rtpp_cfg->locks->glob)");
325
0
    }
326
2
    cfsp->bindaddrs_cf = rtpp_bindaddrs_ctor();
327
2
    if (cfsp->bindaddrs_cf == NULL) {
328
0
        err(1, "malloc(rtpp_cfg->bindaddrs_cf)");
329
0
    }
330
331
2
    cfsp->nofile = rtpp_nofile_ctor();
332
2
    if (cfsp->nofile == NULL)
333
0
        err(1, "malloc(rtpp_cfg->nofile)");
334
335
2
    cfsp->sessions_wrt = rtpp_weakref_ctor();
336
2
    if (cfsp->sessions_wrt == NULL) {
337
0
        err(1, "can't allocate memory for the sessions weakref table");
338
         /* NOTREACHED */
339
0
    }
340
341
2
    option_index = -1;
342
2
    brsym = 0;
343
24
    while ((ch = getopt_long(argc, argv, "vf2Rl:6:s:S:t:r:p:T:L:m:M:u:Fin:Pad:"
344
24
      "Vc:A:w:bW:DC", longopts, &option_index)) != -1) {
345
22
  switch (ch) {
346
6
        case LOPT_DSO:
347
6
            cp = NULL;
348
6
#if defined(LIBRTPPROXY)
349
6
            if (rtpp_static_modules_lookup(optarg) != NULL) {
350
6
                cp = optarg;
351
6
            }
352
6
#endif
353
6
            if (cp == NULL)
354
0
                cp = realpath(optarg, mpath);
355
6
            if (cp == NULL) {
356
0
                 err(1, "realpath: %s", optarg);
357
0
            }
358
6
            mif = rtpp_module_if_ctor(cp);
359
6
            if (mif == NULL) {
360
0
                err(1, "%s: dymanic module constructor has failed", cp);
361
0
            }
362
6
            if (CALL_METHOD(mif, load, cfsp, cfsp->glog) != 0) {
363
0
                errx(1, "%p: dymanic module load has failed", mif);
364
0
            }
365
6
            if (CALL_METHOD(mif, get_mconf, &mcp) != 0) {
366
0
                errx(1, "%p->get_mconf() method has failed: %s", mif, cp);
367
0
            }
368
6
            if (mcp != NULL) {
369
0
                 errx(1, "%s: dymanic module requires configuration, cannot be "
370
0
                   "loaded via --dso option", cp);
371
0
            }
372
6
            CALL_METHOD(cfsp->modules_cf, insert, mif);
373
6
            break;
374
375
0
        case LOPT_BRSYM:
376
0
            brsym = 1;
377
0
            break;
378
379
0
        case LOPT_NICE:
380
0
            switch (atoi_saferange(optarg, &cfsp->sched_nice, PRIO_MIN, PRIO_MAX)) {
381
0
            case ATOI_OK:
382
0
                break;
383
0
            case ATOI_OUTRANGE:
384
0
                errx(1, "%s: nice level is out of range %d..%d", optarg,
385
0
                  PRIO_MIN, PRIO_MAX);
386
0
            default:
387
0
                errx(1, "%s: nice level argument is invalid", optarg);
388
0
            }
389
0
            break;
390
391
0
        case LOPT_OVL_PROT:
392
0
            cfsp->overload_prot.low_trs = 0.85;
393
0
            cfsp->overload_prot.high_trs = 0.90;
394
0
            cfsp->overload_prot.ecode = ECODE_OVERLOAD;
395
0
            break;
396
397
0
        case LOPT_CONFIG:
398
0
            cfsp->cfile = optarg;
399
0
            break;
400
401
0
        case LOPT_FORC_ASM:
402
0
            cfsp->aforce = 1;
403
0
            break;
404
405
0
        case 'c':
406
0
            if (strcmp(optarg, "fifo") == 0) {
407
0
                 cfsp->sched_policy = SCHED_FIFO;
408
0
                 break;
409
0
            }
410
0
            if (strcmp(optarg, "rr") == 0) {
411
0
                 cfsp->sched_policy = SCHED_RR;
412
0
                 break;
413
0
            }
414
0
            errx(1, "%s: unknown scheduling policy", optarg);
415
0
            break;
416
417
2
  case 'f':
418
2
      cfsp->ropts.no_daemon = 1;
419
2
      break;
420
421
0
  case 'l':
422
0
      bh[0] = optarg;
423
0
      bh[1] = strchr(bh[0], '/');
424
0
      if (bh[1] != NULL) {
425
0
    *bh[1] = '\0';
426
0
    bh[1]++;
427
0
    cfsp->bmode = 1;
428
    /*
429
     * Historically, in bridge mode all clients are assumed to
430
     * be asymmetric
431
     */
432
0
    cfsp->aforce = 1;
433
0
      }
434
0
      break;
435
436
0
  case '6':
437
0
      bh6[0] = optarg;
438
0
      bh6[1] = strchr(bh6[0], '/');
439
0
      if (bh6[1] != NULL) {
440
0
    *bh6[1] = '\0';
441
0
    bh6[1]++;
442
0
    cfsp->bmode = 1;
443
0
    cfsp->aforce = 1;
444
0
      }
445
0
      break;
446
447
0
    case 'A':
448
0
        if (*optarg == '\0') {
449
0
            errx(1, "first advertised address is invalid");
450
0
        }
451
0
        cfsp->advaddr[0] = optarg;
452
0
        cp = strchr(optarg, '/');
453
0
        if (cp != NULL) {
454
0
            *cp = '\0';
455
0
            cp++;
456
0
            if (*cp == '\0') {
457
0
                errx(1, "second advertised address is invalid");
458
0
            }
459
0
        }
460
0
        cfsp->advaddr[1] = cp;
461
0
        break;
462
463
2
  case 's':
464
2
            ctrl_sock = rtpp_ctrl_sock_parse(optarg);
465
2
            if (ctrl_sock == NULL) {
466
0
                errx(1, "can't parse control socket argument");
467
0
            }
468
2
            rtpp_list_append(cfsp->ctrl_socks, ctrl_sock);
469
2
            if (RTPP_CTRL_ISDG(ctrl_sock)) {
470
0
                umode = 1;
471
2
            } else if (ctrl_sock->type == RTPC_STDIO) {
472
2
                stdio_mode = 1;
473
2
            }
474
2
      break;
475
476
0
  case 't':
477
0
            switch (atoi_saferange(optarg, &cfsp->tos, 0, 255)) {
478
0
            case ATOI_OK:
479
0
                break;
480
0
            case ATOI_OUTRANGE:
481
0
                errx(1, "%s: TOS is too small/large", optarg);
482
0
            default:
483
0
                errx(1, "%s: TOS argument is invalid", optarg);
484
0
      }
485
0
            break;
486
487
0
  case '2':
488
0
      cfsp->dmode = 1;
489
0
      break;
490
491
0
  case 'v':
492
0
      printf("Basic version: %d\n", CPROTOVER);
493
0
      for (pcp = iterate_proto_caps(NULL); pcp != NULL; pcp = iterate_proto_caps(pcp)) {
494
0
    printf("Extension %s: %s\n", pcp->pc_id, pcp->pc_description);
495
0
      }
496
0
      init_config_bail(cfsp, 0, NULL, 0);
497
0
      break;
498
499
2
  case 'r':
500
2
      cfsp->rdir = optarg;
501
2
      break;
502
503
2
  case 'S':
504
2
      cfsp->sdir = optarg;
505
2
      break;
506
507
0
  case 'R':
508
0
      cfsp->rrtcp = 0;
509
0
      break;
510
511
0
  case 'p':
512
0
      cfsp->pid_file = optarg;
513
0
      break;
514
515
2
  case 'T':
516
2
      if (atoi_saferange(optarg, &cfsp->max_ttl, 1, -1))
517
0
                errx(1, "%s: max TTL argument is invalid", optarg);
518
2
      break;
519
520
2
  case 'L': {
521
0
            int rlim_max_opt;
522
523
0
            if (atoi_saferange(optarg, &rlim_max_opt, 0, -1))
524
0
                errx(1, "%s: max file rlimit argument is invalid", optarg);
525
0
      cfsp->nofile->limit->rlim_cur = rlim_max_opt;
526
0
      cfsp->nofile->limit->rlim_max = rlim_max_opt;
527
0
      if (setrlimit(RLIMIT_NOFILE, cfsp->nofile->limit) != 0)
528
0
    err(1, "setrlimit");
529
0
      if (getrlimit(RLIMIT_NOFILE, cfsp->nofile->limit) != 0)
530
0
    err(1, "getrlimit");
531
0
      if (cfsp->nofile->limit->rlim_max < rlim_max_opt)
532
0
    warnx("limit allocated by setrlimit (%d) is less than "
533
0
      "requested (%d)", (int) cfsp->nofile->limit->rlim_max,
534
0
      rlim_max_opt);
535
0
      break;
536
0
            }
537
538
0
  case 'm':
539
0
      switch (atoi_saferange(optarg, &cfsp->port_min, 1, 65535)) {
540
0
            case ATOI_OK:
541
0
                break;
542
0
            case ATOI_OUTRANGE:
543
0
                errx(1, "invalid value of the port_min argument, "
544
0
                  "not in the range 1-65535");
545
0
            default:
546
0
                errx(1, "%s: min port argument is invalid", optarg);
547
0
            }
548
0
      break;
549
550
0
  case 'M':
551
0
      switch (atoi_saferange(optarg, &cfsp->port_max, 1, 65535)) {
552
0
            case ATOI_OK:
553
0
                break;
554
0
            case ATOI_OUTRANGE:
555
0
                errx(1, "invalid value of the port_max argument, "
556
0
                  "not in the range 1-65535");
557
0
            default:
558
0
                errx(1, "%s: max port argument is invalid", optarg);
559
0
            }
560
0
      break;
561
562
0
  case 'u':
563
0
      cfsp->runcreds->uname = optarg;
564
0
      cp = strchr(optarg, ':');
565
0
      if (cp != NULL) {
566
0
    if (cp == optarg)
567
0
        cfsp->runcreds->uname = NULL;
568
0
    cp[0] = '\0';
569
0
    cp++;
570
0
      }
571
0
      cfsp->runcreds->gname = cp;
572
0
      cfsp->runcreds->uid = -1;
573
0
      cfsp->runcreds->gid = -1;
574
0
      if (cfsp->runcreds->uname != NULL) {
575
0
    pp = getpwnam(cfsp->runcreds->uname);
576
0
    if (pp == NULL)
577
0
        errx(1, "can't find ID for the user: %s", cfsp->runcreds->uname);
578
0
    cfsp->runcreds->uid = pp->pw_uid;
579
0
    if (cfsp->runcreds->gname == NULL)
580
0
        cfsp->runcreds->gid = pp->pw_gid;
581
0
      }
582
0
      if (cfsp->runcreds->gname != NULL) {
583
0
    gp = getgrnam(cfsp->runcreds->gname);
584
0
    if (gp == NULL)
585
0
        errx(1, "can't find ID for the group: %s", cfsp->runcreds->gname);
586
0
    cfsp->runcreds->gid = gp->gr_gid;
587
0
                if (cfsp->runcreds->sock_mode == 0) {
588
0
                    cfsp->runcreds->sock_mode = 0755;
589
0
                }
590
0
      }
591
0
      break;
592
593
0
  case 'w': {
594
0
            int sock_mode;
595
596
0
      if (atoi_saferange(optarg, &sock_mode, 0, 4095))
597
0
                errx(1, "%s: socket mode argument is invalid", optarg);
598
0
            cfsp->runcreds->sock_mode = sock_mode;
599
0
      break;
600
0
            }
601
602
0
  case 'F':
603
0
      cfsp->no_check = 1;
604
0
      break;
605
606
0
  case 'i':
607
0
      cfsp->ttl_mode = TTL_INDEPENDENT;
608
0
      break;
609
610
2
  case 'n':
611
2
      if(strlen(optarg) == 0)
612
0
    errx(1, "timeout notification socket name too short");
613
2
            if (CALL_METHOD(cfsp->rtpp_tnset_cf, append, optarg,
614
2
              &errmsg) != 0) {
615
0
                errx(1, "error adding timeout notification: %s", errmsg);
616
0
            }
617
2
      break;
618
619
2
  case 'P':
620
0
      cfsp->record_pcap = 1;
621
0
      break;
622
623
0
  case 'a':
624
0
      cfsp->record_all = 1;
625
0
      break;
626
627
2
  case 'd':
628
2
      cp = strchr(optarg, ':');
629
2
      if (cp != NULL) {
630
0
    cfsp->log_facility = rtpp_log_str2fac(cp + 1);
631
0
    if (cfsp->log_facility == -1)
632
0
        errx(1, "%s: invalid log facility", cp + 1);
633
0
    *cp = '\0';
634
0
      }
635
2
      cfsp->log_level = rtpp_log_str2lvl(optarg);
636
2
      if (cfsp->log_level == -1)
637
0
    errx(1, "%s: invalid log level", optarg);
638
2
            CALL_METHOD(cfsp->glog, setlevel, cfsp->log_level);
639
2
      break;
640
641
0
  case 'V':
642
0
      printf("%s\n", RTPP_SW_VERSION);
643
0
      init_config_bail(cfsp, 0, NULL, 0);
644
0
      break;
645
646
2
        case 'W':
647
2
            if (atoi_saferange(optarg, &cfsp->max_setup_ttl, 1, -1))
648
0
                errx(1, "%s: max setup TTL argument is invalid", optarg);
649
2
            break;
650
651
2
        case 'b':
652
0
            cfsp->seq_ports = 1;
653
0
            break;
654
655
0
        case 'D':
656
0
      cfsp->ropts.no_chdir = 1;
657
0
      break;
658
659
0
        case 'C':
660
0
      printf("%s\n", get_mclock_name());
661
0
      init_config_bail(cfsp, 0, NULL, 0);
662
0
      break;
663
664
0
  case '?':
665
0
  default:
666
0
      usage();
667
22
  }
668
22
    }
669
670
2
    if (optind != argc) {
671
0
       warnx("%d extra unhandled argument%s at the end of the command line",
672
0
         argc - optind, (argc - optind) > 1 ? "s" : "");
673
0
       usage();
674
0
    }
675
676
2
    if (cfsp->cfile != NULL) {
677
0
        if (rtpp_cfile_process(cfsp) < 0) {
678
0
            init_config_bail(cfsp, 1, "rtpp_cfile_process() failed", 1);
679
0
        }
680
0
    }
681
682
2
    if (cfsp->bmode != 0 && brsym != 0) {
683
0
        cfsp->aforce = 0;
684
0
    }
685
686
2
    if (cfsp->max_setup_ttl == 0) {
687
0
        cfsp->max_setup_ttl = cfsp->max_ttl;
688
0
    }
689
690
    /* No control socket has been specified, add a default one */
691
2
    if (RTPP_LIST_IS_EMPTY(cfsp->ctrl_socks)) {
692
0
        ctrl_sock = rtpp_ctrl_sock_parse(CMD_SOCK);
693
0
        if (ctrl_sock == NULL) {
694
0
            errx(1, "can't parse control socket: \"%s\"", CMD_SOCK);
695
0
        }
696
0
        rtpp_list_append(cfsp->ctrl_socks, ctrl_sock);
697
0
    }
698
699
2
    if (cfsp->rdir == NULL && cfsp->sdir != NULL)
700
0
  errx(1, "-S switch requires -r switch");
701
702
2
    if (cfsp->ropts.no_daemon == 0 && stdio_mode != 0)
703
0
        errx(1, "stdio command mode requires -f switch");
704
705
2
    if (cfsp->no_check == 0 && getuid() == 0 && cfsp->runcreds->uname == NULL) {
706
2
  if (umode != 0) {
707
0
      errx(1, "running this program as superuser in a remote control "
708
0
        "mode is strongly not recommended, as it poses serious security "
709
0
        "threat to your system. Use -u option to run as an unprivileged "
710
0
        "user or -F is you want to run as a superuser anyway.");
711
2
  } else {
712
2
      warnx("WARNING!!! Running this program as superuser is strongly "
713
2
        "not recommended, as it may pose serious security threat to "
714
2
        "your system. Use -u option to run as an unprivileged user "
715
2
        "or -F to surpress this warning.");
716
2
  }
717
2
    }
718
719
    /* make sure that port_min and port_max are even */
720
2
    if ((cfsp->port_min % 2) != 0)
721
0
  cfsp->port_min++;
722
2
    if ((cfsp->port_max % 2) != 0) {
723
0
  cfsp->port_max--;
724
2
    } else {
725
  /*
726
   * If port_max is already even then there is no
727
   * "room" for the RTCP port, go back by two ports.
728
   */
729
2
  cfsp->port_max -= 2;
730
2
    }
731
732
2
    if (cfsp->port_min > cfsp->port_max)
733
0
  errx(1, "port_min should be less than port_max");
734
735
2
    if (bh[0] == NULL && bh[1] == NULL && bh6[0] == NULL && bh6[1] == NULL) {
736
2
  bh[0] = "*";
737
2
    }
738
739
6
    for (i = 0; i < 2; i++) {
740
4
  if (bh[i] != NULL && *bh[i] == '\0')
741
0
      bh[i] = NULL;
742
4
  if (bh6[i] != NULL && *bh6[i] == '\0')
743
0
      bh6[i] = NULL;
744
4
    }
745
746
2
    i = ((bh[0] == NULL) ? 0 : 1) + ((bh[1] == NULL) ? 0 : 1) +
747
2
      ((bh6[0] == NULL) ? 0 : 1) + ((bh6[1] == NULL) ? 0 : 1);
748
2
    if (cfsp->bmode != 0) {
749
0
  if (bh[0] != NULL && bh6[0] != NULL)
750
0
      errx(1, "either IPv4 or IPv6 should be configured for external "
751
0
        "interface in bridging mode, not both");
752
0
  if (bh[1] != NULL && bh6[1] != NULL)
753
0
      errx(1, "either IPv4 or IPv6 should be configured for internal "
754
0
        "interface in bridging mode, not both");
755
0
        if (cfsp->advaddr[0] != NULL && cfsp->advaddr[1] == NULL)
756
0
            errx(1, "two advertised addresses are required for internal "
757
0
              "and external interfaces in bridging mode");
758
0
  if (i != 2)
759
0
      errx(1, "incomplete configuration of the bridging mode - exactly "
760
0
        "2 listen addresses required, %d provided", i);
761
2
    } else if (i != 1) {
762
0
  errx(1, "exactly 1 listen addresses required, %d provided", i);
763
0
    }
764
765
6
    for (i = 0; i < 2; i++) {
766
4
  cfsp->bindaddr[i] = NULL;
767
4
  if (bh[i] != NULL) {
768
2
      cfsp->bindaddr[i] = CALL_METHOD(cfsp->bindaddrs_cf,
769
2
              host2, bh[i], AF_INET, AI_PASSIVE, &errmsg);
770
2
      if (cfsp->bindaddr[i] == NULL)
771
0
    errx(1, "host2bindaddr: %s", errmsg);
772
2
      continue;
773
2
  }
774
2
  if (bh6[i] != NULL) {
775
0
      cfsp->bindaddr[i] = CALL_METHOD(cfsp->bindaddrs_cf,
776
0
              host2, bh6[i], AF_INET6, AI_PASSIVE, &errmsg);
777
0
      if (cfsp->bindaddr[i] == NULL)
778
0
    errx(1, "host2bindaddr: %s", errmsg);
779
0
      continue;
780
0
  }
781
2
    }
782
2
    if (cfsp->bindaddr[0] == NULL) {
783
0
  cfsp->bindaddr[0] = cfsp->bindaddr[1];
784
0
  cfsp->bindaddr[1] = NULL;
785
0
    }
786
2
}
787
788
static enum rtpp_timed_cb_rvals
789
update_derived_stats(double dtime, void *argp)
790
1
{
791
1
    struct rtpp_stats *rtpp_stats;
792
793
1
    rtpp_stats = (struct rtpp_stats *)argp;
794
1
    CALL_SMETHOD(rtpp_stats, update_derived, dtime);
795
1
    return (CB_MORE);
796
1
}
797
798
#if !defined(LIBRTPPROXY)
799
static void
800
#else
801
void
802
#endif
803
rtpp_shutdown(struct rtpp_cfg *cfsp)
804
0
{
805
0
    struct rtpp_ctrl_sock *ctrl_sock, *ctrl_sock_next;
806
807
0
    CALL_METHOD(cfsp->rtpp_cmd_cf, dtor);
808
0
    CALL_SMETHOD(cfsp->sessions_wrt, purge);
809
0
    CALL_SMETHOD(cfsp->sessions_ht, purge);
810
811
0
    while ((CALL_SMETHOD(cfsp->rtp_streams_wrt, get_length) > 0) ||
812
0
      (CALL_SMETHOD(cfsp->rtcp_streams_wrt, get_length) > 0))
813
0
        continue;
814
815
0
    RTPP_OBJ_DECREF(cfsp->modules_cf);
816
0
    RTPP_OBJ_DECREF(cfsp->pproc_manager);
817
0
    free(cfsp->runcreds);
818
0
    RTPP_OBJ_DECREF(cfsp->rtpp_notify_cf);
819
0
    CALL_METHOD(cfsp->bindaddrs_cf, dtor);
820
0
    free(cfsp->locks);
821
0
    CALL_METHOD(cfsp->rtpp_tnset_cf, dtor);
822
0
    CALL_SMETHOD(cfsp->rtpp_timed_cf, shutdown);
823
0
    RTPP_OBJ_DECREF(cfsp->rtpp_timed_cf);
824
0
    CALL_METHOD(cfsp->rtpp_proc_ttl_cf, dtor);
825
0
    RTPP_OBJ_DECREF(cfsp->proc_servers);
826
0
    CALL_METHOD(cfsp->rtpp_proc_cf, dtor);
827
0
    RTPP_OBJ_DECREF(cfsp->sessinfo);
828
0
    RTPP_OBJ_DECREF(cfsp->rtpp_stats);
829
0
    for (int i = 0; i <= RTPP_PT_MAX; i++) {
830
0
        RTPP_OBJ_DECREF(cfsp->port_table[i]);
831
0
    }
832
0
    RTPP_OBJ_DECREF(cfsp->sessions_wrt);
833
0
    RTPP_OBJ_DECREF(cfsp->sessions_ht);
834
0
    RTPP_OBJ_DECREF(cfsp->rtp_streams_wrt);
835
0
    RTPP_OBJ_DECREF(cfsp->rtcp_streams_wrt);
836
0
    CALL_METHOD(cfsp->nofile, dtor);
837
0
    rtpp_controlfd_cleanup(cfsp);
838
0
    for (ctrl_sock = RTPP_LIST_HEAD(cfsp->ctrl_socks);
839
0
      ctrl_sock != NULL; ctrl_sock = ctrl_sock_next) {
840
0
        ctrl_sock_next = RTPP_ITER_NEXT(ctrl_sock);
841
0
        free(ctrl_sock);
842
0
    }
843
0
    free(cfsp->ctrl_socks);
844
0
    cfsp->ctrl_socks = NULL;
845
0
    rtpp_gen_uid_free();
846
0
}
847
848
#if !defined(LIBRTPPROXY)
849
int
850
main(int argc, char **argv)
851
#else
852
struct rtpp_cfg *
853
rtpp_main(int argc, char **argv)
854
#endif
855
2
{
856
2
    int i, len, pid_fd;
857
2
    static struct rtpp_cfg cfs;
858
2
    char buf[256];
859
2
    struct sched_param sparam;
860
2
    void *elp;
861
2
    struct rtpp_timed_task *tp;
862
2
    struct rtpp_daemon_rope drop;
863
864
2
    memset(&cfs, 0, sizeof(cfs));
865
866
2
#if defined(LIBRTPPROXY)
867
2
    cfs.ropts = (struct rtpp_run_options){
868
2
        .no_pid = 1, .no_chdir = 1, .no_daemon = 1, .no_sigtrap = 1
869
2
    };
870
2
#endif
871
872
#ifdef RTPP_CHECK_LEAKS
873
    RTPP_MEMDEB_APP_INIT();
874
#endif
875
2
    if (getdtime() == -1) {
876
0
        err(1, "timer self-test has failed: please check your build configuration");
877
        /* NOTREACHED */
878
0
    }
879
880
#ifdef RTPP_CHECK_LEAKS
881
    if (rtpp_memdeb_selftest(MEMDEB_SYM) != 0) {
882
        errx(1, "MEMDEB self-test has failed");
883
        /* NOTREACHED */
884
    }
885
#endif
886
887
2
    cfs.ctrl_socks = rtpp_zmalloc(sizeof(struct rtpp_list));
888
2
    if (cfs.ctrl_socks == NULL) {
889
0
         err(1, "can't allocate memory for the struct ctrl_socks");
890
         /* NOTREACHED */
891
0
    }
892
893
2
    cfs.modules_cf = rtpp_modman_ctor();
894
2
    if (cfs.modules_cf == NULL) {
895
0
         err(1, "can't allocate memory for the struct modules_cf");
896
         /* NOTREACHED */
897
0
    }
898
899
2
    cfs.runcreds = rtpp_zmalloc(sizeof(struct rtpp_runcreds));
900
2
    if (cfs.runcreds == NULL) {
901
0
         err(1, "can't allocate memory for the struct runcreds");
902
         /* NOTREACHED */
903
0
    }
904
905
2
    seedrandom();
906
2
    if (rtpp_gen_uid_init() != 0) {
907
0
        err(1, "rtpp_gen_uid_init() failed");
908
        /* NOTREACHED */
909
0
    }
910
911
2
    cfs.glog = rtpp_log_ctor("rtpproxy", NULL, LF_REOPEN);
912
2
    if (cfs.glog == NULL) {
913
0
        err(1, "can't initialize logging subsystem");
914
        /* NOTREACHED */
915
0
    }
916
 #ifdef RTPP_CHECK_LEAKS
917
    rtpp_memdeb_setlog(MEMDEB_SYM, cfs.glog);
918
    rtpp_memdeb_approve(MEMDEB_SYM, "_rtpp_log_open", 1, "Referenced by memdeb itself");
919
 #endif
920
921
2
    _sig_cf = &cfs;
922
2
    atexit(rtpp_glog_fin);
923
924
2
    init_config(&cfs, argc, argv);
925
926
2
    cfs.sessions_ht = rtpp_hash_table_ctor(rtpp_ht_key_str_t, 0);
927
2
    if (cfs.sessions_ht == NULL) {
928
0
        err(1, "can't allocate memory for the hash table");
929
         /* NOTREACHED */
930
0
    }
931
2
    cfs.rtp_streams_wrt = rtpp_weakref_ctor();
932
2
    if (cfs.rtp_streams_wrt == NULL) {
933
0
        err(1, "can't allocate memory for the RTP streams weakref table");
934
         /* NOTREACHED */
935
0
    }
936
2
    cfs.rtcp_streams_wrt = rtpp_weakref_ctor();
937
2
    if (cfs.rtcp_streams_wrt == NULL) {
938
0
        err(1, "can't allocate memory for the RTCP streams weakref table");
939
         /* NOTREACHED */
940
0
    }
941
2
    cfs.sessinfo = rtpp_sessinfo_ctor(&cfs);
942
2
    if (cfs.sessinfo == NULL) {
943
0
        errx(1, "cannot construct rtpp_sessinfo structure");
944
0
    }
945
946
2
    cfs.rtpp_stats = rtpp_stats_ctor();
947
2
    if (cfs.rtpp_stats == NULL) {
948
0
        err(1, "can't allocate memory for the stats data");
949
         /* NOTREACHED */
950
0
    }
951
952
6
    for (i = 0; i <= RTPP_PT_MAX; i++) {
953
4
        cfs.port_table[i] = rtpp_port_table_ctor(cfs.port_min,
954
4
          cfs.port_max, cfs.seq_ports, cfs.port_ctl);
955
4
        if (cfs.port_table[i] == NULL) {
956
0
            err(1, "can't allocate memory for the ports data");
957
            /* NOTREACHED */
958
0
        }
959
4
    }
960
961
2
    if (rtpp_controlfd_init(&cfs) != 0) {
962
0
        err(1, "can't initialize control socket%s",
963
0
          cfs.ctrl_socks->len > 1 ? "s" : "");
964
0
    }
965
966
2
    if (cfs.ropts.no_daemon == 0) {
967
0
        if (cfs.ropts.no_chdir == 0) {
968
0
            cfs.cwd_orig = getcwd(NULL, 0);
969
0
            if (cfs.cwd_orig == NULL) {
970
0
                err(1, "getcwd");
971
0
            }
972
0
        }
973
0
  drop = rtpp_daemon(cfs.ropts.no_chdir, 0);
974
0
  if (drop.result == -1)
975
0
      err(1, "can't switch into daemon mode");
976
      /* NOTREACHED */
977
0
    }
978
979
2
    if (CALL_METHOD(cfs.glog, start, &cfs) != 0) {
980
        /* We cannot possibly function with broken logs, bail out */
981
0
        syslog(LOG_CRIT, "rtpproxy pid %d has failed to initialize logging"
982
0
            " facilities: crash", getpid());
983
0
        err(1, "rtpproxy has failed to initialize logging facilities");
984
0
    }
985
986
2
    atexit(ehandler);
987
2
    RTPP_LOG(cfs.glog, RTPP_LOG_INFO, "rtpproxy started, pid %d", getpid());
988
989
2
    if (cfs.sched_policy != SCHED_OTHER) {
990
0
        sparam.sched_priority = sched_get_priority_max(cfs.sched_policy);
991
0
        if (sched_setscheduler(0, cfs.sched_policy, &sparam) == -1) {
992
0
            RTPP_ELOG(cfs.glog, RTPP_LOG_ERR, "sched_setscheduler(SCHED_%s, %d)",
993
0
              (cfs.sched_policy == SCHED_FIFO) ? "FIFO" : "RR", sparam.sched_priority);
994
0
        }
995
0
    }
996
2
    if (cfs.sched_nice != PRIO_UNSET) {
997
0
        if (setpriority(PRIO_PROCESS, 0, cfs.sched_nice) == -1) {
998
0
            RTPP_ELOG(cfs.glog, RTPP_LOG_ERR, "can't set scheduling "
999
0
              "priority to %d", cfs.sched_nice);
1000
0
            exit(1);
1001
0
        }
1002
0
    }
1003
1004
2
    if (cfs.ropts.no_pid == 0) {
1005
0
        pid_fd = open(cfs.pid_file, O_WRONLY | O_CREAT, DEFFILEMODE);
1006
0
        if (pid_fd < 0) {
1007
0
            RTPP_ELOG(cfs.glog, RTPP_LOG_ERR, "can't open pidfile for writing");
1008
0
        }
1009
2
    } else {
1010
2
        pid_fd = -1;
1011
2
    }
1012
1013
2
    if (cfs.runcreds->uname != NULL || cfs.runcreds->gname != NULL) {
1014
0
  if (drop_privileges(&cfs) != 0) {
1015
0
      RTPP_ELOG(cfs.glog, RTPP_LOG_ERR,
1016
0
        "can't switch to requested user/group");
1017
0
      exit(1);
1018
0
  }
1019
0
    }
1020
2
    set_rlimits(&cfs);
1021
1022
2
    cfs.pproc_manager = pproc_manager_ctor(cfs.rtpp_stats, 0);
1023
2
    if (cfs.pproc_manager == NULL) {
1024
0
        RTPP_LOG(cfs.glog, RTPP_LOG_ERR,
1025
0
          "can't init packet prosessing subsystem");
1026
0
        exit(1);
1027
0
    }
1028
1029
2
    cfs.rtpp_proc_cf = rtpp_proc_async_ctor(&cfs);
1030
2
    if (cfs.rtpp_proc_cf == NULL) {
1031
0
        RTPP_LOG(cfs.glog, RTPP_LOG_ERR,
1032
0
          "can't init RTP processing subsystem");
1033
0
        exit(1);
1034
0
    }
1035
1036
2
    cfs.proc_servers = rtpp_proc_servers_ctor(&cfs, cfs.rtpp_proc_cf->netio);
1037
2
    if (cfs.proc_servers == NULL) {
1038
0
        RTPP_LOG(cfs.glog, RTPP_LOG_ERR,
1039
0
          "can't init RTP playback subsystem");
1040
0
        exit(1);
1041
0
    }
1042
1043
2
    cfs.rtpp_timed_cf = rtpp_timed_ctor(0.01);
1044
2
    if (cfs.rtpp_timed_cf == NULL) {
1045
0
        RTPP_ELOG(cfs.glog, RTPP_LOG_ERR,
1046
0
          "can't init scheduling subsystem");
1047
0
        exit(1);
1048
0
    }
1049
1050
2
    tp = CALL_SMETHOD(cfs.rtpp_timed_cf, schedule_rc, 1.0,
1051
2
      cfs.rtpp_stats->rcnt, update_derived_stats, NULL,
1052
2
      cfs.rtpp_stats);
1053
2
    if (tp == NULL) {
1054
0
        RTPP_ELOG(cfs.glog, RTPP_LOG_ERR,
1055
0
          "can't schedule notification to derive stats");
1056
0
        exit(1);
1057
0
    }
1058
2
    RTPP_OBJ_DECREF(tp);
1059
1060
2
    cfs.rtpp_notify_cf = rtpp_notify_ctor(cfs.glog);
1061
2
    if (cfs.rtpp_notify_cf == NULL) {
1062
0
        RTPP_ELOG(cfs.glog, RTPP_LOG_ERR,
1063
0
          "can't init timeout notification subsystem");
1064
0
        exit(1);
1065
0
    }
1066
1067
2
    cfs.rtpp_proc_ttl_cf = rtpp_proc_ttl_ctor(&cfs);
1068
2
    if (cfs.rtpp_proc_ttl_cf == NULL) {
1069
0
        RTPP_LOG(cfs.glog, RTPP_LOG_ERR,
1070
0
          "can't init TTL processing subsystem");
1071
0
        exit(1);
1072
0
    }
1073
1074
2
#if ENABLE_MODULE_IF
1075
2
    const char *failmod;
1076
2
    if (CALL_METHOD(cfs.modules_cf, startall, &cfs, &failmod) != 0) {
1077
0
        RTPP_ELOG(cfs.glog, RTPP_LOG_ERR,
1078
0
          "%s: dymanic module start has failed", failmod);
1079
0
        exit(1);
1080
0
    }
1081
2
#endif
1082
1083
2
    cfs.rtpp_cmd_cf = rtpp_command_async_ctor(&cfs);
1084
2
    if (cfs.rtpp_cmd_cf == NULL) {
1085
0
        RTPP_ELOG(cfs.glog, RTPP_LOG_ERR,
1086
0
          "can't init command processing subsystem");
1087
0
        exit(1);
1088
0
    }
1089
1090
2
    if (cfs.ropts.no_sigtrap == 0) {
1091
0
        signal(SIGHUP, sighup);
1092
0
        signal(SIGINT, fatsignal);
1093
0
        signal(SIGKILL, fatsignal);
1094
0
        signal(SIGPIPE, SIG_IGN);
1095
0
        signal(SIGTERM, fatsignal);
1096
0
        signal(SIGXCPU, fatsignal);
1097
0
        signal(SIGXFSZ, fatsignal);
1098
0
        signal(SIGVTALRM, fatsignal);
1099
0
        signal(SIGPROF, fatsignal);
1100
0
        signal(SIGUSR1, fatsignal);
1101
0
        signal(SIGUSR2, fatsignal);
1102
0
        RTPP_DBGCODE(catchtrace) {
1103
0
            signal(SIGQUIT, rtpp_stacktrace);
1104
0
            signal(SIGILL, rtpp_stacktrace);
1105
0
            signal(SIGTRAP, rtpp_stacktrace);
1106
0
            signal(SIGABRT, rtpp_stacktrace);
1107
#if defined(SIGEMT)
1108
            signal(SIGEMT, rtpp_stacktrace);
1109
#endif
1110
0
            signal(SIGFPE, rtpp_stacktrace);
1111
0
            signal(SIGBUS, rtpp_stacktrace);
1112
0
            signal(SIGSEGV, rtpp_stacktrace);
1113
0
            signal(SIGSYS, rtpp_stacktrace);
1114
0
        }
1115
0
    }
1116
1117
#if !defined(LIBRTPPROXY)
1118
    elp = prdic_init(cfs.target_pfreq / 10.0, 0.0);
1119
    if (elp == NULL) {
1120
        RTPP_LOG(cfs.glog, RTPP_LOG_ERR, "prdic_init() failed");
1121
        exit(1);
1122
    }
1123
#endif
1124
1125
2
    if (pid_fd >= 0) {
1126
0
        if (ftruncate(pid_fd, 0) != 0) {
1127
0
            RTPP_ELOG(cfs.glog, RTPP_LOG_ERR, "can't truncate pidfile");
1128
0
            exit(1);
1129
0
        }
1130
0
        len = sprintf(buf, "%u\n", (unsigned int)getpid());
1131
0
        if (write(pid_fd, buf, len) != len) {
1132
0
            RTPP_ELOG(cfs.glog, RTPP_LOG_ERR, "can't write pidfile");
1133
0
            exit(1);
1134
0
        }
1135
0
        close(pid_fd);
1136
0
    }
1137
1138
#ifdef HAVE_SYSTEMD_DAEMON
1139
    sd_notify(0, "READY=1");
1140
#endif
1141
1142
2
    if (cfs.ropts.no_daemon == 0) {
1143
0
        if (rtpp_daemon_rel_parent(&drop) != 0) {
1144
0
            RTPP_LOG(cfs.glog, RTPP_LOG_ERR, "parent died prematurely #cry #die");
1145
0
            exit(1);
1146
0
        }
1147
0
    }
1148
1149
2
#if defined(LIBRTPPROXY)
1150
2
    return (&cfs);
1151
0
#endif
1152
1153
0
    for (;;) {
1154
0
        if (cfs.fastshutdown != 0) {
1155
0
            break;
1156
0
        }
1157
0
        if (cfs.slowshutdown != 0 &&
1158
0
          CALL_SMETHOD(cfs.sessions_wrt, get_length) == 0) {
1159
0
            RTPP_LOG(cfs.glog, RTPP_LOG_INFO,
1160
0
              "deorbiting-burn sequence completed, exiting");
1161
0
            break;
1162
0
        }
1163
0
        prdic_procrastinate(elp);
1164
0
    }
1165
0
    prdic_free(elp);
1166
1167
0
    rtpp_shutdown(&cfs);
1168
1169
#ifdef HAVE_SYSTEMD_DAEMON
1170
    sd_notify(0, "STATUS=Exited");
1171
#endif
1172
1173
0
    rtpp_exit(1, 0);
1174
2
}