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