GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/npppd_config.c Lines: 0 127 0.0 %
Date: 2017-11-07 Branches: 0 88 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: npppd_config.c,v 1.14 2015/01/19 01:48:59 deraadt Exp $ */
2
3
/*-
4
 * Copyright (c) 2009 Internet Initiative Japan Inc.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 */
28
/* $Id: npppd_config.c,v 1.14 2015/01/19 01:48:59 deraadt Exp $ */
29
/*@file
30
 * This file provides functions which operates configuration and so on.
31
 */
32
#include <sys/socket.h>
33
#include <netinet/in.h>
34
#include <net/if_dl.h>
35
#include <netinet/ip.h>
36
#include <net/route.h>
37
#include <arpa/inet.h>
38
#include <syslog.h>
39
#include <time.h>
40
#include <event.h>
41
#include <stdio.h>
42
#include <string.h>
43
#include <stdlib.h>
44
#include <stddef.h>
45
#include <errno.h>
46
47
#include "addr_range.h"
48
#include "debugutil.h"
49
#include "npppd_subr.h"
50
#include "npppd_local.h"
51
#include "npppd_auth.h"
52
#include "npppd_iface.h"
53
#include "radish.h"
54
55
#include "pathnames.h"
56
57
#ifdef NPPPD_CONFIG_DEBUG
58
#define NPPPD_CONFIG_DBG(x) 	log_printf x
59
#define NPPPD_CONFIG_ASSERT(x) ASSERT(x)
60
#else
61
#define NPPPD_CONFIG_DBG(x)
62
#define NPPPD_CONFIG_ASSERT(x)
63
#endif
64
65
static int              npppd_pool_load(npppd *);
66
static int              npppd_auth_realm_reload (npppd *);
67
static npppd_auth_base *realm_list_remove (slist *, const char *);
68
69
int
70
npppd_config_check(const char *path)
71
{
72
	struct npppd_conf  conf;
73
74
	npppd_conf_init(&conf);
75
	return npppd_conf_parse(&conf, path);
76
}
77
78
/***********************************************************************
79
 * Reading the configuration. This is the export function which
80
 * aggregates functions to read from each part.
81
 ***********************************************************************/
82
/**
83
 * reload the configuration file.
84
 * @param   _this   pointer indicated to npppd
85
 * @returns A 0 is returned if succeeds, otherwise non 0 is returned
86
 *	    in case of configuration error.
87
 */
88
int
89
npppd_reload_config(npppd *_this)
90
{
91
	int                retval = -1;
92
	struct npppd_conf  conf;
93
94
	npppd_conf_init(&conf);
95
	if (npppd_conf_parse(&conf, _this->config_file) != 0) {
96
		log_printf(LOG_ERR, "Load configuration from='%s' failed",
97
		    _this->config_file);
98
		retval = -1;
99
		goto fail;
100
	}
101
102
	_this->conf = conf;
103
104
	retval = 0;
105
	log_printf(LOG_NOTICE, "Load configuration from='%s' successfully.",
106
	    _this->config_file);
107
108
	/* FALLTHROUGH */
109
fail:
110
111
	return retval;
112
}
113
114
/** reload the configuration for each module */
115
int
116
npppd_modules_reload(npppd *_this)
117
{
118
	int  rval;
119
120
	rval = 0;
121
	if (npppd_pool_load(_this) != 0)
122
		return -1;
123
124
	npppd_auth_realm_reload(_this);
125
#ifdef USE_NPPPD_L2TP
126
	rval |= l2tpd_reload(&_this->l2tpd, &_this->conf.l2tp_confs);
127
#endif
128
#ifdef USE_NPPPD_PPTP
129
	rval |= pptpd_reload(&_this->pptpd, &_this->conf.pptp_confs);
130
#endif
131
#ifdef USE_NPPPD_PPPOE
132
	rval |= pppoed_reload(&_this->pppoed, &_this->conf.pppoe_confs);
133
#endif
134
135
	return rval;
136
}
137
138
/***********************************************************************
139
 * reload the configuration on each part
140
 ***********************************************************************/
141
/** load the configuration for IP address pool */
142
static int
143
npppd_pool_load(npppd *_this)
144
{
145
	int n, i, j;
146
	npppd_pool pool0[NPPPD_MAX_IFACE];
147
	struct radish_head *rd_curr, *rd_new;
148
	struct ipcpconf *ipcp;
149
150
	rd_curr = _this->rd;
151
	rd_new = NULL;
152
153
	n = 0;
154
	if (!rd_inithead((void *)&rd_new, 0x41,
155
	    sizeof(struct sockaddr_npppd),
156
	    offsetof(struct sockaddr_npppd, snp_addr),
157
	    sizeof(struct in_addr), sockaddr_npppd_match)) {
158
		goto fail;
159
	}
160
	_this->rd = rd_new;
161
162
	TAILQ_FOREACH(ipcp, &_this->conf.ipcpconfs, entry) {
163
		if (n >= countof(_this->pool)) {
164
			log_printf(LOG_WARNING, "number of the pool reached "
165
			    "limit=%d",(int)countof(_this->pool));
166
			break;
167
		}
168
		if (npppd_pool_init(&pool0[n], _this, ipcp->name) != 0) {
169
			log_printf(LOG_WARNING, "Failed to initialize "
170
			    "npppd_pool '%s': %m", ipcp->name);
171
			goto fail;
172
		}
173
		if (npppd_pool_reload(&pool0[n]) != 0)
174
			goto fail;
175
		n++;
176
	}
177
	for (; n < countof(pool0); n++)
178
		pool0[n].initialized = 0;
179
180
	_this->rd = rd_curr;	/* backup */
181
	if (npppd_set_radish(_this, rd_new) != 0)
182
		goto fail;
183
184
	for (i = 0; i < countof(_this->pool); i++) {
185
		if (_this->pool[i].initialized != 0)
186
			npppd_pool_uninit(&_this->pool[i]);
187
		if (pool0[i].initialized == 0)
188
			continue;
189
		_this->pool[i] = pool0[i];
190
		/* swap references */
191
		for (j = 0; j < _this->pool[i].addrs_size; j++) {
192
			if (_this->pool[i].initialized == 0)
193
				continue;
194
			_this->pool[i].addrs[j].snp_data_ptr = &_this->pool[i];
195
		}
196
	}
197
	log_printf(LOG_INFO, "Loading pool config successfully.");
198
199
	return 0;
200
fail:
201
	/* rollback */
202
	for (i = 0; i < n; i++) {
203
		if (pool0[i].initialized != 0)
204
			npppd_pool_uninit(&pool0[i]);
205
	}
206
207
	if (rd_curr != NULL)
208
		_this->rd = rd_curr;
209
210
	if (rd_new != NULL) {
211
		rd_walktree(rd_new,
212
		    (int (*)(struct radish *, void *))rd_unlink,
213
		    rd_new->rdh_top);
214
		free(rd_new);
215
	}
216
	log_printf(LOG_NOTICE, "Loading pool config failed");
217
218
	return 1;
219
}
220
221
/* authentication realm */
222
static int
223
npppd_auth_realm_reload(npppd *_this)
224
{
225
	int              rval;
226
	slist            realms0, nrealms;
227
	struct authconf *auth;
228
	npppd_auth_base *auth_base;
229
230
	rval = 0;
231
	slist_init(&realms0);
232
	slist_init(&nrealms);
233
234
	if (slist_add_all(&realms0, &_this->realms) != 0) {
235
		log_printf(LOG_WARNING, "slist_add_all() failed in %s(): %m",
236
		__func__);
237
		goto fail;
238
	}
239
240
	TAILQ_FOREACH(auth, &_this->conf.authconfs, entry) {
241
#ifndef USE_NPPPD_RADIUS
242
		if (auth->auth_type == NPPPD_AUTH_TYPE_RADIUS)  {
243
			log_printf(LOG_WARNING, "radius support is not "
244
			    "enabled by compile time.");
245
			continue;
246
		}
247
#endif
248
		auth_base = realm_list_remove(&realms0, auth->name);
249
		if (auth_base != NULL &&
250
		    npppd_auth_get_type(auth_base) != auth->auth_type) {
251
			/*
252
			 * The type of authentication has been changed in the
253
			 * same label name.
254
			 */
255
			slist_add(&realms0, auth_base);
256
			auth_base = NULL;
257
		}
258
259
		if (auth_base == NULL) {
260
			/* create newly */
261
			if ((auth_base = npppd_auth_create(auth->auth_type,
262
			    auth->name, _this)) == NULL) {
263
				log_printf(LOG_WARNING, "npppd_auth_create() "
264
				    "failed in %s(): %m", __func__);
265
				goto fail;
266
			}
267
		}
268
		slist_add(&nrealms, auth_base);
269
	}
270
	if (slist_set_size(&_this->realms, slist_length(&nrealms)) != 0) {
271
		log_printf(LOG_WARNING, "slist_set_size() failed in %s(): %m",
272
		    __func__);
273
		goto fail;
274
	}
275
276
	slist_itr_first(&realms0);
277
	while (slist_itr_has_next(&realms0)) {
278
		auth_base = slist_itr_next(&realms0);
279
		if (npppd_auth_is_disposing(auth_base))
280
			continue;
281
		npppd_auth_dispose(auth_base);
282
	}
283
284
	slist_itr_first(&nrealms);
285
	while (slist_itr_has_next(&nrealms)) {
286
		auth_base = slist_itr_next(&nrealms);
287
		rval |= npppd_auth_reload(auth_base);
288
	}
289
	slist_remove_all(&_this->realms);
290
	(void)slist_add_all(&_this->realms, &nrealms);
291
	(void)slist_add_all(&_this->realms, &realms0);
292
293
	slist_fini(&realms0);
294
	slist_fini(&nrealms);
295
296
	return rval;
297
fail:
298
299
	slist_itr_first(&nrealms);
300
	while (slist_itr_has_next(&nrealms)) {
301
		auth_base = slist_itr_next(&nrealms);
302
		npppd_auth_destroy(auth_base);
303
	}
304
	slist_fini(&realms0);
305
	slist_fini(&nrealms);
306
307
	return 1;
308
}
309
310
static npppd_auth_base *
311
realm_list_remove(slist *list0, const char *label)
312
{
313
	npppd_auth_base *base;
314
315
	for (slist_itr_first(list0); slist_itr_has_next(list0); ) {
316
		base = slist_itr_next(list0);
317
		if (npppd_auth_is_disposing(base))
318
			continue;
319
		if (strcmp(npppd_auth_get_name(base), label) == 0)
320
			return slist_itr_remove(list0);
321
	}
322
323
	return NULL;
324
}
325
326
/** load the interface configuration */
327
int
328
npppd_ifaces_load_config(npppd *_this)
329
{
330
	int           i;
331
	struct iface *iface;
332
	npppd_iface  *niface;
333
334
	for (i = 0; i < countof(_this->iface); i++) {
335
		if (_this->iface[i].initialized == 0)
336
			continue;
337
		TAILQ_FOREACH(iface, &_this->conf.ifaces, entry) {
338
			if (strcmp(_this->iface[i].ifname, iface->name) == 0)
339
				break;
340
		}
341
		if (iface == NULL) {
342
			npppd_iface_stop(&_this->iface[i]);
343
			npppd_iface_fini(&_this->iface[i]);
344
		}
345
	}
346
	TAILQ_FOREACH(iface, &_this->conf.ifaces, entry) {
347
		/* find the existing entry or first free entry */
348
		niface = NULL;
349
		for (i = 0; i < countof(_this->iface); i++) {
350
			if (_this->iface[i].initialized == 0) {
351
				if (niface == NULL)
352
					niface = &_this->iface[i];
353
				continue;
354
			}
355
			if (strcmp(_this->iface[i].ifname, iface->name) == 0) {
356
				niface = &_this->iface[i];
357
				break;
358
			}
359
		}
360
		if (niface == NULL) {
361
			log_printf(LOG_WARNING,
362
			    "number of the interface reached limit=%d",
363
			    (int)countof(_this->iface));
364
			break;
365
		}
366
		if (niface->initialized == 0)
367
			npppd_iface_init(_this, niface, iface);
368
		else
369
			npppd_iface_reinit(niface, iface);
370
	}
371
372
	return 0;
373
}