xref: /freebsd/contrib/blocklist/bin/conf.c (revision 5f4c09dd85bff675e0ca63c55ea3c517e0fddfcc)
1*5f4c09ddSEd Maste /*	$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $	*/
2*5f4c09ddSEd Maste 
3*5f4c09ddSEd Maste /*-
4*5f4c09ddSEd Maste  * Copyright (c) 2015 The NetBSD Foundation, Inc.
5*5f4c09ddSEd Maste  * All rights reserved.
6*5f4c09ddSEd Maste  *
7*5f4c09ddSEd Maste  * This code is derived from software contributed to The NetBSD Foundation
8*5f4c09ddSEd Maste  * by Christos Zoulas.
9*5f4c09ddSEd Maste  *
10*5f4c09ddSEd Maste  * Redistribution and use in source and binary forms, with or without
11*5f4c09ddSEd Maste  * modification, are permitted provided that the following conditions
12*5f4c09ddSEd Maste  * are met:
13*5f4c09ddSEd Maste  * 1. Redistributions of source code must retain the above copyright
14*5f4c09ddSEd Maste  *    notice, this list of conditions and the following disclaimer.
15*5f4c09ddSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
16*5f4c09ddSEd Maste  *    notice, this list of conditions and the following disclaimer in the
17*5f4c09ddSEd Maste  *    documentation and/or other materials provided with the distribution.
18*5f4c09ddSEd Maste  *
19*5f4c09ddSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*5f4c09ddSEd Maste  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*5f4c09ddSEd Maste  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*5f4c09ddSEd Maste  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*5f4c09ddSEd Maste  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*5f4c09ddSEd Maste  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*5f4c09ddSEd Maste  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*5f4c09ddSEd Maste  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*5f4c09ddSEd Maste  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*5f4c09ddSEd Maste  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*5f4c09ddSEd Maste  * POSSIBILITY OF SUCH DAMAGE.
30*5f4c09ddSEd Maste  */
31*5f4c09ddSEd Maste #ifdef HAVE_CONFIG_H
32*5f4c09ddSEd Maste #include "config.h"
33*5f4c09ddSEd Maste #endif
34*5f4c09ddSEd Maste 
35*5f4c09ddSEd Maste #include <sys/cdefs.h>
36*5f4c09ddSEd Maste __RCSID("$NetBSD: conf.c,v 1.24 2016/04/04 15:52:56 christos Exp $");
37*5f4c09ddSEd Maste 
38*5f4c09ddSEd Maste #include <stdio.h>
39*5f4c09ddSEd Maste #ifdef HAVE_LIBUTIL_H
40*5f4c09ddSEd Maste #include <libutil.h>
41*5f4c09ddSEd Maste #endif
42*5f4c09ddSEd Maste #ifdef HAVE_UTIL_H
43*5f4c09ddSEd Maste #include <util.h>
44*5f4c09ddSEd Maste #endif
45*5f4c09ddSEd Maste #include <string.h>
46*5f4c09ddSEd Maste #include <ctype.h>
47*5f4c09ddSEd Maste #include <inttypes.h>
48*5f4c09ddSEd Maste #include <netdb.h>
49*5f4c09ddSEd Maste #include <unistd.h>
50*5f4c09ddSEd Maste #include <pwd.h>
51*5f4c09ddSEd Maste #include <syslog.h>
52*5f4c09ddSEd Maste #include <errno.h>
53*5f4c09ddSEd Maste #include <stdlib.h>
54*5f4c09ddSEd Maste #include <limits.h>
55*5f4c09ddSEd Maste #include <ifaddrs.h>
56*5f4c09ddSEd Maste #include <arpa/inet.h>
57*5f4c09ddSEd Maste #include <netinet/in.h>
58*5f4c09ddSEd Maste #include <net/if.h>
59*5f4c09ddSEd Maste #include <net/route.h>
60*5f4c09ddSEd Maste #include <sys/socket.h>
61*5f4c09ddSEd Maste 
62*5f4c09ddSEd Maste #include "bl.h"
63*5f4c09ddSEd Maste #include "internal.h"
64*5f4c09ddSEd Maste #include "support.h"
65*5f4c09ddSEd Maste #include "conf.h"
66*5f4c09ddSEd Maste 
67*5f4c09ddSEd Maste 
68*5f4c09ddSEd Maste struct sockaddr_if {
69*5f4c09ddSEd Maste 	uint8_t		sif_len;
70*5f4c09ddSEd Maste 	sa_family_t	sif_family;
71*5f4c09ddSEd Maste 	in_port_t	sif_port;
72*5f4c09ddSEd Maste 	char		sif_name[16];
73*5f4c09ddSEd Maste };
74*5f4c09ddSEd Maste 
75*5f4c09ddSEd Maste #define SIF_NAME(a) \
76*5f4c09ddSEd Maste     ((const struct sockaddr_if *)(const void *)(a))->sif_name
77*5f4c09ddSEd Maste 
78*5f4c09ddSEd Maste static int conf_is_interface(const char *);
79*5f4c09ddSEd Maste 
80*5f4c09ddSEd Maste #define FSTAR	-1
81*5f4c09ddSEd Maste #define FEQUAL	-2
82*5f4c09ddSEd Maste 
83*5f4c09ddSEd Maste static void
advance(char ** p)84*5f4c09ddSEd Maste advance(char **p)
85*5f4c09ddSEd Maste {
86*5f4c09ddSEd Maste 	char *ep = *p;
87*5f4c09ddSEd Maste 	while (*ep && !isspace((unsigned char)*ep))
88*5f4c09ddSEd Maste 		ep++;
89*5f4c09ddSEd Maste 	while (*ep && isspace((unsigned char)*ep))
90*5f4c09ddSEd Maste 		*ep++ = '\0';
91*5f4c09ddSEd Maste 	*p = ep;
92*5f4c09ddSEd Maste }
93*5f4c09ddSEd Maste 
94*5f4c09ddSEd Maste static int
conf_getnum(const char * f,size_t l,bool local,void * rp,const char * name,const char * p)95*5f4c09ddSEd Maste conf_getnum(const char *f, size_t l, bool local, void *rp, const char *name,
96*5f4c09ddSEd Maste     const char *p)
97*5f4c09ddSEd Maste {
98*5f4c09ddSEd Maste 	int e;
99*5f4c09ddSEd Maste 	intmax_t im;
100*5f4c09ddSEd Maste 	int *r = rp;
101*5f4c09ddSEd Maste 
102*5f4c09ddSEd Maste 	if (strcmp(p, "*") == 0) {
103*5f4c09ddSEd Maste 		*r = FSTAR;
104*5f4c09ddSEd Maste 		return 0;
105*5f4c09ddSEd Maste 	}
106*5f4c09ddSEd Maste 	if (strcmp(p, "=") == 0) {
107*5f4c09ddSEd Maste 		if (local)
108*5f4c09ddSEd Maste 			goto out;
109*5f4c09ddSEd Maste 		*r = FEQUAL;
110*5f4c09ddSEd Maste 		return 0;
111*5f4c09ddSEd Maste 	}
112*5f4c09ddSEd Maste 
113*5f4c09ddSEd Maste 	im = strtoi(p, NULL, 0, 0, INT_MAX, &e);
114*5f4c09ddSEd Maste 	if (e == 0) {
115*5f4c09ddSEd Maste 		*r = (int)im;
116*5f4c09ddSEd Maste 		return 0;
117*5f4c09ddSEd Maste 	}
118*5f4c09ddSEd Maste 
119*5f4c09ddSEd Maste 	if (f == NULL)
120*5f4c09ddSEd Maste 		return -1;
121*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: Bad number for %s [%s]", __func__, f, l,
122*5f4c09ddSEd Maste 	   name,  p);
123*5f4c09ddSEd Maste 	return -1;
124*5f4c09ddSEd Maste out:
125*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: `=' for %s not allowed in local config",
126*5f4c09ddSEd Maste 	    __func__, f, l, name);
127*5f4c09ddSEd Maste 	return -1;
128*5f4c09ddSEd Maste 
129*5f4c09ddSEd Maste }
130*5f4c09ddSEd Maste 
131*5f4c09ddSEd Maste static int
conf_getnfail(const char * f,size_t l,bool local,struct conf * c,const char * p)132*5f4c09ddSEd Maste conf_getnfail(const char *f, size_t l, bool local, struct conf *c,
133*5f4c09ddSEd Maste     const char *p)
134*5f4c09ddSEd Maste {
135*5f4c09ddSEd Maste 	return conf_getnum(f, l, local, &c->c_nfail, "nfail", p);
136*5f4c09ddSEd Maste }
137*5f4c09ddSEd Maste 
138*5f4c09ddSEd Maste static int
conf_getsecs(const char * f,size_t l,bool local,struct conf * c,const char * p)139*5f4c09ddSEd Maste conf_getsecs(const char *f, size_t l, bool local, struct conf *c, const char *p)
140*5f4c09ddSEd Maste {
141*5f4c09ddSEd Maste 	int e;
142*5f4c09ddSEd Maste 	char *ep;
143*5f4c09ddSEd Maste 	intmax_t tot, im;
144*5f4c09ddSEd Maste 
145*5f4c09ddSEd Maste 	tot = 0;
146*5f4c09ddSEd Maste 	if (strcmp(p, "*") == 0) {
147*5f4c09ddSEd Maste 		c->c_duration = FSTAR;
148*5f4c09ddSEd Maste 		return 0;
149*5f4c09ddSEd Maste 	}
150*5f4c09ddSEd Maste 	if (strcmp(p, "=") == 0) {
151*5f4c09ddSEd Maste 		if (local)
152*5f4c09ddSEd Maste 			goto out;
153*5f4c09ddSEd Maste 		c->c_duration = FEQUAL;
154*5f4c09ddSEd Maste 		return 0;
155*5f4c09ddSEd Maste 	}
156*5f4c09ddSEd Maste again:
157*5f4c09ddSEd Maste 	im = strtoi(p, &ep, 0, 0, INT_MAX, &e);
158*5f4c09ddSEd Maste 
159*5f4c09ddSEd Maste 	if (e == ENOTSUP) {
160*5f4c09ddSEd Maste 		switch (*ep) {
161*5f4c09ddSEd Maste 		case 'd':
162*5f4c09ddSEd Maste 			im *= 24;
163*5f4c09ddSEd Maste 			/*FALLTHROUGH*/
164*5f4c09ddSEd Maste 		case 'h':
165*5f4c09ddSEd Maste 			im *= 60;
166*5f4c09ddSEd Maste 			/*FALLTHROUGH*/
167*5f4c09ddSEd Maste 		case 'm':
168*5f4c09ddSEd Maste 			im *= 60;
169*5f4c09ddSEd Maste 			/*FALLTHROUGH*/
170*5f4c09ddSEd Maste 		case 's':
171*5f4c09ddSEd Maste 			e = 0;
172*5f4c09ddSEd Maste 			tot += im;
173*5f4c09ddSEd Maste 			if (ep[1] != '\0') {
174*5f4c09ddSEd Maste 				p = ep + 2;
175*5f4c09ddSEd Maste 				goto again;
176*5f4c09ddSEd Maste 			}
177*5f4c09ddSEd Maste 			break;
178*5f4c09ddSEd Maste 		}
179*5f4c09ddSEd Maste 	} else
180*5f4c09ddSEd Maste 		tot = im;
181*5f4c09ddSEd Maste 
182*5f4c09ddSEd Maste 	if (e == 0) {
183*5f4c09ddSEd Maste 		c->c_duration = (int)tot;
184*5f4c09ddSEd Maste 		return 0;
185*5f4c09ddSEd Maste 	}
186*5f4c09ddSEd Maste 
187*5f4c09ddSEd Maste 	if (f == NULL)
188*5f4c09ddSEd Maste 		return -1;
189*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: Bad number [%s]", __func__, f, l, p);
190*5f4c09ddSEd Maste 	return -1;
191*5f4c09ddSEd Maste out:
192*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: `=' duration not allowed in local"
193*5f4c09ddSEd Maste 	    " config", __func__, f, l);
194*5f4c09ddSEd Maste 	return -1;
195*5f4c09ddSEd Maste 
196*5f4c09ddSEd Maste }
197*5f4c09ddSEd Maste 
198*5f4c09ddSEd Maste static int
conf_getport(const char * f,size_t l,bool local,void * r,const char * p)199*5f4c09ddSEd Maste conf_getport(const char *f, size_t l, bool local, void *r, const char *p)
200*5f4c09ddSEd Maste {
201*5f4c09ddSEd Maste 	struct servent *sv;
202*5f4c09ddSEd Maste 
203*5f4c09ddSEd Maste 	// XXX: Pass in the proto instead
204*5f4c09ddSEd Maste 	if ((sv = getservbyname(p, "tcp")) != NULL) {
205*5f4c09ddSEd Maste 		*(int *)r = ntohs(sv->s_port);
206*5f4c09ddSEd Maste 		return 0;
207*5f4c09ddSEd Maste 	}
208*5f4c09ddSEd Maste 	if ((sv = getservbyname(p, "udp")) != NULL) {
209*5f4c09ddSEd Maste 		*(int *)r = ntohs(sv->s_port);
210*5f4c09ddSEd Maste 		return 0;
211*5f4c09ddSEd Maste 	}
212*5f4c09ddSEd Maste 
213*5f4c09ddSEd Maste 	return conf_getnum(f, l, local, r, "service", p);
214*5f4c09ddSEd Maste }
215*5f4c09ddSEd Maste 
216*5f4c09ddSEd Maste static int
conf_getmask(const char * f,size_t l,bool local,const char ** p,int * mask)217*5f4c09ddSEd Maste conf_getmask(const char *f, size_t l, bool local, const char **p, int *mask)
218*5f4c09ddSEd Maste {
219*5f4c09ddSEd Maste 	char *d;
220*5f4c09ddSEd Maste 	const char *s = *p;
221*5f4c09ddSEd Maste 
222*5f4c09ddSEd Maste 	if ((d = strchr(s, ':')) != NULL) {
223*5f4c09ddSEd Maste 		*d++ = '\0';
224*5f4c09ddSEd Maste 		*p = d;
225*5f4c09ddSEd Maste 	}
226*5f4c09ddSEd Maste 	if ((d = strchr(s, '/')) == NULL) {
227*5f4c09ddSEd Maste 		*mask = FSTAR;
228*5f4c09ddSEd Maste 		return 0;
229*5f4c09ddSEd Maste 	}
230*5f4c09ddSEd Maste 
231*5f4c09ddSEd Maste 	*d++ = '\0';
232*5f4c09ddSEd Maste 	return conf_getnum(f, l, local, mask, "mask", d);
233*5f4c09ddSEd Maste }
234*5f4c09ddSEd Maste 
235*5f4c09ddSEd Maste static int
conf_gethostport(const char * f,size_t l,bool local,struct conf * c,const char * p)236*5f4c09ddSEd Maste conf_gethostport(const char *f, size_t l, bool local, struct conf *c,
237*5f4c09ddSEd Maste     const char *p)
238*5f4c09ddSEd Maste {
239*5f4c09ddSEd Maste 	char *d;	// XXX: Ok to write to string.
240*5f4c09ddSEd Maste 	in_port_t *port = NULL;
241*5f4c09ddSEd Maste 	const char *pstr;
242*5f4c09ddSEd Maste 
243*5f4c09ddSEd Maste 	if (strcmp(p, "*") == 0) {
244*5f4c09ddSEd Maste 		c->c_port = FSTAR;
245*5f4c09ddSEd Maste 		c->c_lmask = FSTAR;
246*5f4c09ddSEd Maste 		return 0;
247*5f4c09ddSEd Maste 	}
248*5f4c09ddSEd Maste 
249*5f4c09ddSEd Maste 	if ((d = strchr(p, ']')) != NULL) {
250*5f4c09ddSEd Maste 		*d++ = '\0';
251*5f4c09ddSEd Maste 		pstr = d;
252*5f4c09ddSEd Maste 		p++;
253*5f4c09ddSEd Maste 	} else
254*5f4c09ddSEd Maste 		pstr = p;
255*5f4c09ddSEd Maste 
256*5f4c09ddSEd Maste 	if (conf_getmask(f, l, local, &pstr, &c->c_lmask) == -1)
257*5f4c09ddSEd Maste 		goto out;
258*5f4c09ddSEd Maste 
259*5f4c09ddSEd Maste 	if (d) {
260*5f4c09ddSEd Maste 		struct sockaddr_in6 *sin6 = (void *)&c->c_ss;
261*5f4c09ddSEd Maste 		if (debug)
262*5f4c09ddSEd Maste 			(*lfun)(LOG_DEBUG, "%s: host6 %s", __func__, p);
263*5f4c09ddSEd Maste 		if (strcmp(p, "*") != 0) {
264*5f4c09ddSEd Maste 			if (inet_pton(AF_INET6, p, &sin6->sin6_addr) == -1)
265*5f4c09ddSEd Maste 				goto out;
266*5f4c09ddSEd Maste 			sin6->sin6_family = AF_INET6;
267*5f4c09ddSEd Maste #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
268*5f4c09ddSEd Maste 			sin6->sin6_len = sizeof(*sin6);
269*5f4c09ddSEd Maste #endif
270*5f4c09ddSEd Maste 			port = &sin6->sin6_port;
271*5f4c09ddSEd Maste 		}
272*5f4c09ddSEd Maste 	} else if (pstr != p || strchr(p, '.') || conf_is_interface(p)) {
273*5f4c09ddSEd Maste 		if (pstr == p)
274*5f4c09ddSEd Maste 			pstr = "*";
275*5f4c09ddSEd Maste 		struct sockaddr_in *sin = (void *)&c->c_ss;
276*5f4c09ddSEd Maste 		struct sockaddr_if *sif = (void *)&c->c_ss;
277*5f4c09ddSEd Maste 		if (debug)
278*5f4c09ddSEd Maste 			(*lfun)(LOG_DEBUG, "%s: host4 %s", __func__, p);
279*5f4c09ddSEd Maste 		if (strcmp(p, "*") != 0) {
280*5f4c09ddSEd Maste 			if (conf_is_interface(p)) {
281*5f4c09ddSEd Maste 				if (!local)
282*5f4c09ddSEd Maste 					goto out2;
283*5f4c09ddSEd Maste 				if (debug)
284*5f4c09ddSEd Maste 					(*lfun)(LOG_DEBUG, "%s: interface %s",
285*5f4c09ddSEd Maste 					    __func__, p);
286*5f4c09ddSEd Maste 				if (c->c_lmask != FSTAR)
287*5f4c09ddSEd Maste 					goto out1;
288*5f4c09ddSEd Maste 				sif->sif_family = AF_MAX;
289*5f4c09ddSEd Maste 				strlcpy(sif->sif_name, p,
290*5f4c09ddSEd Maste 				    sizeof(sif->sif_name));
291*5f4c09ddSEd Maste #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
292*5f4c09ddSEd Maste 				sif->sif_len = sizeof(*sif);
293*5f4c09ddSEd Maste #endif
294*5f4c09ddSEd Maste 				port = &sif->sif_port;
295*5f4c09ddSEd Maste 			} else if (inet_pton(AF_INET, p, &sin->sin_addr) != -1)
296*5f4c09ddSEd Maste 			{
297*5f4c09ddSEd Maste 				sin->sin_family = AF_INET;
298*5f4c09ddSEd Maste #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
299*5f4c09ddSEd Maste 				sin->sin_len = sizeof(*sin);
300*5f4c09ddSEd Maste #endif
301*5f4c09ddSEd Maste 				port = &sin->sin_port;
302*5f4c09ddSEd Maste 			} else
303*5f4c09ddSEd Maste 				goto out;
304*5f4c09ddSEd Maste 		}
305*5f4c09ddSEd Maste 	}
306*5f4c09ddSEd Maste 
307*5f4c09ddSEd Maste 	if (conf_getport(f, l, local, &c->c_port, pstr) == -1)
308*5f4c09ddSEd Maste 		return -1;
309*5f4c09ddSEd Maste 
310*5f4c09ddSEd Maste 	if (port && c->c_port != FSTAR && c->c_port != FEQUAL)
311*5f4c09ddSEd Maste 		*port = htons((in_port_t)c->c_port);
312*5f4c09ddSEd Maste 	return 0;
313*5f4c09ddSEd Maste out:
314*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: Bad address [%s]", __func__, f, l, pstr);
315*5f4c09ddSEd Maste 	return -1;
316*5f4c09ddSEd Maste out1:
317*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: Can't specify mask %d with "
318*5f4c09ddSEd Maste 	    "interface [%s]", __func__, f, l, c->c_lmask, p);
319*5f4c09ddSEd Maste 	return -1;
320*5f4c09ddSEd Maste out2:
321*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: Interface spec does not make sense "
322*5f4c09ddSEd Maste 	    "with remote config [%s]", __func__, f, l, p);
323*5f4c09ddSEd Maste 	return -1;
324*5f4c09ddSEd Maste }
325*5f4c09ddSEd Maste 
326*5f4c09ddSEd Maste static int
conf_getproto(const char * f,size_t l,bool local __unused,struct conf * c,const char * p)327*5f4c09ddSEd Maste conf_getproto(const char *f, size_t l, bool local __unused, struct conf *c,
328*5f4c09ddSEd Maste     const char *p)
329*5f4c09ddSEd Maste {
330*5f4c09ddSEd Maste 	if (strcmp(p, "stream") == 0) {
331*5f4c09ddSEd Maste 		c->c_proto = IPPROTO_TCP;
332*5f4c09ddSEd Maste 		return 0;
333*5f4c09ddSEd Maste 	}
334*5f4c09ddSEd Maste 	if (strcmp(p, "dgram") == 0) {
335*5f4c09ddSEd Maste 		c->c_proto = IPPROTO_UDP;
336*5f4c09ddSEd Maste 		return 0;
337*5f4c09ddSEd Maste 	}
338*5f4c09ddSEd Maste 	return conf_getnum(f, l, local, &c->c_proto, "protocol", p);
339*5f4c09ddSEd Maste }
340*5f4c09ddSEd Maste 
341*5f4c09ddSEd Maste static int
conf_getfamily(const char * f,size_t l,bool local __unused,struct conf * c,const char * p)342*5f4c09ddSEd Maste conf_getfamily(const char *f, size_t l, bool local __unused, struct conf *c,
343*5f4c09ddSEd Maste     const char *p)
344*5f4c09ddSEd Maste {
345*5f4c09ddSEd Maste 	if (strncmp(p, "tcp", 3) == 0 || strncmp(p, "udp", 3) == 0) {
346*5f4c09ddSEd Maste 		c->c_family = p[3] == '6' ? AF_INET6 : AF_INET;
347*5f4c09ddSEd Maste 		return 0;
348*5f4c09ddSEd Maste 	}
349*5f4c09ddSEd Maste 	return conf_getnum(f, l, local, &c->c_family, "family", p);
350*5f4c09ddSEd Maste }
351*5f4c09ddSEd Maste 
352*5f4c09ddSEd Maste static int
conf_getuid(const char * f,size_t l,bool local __unused,struct conf * c,const char * p)353*5f4c09ddSEd Maste conf_getuid(const char *f, size_t l, bool local __unused, struct conf *c,
354*5f4c09ddSEd Maste     const char *p)
355*5f4c09ddSEd Maste {
356*5f4c09ddSEd Maste 	struct passwd *pw;
357*5f4c09ddSEd Maste 
358*5f4c09ddSEd Maste 	if ((pw = getpwnam(p)) != NULL) {
359*5f4c09ddSEd Maste 		c->c_uid = (int)pw->pw_uid;
360*5f4c09ddSEd Maste 		return 0;
361*5f4c09ddSEd Maste 	}
362*5f4c09ddSEd Maste 
363*5f4c09ddSEd Maste 	return conf_getnum(f, l, local, &c->c_uid, "user", p);
364*5f4c09ddSEd Maste }
365*5f4c09ddSEd Maste 
366*5f4c09ddSEd Maste 
367*5f4c09ddSEd Maste static int
conf_getname(const char * f,size_t l,bool local,struct conf * c,const char * p)368*5f4c09ddSEd Maste conf_getname(const char *f, size_t l, bool local, struct conf *c,
369*5f4c09ddSEd Maste     const char *p)
370*5f4c09ddSEd Maste {
371*5f4c09ddSEd Maste 	if (conf_getmask(f, l, local, &p, &c->c_rmask) == -1)
372*5f4c09ddSEd Maste 		return -1;
373*5f4c09ddSEd Maste 
374*5f4c09ddSEd Maste 	if (strcmp(p, "*") == 0) {
375*5f4c09ddSEd Maste 		strlcpy(c->c_name, rulename, CONFNAMESZ);
376*5f4c09ddSEd Maste 		return 0;
377*5f4c09ddSEd Maste 	}
378*5f4c09ddSEd Maste 
379*5f4c09ddSEd Maste 	if (strcmp(p, "=") == 0) {
380*5f4c09ddSEd Maste 		if (local)
381*5f4c09ddSEd Maste 			goto out;
382*5f4c09ddSEd Maste 		c->c_name[0] = '\0';
383*5f4c09ddSEd Maste 		return 0;
384*5f4c09ddSEd Maste 	}
385*5f4c09ddSEd Maste 
386*5f4c09ddSEd Maste 	snprintf(c->c_name, CONFNAMESZ, "%s%s", *p == '-' ? rulename : "", p);
387*5f4c09ddSEd Maste 	return 0;
388*5f4c09ddSEd Maste out:
389*5f4c09ddSEd Maste 	(*lfun)(LOG_ERR, "%s: %s, %zu: `=' name not allowed in local"
390*5f4c09ddSEd Maste 	    " config", __func__, f, l);
391*5f4c09ddSEd Maste 	return -1;
392*5f4c09ddSEd Maste }
393*5f4c09ddSEd Maste 
394*5f4c09ddSEd Maste static int
getvalue(const char * f,size_t l,bool local,void * r,char ** p,int (* fun)(const char *,size_t,bool,struct conf *,const char *))395*5f4c09ddSEd Maste getvalue(const char *f, size_t l, bool local, void *r, char **p,
396*5f4c09ddSEd Maste     int (*fun)(const char *, size_t, bool, struct conf *, const char *))
397*5f4c09ddSEd Maste {
398*5f4c09ddSEd Maste 	char *ep = *p;
399*5f4c09ddSEd Maste 
400*5f4c09ddSEd Maste 	advance(p);
401*5f4c09ddSEd Maste 	return (*fun)(f, l, local, r, ep);
402*5f4c09ddSEd Maste }
403*5f4c09ddSEd Maste 
404*5f4c09ddSEd Maste 
405*5f4c09ddSEd Maste static int
conf_parseline(const char * f,size_t l,char * p,struct conf * c,bool local)406*5f4c09ddSEd Maste conf_parseline(const char *f, size_t l, char *p, struct conf *c, bool local)
407*5f4c09ddSEd Maste {
408*5f4c09ddSEd Maste 	int e;
409*5f4c09ddSEd Maste 
410*5f4c09ddSEd Maste 	while (*p && isspace((unsigned char)*p))
411*5f4c09ddSEd Maste 		p++;
412*5f4c09ddSEd Maste 
413*5f4c09ddSEd Maste 	memset(c, 0, sizeof(*c));
414*5f4c09ddSEd Maste 	e = getvalue(f, l, local, c, &p, conf_gethostport);
415*5f4c09ddSEd Maste 	if (e) return -1;
416*5f4c09ddSEd Maste 	e = getvalue(f, l, local, c, &p, conf_getproto);
417*5f4c09ddSEd Maste 	if (e) return -1;
418*5f4c09ddSEd Maste 	e = getvalue(f, l, local, c, &p, conf_getfamily);
419*5f4c09ddSEd Maste 	if (e) return -1;
420*5f4c09ddSEd Maste 	e = getvalue(f, l, local, c, &p, conf_getuid);
421*5f4c09ddSEd Maste 	if (e) return -1;
422*5f4c09ddSEd Maste 	e = getvalue(f, l, local, c, &p, conf_getname);
423*5f4c09ddSEd Maste 	if (e) return -1;
424*5f4c09ddSEd Maste 	e = getvalue(f, l, local, c, &p, conf_getnfail);
425*5f4c09ddSEd Maste 	if (e) return -1;
426*5f4c09ddSEd Maste 	e = getvalue(f, l, local, c, &p, conf_getsecs);
427*5f4c09ddSEd Maste 	if (e) return -1;
428*5f4c09ddSEd Maste 
429*5f4c09ddSEd Maste 	return 0;
430*5f4c09ddSEd Maste }
431*5f4c09ddSEd Maste 
432*5f4c09ddSEd Maste static int
conf_sort(const void * v1,const void * v2)433*5f4c09ddSEd Maste conf_sort(const void *v1, const void *v2)
434*5f4c09ddSEd Maste {
435*5f4c09ddSEd Maste 	const struct conf *c1 = v1;
436*5f4c09ddSEd Maste 	const struct conf *c2 = v2;
437*5f4c09ddSEd Maste 
438*5f4c09ddSEd Maste #define CMP(a, b, f) \
439*5f4c09ddSEd Maste 	if ((a)->f > (b)->f) return -1; \
440*5f4c09ddSEd Maste 	else if ((a)->f < (b)->f) return 1
441*5f4c09ddSEd Maste 
442*5f4c09ddSEd Maste 	CMP(c1, c2, c_ss.ss_family);
443*5f4c09ddSEd Maste 	CMP(c1, c2, c_lmask);
444*5f4c09ddSEd Maste 	CMP(c1, c2, c_port);
445*5f4c09ddSEd Maste 	CMP(c1, c2, c_proto);
446*5f4c09ddSEd Maste 	CMP(c1, c2, c_family);
447*5f4c09ddSEd Maste 	CMP(c1, c2, c_rmask);
448*5f4c09ddSEd Maste 	CMP(c1, c2, c_uid);
449*5f4c09ddSEd Maste #undef CMP
450*5f4c09ddSEd Maste 	return 0;
451*5f4c09ddSEd Maste }
452*5f4c09ddSEd Maste 
453*5f4c09ddSEd Maste static int
conf_is_interface(const char * name)454*5f4c09ddSEd Maste conf_is_interface(const char *name)
455*5f4c09ddSEd Maste {
456*5f4c09ddSEd Maste 	const struct ifaddrs *ifa;
457*5f4c09ddSEd Maste 
458*5f4c09ddSEd Maste 	for (ifa = ifas; ifa; ifa = ifa->ifa_next)
459*5f4c09ddSEd Maste 		if (strcmp(ifa->ifa_name, name) == 0)
460*5f4c09ddSEd Maste 			return 1;
461*5f4c09ddSEd Maste 	return 0;
462*5f4c09ddSEd Maste }
463*5f4c09ddSEd Maste 
464*5f4c09ddSEd Maste #define MASK(m)  ((uint32_t)~((1 << (32 - (m))) - 1))
465*5f4c09ddSEd Maste 
466*5f4c09ddSEd Maste static int
conf_amask_eq(const void * v1,const void * v2,size_t len,int mask)467*5f4c09ddSEd Maste conf_amask_eq(const void *v1, const void *v2, size_t len, int mask)
468*5f4c09ddSEd Maste {
469*5f4c09ddSEd Maste 	const uint32_t *a1 = v1;
470*5f4c09ddSEd Maste 	const uint32_t *a2 = v2;
471*5f4c09ddSEd Maste 	uint32_t m;
472*5f4c09ddSEd Maste 	int omask = mask;
473*5f4c09ddSEd Maste 
474*5f4c09ddSEd Maste 	len >>= 2;
475*5f4c09ddSEd Maste 	switch (mask) {
476*5f4c09ddSEd Maste 	case FSTAR:
477*5f4c09ddSEd Maste 		if (memcmp(v1, v2, len) == 0)
478*5f4c09ddSEd Maste 			return 1;
479*5f4c09ddSEd Maste 		goto out;
480*5f4c09ddSEd Maste 	case FEQUAL:
481*5f4c09ddSEd Maste 		(*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__,
482*5f4c09ddSEd Maste 		    mask);
483*5f4c09ddSEd Maste 		abort();
484*5f4c09ddSEd Maste 	default:
485*5f4c09ddSEd Maste 		break;
486*5f4c09ddSEd Maste 	}
487*5f4c09ddSEd Maste 
488*5f4c09ddSEd Maste 	for (size_t i = 0; i < len; i++) {
489*5f4c09ddSEd Maste 		if (mask > 32) {
490*5f4c09ddSEd Maste 			m = htonl((uint32_t)~0);
491*5f4c09ddSEd Maste 			mask -= 32;
492*5f4c09ddSEd Maste 		} else if (mask) {
493*5f4c09ddSEd Maste 			m = htonl(MASK(mask));
494*5f4c09ddSEd Maste 			mask = 0;
495*5f4c09ddSEd Maste 		} else
496*5f4c09ddSEd Maste 			return 1;
497*5f4c09ddSEd Maste 		if ((a1[i] & m) != (a2[i] & m))
498*5f4c09ddSEd Maste 			goto out;
499*5f4c09ddSEd Maste 	}
500*5f4c09ddSEd Maste 	return 1;
501*5f4c09ddSEd Maste out:
502*5f4c09ddSEd Maste 	if (debug > 1) {
503*5f4c09ddSEd Maste 		char b1[256], b2[256];
504*5f4c09ddSEd Maste 		len <<= 2;
505*5f4c09ddSEd Maste 		blhexdump(b1, sizeof(b1), "a1", v1, len);
506*5f4c09ddSEd Maste 		blhexdump(b2, sizeof(b2), "a2", v2, len);
507*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s: %s != %s [0x%x]", __func__,
508*5f4c09ddSEd Maste 		    b1, b2, omask);
509*5f4c09ddSEd Maste 	}
510*5f4c09ddSEd Maste 	return 0;
511*5f4c09ddSEd Maste }
512*5f4c09ddSEd Maste 
513*5f4c09ddSEd Maste /*
514*5f4c09ddSEd Maste  * Apply the mask to the given address
515*5f4c09ddSEd Maste  */
516*5f4c09ddSEd Maste static void
conf_apply_mask(void * v,size_t len,int mask)517*5f4c09ddSEd Maste conf_apply_mask(void *v, size_t len, int mask)
518*5f4c09ddSEd Maste {
519*5f4c09ddSEd Maste 	uint32_t *a = v;
520*5f4c09ddSEd Maste 	uint32_t m;
521*5f4c09ddSEd Maste 
522*5f4c09ddSEd Maste 	switch (mask) {
523*5f4c09ddSEd Maste 	case FSTAR:
524*5f4c09ddSEd Maste 		return;
525*5f4c09ddSEd Maste 	case FEQUAL:
526*5f4c09ddSEd Maste 		(*lfun)(LOG_CRIT, "%s: Internal error: bad mask %d", __func__,
527*5f4c09ddSEd Maste 		    mask);
528*5f4c09ddSEd Maste 		abort();
529*5f4c09ddSEd Maste 	default:
530*5f4c09ddSEd Maste 		break;
531*5f4c09ddSEd Maste 	}
532*5f4c09ddSEd Maste 	len >>= 2;
533*5f4c09ddSEd Maste 
534*5f4c09ddSEd Maste 	for (size_t i = 0; i < len; i++) {
535*5f4c09ddSEd Maste 		if (mask > 32) {
536*5f4c09ddSEd Maste 			m = htonl((uint32_t)~0);
537*5f4c09ddSEd Maste 			mask -= 32;
538*5f4c09ddSEd Maste 		} else if (mask) {
539*5f4c09ddSEd Maste 			m = htonl(MASK(mask));
540*5f4c09ddSEd Maste 			mask = 0;
541*5f4c09ddSEd Maste 		} else
542*5f4c09ddSEd Maste 			m = 0;
543*5f4c09ddSEd Maste 		a[i] &= m;
544*5f4c09ddSEd Maste 	}
545*5f4c09ddSEd Maste }
546*5f4c09ddSEd Maste 
547*5f4c09ddSEd Maste /*
548*5f4c09ddSEd Maste  * apply the mask and the port to the address given
549*5f4c09ddSEd Maste  */
550*5f4c09ddSEd Maste static void
conf_addr_set(struct conf * c,const struct sockaddr_storage * ss)551*5f4c09ddSEd Maste conf_addr_set(struct conf *c, const struct sockaddr_storage *ss)
552*5f4c09ddSEd Maste {
553*5f4c09ddSEd Maste 	struct sockaddr_in *sin;
554*5f4c09ddSEd Maste 	struct sockaddr_in6 *sin6;
555*5f4c09ddSEd Maste 	in_port_t *port;
556*5f4c09ddSEd Maste 	void *addr;
557*5f4c09ddSEd Maste 	size_t alen;
558*5f4c09ddSEd Maste 
559*5f4c09ddSEd Maste 	c->c_lmask = c->c_rmask;
560*5f4c09ddSEd Maste 	c->c_ss = *ss;
561*5f4c09ddSEd Maste 
562*5f4c09ddSEd Maste 	if (c->c_ss.ss_family != c->c_family) {
563*5f4c09ddSEd Maste 		(*lfun)(LOG_CRIT, "%s: Internal error: mismatched family "
564*5f4c09ddSEd Maste 		    "%u != %u", __func__, c->c_ss.ss_family, c->c_family);
565*5f4c09ddSEd Maste 		abort();
566*5f4c09ddSEd Maste 	}
567*5f4c09ddSEd Maste 
568*5f4c09ddSEd Maste 	switch (c->c_ss.ss_family) {
569*5f4c09ddSEd Maste 	case AF_INET:
570*5f4c09ddSEd Maste 		sin = (void *)&c->c_ss;
571*5f4c09ddSEd Maste 		port = &sin->sin_port;
572*5f4c09ddSEd Maste 		addr = &sin->sin_addr;
573*5f4c09ddSEd Maste 		alen = sizeof(sin->sin_addr);
574*5f4c09ddSEd Maste 		break;
575*5f4c09ddSEd Maste 	case AF_INET6:
576*5f4c09ddSEd Maste 		sin6 = (void *)&c->c_ss;
577*5f4c09ddSEd Maste 		port = &sin6->sin6_port;
578*5f4c09ddSEd Maste 		addr = &sin6->sin6_addr;
579*5f4c09ddSEd Maste 		alen = sizeof(sin6->sin6_addr);
580*5f4c09ddSEd Maste 		break;
581*5f4c09ddSEd Maste 	default:
582*5f4c09ddSEd Maste 		(*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
583*5f4c09ddSEd Maste 		    __func__, c->c_ss.ss_family);
584*5f4c09ddSEd Maste 		abort();
585*5f4c09ddSEd Maste 	}
586*5f4c09ddSEd Maste 
587*5f4c09ddSEd Maste 	*port = htons((in_port_t)c->c_port);
588*5f4c09ddSEd Maste 	conf_apply_mask(addr, alen, c->c_lmask);
589*5f4c09ddSEd Maste 	if (c->c_lmask == FSTAR)
590*5f4c09ddSEd Maste 		c->c_lmask = (int)(alen * 8);
591*5f4c09ddSEd Maste 	if (debug) {
592*5f4c09ddSEd Maste 		char buf[128];
593*5f4c09ddSEd Maste 		sockaddr_snprintf(buf, sizeof(buf), "%a:%p", (void *)&c->c_ss);
594*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "Applied address %s", buf);
595*5f4c09ddSEd Maste 	}
596*5f4c09ddSEd Maste }
597*5f4c09ddSEd Maste 
598*5f4c09ddSEd Maste /*
599*5f4c09ddSEd Maste  * Compared two addresses for equality applying the mask
600*5f4c09ddSEd Maste  */
601*5f4c09ddSEd Maste static int
conf_inet_eq(const void * v1,const void * v2,int mask)602*5f4c09ddSEd Maste conf_inet_eq(const void *v1, const void *v2, int mask)
603*5f4c09ddSEd Maste {
604*5f4c09ddSEd Maste 	const struct sockaddr *sa1 = v1;
605*5f4c09ddSEd Maste 	const struct sockaddr *sa2 = v2;
606*5f4c09ddSEd Maste 	size_t size;
607*5f4c09ddSEd Maste 
608*5f4c09ddSEd Maste 	if (sa1->sa_family != sa2->sa_family)
609*5f4c09ddSEd Maste 		return 0;
610*5f4c09ddSEd Maste 
611*5f4c09ddSEd Maste 	switch (sa1->sa_family) {
612*5f4c09ddSEd Maste 	case AF_INET: {
613*5f4c09ddSEd Maste 		const struct sockaddr_in *s1 = v1;
614*5f4c09ddSEd Maste 		const struct sockaddr_in *s2 = v2;
615*5f4c09ddSEd Maste 		size = sizeof(s1->sin_addr);
616*5f4c09ddSEd Maste 		v1 = &s1->sin_addr;
617*5f4c09ddSEd Maste 		v2 = &s2->sin_addr;
618*5f4c09ddSEd Maste 		break;
619*5f4c09ddSEd Maste 	}
620*5f4c09ddSEd Maste 
621*5f4c09ddSEd Maste 	case AF_INET6: {
622*5f4c09ddSEd Maste 		const struct sockaddr_in6 *s1 = v1;
623*5f4c09ddSEd Maste 		const struct sockaddr_in6 *s2 = v2;
624*5f4c09ddSEd Maste 		size = sizeof(s1->sin6_addr);
625*5f4c09ddSEd Maste 		v1 = &s1->sin6_addr;
626*5f4c09ddSEd Maste 		v2 = &s2->sin6_addr;
627*5f4c09ddSEd Maste 		break;
628*5f4c09ddSEd Maste 	}
629*5f4c09ddSEd Maste 
630*5f4c09ddSEd Maste 	default:
631*5f4c09ddSEd Maste 		(*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
632*5f4c09ddSEd Maste 		    __func__, sa1->sa_family);
633*5f4c09ddSEd Maste 		abort();
634*5f4c09ddSEd Maste 	}
635*5f4c09ddSEd Maste 
636*5f4c09ddSEd Maste 	return conf_amask_eq(v1, v2, size, mask);
637*5f4c09ddSEd Maste }
638*5f4c09ddSEd Maste 
639*5f4c09ddSEd Maste static int
conf_addr_in_interface(const struct sockaddr_storage * s1,const struct sockaddr_storage * s2,int mask)640*5f4c09ddSEd Maste conf_addr_in_interface(const struct sockaddr_storage *s1,
641*5f4c09ddSEd Maste     const struct sockaddr_storage *s2, int mask)
642*5f4c09ddSEd Maste {
643*5f4c09ddSEd Maste 	const char *name = SIF_NAME(s2);
644*5f4c09ddSEd Maste 	const struct ifaddrs *ifa;
645*5f4c09ddSEd Maste 
646*5f4c09ddSEd Maste 	for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
647*5f4c09ddSEd Maste 		if ((ifa->ifa_flags & IFF_UP) == 0)
648*5f4c09ddSEd Maste 			continue;
649*5f4c09ddSEd Maste 
650*5f4c09ddSEd Maste 		if (strcmp(ifa->ifa_name, name) != 0)
651*5f4c09ddSEd Maste 			continue;
652*5f4c09ddSEd Maste 
653*5f4c09ddSEd Maste 		if (s1->ss_family != ifa->ifa_addr->sa_family)
654*5f4c09ddSEd Maste 			continue;
655*5f4c09ddSEd Maste 
656*5f4c09ddSEd Maste 		bool eq;
657*5f4c09ddSEd Maste 		switch (s1->ss_family) {
658*5f4c09ddSEd Maste 		case AF_INET:
659*5f4c09ddSEd Maste 		case AF_INET6:
660*5f4c09ddSEd Maste 			eq = conf_inet_eq(ifa->ifa_addr, s1, mask);
661*5f4c09ddSEd Maste 			break;
662*5f4c09ddSEd Maste 		default:
663*5f4c09ddSEd Maste 			(*lfun)(LOG_ERR, "Bad family %u", s1->ss_family);
664*5f4c09ddSEd Maste 			continue;
665*5f4c09ddSEd Maste 		}
666*5f4c09ddSEd Maste 		if (eq)
667*5f4c09ddSEd Maste 			return 1;
668*5f4c09ddSEd Maste 	}
669*5f4c09ddSEd Maste 	return 0;
670*5f4c09ddSEd Maste }
671*5f4c09ddSEd Maste 
672*5f4c09ddSEd Maste static int
conf_addr_eq(const struct sockaddr_storage * s1,const struct sockaddr_storage * s2,int mask)673*5f4c09ddSEd Maste conf_addr_eq(const struct sockaddr_storage *s1,
674*5f4c09ddSEd Maste     const struct sockaddr_storage *s2, int mask)
675*5f4c09ddSEd Maste {
676*5f4c09ddSEd Maste 	switch (s2->ss_family) {
677*5f4c09ddSEd Maste 	case 0:
678*5f4c09ddSEd Maste 		return 1;
679*5f4c09ddSEd Maste 	case AF_MAX:
680*5f4c09ddSEd Maste 		return conf_addr_in_interface(s1, s2, mask);
681*5f4c09ddSEd Maste 	case AF_INET:
682*5f4c09ddSEd Maste 	case AF_INET6:
683*5f4c09ddSEd Maste 		return conf_inet_eq(s1, s2, mask);
684*5f4c09ddSEd Maste 	default:
685*5f4c09ddSEd Maste 		(*lfun)(LOG_CRIT, "%s: Internal error: bad family %u",
686*5f4c09ddSEd Maste 		    __func__, s1->ss_family);
687*5f4c09ddSEd Maste 		abort();
688*5f4c09ddSEd Maste 	}
689*5f4c09ddSEd Maste }
690*5f4c09ddSEd Maste 
691*5f4c09ddSEd Maste static int
conf_eq(const struct conf * c1,const struct conf * c2)692*5f4c09ddSEd Maste conf_eq(const struct conf *c1, const struct conf *c2)
693*5f4c09ddSEd Maste {
694*5f4c09ddSEd Maste 
695*5f4c09ddSEd Maste 	if (!conf_addr_eq(&c1->c_ss, &c2->c_ss, c2->c_lmask))
696*5f4c09ddSEd Maste 		return 0;
697*5f4c09ddSEd Maste 
698*5f4c09ddSEd Maste #define CMP(a, b, f) \
699*5f4c09ddSEd Maste 	if ((a)->f != (b)->f && (b)->f != FSTAR && (b)->f != FEQUAL) { \
700*5f4c09ddSEd Maste 		if (debug > 1) \
701*5f4c09ddSEd Maste 			(*lfun)(LOG_DEBUG, "%s: %s fail %d != %d", __func__, \
702*5f4c09ddSEd Maste 			    __STRING(f), (a)->f, (b)->f); \
703*5f4c09ddSEd Maste 		return 0; \
704*5f4c09ddSEd Maste 	}
705*5f4c09ddSEd Maste 	CMP(c1, c2, c_port);
706*5f4c09ddSEd Maste 	CMP(c1, c2, c_proto);
707*5f4c09ddSEd Maste 	CMP(c1, c2, c_family);
708*5f4c09ddSEd Maste 	CMP(c1, c2, c_uid);
709*5f4c09ddSEd Maste #undef CMP
710*5f4c09ddSEd Maste 	return 1;
711*5f4c09ddSEd Maste }
712*5f4c09ddSEd Maste 
713*5f4c09ddSEd Maste static const char *
conf_num(char * b,size_t l,int n)714*5f4c09ddSEd Maste conf_num(char *b, size_t l, int n)
715*5f4c09ddSEd Maste {
716*5f4c09ddSEd Maste 	switch (n) {
717*5f4c09ddSEd Maste 	case FSTAR:
718*5f4c09ddSEd Maste 		return "*";
719*5f4c09ddSEd Maste 	case FEQUAL:
720*5f4c09ddSEd Maste 		return "=";
721*5f4c09ddSEd Maste 	default:
722*5f4c09ddSEd Maste 		snprintf(b, l, "%d", n);
723*5f4c09ddSEd Maste 		return b;
724*5f4c09ddSEd Maste 	}
725*5f4c09ddSEd Maste }
726*5f4c09ddSEd Maste 
727*5f4c09ddSEd Maste static const char *
fmtname(const char * n)728*5f4c09ddSEd Maste fmtname(const char *n) {
729*5f4c09ddSEd Maste 	size_t l = strlen(rulename);
730*5f4c09ddSEd Maste 	if (l == 0)
731*5f4c09ddSEd Maste 		return "*";
732*5f4c09ddSEd Maste 	if (strncmp(n, rulename, l) == 0) {
733*5f4c09ddSEd Maste 		if (n[l] != '\0')
734*5f4c09ddSEd Maste 			return n + l;
735*5f4c09ddSEd Maste 		else
736*5f4c09ddSEd Maste 			return "*";
737*5f4c09ddSEd Maste 	} else if (!*n)
738*5f4c09ddSEd Maste 		return "=";
739*5f4c09ddSEd Maste 	else
740*5f4c09ddSEd Maste 		return n;
741*5f4c09ddSEd Maste }
742*5f4c09ddSEd Maste 
743*5f4c09ddSEd Maste static void
fmtport(char * b,size_t l,int port)744*5f4c09ddSEd Maste fmtport(char *b, size_t l, int port)
745*5f4c09ddSEd Maste {
746*5f4c09ddSEd Maste 	char buf[128];
747*5f4c09ddSEd Maste 
748*5f4c09ddSEd Maste 	if (port == FSTAR)
749*5f4c09ddSEd Maste 		return;
750*5f4c09ddSEd Maste 
751*5f4c09ddSEd Maste 	if (b[0] == '\0' || strcmp(b, "*") == 0)
752*5f4c09ddSEd Maste 		snprintf(b, l, "%d", port);
753*5f4c09ddSEd Maste 	else {
754*5f4c09ddSEd Maste 		snprintf(buf, sizeof(buf), ":%d", port);
755*5f4c09ddSEd Maste 		strlcat(b, buf, l);
756*5f4c09ddSEd Maste 	}
757*5f4c09ddSEd Maste }
758*5f4c09ddSEd Maste 
759*5f4c09ddSEd Maste static const char *
fmtmask(char * b,size_t l,int fam,int mask)760*5f4c09ddSEd Maste fmtmask(char *b, size_t l, int fam, int mask)
761*5f4c09ddSEd Maste {
762*5f4c09ddSEd Maste 	char buf[128];
763*5f4c09ddSEd Maste 
764*5f4c09ddSEd Maste 	switch (mask) {
765*5f4c09ddSEd Maste 	case FSTAR:
766*5f4c09ddSEd Maste 		return "";
767*5f4c09ddSEd Maste 	case FEQUAL:
768*5f4c09ddSEd Maste 		if (strcmp(b, "=") == 0)
769*5f4c09ddSEd Maste 			return "";
770*5f4c09ddSEd Maste 		else {
771*5f4c09ddSEd Maste 			strlcat(b, "/=", l);
772*5f4c09ddSEd Maste 			return b;
773*5f4c09ddSEd Maste 		}
774*5f4c09ddSEd Maste 	default:
775*5f4c09ddSEd Maste 		break;
776*5f4c09ddSEd Maste 	}
777*5f4c09ddSEd Maste 
778*5f4c09ddSEd Maste 	switch (fam) {
779*5f4c09ddSEd Maste 	case AF_INET:
780*5f4c09ddSEd Maste 		if (mask == 32)
781*5f4c09ddSEd Maste 			return "";
782*5f4c09ddSEd Maste 		break;
783*5f4c09ddSEd Maste 	case AF_INET6:
784*5f4c09ddSEd Maste 		if (mask == 128)
785*5f4c09ddSEd Maste 			return "";
786*5f4c09ddSEd Maste 		break;
787*5f4c09ddSEd Maste 	default:
788*5f4c09ddSEd Maste 		break;
789*5f4c09ddSEd Maste 	}
790*5f4c09ddSEd Maste 
791*5f4c09ddSEd Maste 	snprintf(buf, sizeof(buf), "/%d", mask);
792*5f4c09ddSEd Maste 	strlcat(b, buf, l);
793*5f4c09ddSEd Maste 	return b;
794*5f4c09ddSEd Maste }
795*5f4c09ddSEd Maste 
796*5f4c09ddSEd Maste static const char *
conf_namemask(char * b,size_t l,const struct conf * c)797*5f4c09ddSEd Maste conf_namemask(char *b, size_t l, const struct conf *c)
798*5f4c09ddSEd Maste {
799*5f4c09ddSEd Maste 	strlcpy(b, fmtname(c->c_name), l);
800*5f4c09ddSEd Maste 	fmtmask(b, l, c->c_family, c->c_rmask);
801*5f4c09ddSEd Maste 	return b;
802*5f4c09ddSEd Maste }
803*5f4c09ddSEd Maste 
804*5f4c09ddSEd Maste const char *
conf_print(char * buf,size_t len,const char * pref,const char * delim,const struct conf * c)805*5f4c09ddSEd Maste conf_print(char *buf, size_t len, const char *pref, const char *delim,
806*5f4c09ddSEd Maste     const struct conf *c)
807*5f4c09ddSEd Maste {
808*5f4c09ddSEd Maste 	char ha[128], hb[32], b[5][64];
809*5f4c09ddSEd Maste 	int sp;
810*5f4c09ddSEd Maste 
811*5f4c09ddSEd Maste #define N(n, v) conf_num(b[n], sizeof(b[n]), (v))
812*5f4c09ddSEd Maste 
813*5f4c09ddSEd Maste 	switch (c->c_ss.ss_family) {
814*5f4c09ddSEd Maste 	case 0:
815*5f4c09ddSEd Maste 		snprintf(ha, sizeof(ha), "*");
816*5f4c09ddSEd Maste 		break;
817*5f4c09ddSEd Maste 	case AF_MAX:
818*5f4c09ddSEd Maste 		snprintf(ha, sizeof(ha), "%s", SIF_NAME(&c->c_ss));
819*5f4c09ddSEd Maste 		break;
820*5f4c09ddSEd Maste 	default:
821*5f4c09ddSEd Maste 		sockaddr_snprintf(ha, sizeof(ha), "%a", (const void *)&c->c_ss);
822*5f4c09ddSEd Maste 		break;
823*5f4c09ddSEd Maste 	}
824*5f4c09ddSEd Maste 
825*5f4c09ddSEd Maste 	fmtmask(ha, sizeof(ha), c->c_family, c->c_lmask);
826*5f4c09ddSEd Maste 	fmtport(ha, sizeof(ha), c->c_port);
827*5f4c09ddSEd Maste 
828*5f4c09ddSEd Maste 	sp = *delim == '\t' ? 20 : -1;
829*5f4c09ddSEd Maste 	hb[0] = '\0';
830*5f4c09ddSEd Maste 	if (*delim)
831*5f4c09ddSEd Maste 		snprintf(buf, len, "%s%*.*s%s%s%s" "%s%s%s%s"
832*5f4c09ddSEd Maste 		    "%s%s" "%s%s%s",
833*5f4c09ddSEd Maste 		    pref, sp, sp, ha, delim, N(0, c->c_proto), delim,
834*5f4c09ddSEd Maste 		    N(1, c->c_family), delim, N(2, c->c_uid), delim,
835*5f4c09ddSEd Maste 		    conf_namemask(hb, sizeof(hb), c), delim,
836*5f4c09ddSEd Maste 		    N(3, c->c_nfail), delim, N(4, c->c_duration));
837*5f4c09ddSEd Maste 	else
838*5f4c09ddSEd Maste 		snprintf(buf, len, "%starget:%s, proto:%s, family:%s, "
839*5f4c09ddSEd Maste 		    "uid:%s, name:%s, nfail:%s, duration:%s", pref,
840*5f4c09ddSEd Maste 		    ha, N(0, c->c_proto), N(1, c->c_family), N(2, c->c_uid),
841*5f4c09ddSEd Maste 		    conf_namemask(hb, sizeof(hb), c),
842*5f4c09ddSEd Maste 		    N(3, c->c_nfail), N(4, c->c_duration));
843*5f4c09ddSEd Maste 	return buf;
844*5f4c09ddSEd Maste }
845*5f4c09ddSEd Maste 
846*5f4c09ddSEd Maste /*
847*5f4c09ddSEd Maste  * Apply the local config match to the result
848*5f4c09ddSEd Maste  */
849*5f4c09ddSEd Maste static void
conf_apply(struct conf * c,const struct conf * sc)850*5f4c09ddSEd Maste conf_apply(struct conf *c, const struct conf *sc)
851*5f4c09ddSEd Maste {
852*5f4c09ddSEd Maste 	char buf[BUFSIZ];
853*5f4c09ddSEd Maste 
854*5f4c09ddSEd Maste 	if (debug) {
855*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s: %s", __func__,
856*5f4c09ddSEd Maste 		    conf_print(buf, sizeof(buf), "merge:\t", "", sc));
857*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s: %s", __func__,
858*5f4c09ddSEd Maste 		    conf_print(buf, sizeof(buf), "to:\t", "", c));
859*5f4c09ddSEd Maste 	}
860*5f4c09ddSEd Maste 	memcpy(c->c_name, sc->c_name, CONFNAMESZ);
861*5f4c09ddSEd Maste 	c->c_uid = sc->c_uid;
862*5f4c09ddSEd Maste 	c->c_rmask = sc->c_rmask;
863*5f4c09ddSEd Maste 	c->c_nfail = sc->c_nfail;
864*5f4c09ddSEd Maste 	c->c_duration = sc->c_duration;
865*5f4c09ddSEd Maste 
866*5f4c09ddSEd Maste 	if (debug)
867*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s: %s", __func__,
868*5f4c09ddSEd Maste 		    conf_print(buf, sizeof(buf), "result:\t", "", c));
869*5f4c09ddSEd Maste }
870*5f4c09ddSEd Maste 
871*5f4c09ddSEd Maste /*
872*5f4c09ddSEd Maste  * Merge a remote configuration to the result
873*5f4c09ddSEd Maste  */
874*5f4c09ddSEd Maste static void
conf_merge(struct conf * c,const struct conf * sc)875*5f4c09ddSEd Maste conf_merge(struct conf *c, const struct conf *sc)
876*5f4c09ddSEd Maste {
877*5f4c09ddSEd Maste 	char buf[BUFSIZ];
878*5f4c09ddSEd Maste 
879*5f4c09ddSEd Maste 	if (debug) {
880*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s: %s", __func__,
881*5f4c09ddSEd Maste 		    conf_print(buf, sizeof(buf), "merge:\t", "", sc));
882*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s: %s", __func__,
883*5f4c09ddSEd Maste 		    conf_print(buf, sizeof(buf), "to:\t", "", c));
884*5f4c09ddSEd Maste 	}
885*5f4c09ddSEd Maste 
886*5f4c09ddSEd Maste 	if (sc->c_name[0])
887*5f4c09ddSEd Maste 		memcpy(c->c_name, sc->c_name, CONFNAMESZ);
888*5f4c09ddSEd Maste 	if (sc->c_uid != FEQUAL)
889*5f4c09ddSEd Maste 		c->c_uid = sc->c_uid;
890*5f4c09ddSEd Maste 	if (sc->c_rmask != FEQUAL)
891*5f4c09ddSEd Maste 		c->c_lmask = c->c_rmask = sc->c_rmask;
892*5f4c09ddSEd Maste 	if (sc->c_nfail != FEQUAL)
893*5f4c09ddSEd Maste 		c->c_nfail = sc->c_nfail;
894*5f4c09ddSEd Maste 	if (sc->c_duration != FEQUAL)
895*5f4c09ddSEd Maste 		c->c_duration = sc->c_duration;
896*5f4c09ddSEd Maste 	if (debug)
897*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s: %s", __func__,
898*5f4c09ddSEd Maste 		    conf_print(buf, sizeof(buf), "result:\t", "", c));
899*5f4c09ddSEd Maste }
900*5f4c09ddSEd Maste 
901*5f4c09ddSEd Maste static void
confset_init(struct confset * cs)902*5f4c09ddSEd Maste confset_init(struct confset *cs)
903*5f4c09ddSEd Maste {
904*5f4c09ddSEd Maste 	cs->cs_c = NULL;
905*5f4c09ddSEd Maste 	cs->cs_n = 0;
906*5f4c09ddSEd Maste 	cs->cs_m = 0;
907*5f4c09ddSEd Maste }
908*5f4c09ddSEd Maste 
909*5f4c09ddSEd Maste static int
confset_grow(struct confset * cs)910*5f4c09ddSEd Maste confset_grow(struct confset *cs)
911*5f4c09ddSEd Maste {
912*5f4c09ddSEd Maste 	void *tc;
913*5f4c09ddSEd Maste 
914*5f4c09ddSEd Maste 	cs->cs_m += 10;
915*5f4c09ddSEd Maste 	tc = realloc(cs->cs_c, cs->cs_m * sizeof(*cs->cs_c));
916*5f4c09ddSEd Maste 	if (tc == NULL) {
917*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR, "%s: Can't grow confset (%m)", __func__);
918*5f4c09ddSEd Maste 		return -1;
919*5f4c09ddSEd Maste 	}
920*5f4c09ddSEd Maste 	cs->cs_c = tc;
921*5f4c09ddSEd Maste 	return 0;
922*5f4c09ddSEd Maste }
923*5f4c09ddSEd Maste 
924*5f4c09ddSEd Maste static struct conf *
confset_get(struct confset * cs)925*5f4c09ddSEd Maste confset_get(struct confset *cs)
926*5f4c09ddSEd Maste {
927*5f4c09ddSEd Maste 	return &cs->cs_c[cs->cs_n];
928*5f4c09ddSEd Maste }
929*5f4c09ddSEd Maste 
930*5f4c09ddSEd Maste static bool
confset_full(const struct confset * cs)931*5f4c09ddSEd Maste confset_full(const struct confset *cs)
932*5f4c09ddSEd Maste {
933*5f4c09ddSEd Maste 	return cs->cs_n == cs->cs_m;
934*5f4c09ddSEd Maste }
935*5f4c09ddSEd Maste 
936*5f4c09ddSEd Maste static void
confset_sort(struct confset * cs)937*5f4c09ddSEd Maste confset_sort(struct confset *cs)
938*5f4c09ddSEd Maste {
939*5f4c09ddSEd Maste 	qsort(cs->cs_c, cs->cs_n, sizeof(*cs->cs_c), conf_sort);
940*5f4c09ddSEd Maste }
941*5f4c09ddSEd Maste 
942*5f4c09ddSEd Maste static void
confset_add(struct confset * cs)943*5f4c09ddSEd Maste confset_add(struct confset *cs)
944*5f4c09ddSEd Maste {
945*5f4c09ddSEd Maste 	cs->cs_n++;
946*5f4c09ddSEd Maste }
947*5f4c09ddSEd Maste 
948*5f4c09ddSEd Maste static void
confset_free(struct confset * cs)949*5f4c09ddSEd Maste confset_free(struct confset *cs)
950*5f4c09ddSEd Maste {
951*5f4c09ddSEd Maste 	free(cs->cs_c);
952*5f4c09ddSEd Maste 	confset_init(cs);
953*5f4c09ddSEd Maste }
954*5f4c09ddSEd Maste 
955*5f4c09ddSEd Maste static void
confset_replace(struct confset * dc,struct confset * sc)956*5f4c09ddSEd Maste confset_replace(struct confset *dc, struct confset *sc)
957*5f4c09ddSEd Maste {
958*5f4c09ddSEd Maste 	struct confset tc;
959*5f4c09ddSEd Maste 	tc = *dc;
960*5f4c09ddSEd Maste 	*dc = *sc;
961*5f4c09ddSEd Maste 	confset_init(sc);
962*5f4c09ddSEd Maste 	confset_free(&tc);
963*5f4c09ddSEd Maste }
964*5f4c09ddSEd Maste 
965*5f4c09ddSEd Maste static void
confset_list(const struct confset * cs,const char * msg,const char * where)966*5f4c09ddSEd Maste confset_list(const struct confset *cs, const char *msg, const char *where)
967*5f4c09ddSEd Maste {
968*5f4c09ddSEd Maste 	char buf[BUFSIZ];
969*5f4c09ddSEd Maste 
970*5f4c09ddSEd Maste 	(*lfun)(LOG_DEBUG, "[%s]", msg);
971*5f4c09ddSEd Maste 	(*lfun)(LOG_DEBUG, "%20.20s\ttype\tproto\towner\tname\tnfail\tduration",
972*5f4c09ddSEd Maste 	    where);
973*5f4c09ddSEd Maste 	for (size_t i = 0; i < cs->cs_n; i++)
974*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf), "", "\t",
975*5f4c09ddSEd Maste 		    &cs->cs_c[i]));
976*5f4c09ddSEd Maste }
977*5f4c09ddSEd Maste 
978*5f4c09ddSEd Maste /*
979*5f4c09ddSEd Maste  * Match a configuration against the given list and apply the function
980*5f4c09ddSEd Maste  * to it, returning the matched entry number.
981*5f4c09ddSEd Maste  */
982*5f4c09ddSEd Maste static size_t
confset_match(const struct confset * cs,struct conf * c,void (* fun)(struct conf *,const struct conf *))983*5f4c09ddSEd Maste confset_match(const struct confset *cs, struct conf *c,
984*5f4c09ddSEd Maste     void (*fun)(struct conf *, const struct conf *))
985*5f4c09ddSEd Maste {
986*5f4c09ddSEd Maste 	char buf[BUFSIZ];
987*5f4c09ddSEd Maste 	size_t i;
988*5f4c09ddSEd Maste 
989*5f4c09ddSEd Maste 	for (i = 0; i < cs->cs_n; i++) {
990*5f4c09ddSEd Maste 		if (debug)
991*5f4c09ddSEd Maste 			(*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
992*5f4c09ddSEd Maste 			    "check:\t", "", &cs->cs_c[i]));
993*5f4c09ddSEd Maste 		if (conf_eq(c, &cs->cs_c[i])) {
994*5f4c09ddSEd Maste 			if (debug)
995*5f4c09ddSEd Maste 				(*lfun)(LOG_DEBUG, "%s",
996*5f4c09ddSEd Maste 				    conf_print(buf, sizeof(buf),
997*5f4c09ddSEd Maste 				    "found:\t", "", &cs->cs_c[i]));
998*5f4c09ddSEd Maste 			(*fun)(c, &cs->cs_c[i]);
999*5f4c09ddSEd Maste 			break;
1000*5f4c09ddSEd Maste 		}
1001*5f4c09ddSEd Maste 	}
1002*5f4c09ddSEd Maste 	return i;
1003*5f4c09ddSEd Maste }
1004*5f4c09ddSEd Maste 
1005*5f4c09ddSEd Maste #ifdef AF_ROUTE
1006*5f4c09ddSEd Maste static int
conf_route_perm(int fd)1007*5f4c09ddSEd Maste conf_route_perm(int fd) {
1008*5f4c09ddSEd Maste #if defined(RTM_IFANNOUNCE) && defined(SA_SIZE)
1009*5f4c09ddSEd Maste 	/*
1010*5f4c09ddSEd Maste 	 * Send a routing message that is not supported to check for access
1011*5f4c09ddSEd Maste 	 * We expect EOPNOTSUPP for having access, since we are sending a
1012*5f4c09ddSEd Maste 	 * request the system does not understand and EACCES if we don't have
1013*5f4c09ddSEd Maste 	 * access.
1014*5f4c09ddSEd Maste 	 */
1015*5f4c09ddSEd Maste 	static struct sockaddr_in sin = {
1016*5f4c09ddSEd Maste #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1017*5f4c09ddSEd Maste 		.sin_len = sizeof(sin),
1018*5f4c09ddSEd Maste #endif
1019*5f4c09ddSEd Maste 		.sin_family = AF_INET,
1020*5f4c09ddSEd Maste 	};
1021*5f4c09ddSEd Maste 	char buf[4096];
1022*5f4c09ddSEd Maste 	struct rt_msghdr *rtm = (void *)buf;
1023*5f4c09ddSEd Maste 	char *cp = (char *)(rtm + 1);
1024*5f4c09ddSEd Maste 	size_t l;
1025*5f4c09ddSEd Maste 
1026*5f4c09ddSEd Maste #define NEXTADDR(s) \
1027*5f4c09ddSEd Maste 	l = SA_SIZE(sizeof(*s)); memmove(cp, s, l); cp += l;
1028*5f4c09ddSEd Maste 	memset(buf, 0, sizeof(buf));
1029*5f4c09ddSEd Maste 	rtm->rtm_type = RTM_IFANNOUNCE;
1030*5f4c09ddSEd Maste 	rtm->rtm_flags = 0;
1031*5f4c09ddSEd Maste 	rtm->rtm_addrs = RTA_DST|RTA_GATEWAY;
1032*5f4c09ddSEd Maste 	rtm->rtm_version = RTM_VERSION;
1033*5f4c09ddSEd Maste 	rtm->rtm_seq = 666;
1034*5f4c09ddSEd Maste 	NEXTADDR(&sin);
1035*5f4c09ddSEd Maste 	NEXTADDR(&sin);
1036*5f4c09ddSEd Maste 	rtm->rtm_msglen = (u_short)((char *)cp - (char *)rtm);
1037*5f4c09ddSEd Maste 	if (write(fd, rtm, rtm->rtm_msglen) != -1) {
1038*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR, "Writing to routing socket succeeded!");
1039*5f4c09ddSEd Maste 		return 0;
1040*5f4c09ddSEd Maste 	}
1041*5f4c09ddSEd Maste 	switch (errno) {
1042*5f4c09ddSEd Maste 	case EACCES:
1043*5f4c09ddSEd Maste 		return 0;
1044*5f4c09ddSEd Maste 	case EOPNOTSUPP:
1045*5f4c09ddSEd Maste 		return 1;
1046*5f4c09ddSEd Maste 	default:
1047*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR,
1048*5f4c09ddSEd Maste 		    "Unexpected error writing to routing socket (%m)");
1049*5f4c09ddSEd Maste 		return 0;
1050*5f4c09ddSEd Maste 	}
1051*5f4c09ddSEd Maste #else
1052*5f4c09ddSEd Maste 	return 0;
1053*5f4c09ddSEd Maste #endif
1054*5f4c09ddSEd Maste }
1055*5f4c09ddSEd Maste #endif
1056*5f4c09ddSEd Maste 
1057*5f4c09ddSEd Maste static int
conf_handle_inet(int fd,const void * lss,struct conf * cr)1058*5f4c09ddSEd Maste conf_handle_inet(int fd, const void *lss, struct conf *cr)
1059*5f4c09ddSEd Maste {
1060*5f4c09ddSEd Maste 	char buf[BUFSIZ];
1061*5f4c09ddSEd Maste 	int proto;
1062*5f4c09ddSEd Maste 	socklen_t slen = sizeof(proto);
1063*5f4c09ddSEd Maste 
1064*5f4c09ddSEd Maste 	if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &proto, &slen) == -1) {
1065*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR, "getsockopt failed (%m)");
1066*5f4c09ddSEd Maste 		return -1;
1067*5f4c09ddSEd Maste 	}
1068*5f4c09ddSEd Maste 
1069*5f4c09ddSEd Maste 	if (debug) {
1070*5f4c09ddSEd Maste 		sockaddr_snprintf(buf, sizeof(buf), "%a:%p", lss);
1071*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "listening socket: %s", buf);
1072*5f4c09ddSEd Maste 	}
1073*5f4c09ddSEd Maste 
1074*5f4c09ddSEd Maste 	switch (proto) {
1075*5f4c09ddSEd Maste 	case SOCK_STREAM:
1076*5f4c09ddSEd Maste 		cr->c_proto = IPPROTO_TCP;
1077*5f4c09ddSEd Maste 		break;
1078*5f4c09ddSEd Maste 	case SOCK_DGRAM:
1079*5f4c09ddSEd Maste 		cr->c_proto = IPPROTO_UDP;
1080*5f4c09ddSEd Maste 		break;
1081*5f4c09ddSEd Maste 	default:
1082*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR, "unsupported protocol %d", proto);
1083*5f4c09ddSEd Maste 		return -1;
1084*5f4c09ddSEd Maste 	}
1085*5f4c09ddSEd Maste 	return 0;
1086*5f4c09ddSEd Maste }
1087*5f4c09ddSEd Maste 
1088*5f4c09ddSEd Maste const struct conf *
conf_find(int fd,uid_t uid,const struct sockaddr_storage * rss,struct conf * cr)1089*5f4c09ddSEd Maste conf_find(int fd, uid_t uid, const struct sockaddr_storage *rss,
1090*5f4c09ddSEd Maste     struct conf *cr)
1091*5f4c09ddSEd Maste {
1092*5f4c09ddSEd Maste 	socklen_t slen;
1093*5f4c09ddSEd Maste 	struct sockaddr_storage lss;
1094*5f4c09ddSEd Maste 	size_t i;
1095*5f4c09ddSEd Maste 	char buf[BUFSIZ];
1096*5f4c09ddSEd Maste 
1097*5f4c09ddSEd Maste 	memset(cr, 0, sizeof(*cr));
1098*5f4c09ddSEd Maste 	slen = sizeof(lss);
1099*5f4c09ddSEd Maste 	memset(&lss, 0, slen);
1100*5f4c09ddSEd Maste 	if (getsockname(fd, (void *)&lss, &slen) == -1) {
1101*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR, "getsockname failed (%m)");
1102*5f4c09ddSEd Maste 		return NULL;
1103*5f4c09ddSEd Maste 	}
1104*5f4c09ddSEd Maste 
1105*5f4c09ddSEd Maste 	switch (lss.ss_family) {
1106*5f4c09ddSEd Maste 	case AF_INET:
1107*5f4c09ddSEd Maste 		cr->c_port = ntohs(((struct sockaddr_in *)&lss)->sin_port);
1108*5f4c09ddSEd Maste 		if (conf_handle_inet(fd, &lss, cr) == -1)
1109*5f4c09ddSEd Maste 			return NULL;
1110*5f4c09ddSEd Maste 		break;
1111*5f4c09ddSEd Maste 	case AF_INET6:
1112*5f4c09ddSEd Maste 		cr->c_port = ntohs(((struct sockaddr_in6 *)&lss)->sin6_port);
1113*5f4c09ddSEd Maste 		if (conf_handle_inet(fd, &lss, cr) == -1)
1114*5f4c09ddSEd Maste 			return NULL;
1115*5f4c09ddSEd Maste 		break;
1116*5f4c09ddSEd Maste #ifdef AF_ROUTE
1117*5f4c09ddSEd Maste 	case AF_ROUTE:
1118*5f4c09ddSEd Maste 		if (!conf_route_perm(fd)) {
1119*5f4c09ddSEd Maste 			(*lfun)(LOG_ERR,
1120*5f4c09ddSEd Maste 			    "permission denied to routing socket (%m)");
1121*5f4c09ddSEd Maste 			return NULL;
1122*5f4c09ddSEd Maste 		}
1123*5f4c09ddSEd Maste 		cr->c_proto = FSTAR;
1124*5f4c09ddSEd Maste 		cr->c_port = FSTAR;
1125*5f4c09ddSEd Maste 		memcpy(&lss, rss, sizeof(lss));
1126*5f4c09ddSEd Maste 		break;
1127*5f4c09ddSEd Maste #endif
1128*5f4c09ddSEd Maste 	default:
1129*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR, "unsupported family %d", lss.ss_family);
1130*5f4c09ddSEd Maste 		return NULL;
1131*5f4c09ddSEd Maste 	}
1132*5f4c09ddSEd Maste 
1133*5f4c09ddSEd Maste 	cr->c_ss = lss;
1134*5f4c09ddSEd Maste 	cr->c_lmask = FSTAR;
1135*5f4c09ddSEd Maste 	cr->c_uid = (int)uid;
1136*5f4c09ddSEd Maste 	cr->c_family = lss.ss_family;
1137*5f4c09ddSEd Maste 	cr->c_name[0] = '\0';
1138*5f4c09ddSEd Maste 	cr->c_rmask = FSTAR;
1139*5f4c09ddSEd Maste 	cr->c_nfail = FSTAR;
1140*5f4c09ddSEd Maste 	cr->c_duration = FSTAR;
1141*5f4c09ddSEd Maste 
1142*5f4c09ddSEd Maste 	if (debug)
1143*5f4c09ddSEd Maste 		(*lfun)(LOG_DEBUG, "%s", conf_print(buf, sizeof(buf),
1144*5f4c09ddSEd Maste 		    "look:\t", "", cr));
1145*5f4c09ddSEd Maste 
1146*5f4c09ddSEd Maste 	/* match the local config */
1147*5f4c09ddSEd Maste 	i = confset_match(&lconf, cr, conf_apply);
1148*5f4c09ddSEd Maste 	if (i == lconf.cs_n) {
1149*5f4c09ddSEd Maste 		if (debug)
1150*5f4c09ddSEd Maste 			(*lfun)(LOG_DEBUG, "not found");
1151*5f4c09ddSEd Maste 		return NULL;
1152*5f4c09ddSEd Maste 	}
1153*5f4c09ddSEd Maste 
1154*5f4c09ddSEd Maste 	conf_addr_set(cr, rss);
1155*5f4c09ddSEd Maste 	/* match the remote config */
1156*5f4c09ddSEd Maste 	confset_match(&rconf, cr, conf_merge);
1157*5f4c09ddSEd Maste 	/* to apply the mask */
1158*5f4c09ddSEd Maste 	conf_addr_set(cr, &cr->c_ss);
1159*5f4c09ddSEd Maste 
1160*5f4c09ddSEd Maste 	return cr;
1161*5f4c09ddSEd Maste }
1162*5f4c09ddSEd Maste 
1163*5f4c09ddSEd Maste 
1164*5f4c09ddSEd Maste void
conf_parse(const char * f)1165*5f4c09ddSEd Maste conf_parse(const char *f)
1166*5f4c09ddSEd Maste {
1167*5f4c09ddSEd Maste 	FILE *fp;
1168*5f4c09ddSEd Maste 	char *line;
1169*5f4c09ddSEd Maste 	size_t lineno, len;
1170*5f4c09ddSEd Maste 	struct confset lc, rc, *cs;
1171*5f4c09ddSEd Maste 
1172*5f4c09ddSEd Maste 	if ((fp = fopen(f, "r")) == NULL) {
1173*5f4c09ddSEd Maste 		(*lfun)(LOG_ERR, "%s: Cannot open `%s' (%m)", __func__, f);
1174*5f4c09ddSEd Maste 		return;
1175*5f4c09ddSEd Maste 	}
1176*5f4c09ddSEd Maste 
1177*5f4c09ddSEd Maste 	lineno = 1;
1178*5f4c09ddSEd Maste 
1179*5f4c09ddSEd Maste 	confset_init(&rc);
1180*5f4c09ddSEd Maste 	confset_init(&lc);
1181*5f4c09ddSEd Maste 	cs = &lc;
1182*5f4c09ddSEd Maste 	for (; (line = fparseln(fp, &len, &lineno, NULL, 0)) != NULL;
1183*5f4c09ddSEd Maste 	    free(line))
1184*5f4c09ddSEd Maste 	{
1185*5f4c09ddSEd Maste 		if (!*line)
1186*5f4c09ddSEd Maste 			continue;
1187*5f4c09ddSEd Maste 		if (strcmp(line, "[local]") == 0) {
1188*5f4c09ddSEd Maste 			cs = &lc;
1189*5f4c09ddSEd Maste 			continue;
1190*5f4c09ddSEd Maste 		}
1191*5f4c09ddSEd Maste 		if (strcmp(line, "[remote]") == 0) {
1192*5f4c09ddSEd Maste 			cs = &rc;
1193*5f4c09ddSEd Maste 			continue;
1194*5f4c09ddSEd Maste 		}
1195*5f4c09ddSEd Maste 
1196*5f4c09ddSEd Maste 		if (confset_full(cs)) {
1197*5f4c09ddSEd Maste 			if (confset_grow(cs) == -1) {
1198*5f4c09ddSEd Maste 				confset_free(&lc);
1199*5f4c09ddSEd Maste 				confset_free(&rc);
1200*5f4c09ddSEd Maste 				fclose(fp);
1201*5f4c09ddSEd Maste 				free(line);
1202*5f4c09ddSEd Maste 				return;
1203*5f4c09ddSEd Maste 			}
1204*5f4c09ddSEd Maste 		}
1205*5f4c09ddSEd Maste 		if (conf_parseline(f, lineno, line, confset_get(cs),
1206*5f4c09ddSEd Maste 		    cs == &lc) == -1)
1207*5f4c09ddSEd Maste 			continue;
1208*5f4c09ddSEd Maste 		confset_add(cs);
1209*5f4c09ddSEd Maste 	}
1210*5f4c09ddSEd Maste 
1211*5f4c09ddSEd Maste 	fclose(fp);
1212*5f4c09ddSEd Maste 	confset_sort(&lc);
1213*5f4c09ddSEd Maste 	confset_sort(&rc);
1214*5f4c09ddSEd Maste 
1215*5f4c09ddSEd Maste 	confset_replace(&rconf, &rc);
1216*5f4c09ddSEd Maste 	confset_replace(&lconf, &lc);
1217*5f4c09ddSEd Maste 
1218*5f4c09ddSEd Maste 	if (debug) {
1219*5f4c09ddSEd Maste 		confset_list(&lconf, "local", "target");
1220*5f4c09ddSEd Maste 		confset_list(&rconf, "remote", "source");
1221*5f4c09ddSEd Maste 	}
1222*5f4c09ddSEd Maste }
1223