1 /*-
2  * Copyright (c) 2008-2010 Varnish Software AS
3  * All rights reserved.
4  *
5  * Author: Frédéric Lécaille <flecaille@haproxy.com>
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 
31 #include "config.h"
32 
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 
41 #include "vtc.h"
42 
43 #include "vsa.h"
44 #include "vss.h"
45 #include "vtcp.h"
46 #include "vre.h"
47 
48 struct syslog_srv {
49 	unsigned			magic;
50 #define SYSLOG_SRV_MAGIC		0xbf28a692
51 	char				*name;
52 	struct vtclog			*vl;
53 	VTAILQ_ENTRY(syslog_srv)	list;
54 	char				run;
55 
56 	int				repeat;
57 	char				*spec;
58 
59 	int				sock;
60 	char				bind[256];
61 	int				lvl;
62 
63 	pthread_t			tp;
64 	ssize_t				rxbuf_left;
65 	size_t				rxbuf_sz;
66 	char				*rxbuf;
67 	vtim_dur			timeout;
68 };
69 
70 static pthread_mutex_t			syslog_mtx;
71 
72 static VTAILQ_HEAD(, syslog_srv)	syslogs =
73     VTAILQ_HEAD_INITIALIZER(syslogs);
74 
75 #define SYSLOGCMDS \
76 	CMD_SYSLOG(expect) \
77 	CMD_SYSLOG(recv)
78 
79 #define CMD_SYSLOG(nm) static cmd_f cmd_syslog_##nm;
80 SYSLOGCMDS
81 #undef CMD_SYSLOG
82 
83 static const struct cmds syslog_cmds[] = {
84 #define CMD_SYSLOG(n) { #n, cmd_syslog_##n },
85 SYSLOGCMDS
86 #undef CMD_SYSLOG
87 	{ NULL, NULL }
88 };
89 
90 static const char * const syslog_levels[] = {
91 	"emerg",
92 	"alert",
93 	"crit",
94 	"err",
95 	"warning",
96 	"notice",
97 	"info",
98 	"debug",
99 	NULL,
100 };
101 
102 static int
get_syslog_level(struct vtclog * vl,const char * lvl)103 get_syslog_level(struct vtclog *vl, const char *lvl)
104 {
105 	int i;
106 
107 	for (i = 0; syslog_levels[i]; i++)
108 		if (!strcmp(lvl, syslog_levels[i]))
109 			return (i);
110 	vtc_fatal(vl, "wrong syslog level '%s'\n", lvl);
111 }
112 
113 /*--------------------------------------------------------------------
114  * Check if a UDP syscall return value is fatal
115  * XXX: Largely copied from VTCP, not sure if really applicable
116  */
117 
118 static int
VUDP_Check(int a)119 VUDP_Check(int a)
120 {
121 	if (a == 0)
122 		return (1);
123 	if (errno == ECONNRESET)
124 		return (1);
125 #if (defined (__SVR4) && defined (__sun)) || defined (__NetBSD__)
126 	/*
127 	 * Solaris returns EINVAL if the other end unexpectedly reset the
128 	 * connection.
129 	 * This is a bug in Solaris and documented behaviour on NetBSD.
130 	 */
131 	if (errno == EINVAL || errno == ETIMEDOUT || errno == EPIPE)
132 		return (1);
133 #elif defined (__APPLE__)
134 	/*
135 	 * MacOS returns EINVAL if the other end unexpectedly reset
136 	 * the connection.
137 	 */
138 	if (errno == EINVAL)
139 		return (1);
140 #endif
141 	return (0);
142 }
143 
144 /*--------------------------------------------------------------------
145  * When closing a UDP connection, a couple of errno's are legit, we
146  * can't be held responsible for the other end wanting to talk to us.
147  */
148 
149 static void
VUDP_close(int * s)150 VUDP_close(int *s)
151 {
152 	int i;
153 
154 	i = close(*s);
155 
156 	assert(VUDP_Check(i));
157 	*s = -1;
158 }
159 
160 /*--------------------------------------------------------------------
161  * Given a struct suckaddr, open a socket of the appropriate type, and bind
162  * it to the requested address.
163  *
164  * If the address is an IPv6 address, the IPV6_V6ONLY option is set to
165  * avoid conflicts between INADDR_ANY and IN6ADDR_ANY.
166  */
167 
168 static int
VUDP_bind(const struct suckaddr * sa,const char ** errp)169 VUDP_bind(const struct suckaddr *sa, const char **errp)
170 {
171 #ifdef IPV6_V6ONLY
172 	int val;
173 #endif
174 	int sd, e;
175 	socklen_t sl;
176 	const struct sockaddr *so;
177 	int proto;
178 
179 	if (errp != NULL)
180 		*errp = NULL;
181 
182 	proto = VSA_Get_Proto(sa);
183 	sd = socket(proto, SOCK_DGRAM, 0);
184 	if (sd < 0) {
185 		if (errp != NULL)
186 			*errp = "socket(2)";
187 		return (-1);
188 	}
189 
190 #ifdef IPV6_V6ONLY
191 	/* forcibly use separate sockets for IPv4 and IPv6 */
192 	val = 1;
193 	if (proto == AF_INET6 &&
194 	    setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof val) != 0) {
195 		if (errp != NULL)
196 			*errp = "setsockopt(IPV6_V6ONLY, 1)";
197 		e = errno;
198 		closefd(&sd);
199 		errno = e;
200 		return (-1);
201 	}
202 #endif
203 	so = VSA_Get_Sockaddr(sa, &sl);
204 	if (bind(sd, so, sl) != 0) {
205 		if (errp != NULL)
206 			*errp = "bind(2)";
207 		e = errno;
208 		closefd(&sd);
209 		errno = e;
210 		return (-1);
211 	}
212 	return (sd);
213 }
214 
215 /*--------------------------------------------------------------------*/
216 
217 struct udp_helper {
218 	const char	**errp;
219 };
220 
v_matchproto_(vss_resolved_f)221 static int v_matchproto_(vss_resolved_f)
222 vudp_lo_cb(void *priv, const struct suckaddr *sa)
223 {
224 	int sock;
225 	struct udp_helper *hp = priv;
226 
227 	sock = VUDP_bind(sa, hp->errp);
228 	if (sock > 0) {
229 		*hp->errp = NULL;
230 		return (sock);
231 	}
232 	AN(*hp->errp);
233 	return (0);
234 }
235 
236 static int
VUDP_bind_on(const char * addr,const char * def_port,const char ** errp)237 VUDP_bind_on(const char *addr, const char *def_port, const char **errp)
238 {
239 	struct udp_helper h;
240 	int sock;
241 
242 	h.errp = errp;
243 
244 	sock = VSS_resolver_socktype(
245 	    addr, def_port, vudp_lo_cb, &h, errp, SOCK_DGRAM);
246 	if (*errp != NULL)
247 		return (-1);
248 	return (sock);
249 }
250 
251 /**********************************************************************
252  * Allocate and initialize a syslog
253  */
254 
255 static struct syslog_srv *
syslog_new(const char * name,struct vtclog * vl)256 syslog_new(const char *name, struct vtclog *vl)
257 {
258 	struct syslog_srv *s;
259 
260 	VTC_CHECK_NAME(vl, name, "Syslog", 'S');
261 	ALLOC_OBJ(s, SYSLOG_SRV_MAGIC);
262 	AN(s);
263 	REPLACE(s->name, name);
264 	s->vl = vtc_logopen("%s", s->name);
265 	AN(s->vl);
266 	vtc_log_set_cmd(s->vl, syslog_cmds);
267 
268 	bprintf(s->bind, "%s", default_listen_addr);
269 	s->repeat = 1;
270 	s->sock = -1;
271 	s->lvl = -1;
272 	s->timeout = vtc_maxdur * .5;		// XXX
273 
274 	vl = vtc_logopen("%s", s->name);
275 	AN(vl);
276 
277 	s->rxbuf_sz = s->rxbuf_left = 2048*1024;
278 	s->rxbuf = malloc(s->rxbuf_sz);		/* XXX */
279 	AN(s->rxbuf);
280 
281 	AZ(pthread_mutex_lock(&syslog_mtx));
282 	VTAILQ_INSERT_TAIL(&syslogs, s, list);
283 	AZ(pthread_mutex_unlock(&syslog_mtx));
284 	return (s);
285 }
286 
287 /**********************************************************************
288  * Clean up a syslog
289  */
290 
291 static void
syslog_delete(struct syslog_srv * s)292 syslog_delete(struct syslog_srv *s)
293 {
294 
295 	CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
296 	macro_undef(s->vl, s->name, "addr");
297 	macro_undef(s->vl, s->name, "port");
298 	macro_undef(s->vl, s->name, "sock");
299 	vtc_logclose(s->vl);
300 	free(s->name);
301 	free(s->rxbuf);
302 	/* XXX: MEMLEAK (?) (VSS ??) */
303 	FREE_OBJ(s);
304 }
305 
306 static void
syslog_rx(const struct syslog_srv * s,int lvl)307 syslog_rx(const struct syslog_srv *s, int lvl)
308 {
309 	ssize_t ret;
310 
311 	while (!vtc_error) {
312 		/* Pointers to syslog priority value (see <PRIVAL>, rfc5424). */
313 		char *prib, *prie, *end;
314 		unsigned int prival;
315 
316 		VTCP_set_read_timeout(s->sock, s->timeout);
317 
318 		ret = recv(s->sock, s->rxbuf, s->rxbuf_sz - 1, 0);
319 		if (ret < 0) {
320 			if (errno == EINTR || errno == EAGAIN)
321 				continue;
322 
323 			vtc_fatal(s->vl,
324 			    "%s: recv failed (fd: %d read: %s", __func__,
325 			    s->sock, strerror(errno));
326 		}
327 		if (ret == 0)
328 			vtc_fatal(s->vl,
329 			    "syslog rx timeout (fd: %d %.3fs ret: %zd)",
330 			    s->sock, s->timeout, ret);
331 
332 		s->rxbuf[ret] = '\0';
333 		vtc_dump(s->vl, 4, "syslog", s->rxbuf, ret);
334 
335 		prib = s->rxbuf;
336 		if (*prib++ != '<')
337 			vtc_fatal(s->vl, "syslog PRI, no '<'");
338 		prie = strchr(prib, '>');
339 		if (prie == NULL)
340 			vtc_fatal(s->vl, "syslog PRI, no '>'");
341 
342 		prival = strtoul(prib, &end, 10);
343 		if (end != prie)
344 			vtc_fatal(s->vl, "syslog PRI, bad number");
345 
346 		if (lvl >= 0 && lvl == (prival & 0x7))
347 			return;
348 	}
349 }
350 
351 /**********************************************************************
352  * Syslog server bind
353  */
354 
355 static void
syslog_bind(struct syslog_srv * s)356 syslog_bind(struct syslog_srv *s)
357 {
358 	const char *err;
359 	char aaddr[VTCP_ADDRBUFSIZE];
360 	char aport[VTCP_PORTBUFSIZE];
361 	char buf[vsa_suckaddr_len];
362 	struct suckaddr *sua;
363 
364 	CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
365 
366 	if (s->sock >= 0)
367 		VUDP_close(&s->sock);
368 	s->sock = VUDP_bind_on(s->bind, "0", &err);
369 	if (err != NULL)
370 		vtc_fatal(s->vl,
371 		    "Syslog server bind address (%s) cannot be resolved: %s",
372 		    s->bind, err);
373 	assert(s->sock > 0);
374 	sua = VSA_getsockname(s->sock, buf, sizeof buf);
375 	AN(sua);
376 	VTCP_name(sua, aaddr, sizeof aaddr, aport, sizeof aport);
377 	macro_def(s->vl, s->name, "addr", "%s", aaddr);
378 	macro_def(s->vl, s->name, "port", "%s", aport);
379 	if (VSA_Get_Proto(sua) == AF_INET)
380 		macro_def(s->vl, s->name, "sock", "%s:%s", aaddr, aport);
381 	else
382 		macro_def(s->vl, s->name, "sock", "[%s]:%s", aaddr, aport);
383 	/* Record the actual port, and reuse it on subsequent starts */
384 	bprintf(s->bind, "%s %s", aaddr, aport);
385 }
386 
v_matchproto_(cmd_f)387 static void v_matchproto_(cmd_f)
388 cmd_syslog_expect(CMD_ARGS)
389 {
390 	struct syslog_srv *s;
391 	vre_t *vre;
392 	const char *error;
393 	int erroroffset, i, ret;
394 	char *cmp, *spec;
395 
396 	(void)vl;
397 	CAST_OBJ_NOTNULL(s, priv, SYSLOG_SRV_MAGIC);
398 	AZ(strcmp(av[0], "expect"));
399 	av++;
400 
401 	cmp = av[0];
402 	spec = av[1];
403 	AN(cmp);
404 	AN(spec);
405 	AZ(av[2]);
406 
407 	assert(!strcmp(cmp, "~") || !strcmp(cmp, "!~"));
408 
409 	vre = VRE_compile(spec, 0, &error, &erroroffset);
410 	if (!vre)
411 		vtc_fatal(s->vl, "REGEXP error: '%s' (@%d) (%s)",
412 		    error, erroroffset, spec);
413 
414 	i = VRE_exec(vre, s->rxbuf, strlen(s->rxbuf), 0, 0, NULL, 0, 0);
415 
416 	VRE_free(&vre);
417 
418 	ret = (i >= 0 && *cmp == '~') || (i < 0 && *cmp == '!');
419 	if (!ret)
420 		vtc_fatal(s->vl, "EXPECT FAILED %s \"%s\"", cmp, spec);
421 	else
422 		vtc_log(s->vl, 4, "EXPECT MATCH %s \"%s\"", cmp, spec);
423 }
424 
v_matchproto_(cmd_f)425 static void v_matchproto_(cmd_f)
426 cmd_syslog_recv(CMD_ARGS)
427 {
428 	int lvl;
429 	struct syslog_srv *s;
430 
431 	CAST_OBJ_NOTNULL(s, priv, SYSLOG_SRV_MAGIC);
432 	(void)vl;
433 	AZ(strcmp(av[0], "recv"));
434 	av++;
435 	if (av[0] == NULL)
436 		lvl = s->lvl;
437 	else
438 		lvl = get_syslog_level(vl, av[0]);
439 
440 	syslog_rx(s, lvl);
441 }
442 
443 /**********************************************************************
444  * Syslog server thread
445  */
446 
447 static void *
syslog_thread(void * priv)448 syslog_thread(void *priv)
449 {
450 	struct syslog_srv *s;
451 	int i;
452 
453 	CAST_OBJ_NOTNULL(s, priv, SYSLOG_SRV_MAGIC);
454 	assert(s->sock >= 0);
455 
456 	vtc_log(s->vl, 2, "Started on %s (level: %d)", s->bind, s->lvl);
457 	for (i = 0; i < s->repeat; i++) {
458 		if (s->repeat > 1)
459 			vtc_log(s->vl, 3, "Iteration %d", i);
460 		parse_string(s->vl, s, s->spec);
461 		vtc_log(s->vl, 3, "shutting fd %d", s->sock);
462 	}
463 	VUDP_close(&s->sock);
464 	vtc_log(s->vl, 2, "Ending");
465 	return (NULL);
466 }
467 
468 /**********************************************************************
469  * Start the syslog thread
470  */
471 
472 static void
syslog_start(struct syslog_srv * s)473 syslog_start(struct syslog_srv *s)
474 {
475 	CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
476 	vtc_log(s->vl, 2, "Starting syslog server");
477 	if (s->sock == -1)
478 		syslog_bind(s);
479 	vtc_log(s->vl, 1, "Bound on %s", s->bind);
480 	s->run = 1;
481 	AZ(pthread_create(&s->tp, NULL, syslog_thread, s));
482 }
483 
484 /**********************************************************************
485  * Force stop the syslog thread
486  */
487 
488 static void
syslog_stop(struct syslog_srv * s)489 syslog_stop(struct syslog_srv *s)
490 {
491 	void *res;
492 
493 	CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
494 	vtc_log(s->vl, 2, "Stopping for syslog server");
495 	(void)pthread_cancel(s->tp);
496 	AZ(pthread_join(s->tp, &res));
497 	s->tp = 0;
498 	s->run = 0;
499 }
500 
501 /**********************************************************************
502  * Wait for syslog thread to stop
503  */
504 
505 static void
syslog_wait(struct syslog_srv * s)506 syslog_wait(struct syslog_srv *s)
507 {
508 	void *res;
509 
510 	CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
511 	vtc_log(s->vl, 2, "Waiting for syslog server (%d)", s->sock);
512 	AZ(pthread_join(s->tp, &res));
513 	if (res != NULL && !vtc_stop)
514 		vtc_fatal(s->vl, "Syslog server returned \"%p\"",
515 		    (char *)res);
516 	s->tp = 0;
517 	s->run = 0;
518 }
519 
520 /* SECTION: syslog syslog
521  *
522  * Define and interact with syslog instances (for use with haproxy)
523  *
524  * To define a syslog server, you'll use this syntax::
525  *
526  *     syslog SNAME
527  *
528  * Arguments:
529  *
530  * SNAME
531  *     Identify the syslog server with a string which must start with 'S'.
532  *
533  * \-level STRING
534  *         Set the default syslog priority level used by any subsequent "recv"
535  *         command.
536  *         Any syslog dgram with a different level will be skipped by
537  *         "recv" command. This default level value may be superseded
538  *         by "recv" command if supplied as first argument: "recv <level>".
539  *
540  * \-start
541  *         Start the syslog server thread in the background.
542  *
543  * \-repeat
544  *         Instead of processing the specification only once, do it
545  *	   NUMBER times.
546  *
547  * \-bind
548  *         Bind the syslog socket to a local address.
549  *
550  * \-wait
551  *         Wait for that thread to terminate.
552  *
553  * \-stop
554  *         Stop the syslog server thread.
555  */
556 
v_matchproto_(cmd_f)557 void v_matchproto_(cmd_f)
558 cmd_syslog(CMD_ARGS)
559 {
560 	struct syslog_srv *s;
561 
562 	(void)priv;
563 
564 	if (av == NULL) {
565 		/* Reset and free */
566 		do {
567 			AZ(pthread_mutex_lock(&syslog_mtx));
568 			s = VTAILQ_FIRST(&syslogs);
569 			CHECK_OBJ_ORNULL(s, SYSLOG_SRV_MAGIC);
570 			if (s != NULL)
571 				VTAILQ_REMOVE(&syslogs, s, list);
572 			AZ(pthread_mutex_unlock(&syslog_mtx));
573 			if (s != NULL) {
574 				if (s->run) {
575 					(void)pthread_cancel(s->tp);
576 					syslog_wait(s);
577 				}
578 				if (s->sock >= 0)
579 					VUDP_close(&s->sock);
580 				syslog_delete(s);
581 			}
582 		} while (s != NULL);
583 		return;
584 	}
585 
586 	AZ(strcmp(av[0], "syslog"));
587 	av++;
588 
589 	AZ(pthread_mutex_lock(&syslog_mtx));
590 	VTAILQ_FOREACH(s, &syslogs, list)
591 		if (!strcmp(s->name, av[0]))
592 			break;
593 	AZ(pthread_mutex_unlock(&syslog_mtx));
594 	if (s == NULL)
595 		s = syslog_new(av[0], vl);
596 	CHECK_OBJ_NOTNULL(s, SYSLOG_SRV_MAGIC);
597 	av++;
598 
599 	for (; *av != NULL; av++) {
600 		if (vtc_error)
601 			break;
602 		if (!strcmp(*av, "-wait")) {
603 			if (!s->run)
604 				vtc_fatal(s->vl, "Syslog server not -started");
605 			syslog_wait(s);
606 			continue;
607 		}
608 
609 		if (!strcmp(*av, "-stop")) {
610 			syslog_stop(s);
611 			continue;
612 		}
613 
614 		/*
615 		 * We do an implict -wait if people muck about with a
616 		 * running syslog.
617 		 * This only works if the previous ->spec has completed
618 		 */
619 		if (s->run)
620 			syslog_wait(s);
621 
622 		AZ(s->run);
623 		if (!strcmp(*av, "-repeat")) {
624 			AN(av[1]);
625 			s->repeat = atoi(av[1]);
626 			av++;
627 			continue;
628 		}
629 		if (!strcmp(*av, "-bind")) {
630 			AN(av[1]);
631 			bprintf(s->bind, "%s", av[1]);
632 			av++;
633 			syslog_bind(s);
634 			continue;
635 		}
636 		if (!strcmp(*av, "-level")) {
637 			AN(av[1]);
638 			s->lvl = get_syslog_level(vl, av[1]);
639 			av++;
640 			continue;
641 		}
642 		if (!strcmp(*av, "-start")) {
643 			syslog_start(s);
644 			continue;
645 		}
646 		if (**av == '-')
647 			vtc_fatal(s->vl, "Unknown syslog argument: %s", *av);
648 		s->spec = *av;
649 	}
650 }
651 
652 void
init_syslog(void)653 init_syslog(void)
654 {
655 	AZ(pthread_mutex_init(&syslog_mtx, NULL));
656 }
657