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