varnish-cache/bin/varnishd/mgt/mgt_main.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2017 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * The management process and CLI handling
31
 */
32
33
#include "config.h"
34
35
#include <ctype.h>
36
#include <fcntl.h>
37
#include <signal.h>
38
#include <stdarg.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
#include <syslog.h>
43
#include <unistd.h>
44
#include <sys/resource.h>
45
#include <sys/stat.h>
46
#include <sys/socket.h>
47
48
#include "mgt/mgt.h"
49
#include "acceptor/mgt_acceptor.h"
50
#include "common/heritage.h"
51
52
#include "hash/hash_slinger.h"
53
#include "libvcc.h"
54
#include "vcli_serve.h"
55
#include "vct.h"
56
#include "vev.h"
57
#include "vfil.h"
58
#include "vin.h"
59
#include "vpf.h"
60
#include "vrnd.h"
61
#include "vsha256.h"
62
#include "vsub.h"
63
#include "vtim.h"
64
#include "waiter/mgt_waiter.h"
65
#include "vsa.h"
66
#include "vus.h"
67
68
struct heritage         heritage;
69
unsigned                d_flag = 0;
70
struct vev_root         *mgt_evb;
71
int                     exit_status = 0;
72
struct vsb              *vident;
73
struct VSC_mgt          *VSC_C_mgt;
74
static int              I_fd = -1;
75
static char             *workdir;
76
77
static struct vfil_path *vcl_path = NULL;
78
79
static const char opt_spec[] = "?a:b:CdE:f:Fh:i:I:j:l:M:n:P:p:r:S:s:T:t:VW:x:";
80
81
/*--------------------------------------------------------------------*/
82
83
// Basic options documentation with compile time dependencies
84
static void
85 40
mgt_DumpOptions(void)
86
{
87 40
        printf(".. _opt_n:\n\n");
88 40
        printf("-n workdir\n\n");
89 40
        printf("  Runtime directory for the shared memory, "
90
               "compiled VCLs etc.\n\n");
91 40
        printf("  In performance critical applications, this directory "
92
               "should be on a RAM backed filesystem.\n\n");
93 40
        printf("  When running multiple varnishd instances, separate "
94
               "directories need to be used.\n\n");
95 40
        VIN_DumpDefaults();
96 40
}
97
98
static void
99 80
usage(void)
100
{
101
        char *p;
102
103
#define FMT_NONL "  %-35s # %s"
104
#define FMT FMT_NONL "\n"
105
106 80
        printf( "Usage: varnishd [options]\n");
107
108 80
        printf("\nBasic options:\n");
109
110 80
        printf(FMT, "[-a [name=][listen_address",
111
            "HTTP listen address, protocol, options.");
112 80
        printf(FMT, "     [,PROTO|,option=value,...]]",
113
            "Can be specified multiple times.");
114 80
        printf(FMT, "",
115
            "  default: \":80,HTTP\"");
116 80
        printf(FMT, "  options:",
117
            "Proto can be \"PROXY\" or \"HTTP\" (default)");
118 80
        printf(FMT, "    [,user=<u>][,group=<g>]",
119
            "user, group and mode set permissions for");
120 80
        printf(FMT, "    [,mode=<m>]",
121
            "  a Unix domain socket.");
122 80
        printf(FMT, "-b none", "No backend");
123 80
        printf(FMT, "-b [addr[:port]|path]", "Backend address and port");
124 80
        printf(FMT, "", "  or socket file path");
125 80
        printf(FMT, "", "  default: \":80\"");
126 80
        printf(FMT, "-f vclfile", "VCL program");
127 80
        printf(FMT, "", "Can be specified multiple times.");
128 80
        printf(FMT, "-n dir", "Working directory");
129
130 80
        p = VIN_n_Arg(NULL);
131 80
        AN(p);
132 80
        printf(FMT_NONL "  default: %s\n", "", "", p);
133 80
        free(p);
134
135 80
        printf("\n-b can be used only once, and not together with -f\n");
136
137 80
        printf("\nDocumentation options:\n");
138 80
        printf(FMT, "-?", "Prints this usage message");
139 80
        printf(FMT, "-x parameter", "Parameter documentation");
140 80
        printf(FMT, "-x vsl", "VSL record documentation");
141 80
        printf(FMT, "-x cli", "CLI command documentation");
142 80
        printf(FMT, "-x builtin", "Builtin VCL program");
143 80
        printf(FMT, "-x optstring", "List of getopt options");
144 80
        printf(FMT, "-x options", "Dynamic options documentation");
145
146 80
        printf("\nOperations options:\n");
147
148 80
        printf(FMT, "-F", "Run in foreground");
149 80
        printf(FMT, "-T address[:port]", "CLI address");
150 80
        printf(FMT, "", "Can be specified multiple times.");
151 80
        printf(FMT, "-M address:port", "Reverse CLI destination");
152 80
        printf(FMT, "", "Can be specified multiple times.");
153 80
        printf(FMT, "-P file", "PID file");
154 80
        printf(FMT, "-i identity", "Identity of varnish instance");
155 80
        printf(FMT, "-I clifile", "Initialization CLI commands");
156 80
        printf(FMT, "-E extension", "Load extension");
157
158 80
        printf("\nTuning options:\n");
159
160 80
        printf(FMT, "-t TTL", "Default TTL");
161 80
        printf(FMT, "-p param=value", "set parameter");
162 80
        printf(FMT, "", "Can be specified multiple times.");
163
164 80
        printf(FMT, "-s [name=]kind[,options]", "Storage specification");
165 80
        printf(FMT, "", "Can be specified multiple times.");
166
#ifdef HAVE_UMEM_H
167
        printf(FMT, "", "  -s default (=umem)");
168
        printf(FMT, "", "  -s umem");
169
#else
170 80
        printf(FMT, "", "  -s default (=malloc)");
171
#endif
172 80
        printf(FMT, "", "  -s malloc");
173 80
        printf(FMT, "", "  -s file");
174
175 80
        printf(FMT, "-l vsl", "Size of shared memory log");
176 80
        printf(FMT, "", "  vsl: space for VSL records [80m]");
177
178 80
        printf("\nSecurity options:\n");
179
180 80
        printf(FMT, "-r param[,param...]", "Set parameters read-only from CLI");
181 80
        printf(FMT, "", "Can be specified multiple times.");
182 80
        printf(FMT, "-S secret-file", "Secret file for CLI authentication");
183 80
        printf(FMT, "-j jail[,options]", "Jail specification");
184
#ifdef HAVE_SETPPRIV
185
        printf(FMT, "", "  -j solaris");
186
#endif
187
#ifdef __linux__
188
        printf(FMT, "", "  -j linux");
189
#endif
190 80
        printf(FMT, "", "  -j unix");
191 80
        printf(FMT, "", "  -j none");
192
193 80
        printf("\nAdvanced/Dev/Debug options:\n");
194
195 80
        printf(FMT, "-d", "debug mode");
196 80
        printf(FMT, "", "Stay in foreground, CLI on stdin.");
197 80
        printf(FMT, "-C", "Output VCL code compiled to C language");
198 80
        printf(FMT, "-V", "version");
199 80
        printf(FMT, "-h kind[,options]", "Hash specification");
200 80
        printf(FMT, "-W waiter", "Waiter implementation");
201 80
}
202
203
/*--------------------------------------------------------------------*/
204
205
struct arg_list {
206
        unsigned                magic;
207
#define ARG_LIST_MAGIC          0x7b0d1bc4
208
        char                    arg[2];
209
        char                    *val;
210
        VTAILQ_ENTRY(arg_list)  list;
211
        void                    *priv;
212
};
213
214
static VTAILQ_HEAD(, arg_list) arglist = VTAILQ_HEAD_INITIALIZER(arglist);
215
216
static struct arg_list *
217 558040
arg_list_add(const char arg, const char *val)
218
{
219
        struct arg_list *alp;
220
221 558040
        ALLOC_OBJ(alp, ARG_LIST_MAGIC);
222 558040
        AN(alp);
223 558040
        alp->arg[0] = arg;
224 558040
        alp->arg[1] = '\0';
225 558040
        REPLACE(alp->val, val);
226 558040
        VTAILQ_INSERT_TAIL(&arglist, alp, list);
227 558040
        return (alp);
228
}
229
230
static unsigned
231 165960
arg_list_count(const char *arg)
232
{
233 165960
        unsigned retval = 0;
234
        struct arg_list *alp;
235
236 2171760
        VTAILQ_FOREACH(alp, &arglist, list) {
237 2005800
                if (!strcmp(alp->arg, arg))
238 6800
                        retval++;
239 2005800
        }
240 165960
        return (retval);
241
}
242
243
/*--------------------------------------------------------------------*/
244
245
static void
246 558240
cli_check(const struct cli *cli)
247
{
248 558240
        if (cli->result == CLIS_OK || cli->result == CLIS_TRUNCATED) {
249 558160
                AZ(VSB_finish(cli->sb));
250 558160
                if (VSB_len(cli->sb) > 0)
251 80
                        fprintf(stderr, "Warnings:\n%s\n", VSB_data(cli->sb));
252 558160
                VSB_clear(cli->sb);
253 558160
                return;
254
        }
255 80
        AZ(VSB_finish(cli->sb));
256 80
        fprintf(stderr, "Error:\n%s\n", VSB_data(cli->sb));
257 80
        exit(2);
258
}
259
260
/*--------------------------------------------------------------------
261
 * This function is called when the CLI on stdin is closed.
262
 */
263
264
static int v_matchproto_(mgt_cli_close_f)
265 38400
mgt_stdin_close(void *priv)
266
{
267
268 38400
        (void)priv;
269 38400
        return (-42);
270
}
271
272
/*--------------------------------------------------------------------
273
 * Autogenerate a -S file using strong random bits from the kernel.
274
 */
275
276
static void
277 185600
mgt_secret_atexit(void)
278
{
279
280
        /* Only master process */
281 185600
        if (getpid() != heritage.mgt_pid)
282 146640
                return;
283 38960
        VJ_master(JAIL_MASTER_FILE);
284 38960
        (void)unlink("_.secret");
285 38960
        VJ_master(JAIL_MASTER_LOW);
286 185600
}
287
288
static const char *
289 39000
make_secret(const char *dirname)
290
{
291
        char *fn;
292
        int fdo;
293
        int i;
294
        unsigned char b;
295
296 39000
        assert(asprintf(&fn, "%s/_.secret", dirname) > 0);
297
298 39000
        VJ_master(JAIL_MASTER_FILE);
299 39000
        if (unlink(fn) < 0 && errno != ENOENT) {
300 40
                ARGV_ERR("Cannot remove preexisting secret-file in %s (%s)\n",
301
                    dirname, VAS_errtxt(errno));
302 0
        }
303
304 0
        fdo = open(fn, O_RDWR|O_CREAT|O_EXCL, 0640);
305 0
        if (fdo < 0) {
306 0
                ARGV_ERR("Cannot create secret-file in %s (%s)\n",
307
                    dirname, VAS_errtxt(errno));
308 0
        }
309
310 10012720
        for (i = 0; i < 256; i++) {
311 9973760
                AZ(VRND_RandomCrypto(&b, 1));
312 9973760
                assert(1 == write(fdo, &b, 1));
313 9973760
        }
314 38960
        closefd(&fdo);
315 38960
        VJ_master(JAIL_MASTER_LOW);
316 38960
        AZ(atexit(mgt_secret_atexit));
317 38960
        return (fn);
318
}
319
320
static void
321 480
mgt_Cflag_atexit(void)
322
{
323
324
        /* Only master process */
325 480
        if (getpid() != heritage.mgt_pid)
326 320
                return;
327 160
        if (arg_list_count("E")) {
328 0
                vext_cleanup(1);
329 0
                VJ_rmdir("vext_cache");
330 0
        }
331 160
        VJ_rmdir("vmod_cache");
332 160
        VJ_rmdir("worker_tmpdir");
333 160
        (void)chdir("/");
334 160
        VJ_rmdir(workdir);
335 480
}
336
337
/*--------------------------------------------------------------------*/
338
339
static void
340 42120
mgt_tests(void)
341
{
342 42120
        assert(VTIM_parse("Sun, 06 Nov 1994 08:49:37 GMT") == 784111777);
343 42120
        assert(VTIM_parse("Sunday, 06-Nov-94 08:49:37 GMT") == 784111777);
344 42120
        assert(VTIM_parse("Sun Nov  6 08:49:37 1994") == 784111777);
345
346
        /* Check that our VSHA256 works */
347 42120
        VSHA256_Test();
348 42120
}
349
350
static void
351 42120
mgt_initialize(struct cli *cli)
352
{
353
        static unsigned clilim = 32768;
354
355
        /* for ASSERT_MGT() */
356 42120
        heritage.mgt_pid = getpid();
357
358
        /* Create a cli for convenience in otherwise CLI functions */
359 42120
        INIT_OBJ(cli, CLI_MAGIC);
360 42120
        cli[0].sb = VSB_new_auto();
361 42120
        AN(cli[0].sb);
362 42120
        cli[0].result = CLIS_OK;
363 42120
        cli[0].limit = &clilim;
364
365 42120
        mgt_cli_init_cls();             // CLI commands can be registered
366
367 42120
        MCF_InitParams(cli);
368
369 42120
        VCC_VCL_Range(&heritage.min_vcl_version, &heritage.max_vcl_version);
370
371 42120
        cli_check(cli);
372 42120
}
373
374
static void
375 360
mgt_x_arg(const char *x_arg)
376
{
377 360
        if (!strcmp(x_arg, "parameter"))
378 80
                MCF_DumpRstParam();
379 280
        else if (!strcmp(x_arg, "vsl"))
380 40
                mgt_DumpRstVsl();
381 240
        else if (!strcmp(x_arg, "cli"))
382 80
                mgt_DumpRstCli();
383 160
        else if (!strcmp(x_arg, "builtin"))
384 40
                mgt_DumpBuiltin();
385 120
        else if (!strcmp(x_arg, "optstring"))
386 40
                (void)printf("%s\n", opt_spec);
387 80
        else if (!strcmp(x_arg, "options"))
388 40
                mgt_DumpOptions();
389
        else
390 40
                ARGV_ERR("Invalid -x argument\n");
391 320
}
392
393
/*--------------------------------------------------------------------*/
394
395
#define ERIC_MAGIC 0x2246988a           /* Eric is not random */
396
397
static int
398 920
mgt_eric(void)
399
{
400
        int eric_pipes[2];
401
        unsigned u;
402
        ssize_t sz;
403
404 920
        AZ(pipe(eric_pipes));
405
406 920
        switch (fork()) {
407
        case -1:
408 0
                fprintf(stderr, "Fork() failed: %s\n", VAS_errtxt(errno));
409 0
                exit(-1);
410
        case 0:
411 920
                closefd(&eric_pipes[0]);
412 920
                assert(setsid() > 1);
413
414 920
                VFIL_null_fd(STDIN_FILENO);
415 920
                return (eric_pipes[1]);
416
        default:
417 920
                break;
418
        }
419 920
        closefd(&eric_pipes[1]);
420 920
        sz = read(eric_pipes[0], &u, sizeof u);
421 920
        if (sz == sizeof u && u == ERIC_MAGIC)
422 0
                exit(0);
423 320
        else if (sz == sizeof u && u != 0)
424 320
                exit(u);
425
        else
426 600
                exit(-1);
427
}
428
429
static void
430 320
mgt_eric_im_done(int eric_fd, unsigned u)
431
{
432
433 320
        if (u == 0)
434 0
                u = ERIC_MAGIC;
435
436 320
        VFIL_null_fd(STDIN_FILENO);
437 320
        VFIL_null_fd(STDOUT_FILENO);
438 320
        VFIL_null_fd(STDERR_FILENO);
439
440 320
        assert(write(eric_fd, &u, sizeof u) == sizeof u);
441 320
        closefd(&eric_fd);
442 320
}
443
444
/*--------------------------------------------------------------------*/
445
446
static int v_matchproto_(vev_cb_f)
447 160
mgt_sigint(const struct vev *e, int what)
448
{
449
450 160
        (void)what;
451 160
        MGT_Complain(C_ERR, "Manager got %s from PID %jd", e->name, (intmax_t)e->siginfo->si_pid);
452 160
        (void)fflush(stdout);
453 160
        if (MCH_Running())
454 120
                MCH_Stop_Child();
455 160
        return (-42);
456
}
457
458
/*--------------------------------------------------------------------*/
459
460
static int v_matchproto_(vev_cb_f)
461 99642
mgt_uptime(const struct vev *e, int what)
462
{
463
        static double mgt_uptime_t0 = 0;
464
465 99642
        (void)e;
466 99642
        (void)what;
467 99642
        AN(VSC_C_mgt);
468 99642
        if (mgt_uptime_t0 == 0)
469 37220
                mgt_uptime_t0 = VTIM_real();
470 99642
        VSC_C_mgt->uptime = (uint64_t)(VTIM_real() - mgt_uptime_t0);
471 99642
        return (0);
472
}
473
474
/*--------------------------------------------------------------------*/
475
476
static int v_matchproto_(mgt_cli_close_f)
477 40
mgt_I_close(void *priv)
478
{
479 40
        (void)priv;
480 40
        fprintf(stderr, "END of -I file processing\n");
481 40
        I_fd = -1;
482 40
        return (0);
483
}
484
485
/*--------------------------------------------------------------------*/
486
487
struct f_arg {
488
        unsigned                magic;
489
#define F_ARG_MAGIC             0x840649a8
490
        char                    *farg;
491
        char                    *src;
492
};
493
494
static struct f_arg *
495 520
mgt_f_read(const char *fn)
496
{
497
        struct f_arg *fa;
498
        char *f, *fnp;
499
500 520
        ALLOC_OBJ(fa, F_ARG_MAGIC);
501 520
        AN(fa);
502 520
        REPLACE(fa->farg, fn);
503 520
        VFIL_setpath(&vcl_path, mgt_vcl_path);
504 520
        if (VFIL_searchpath(vcl_path, NULL, &f, fn, &fnp) || f == NULL) {
505 120
                ARGV_ERR("Cannot read -f file '%s' (%s)\n",
506
                    fnp != NULL ? fnp : fn, VAS_errtxt(errno));
507 0
        }
508 400
        free(fa->farg);
509 400
        fa->farg = fnp;
510 400
        fa->src = f;
511 400
        return (fa);
512
}
513
514
static void
515 1120
mgt_b_conv(const char *b_arg)
516
{
517
        struct f_arg *fa;
518
        struct vsb *vsb;
519
520 1120
        ALLOC_OBJ(fa, F_ARG_MAGIC);
521 1120
        AN(fa);
522 1120
        REPLACE(fa->farg, "<-b argument>");
523 1120
        vsb = VSB_new_auto();
524 1120
        AN(vsb);
525 1120
        VSB_cat(vsb, "vcl 4.1;\n");
526 1120
        VSB_cat(vsb, "backend default ");
527 1120
        if (!strcasecmp(b_arg, "none"))
528 640
                VSB_cat(vsb, "none;\n");
529 480
        else if (VUS_is(b_arg))
530 40
                VSB_printf(vsb, "{\n    .path = \"%s\";\n}\n", b_arg);
531
        else
532 440
                VSB_printf(vsb, "{\n    .host = \"%s\";\n}\n", b_arg);
533 1120
        AZ(VSB_finish(vsb));
534 1120
        fa->src = strdup(VSB_data(vsb));
535 1120
        AN(fa->src);
536 1120
        VSB_destroy(&vsb);
537 1120
        AZ(arg_list_count("f"));
538 1120
        arg_list_add('f', "")->priv = fa;
539 1120
}
540
541
static int
542 1240
mgt_process_f_arg(struct cli *cli, unsigned C_flag, void **fap)
543
{
544 1240
        int retval = 0;
545
        struct f_arg *fa;
546 1240
        const char *name = NULL;
547
548 1240
        TAKE_OBJ_NOTNULL(fa, fap, F_ARG_MAGIC);
549 1240
        if (arg_list_count("f") == 1)
550 1160
                name = "boot";
551 1240
        mgt_vcl_startup(cli, fa->src, name, fa->farg, C_flag);
552 1240
        if (C_flag) {
553 160
                if (cli->result != CLIS_OK &&
554 0
                    cli->result != CLIS_TRUNCATED)
555 0
                        retval = 2;
556 160
                AZ(VSB_finish(cli->sb));
557 160
                fprintf(stderr, "%s\n", VSB_data(cli->sb));
558 160
                VSB_clear(cli->sb);
559 160
        } else {
560 1080
                cli_check(cli);
561
        }
562 1240
        free(fa->farg);
563 1240
        free(fa->src);
564 1240
        FREE_OBJ(fa);
565 1200
        return (retval);
566
}
567
568
static char *
569 0
create_bogo_n_arg(void)
570
{
571
        struct vsb *vsb;
572
        char *p;
573
574 0
        vsb = VSB_new_auto();
575 0
        AN(vsb);
576 0
        if (getenv("TMPDIR") != NULL)
577 0
                VSB_printf(vsb, "%s", getenv("TMPDIR"));
578
        else
579 0
                VSB_cat(vsb, "/tmp");
580 0
        VSB_cat(vsb, "/varnishd_C_XXXXXXX");
581 0
        AZ(VSB_finish(vsb));
582 0
        p = strdup(VSB_data(vsb));
583 0
        AN(p);
584 0
        VSB_destroy(&vsb);
585 0
        AN(mkdtemp(p));
586 0
        AZ(chmod(p, 0750));
587 0
        return (p);
588
}
589
590
static struct vpf_fh *
591 77520
create_pid_file(pid_t *ppid, const char *fmt, ...)
592
{
593
        struct vsb *vsb;
594
        va_list ap;
595
        struct vpf_fh *pfh;
596
597 77520
        va_start(ap, fmt);
598 77520
        vsb = VSB_new_auto();
599 77520
        AN(vsb);
600 77520
        VSB_vprintf(vsb, fmt, ap);
601 77520
        AZ(VSB_finish(vsb));
602 77520
        VJ_master(JAIL_MASTER_FILE);
603 77520
        pfh = VPF_Open(VSB_data(vsb), 0644, ppid);
604 77520
        if (pfh == NULL && errno == EEXIST)
605 120
                ARGV_ERR(
606
                    "Varnishd is already running (pid=%jd) (pidfile=%s)\n",
607
                    (intmax_t)*ppid, VSB_data(vsb));
608 40
        if (pfh == NULL)
609 40
                ARGV_ERR("Could not open pid-file (%s): %s\n",
610
                    VSB_data(vsb), VAS_errtxt(errno));
611 77360
        VJ_master(JAIL_MASTER_LOW);
612 77360
        VSB_destroy(&vsb);
613 77360
        va_end(ap);
614 77360
        return (pfh);
615
}
616
617
int
618 42160
main(int argc, char * const *argv)
619
{
620 42160
        int o, eric_fd = -1;
621 42160
        unsigned C_flag = 0;
622 42160
        unsigned F_flag = 0;
623 42160
        const char *b_arg = NULL;
624 42160
        const char *i_arg = NULL;
625 42160
        const char *j_arg = NULL;
626 42160
        const char *h_arg = "critbit";
627 42160
        const char *n_arg = getenv("VARNISH_DEFAULT_N");
628 42160
        const char *S_arg = NULL;
629 42160
        const char *s_arg = "default,100m";
630 42160
        const char *W_arg = NULL;
631
        const char *c;
632
        char *p;
633
        struct cli cli[1];
634
        const char *err;
635
        unsigned u;
636
        struct sigaction sac;
637
        struct vev *e;
638
        pid_t pid;
639
        struct arg_list *alp;
640 42160
        int first_arg = 1;
641
        struct vsb *vsb;
642
643 42160
        if (argc == 2 && !strcmp(argv[1], "--optstring")) {
644 40
                printf("%s\n", opt_spec);
645 40
                exit(0);
646
        }
647
648 42120
        heritage.argc = argc;
649 42120
        heritage.argv = argv;
650
651 42120
        setbuf(stdout, NULL);
652 42120
        setbuf(stderr, NULL);
653
654 42120
        mgt_tests();
655
656 42120
        mgt_initialize(cli);
657
658 639160
        for (; (o = getopt(argc, argv, opt_spec)) != -1; first_arg = 0) {
659 597680
                switch (o) {
660
                case 'V':
661 120
                        if (!first_arg)
662 40
                                ARGV_ERR("-V must be the first argument\n");
663 40
                        if (argc != 2)
664 40
                                ARGV_ERR("Too many arguments for -V\n");
665 40
                        VCS_Message("varnishd");
666 40
                        exit(0);
667
                case 'x':
668 440
                        if (!first_arg)
669 40
                                ARGV_ERR("-x must be the first argument\n");
670 40
                        if (argc != 3)
671 40
                                ARGV_ERR("Too many arguments for -x\n");
672 360
                        mgt_x_arg(optarg);
673 360
                        exit(0);
674
                case 'b':
675 1240
                        b_arg = optarg;
676 1240
                        break;
677
                case 'C':
678 280
                        C_flag = 1;
679 280
                        break;
680
                case 'd':
681 39760
                        d_flag++;
682 39760
                        break;
683
                case 'F':
684 560
                        F_flag = 1;
685 560
                        break;
686
                case 'j':
687 400
                        j_arg = optarg;
688 400
                        break;
689
                case 'h':
690 160
                        h_arg = optarg;
691 160
                        break;
692
                case 'i':
693 38480
                        i_arg = optarg;
694 38480
                        break;
695
                case 'l':
696 38560
                        arg_list_add('p', "vsl_space")->priv = optarg;
697 38560
                        break;
698
                case 'n':
699 39200
                        n_arg = optarg;
700 39200
                        break;
701
                case 'S':
702 40
                        S_arg = optarg;
703 40
                        break;
704
                case 't':
705 40
                        arg_list_add('p', "default_ttl")->priv = optarg;
706 40
                        break;
707
                case 'W':
708 240
                        W_arg = optarg;
709 240
                        break;
710
                case 'a':
711
                case 'E':
712
                case 'f':
713
                case 'I':
714
                case 'p':
715
                case 'P':
716
                case 'M':
717
                case 'r':
718
                case 's':
719
                case 'T':
720 438080
                        (void)arg_list_add(o, optarg);
721 438080
                        break;
722
                default:
723 80
                        usage();
724 80
                        exit(2);
725
                }
726 597040
        }
727
728 41480
        if (argc != optind)
729 40
                ARGV_ERR("Too many arguments (%s...)\n", argv[optind]);
730
731 1240
        if (b_arg != NULL && arg_list_count("f"))
732 40
                ARGV_ERR("Only one of -b or -f can be specified\n");
733
734 39680
        if (d_flag && F_flag)
735 40
                ARGV_ERR("Only one of -d or -F can be specified\n");
736
737 280
        if (C_flag && b_arg == NULL && !arg_list_count("f"))
738 40
                ARGV_ERR("-C needs either -b <backend> or -f <vcl_file>\n");
739
740 39640
        if (d_flag && C_flag)
741 40
                ARGV_ERR("-d makes no sense with -C\n");
742
743 520
        if (F_flag && C_flag)
744 40
                ARGV_ERR("-F makes no sense with -C\n");
745
746 1640
        if (!d_flag && b_arg == NULL && !arg_list_count("f"))
747 40
                ARGV_ERR("Neither -b nor -f given. (use -f '' to override)\n");
748
749 40
        if (arg_list_count("I") > 1)
750 40
                ARGV_ERR("\tOnly one -I allowed\n");
751
752 1560
        if (d_flag || F_flag)
753 40080
                complain_to_stderr = 1;
754
755 41160
        if (!arg_list_count("T"))
756 41160
                (void)arg_list_add('T', "localhost:0");
757
758
        /*
759
         * Start out by closing all unwanted file descriptors we might
760
         * have inherited from sloppy process control daemons.
761
         */
762 41320
        VSUB_closefrom(STDERR_FILENO + 1);
763 41320
        MCH_TrackHighFd(STDERR_FILENO);
764
765
        /*
766
         * Have Eric Daemonize us if need be
767
         */
768 41320
        if (!C_flag && !d_flag && !F_flag) {
769 920
                eric_fd = mgt_eric();
770 920
                MCH_TrackHighFd(eric_fd);
771 920
                heritage.mgt_pid = getpid();
772 920
        }
773
774 41160
        VRND_SeedAll();
775
776 41160
        vident = mgt_BuildVident();
777
778
        /* Various initializations */
779 41160
        VTAILQ_INIT(&heritage.socks);
780 41160
        VCA_Config();
781 41160
        mgt_evb = VEV_New();
782 41160
        AN(mgt_evb);
783
784
        /* Initialize transport protocols */
785 41160
        XPORT_Init();
786
787 41160
        VJ_Init(j_arg);
788
789
        /* Initialize the bogo-IP VSA */
790 41160
        VSA_Init();
791
792 41160
        if (b_arg != NULL)
793 1120
                mgt_b_conv(b_arg);
794
795
        /* Process delayed arguments */
796 555960
        VTAILQ_FOREACH(alp, &arglist, list) {
797 516520
                switch(alp->arg[0]) {
798
                case 'a':
799 40880
                        VCA_Arg(alp->val);
800 40880
                        break;
801
                case 'f':
802 1880
                        if (*alp->val != '\0')
803 520
                                alp->priv = mgt_f_read(alp->val);
804 1760
                        break;
805
                case 'E':
806 40
                        vext_argument(alp->val);
807 40
                        break;
808
                case 'I':
809 200
                        VJ_master(JAIL_MASTER_FILE);
810 200
                        I_fd = open(alp->val, O_RDONLY);
811 200
                        if (I_fd < 0)
812 40
                                ARGV_ERR("\tCan't open %s: %s\n",
813
                                    alp->val, VAS_errtxt(errno));
814 160
                        VJ_master(JAIL_MASTER_LOW);
815 160
                        break;
816
                case 'p':
817 352960
                        if (alp->priv) {
818 38600
                                MCF_ParamSet(cli, alp->val, alp->priv);
819 38600
                        } else {
820 314360
                                p = strchr(alp->val, '=');
821 314360
                                if (p == NULL)
822 0
                                        ARGV_ERR("\t-p lacks '='\n");
823 314360
                                AN(p);
824 314360
                                *p++ = '\0';
825 314360
                                MCF_ParamSet(cli, alp->val, p);
826
                        }
827 352960
                        break;
828
                case 'r':
829 120
                        MCF_ParamProtect(cli, alp->val);
830 120
                        break;
831
                case 's':
832 4240
                        STV_Config(alp->val);
833 4240
                        break;
834
                default:
835 116200
                        break;
836
                }
837 516360
                cli_check(cli);
838 516360
        }
839
840 39400
        VCLS_SetLimit(mgt_cls, &mgt_param.cli_limit);
841
842 39400
        assert(d_flag == 0 || F_flag == 0);
843
844 39400
        p = NULL;
845 39400
        if (C_flag && n_arg == NULL) {
846 0
                p = create_bogo_n_arg();
847 0
                n_arg = p;
848 0
        }
849
850 40
        if (S_arg != NULL && !strcmp(S_arg, "none")) {
851 0
                fprintf(stderr,
852
                    "Warning: CLI authentication disabled.\n");
853 40
        } else if (S_arg != NULL) {
854 40
                VJ_master(JAIL_MASTER_FILE);
855 40
                o = open(S_arg, O_RDONLY, 0);
856 40
                if (o < 0)
857 40
                        ARGV_ERR("Cannot open -S file (%s): %s\n",
858
                            S_arg, VAS_errtxt(errno));
859 0
                closefd(&o);
860 0
                VJ_master(JAIL_MASTER_LOW);
861 0
        }
862
863 39360
        workdir = VIN_n_Arg(n_arg);
864 39360
        AN(workdir);
865 39360
        if (p != NULL)
866 0
                free(p);
867
868 38360
        if (i_arg == NULL || *i_arg == '\0')
869 1000
                i_arg = mgt_HostName();
870 115800
        else for (c = i_arg; *c != '\0'; c++) {
871 77440
                if (!vct_istchar(*c))
872 0
                        ARGV_ERR("Invalid character '%c' for -i\n", *c);
873 77440
        }
874 39360
        heritage.identity = i_arg;
875
876 39360
        mgt_ProcTitle("Mgt");
877
878 39360
        openlog("varnishd", LOG_PID, LOG_LOCAL0);
879
880 39360
        vsb = VSB_new_auto();
881 39360
        AN(vsb);
882 39360
        o = VJ_make_workdir(workdir, vsb);
883 39360
        MGT_ComplainVSB(o ? C_ERR : C_INFO, vsb);
884 39360
        if (o)
885 0
                ARGV_EXIT;
886
887 39360
        VJ_master(JAIL_MASTER_SYSTEM);
888
#ifdef RLIMIT_MEMLOCK
889
        /* try to raise to max (ignore error), then set _cur to whatever we got */
890
        struct rlimit rlim;
891 39360
        rlim.rlim_cur = 0;
892 39360
        rlim.rlim_max = RLIM_INFINITY;
893 39360
        (void)setrlimit(RLIMIT_MEMLOCK, &rlim);
894 39360
        AZ(getrlimit(RLIMIT_MEMLOCK, &rlim));
895 39360
        rlim.rlim_cur = rlim.rlim_max;
896 39360
        AZ(setrlimit(RLIMIT_MEMLOCK, &rlim));
897
#endif
898
899 39360
        AZ(system("rm -rf vmod_cache vext_cache worker_tmpdir"));
900 39360
        VJ_master(JAIL_MASTER_LOW);
901
902 39360
        VSB_clear(vsb);
903 78720
        o = VJ_make_subdir("vmod_cache", "VMOD cache", vsb) ||
904 39360
            VJ_make_subdir("worker_tmpdir",
905 157440
                "TMPDIR for the worker process", vsb) ||
906 39360
            (arg_list_count("E") &&
907 40
                VJ_make_subdir("vext_cache", "VEXT cache", vsb));
908 78720
        MGT_ComplainVSB(o ? C_ERR : C_INFO, vsb);
909 78720
        VSB_destroy(&vsb);
910 78720
        if (o)
911 0
                ARGV_EXIT;
912
913 39360
        o = open("worker_tmpdir", O_RDONLY);
914 39360
        VJ_master(JAIL_MASTER_SYSTEM);
915 39360
        VJ_fix_fd(o, JAIL_FIXFD_WRKTMP);
916 39360
        VJ_master(JAIL_MASTER_LOW);
917 39360
        closefd(&o);
918
919 39360
        if (C_flag)
920 160
                AZ(atexit(mgt_Cflag_atexit));
921
922
        /* If no -s argument specified, process default -s argument */
923 36440
        if (!arg_list_count("s"))
924 36440
                STV_Config(s_arg);
925
926
        /* Configure CLI and Transient storage, if user did not */
927 39360
        STV_Config_Final();
928
929 39360
        mgt_vcl_init();
930
931 39360
        vext_copyin(vident);
932
933 39360
        u = 0;
934 553240
        VTAILQ_FOREACH(alp, &arglist, list) {
935 513920
                if (!strcmp(alp->arg, "f") && alp->priv != NULL)
936 1240
                        u |= mgt_process_f_arg(cli, C_flag, &alp->priv);
937 513880
        }
938 39320
        if (C_flag)
939 160
                exit(u);
940
941 552320
        VTAILQ_FOREACH(alp, &arglist, list) {
942 513240
                if (!strcmp(alp->arg, "P"))
943 38440
                        alp->priv = create_pid_file(&pid, "%s", alp->val);
944 513160
        }
945
946
        /* Implicit -P argument */
947 39080
        alp = arg_list_add('P', NULL);
948 39080
        alp->priv = create_pid_file(&pid, "%s/_.pid", workdir);
949
950 39080
        if (VTAILQ_EMPTY(&heritage.socks))
951 0
                VCA_Arg(":80\0");       // XXX: extra NUL for FlexeLint
952
953 39000
        assert(!VTAILQ_EMPTY(&heritage.socks));
954
955 39000
        HSH_config(h_arg);
956
957 39000
        Wait_config(W_arg);
958
959 39000
        mgt_SHM_Init();
960
961 39000
        mgt_SHM_static_alloc(i_arg, strlen(i_arg) + 1L, "Arg", "-i");
962 39000
        VSC_C_mgt = VSC_mgt_New(NULL, NULL, "");
963
964 590920
        VTAILQ_FOREACH(alp, &arglist, list) {
965 551920
                if (!strcmp(alp->arg, "M"))
966 38360
                        mgt_cli_master(alp->val);
967 513560
                else if (!strcmp(alp->arg, "T") && strcmp(alp->val, "none"))
968 39000
                        mgt_cli_telnet(alp->val);
969 77360
                else if (!strcmp(alp->arg, "P"))
970 77360
                        VPF_Write(alp->priv);
971 551920
        }
972
973 39000
        AZ(VSB_finish(vident));
974
975 39000
        if (S_arg == NULL)
976 39000
                S_arg = make_secret(workdir);
977 39040
        AN(S_arg);
978
979 38960
        MGT_Complain(C_DEBUG, "Version: %s", VCS_String("V"));
980 38960
        MGT_Complain(C_DEBUG, "Platform: %s", VSB_data(vident) + 1);
981
982 38960
        if (d_flag)
983 38480
                mgt_cli_setup(0, 1, 1, "debug", mgt_stdin_close, NULL);
984
985 38960
        if (strcmp(S_arg, "none"))
986 38960
                mgt_cli_secret(S_arg);
987
988 38960
        memset(&sac, 0, sizeof sac);
989 38960
        sac.sa_handler = SIG_IGN;
990 38960
        sac.sa_flags = SA_RESTART;
991
992 38960
        AZ(sigaction(SIGPIPE, &sac, NULL));
993 38960
        AZ(sigaction(SIGHUP, &sac, NULL));
994
995 38960
        MCH_Init();
996
997 38960
        if (I_fd >= 0) {
998 160
                fprintf(stderr, "BEGIN of -I file processing\n");
999
                /* We must dup stderr, because VCLS closes the output fd */
1000 160
                mgt_cli_setup(I_fd, dup(2), 1, "-I file", mgt_I_close, stderr);
1001 320
                while (I_fd >= 0) {
1002 280
                        o = VEV_Once(mgt_evb);
1003 280
                        if (o != 1)
1004 0
                                MGT_Complain(C_ERR,
1005 0
                                    "VEV_Once() = %d", o);
1006
                }
1007 40
        }
1008 38840
        assert(I_fd == -1);
1009
1010 38840
        err = mgt_has_vcl();
1011 38840
        if (!d_flag && err != NULL && !arg_list_count("f"))
1012 0
                MGT_Complain(C_ERR, "%s", err);
1013
1014 840
        if (err == NULL && !d_flag)
1015 360
                u = MCH_Start_Child();
1016
        else
1017 38480
                u = 0;
1018
1019 38840
        if (eric_fd >= 0)
1020 320
                mgt_eric_im_done(eric_fd, u);
1021
1022 38840
        if (u)
1023 320
                exit(u);
1024
1025
        /* Failure is no longer an option */
1026
1027 38520
        if (F_flag)
1028 120
                VFIL_null_fd(STDIN_FILENO);
1029
1030 38520
        e = VEV_Alloc();
1031 38520
        AN(e);
1032 38520
        e->callback = mgt_uptime;
1033 38520
        e->timeout = 1.0;
1034 38520
        e->name = "mgt_uptime";
1035 38520
        AZ(VEV_Start(mgt_evb, e));
1036
1037 38520
        e = VEV_Alloc();
1038 38520
        AN(e);
1039 38520
        e->sig = SIGTERM;
1040 38520
        e->callback = mgt_sigint;
1041 38520
        e->name = "SIGTERM";
1042 38520
        AZ(VEV_Start(mgt_evb, e));
1043
1044 38520
        e = VEV_Alloc();
1045 38520
        AN(e);
1046 38520
        e->sig = SIGINT;
1047 38520
        e->callback = mgt_sigint;
1048 38520
        e->name = "SIGINT";
1049 38520
        AZ(VEV_Start(mgt_evb, e));
1050
1051 38520
        o = VEV_Loop(mgt_evb);
1052 38520
        if (o != 0 && o != -42)
1053 0
                MGT_Complain(C_ERR, "VEV_Loop() = %d", o);
1054
1055 38520
        MGT_Complain(C_INFO, "manager stopping child");
1056 38520
        MCH_Stop_Child();
1057 38520
        MGT_Complain(C_INFO, "manager dies");
1058 38520
        mgt_cli_close_all();
1059 38520
        VEV_Destroy(&mgt_evb);
1060 38520
        VJ_master(JAIL_MASTER_SYSTEM);
1061
        /*lint -e(730)*/
1062 38520
        vext_cleanup(! MGT_DO_DEBUG(DBG_VMOD_SO_KEEP));
1063 38520
        (void)rmdir("vext_cache");
1064 38520
        VJ_master(JAIL_MASTER_LOW);
1065 587960
        VTAILQ_FOREACH(alp, &arglist, list) {
1066 549440
                if (!strcmp(alp->arg, "P"))
1067 76880
                        VPF_Remove(alp->priv);
1068 549440
        }
1069 38520
        exit(exit_status);
1070
}