xref: /openbsd-src/usr.sbin/radiusd/radiusd_ipcp.c (revision dcc91c2622318df8f66a9bca2d2864253df1bfc3)
1 /*	$OpenBSD: radiusd_ipcp.c,v 1.14 2024/08/27 06:06:14 florian Exp $	*/
2 
3 /*
4  * Copyright (c) 2024 Internet Initiative Japan Inc.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/socket.h>
22 #include <sys/time.h>
23 #include <sys/tree.h>
24 #include <arpa/inet.h>
25 
26 #include <inttypes.h>
27 #include <netdb.h>
28 #include <db.h>
29 #include <err.h>
30 #include <errno.h>
31 #include <event.h>
32 #include <fcntl.h>
33 #include <pwd.h>
34 #include <radius.h>
35 #include <stdbool.h>
36 #include <stddef.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 #include <unistd.h>
43 #include <imsg.h>
44 
45 #include "radiusd.h"
46 #include "radiusd_module.h"
47 #include "radiusd_ipcp.h"
48 #include "log.h"
49 
50 #define RADIUSD_IPCP_START_WAIT	60
51 
52 enum ipcp_address_type {
53 	ADDRESS_TYPE_POOL,
54 	ADDRESS_TYPE_STATIC
55 };
56 
57 struct ipcp_address {
58 	enum ipcp_address_type		 type;
59 	struct in_addr			 start;
60 	struct in_addr			 end;
61 	int				 naddrs;
62 	TAILQ_ENTRY(ipcp_address)	 next;
63 };
64 
65 struct user {
66 	TAILQ_HEAD(, assigned_ipv4)	 ipv4s;
67 	RB_ENTRY(user)			 tree;
68 	char				 name[0];
69 };
70 
71 struct radiusctl_client {
72 	int				 peerid;
73 	TAILQ_ENTRY(radiusctl_client)	 entry;
74 };
75 
76 struct module_ipcp_dae;
77 
78 struct assigned_ipv4 {
79 	struct in_addr			 ipv4;
80 	unsigned			 seq;
81 	char				 session_id[256];
82 	char				 auth_method[16];
83 	struct user			*user;
84 	uint32_t			 session_timeout;
85 	struct timespec			 start;
86 	struct timespec			 timeout;
87 	struct in_addr			 nas_ipv4;
88 	struct in6_addr			 nas_ipv6;
89 	char				 nas_id[256];
90 	const char			*tun_type;
91 	union {
92 		struct sockaddr_in	 sin4;
93 		struct sockaddr_in6	 sin6;
94 	}				 tun_client;
95 
96 	struct timespec			 authtime;
97 	RB_ENTRY(assigned_ipv4)		 tree;
98 	TAILQ_ENTRY(assigned_ipv4)	 next;
99 
100 	/* RFC 5176 Dynamic Authorization Extensions for RADIUS */
101 	struct module_ipcp_dae		*dae;
102 	RADIUS_PACKET			*dae_reqpkt;
103 	TAILQ_ENTRY(assigned_ipv4)	 dae_next;
104 	int				 dae_ntry;
105 	struct event			 dae_evtimer;
106 	TAILQ_HEAD(, radiusctl_client)	 dae_clients;
107 };
108 
109 struct module_ipcp_ctrlconn {
110 	uint32_t			 peerid;
111 	TAILQ_ENTRY(module_ipcp_ctrlconn)
112 					 next;
113 };
114 
115 struct module_ipcp_dae {
116 	struct module_ipcp		*ipcp;
117 	int				 sock;
118 	char				 nas_id[256];
119 	char				 secret[80];
120 	union {
121 		struct sockaddr_in	 sin4;
122 		struct sockaddr_in6	 sin6;
123 	}				 nas_addr;
124 	struct event			 ev_sock;
125 	TAILQ_ENTRY(module_ipcp_dae)	 next;
126 	TAILQ_HEAD(, assigned_ipv4)	 reqs;
127 };
128 
129 struct module_ipcp {
130 	struct module_base		*base;
131 	int				 nsessions;
132 	unsigned			 seq;
133 	int				 max_sessions;
134 	int				 user_max_sessions;
135 	int				 start_wait;
136 	int				 session_timeout;
137 	bool				 no_session_timeout;
138 	struct timespec			 uptime;
139 	struct in_addr			 name_server[2];
140 	struct in_addr			 netbios_server[2];
141 	RB_HEAD(assigned_ipv4_tree, assigned_ipv4)
142 					 ipv4s;
143 	RB_HEAD(user_tree, user)	 users;
144 	int				 npools;
145 	TAILQ_HEAD(,ipcp_address)	 addrs;
146 	TAILQ_HEAD(,module_ipcp_ctrlconn)
147 					 ctrls;
148 	TAILQ_HEAD(,module_ipcp_dae)	 daes;
149 	struct event			 ev_timer;
150 };
151 
152 #ifndef nitems
153 #define nitems(_x)    (sizeof((_x)) / sizeof((_x)[0]))
154 #endif
155 
156 #ifndef MAXIMUM
157 #define MAXIMUM(_a, _b)	(((_a) > (_b))? (_a) : (_b))
158 #endif
159 
160 static void	 ipcp_init(struct module_ipcp *);
161 static void	 ipcp_start(void *);
162 static void	 ipcp_stop(void *);
163 static void	 ipcp_fini(struct module_ipcp *);
164 static void	 ipcp_config_set(void *, const char *, int, char * const *);
165 static void	 ipcp_dispatch_control(void *, struct imsg *);
166 static int	 ipcp_notice_startstop(struct module_ipcp *,
167 		    struct assigned_ipv4 *, int,
168 		    struct radiusd_ipcp_statistics *);
169 static void	 ipcp_resdeco(void *, u_int, const u_char *, size_t reqlen,
170 		    const u_char *, size_t reslen);
171 static void	 ipcp_reject(struct module_ipcp *, RADIUS_PACKET *,
172 		    unsigned int, RADIUS_PACKET *, int);
173 static void	 ipcp_accounting_request(void *, u_int, const u_char *,
174 		    size_t);
175 
176 struct assigned_ipv4
177 		*ipcp_ipv4_assign(struct module_ipcp *, struct user *,
178 		    struct in_addr);
179 static struct assigned_ipv4
180 		*ipcp_ipv4_find(struct module_ipcp *, struct in_addr);
181 static void	 ipcp_ipv4_release(struct module_ipcp *,
182 		    struct assigned_ipv4 *);
183 static int	 assigned_ipv4_compar(struct assigned_ipv4 *,
184 		    struct assigned_ipv4 *);
185 static struct user
186 		*ipcp_user_get(struct module_ipcp *, const char *);
187 static int	 user_compar(struct user *, struct user *);
188 static int	 ipcp_prepare_db(void);
189 static int	 ipcp_restore_from_db(struct module_ipcp *);
190 static void	 ipcp_put_db(struct module_ipcp *, struct assigned_ipv4 *);
191 static void	 ipcp_del_db(struct module_ipcp *, struct assigned_ipv4 *);
192 static void	 ipcp_db_dump_fill_record(struct radiusd_ipcp_db_dump *, int,
193 		    struct assigned_ipv4 *);
194 static void	 ipcp_update_time(struct module_ipcp *);
195 static void	 ipcp_on_timer(int, short, void *);
196 static void	 ipcp_schedule_timer(struct module_ipcp *);
197 static void	 ipcp_dae_send_disconnect_request(struct assigned_ipv4 *);
198 static void	 ipcp_dae_request_on_timeout(int, short, void *);
199 static void	 ipcp_dae_on_event(int, short, void *);
200 static void	 ipcp_dae_reset_request(struct assigned_ipv4 *);
201 static struct ipcp_address
202 		*parse_address_range(const char *);
203 static const char
204 		*radius_tunnel_type_string(unsigned, const char *);
205 static const char
206 		*radius_terminate_cause_string(unsigned);
207 static const char
208 		*radius_error_cause_string(unsigned);
209 static int	 parse_addr(const char *, int, struct sockaddr *, socklen_t);
210 static const char
211 		*print_addr(struct sockaddr *, char *, size_t);
212 
213 RB_PROTOTYPE_STATIC(assigned_ipv4_tree, assigned_ipv4, tree,
214     assigned_ipv4_compar);
215 RB_PROTOTYPE_STATIC(user_tree, user, tree, user_compar);
216 
217 int
218 main(int argc, char *argv[])
219 {
220 	struct module_ipcp	 module_ipcp;
221 	struct module_handlers	 handlers = {
222 		.start =		ipcp_start,
223 		.stop =			ipcp_stop,
224 		.config_set =		ipcp_config_set,
225 		.response_decoration =	ipcp_resdeco,
226 		.accounting_request =	ipcp_accounting_request,
227 		.dispatch_control =	ipcp_dispatch_control
228 	};
229 
230 	ipcp_init(&module_ipcp);
231 
232 	if ((module_ipcp.base = module_create(STDIN_FILENO, &module_ipcp,
233 	    &handlers)) == NULL)
234 		err(1, "Could not create a module instance");
235 
236 	if (ipcp_prepare_db() == -1)
237 		err(1, "ipcp_prepare_db");
238 
239 	module_drop_privilege(module_ipcp.base, 1);
240 	if (unveil(_PATH_RADIUSD_IPCP_DB, "rw") == -1)
241 		err(1, "unveil");
242 	if (pledge("stdio inet rpath wpath flock", NULL) == -1)
243 		err(1, "pledge");
244 	setproctitle("[main]");
245 
246 	module_load(module_ipcp.base);
247 	log_init(0);
248 	event_init();
249 
250 	module_start(module_ipcp.base);
251 	event_loop(0);
252 
253 	ipcp_fini(&module_ipcp);
254 
255 	event_loop(0);
256 	event_base_free(NULL);
257 
258 	exit(EXIT_SUCCESS);
259 }
260 
261 void
262 ipcp_init(struct module_ipcp *self)
263 {
264 	memset(self, 0, sizeof(struct module_ipcp));
265 	TAILQ_INIT(&self->addrs);
266 	RB_INIT(&self->ipv4s);
267 	RB_INIT(&self->users);
268 	TAILQ_INIT(&self->ctrls);
269 	TAILQ_INIT(&self->daes);
270 	self->seq = 1;
271 	self->no_session_timeout = true;
272 	ipcp_update_time(self);
273 }
274 
275 void
276 ipcp_start(void *ctx)
277 {
278 	struct module_ipcp	*self = ctx;
279 	struct ipcp_address	*addr;
280 	struct module_ipcp_dae	*dae;
281 	int			 sock;
282 
283 	ipcp_update_time(self);
284 	if (self->start_wait == 0)
285 		self->start_wait = RADIUSD_IPCP_START_WAIT;
286 
287 	/* count pool address*/
288 	TAILQ_FOREACH(addr, &self->addrs, next) {
289 		if (addr->type == ADDRESS_TYPE_POOL)
290 			self->npools += addr->naddrs;
291 	}
292 	log_info("number of pooled IP addresses = %d", self->npools);
293 
294 	if (ipcp_restore_from_db(self) == -1) {
295 		module_send_message(self->base, IMSG_NG,
296 		    "Restoring the database failed: %s", strerror(errno));
297 		module_stop(self->base);
298 		return;
299 	}
300 	ipcp_schedule_timer(self);
301 
302 	/* prepare socket for DAE */
303 	TAILQ_FOREACH(dae, &self->daes, next) {
304 		if ((sock = socket(dae->nas_addr.sin4.sin_family,
305 		    SOCK_DGRAM, IPPROTO_UDP)) == -1) {
306 			log_warn("could not start dae: %s", strerror(errno));
307 			return;
308 		}
309 		if (connect(sock, (struct sockaddr *)&dae->nas_addr,
310 		    dae->nas_addr.sin4.sin_len) == -1) {
311 			log_warn("could not start dae: %s", strerror(errno));
312 			return;
313 		}
314 		dae->sock = sock;
315 		event_set(&dae->ev_sock, sock, EV_READ | EV_PERSIST,
316 		    ipcp_dae_on_event, dae);
317 		event_add(&dae->ev_sock, NULL);
318 	}
319 
320 	module_send_message(self->base, IMSG_OK, NULL);
321 }
322 
323 void
324 ipcp_stop(void *ctx)
325 {
326 	struct module_ipcp		*self = ctx;
327 	struct module_ipcp_dae		*dae;
328 
329 	ipcp_update_time(self);
330 	/* stop the sockets for DAE */
331 	TAILQ_FOREACH(dae, &self->daes, next) {
332 		if (dae->sock >= 0) {
333 			event_del(&dae->ev_sock);
334 			close(dae->sock);
335 			dae->sock = -1;
336 		}
337 	}
338 	if (evtimer_pending(&self->ev_timer, NULL))
339 		evtimer_del(&self->ev_timer);
340 }
341 
342 void
343 ipcp_fini(struct module_ipcp *self)
344 {
345 	struct assigned_ipv4		*assign, *assignt;
346 	struct user			*user, *usert;
347 	struct module_ipcp_ctrlconn	*ctrl, *ctrlt;
348 	struct module_ipcp_dae		*dae, *daet;
349 	struct ipcp_address		*addr, *addrt;
350 
351 	RB_FOREACH_SAFE(assign, assigned_ipv4_tree, &self->ipv4s, assignt)
352 		ipcp_ipv4_release(self, assign);
353 	RB_FOREACH_SAFE(user, user_tree, &self->users, usert) {
354 		RB_REMOVE(user_tree, &self->users, user);
355 		free(user);
356 	}
357 	TAILQ_FOREACH_SAFE(ctrl, &self->ctrls, next, ctrlt)
358 		free(ctrl);
359 	TAILQ_FOREACH_SAFE(dae, &self->daes, next, daet) {
360 		if (dae->sock >= 0) {
361 			event_del(&dae->ev_sock);
362 			close(dae->sock);
363 		}
364 		free(dae);
365 	}
366 	TAILQ_FOREACH_SAFE(addr, &self->addrs, next, addrt)
367 		free(addr);
368 	if (evtimer_pending(&self->ev_timer, NULL))
369 		evtimer_del(&self->ev_timer);
370 	module_destroy(self->base);
371 }
372 
373 void
374 ipcp_config_set(void *ctx, const char *name, int argc, char * const * argv)
375 {
376 	struct module_ipcp	*module = ctx;
377 	const char		*errmsg = "none";
378 	int			 i;
379 	struct ipcp_address	*addr;
380 	struct in_addr		 ina;
381 	struct module_ipcp_dae	 dae, *dae0;
382 
383 	if (strcmp(name, "address") == 0) {
384 		SYNTAX_ASSERT(argc >= 1,
385 		    "specify one of pool, server, nas-select, or user-select");
386 		if (strcmp(argv[0], "pool") == 0) {
387 			SYNTAX_ASSERT(argc >= 2,
388 			    "`address pool' must have one address range at "
389 			    "least");
390 			addr = TAILQ_FIRST(&module->addrs);
391 			for (i = 0; i < argc - 1; i++) {
392 				if ((addr = parse_address_range(argv[i + 1]))
393 				    == NULL) {
394 					module_send_message(module->base,
395 					    IMSG_NG, "Invalid address range: "
396 					    "%s", argv[i + 1]);
397 					return;
398 				}
399 				addr->type = ADDRESS_TYPE_POOL;
400 				TAILQ_INSERT_TAIL(&module->addrs, addr, next);
401 			}
402 		} else if (strcmp(argv[0], "static") == 0) {
403 			SYNTAX_ASSERT(argc >= 2,
404 			    "`address static' must have one address range at "
405 			    "least");
406 			addr = TAILQ_FIRST(&module->addrs);
407 			for (i = 0; i < argc - 1; i++) {
408 				if ((addr = parse_address_range(argv[i + 1]))
409 				    == NULL) {
410 					module_send_message(module->base,
411 					    IMSG_NG, "Invalid address range: "
412 					    "%s", argv[i + 1]);
413 					return;
414 				}
415 				addr->type = ADDRESS_TYPE_STATIC;
416 				TAILQ_INSERT_TAIL(&module->addrs, addr, next);
417 			}
418 		} else
419 			SYNTAX_ASSERT(0, "specify pool or static");
420 	} else if (strcmp(name, "max-sessions") == 0) {
421 		SYNTAX_ASSERT(argc == 1,
422 		    "`max-sessions' must have an argument");
423 		module->max_sessions = strtonum(argv[0], 0, INT_MAX, &errmsg);
424 		if (errmsg != NULL) {
425 			module_send_message(module->base, IMSG_NG,
426 			    "could not parse `max-sessions': %s", errmsg);
427 			return;
428 		}
429 	} else if (strcmp(name, "user-max-sessions") == 0) {
430 		SYNTAX_ASSERT(argc == 1, "`max-session' must have an argument");
431 		module->user_max_sessions = strtonum(argv[0], 0, INT_MAX,
432 		    &errmsg);
433 		if (errmsg != NULL) {
434 			module_send_message(module->base, IMSG_NG,
435 			    "could not parse `user-max-session': %s", errmsg);
436 			return;
437 		}
438 	} else if (strcmp(name, "start-wait") == 0) {
439 		SYNTAX_ASSERT(argc == 1, "`start-wait' must have an argument");
440 		module->start_wait = strtonum(argv[0], 1, INT_MAX, &errmsg);
441 		if (errmsg != NULL) {
442 			module_send_message(module->base, IMSG_NG,
443 			    "could not parse `start-wait': %s", errmsg);
444 			return;
445 		}
446 	} else if (strcmp(name, "name-server") == 0) {
447 		SYNTAX_ASSERT(argc == 1 || argc == 2,
448 		    "specify 1 or 2 addresses for `name-server'");
449 		for (i = 0; i < argc; i++) {
450 			if (inet_pton(AF_INET, argv[i], &ina) != 1) {
451 				module_send_message(module->base, IMSG_NG,
452 				    "Invalid IP address: %s", argv[i]);
453 				return;
454 			}
455 			if (module->name_server[0].s_addr == 0)
456 				module->name_server[0] = ina;
457 			else if (module->name_server[1].s_addr == 0)
458 				module->name_server[1] = ina;
459 			else
460 				SYNTAX_ASSERT(0,
461 				    "too many `name-server' is configured");
462 		}
463 	} else if (strcmp(name, "netbios-server") == 0) {
464 		SYNTAX_ASSERT(argc == 1 || argc == 2,
465 		    "specify 1 or 2 addresses for `name-server'");
466 		for (i = 0; i < argc; i++) {
467 			if (inet_pton(AF_INET, argv[i], &ina) != 1) {
468 				module_send_message(module->base, IMSG_NG,
469 				    "Invalid IP address: %s", argv[i]);
470 				return;
471 			}
472 			if (module->netbios_server[0].s_addr == 0)
473 				module->netbios_server[0] = ina;
474 			else if (module->netbios_server[1].s_addr == 0)
475 				module->netbios_server[1] = ina;
476 			else
477 				SYNTAX_ASSERT(0,
478 				    "too many `name-server' is configured");
479 		}
480 	} else if (strcmp(name, "session-timeout") == 0) {
481 		SYNTAX_ASSERT(argc == 1,
482 		    "`session-timeout' must have an argument");
483 		if (strcmp(argv[0], "radius") == 0) {
484 			module->no_session_timeout = false;
485 			module->session_timeout = 0;
486 		} else {
487 			module->no_session_timeout = false;
488 			module->session_timeout = strtonum(argv[0], 1, INT_MAX,
489 			    &errmsg);
490 			if (errmsg != NULL) {
491 				module_send_message(module->base, IMSG_NG,
492 				    "could not parse `session-timeout': %s",
493 				    errmsg);
494 				return;
495 			}
496 		}
497 	} else if (strcmp(name, "dae") == 0) {
498 		memset(&dae, 0, sizeof(dae));
499 		dae.sock = -1;
500 		if (!(argc >= 1 || strcmp(argv[1], "server") == 0)) {
501 			module_send_message(module->base, IMSG_NG,
502 			    "`%s' is unknown", argv[1]);
503 			return;
504 		}
505 		i = 1;
506 		SYNTAX_ASSERT(i < argc, "no address[:port] for dae server");
507 		if (i < argc &&
508 		    parse_addr(argv[i], AF_UNSPEC, (struct sockaddr *)
509 		    &dae.nas_addr, sizeof(dae.nas_addr)) == -1) {
510 			module_send_message(module->base, IMSG_NG,
511 			    "failed to parse dae server's address, %s",
512 			    argv[i]);
513 			return;
514 		}
515 		if (ntohs(dae.nas_addr.sin4.sin_port) == 0)
516 			dae.nas_addr.sin4.sin_port =
517 			    htons(RADIUS_DAE_DEFAULT_PORT);
518 		i++;
519 		SYNTAX_ASSERT(i < argc, "no secret for dae server");
520 		if (strlcpy(dae.secret, argv[i++], sizeof(dae.secret)) >=
521 		    sizeof(dae.secret)) {
522 			module_send_message(module->base, IMSG_NG,
523 			    "dae server's secret must be < %d bytes",
524 			    (int)sizeof(dae.secret) - 1);
525 			return;
526 		}
527 		if (i < argc)
528 			strlcpy(dae.nas_id, argv[i++], sizeof(dae.nas_id));
529 		if ((dae0 = calloc(1, sizeof(struct module_ipcp_dae))) == NULL)
530 		{
531 			module_send_message(module->base, IMSG_NG,
532 			    "%s", strerror(errno));
533 			return;
534 		}
535 		*dae0 = dae;
536 		TAILQ_INIT(&dae0->reqs);
537 		TAILQ_INSERT_TAIL(&module->daes, dae0, next);
538 		dae0->ipcp = module;
539 	} else if (strcmp(name, "_debug") == 0)
540 		log_init(1);
541 	else if (strncmp(name, "_", 1) == 0)
542 		/* ignore */;
543 	else {
544 		module_send_message(module->base, IMSG_NG,
545 		    "Unknown config parameter name `%s'", name);
546 		return;
547 	}
548 	module_send_message(module->base, IMSG_OK, NULL);
549 
550 	return;
551  syntax_error:
552 	module_send_message(module->base, IMSG_NG, "%s", errmsg);
553 }
554 
555 void
556 ipcp_dispatch_control(void *ctx, struct imsg *imsg)
557 {
558 	struct module_ipcp		*self = ctx;
559 	struct assigned_ipv4		*assign;
560 	struct radiusd_ipcp_db_dump	*dump;
561 	struct module_ipcp_ctrlconn	*ctrl, *ctrlt;
562 	int				 i;
563 	size_t				 dumpsiz;
564 	u_int				 datalen;
565 	unsigned			 seq;
566 	struct radiusctl_client		*client;
567 	const char			*cause;
568 
569 	ipcp_update_time(self);
570 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
571 	switch (imsg->hdr.type) {
572 	case IMSG_RADIUSD_MODULE_CTRL_UNBIND:
573 		TAILQ_FOREACH_SAFE(ctrl, &self->ctrls, next, ctrlt) {
574 			if (ctrl->peerid == imsg->hdr.peerid) {
575 				TAILQ_REMOVE(&self->ctrls, ctrl, next);
576 				free(ctrl);
577 				break;
578 			}
579 		}
580 		break;
581 	case IMSG_RADIUSD_MODULE_IPCP_MONITOR:
582 	case IMSG_RADIUSD_MODULE_IPCP_DUMP_AND_MONITOR:
583 		if ((ctrl = calloc(1, sizeof(struct module_ipcp_ctrlconn)))
584 		    == NULL) {
585 			log_warn("%s: calloc()", __func__);
586 			goto fail;
587 		}
588 		ctrl->peerid = imsg->hdr.peerid;
589 		TAILQ_INSERT_TAIL(&self->ctrls, ctrl, next);
590 		module_imsg_compose(self->base, IMSG_RADIUSD_MODULE_CTRL_BIND,
591 		    imsg->hdr.peerid, 0, -1, NULL, 0);
592 		if (imsg->hdr.type == IMSG_RADIUSD_MODULE_IPCP_MONITOR)
593 			break;
594 		/* FALLTHROUGH */
595 	case IMSG_RADIUSD_MODULE_IPCP_DUMP:
596 		dumpsiz = MAX_IMSGSIZE;
597 		if ((dump = calloc(1, dumpsiz)) == NULL) {
598 			log_warn("%s: calloc()", __func__);
599 			goto fail;
600 		}
601 		i = 0;
602 		RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) {
603 			if (!timespecisset(&assign->start))
604 				/* not started yet */
605 				continue;
606 			ipcp_db_dump_fill_record(dump, i++, assign);
607 			if (RB_NEXT(assigned_ipv4_tree, &self->ipv4s, assign)
608 			    == NULL)
609 				break;
610 			if (offsetof(struct radiusd_ipcp_db_dump,
611 			    records[i + 1]) >= dumpsiz) {
612 				module_imsg_compose(self->base,
613 				    IMSG_RADIUSD_MODULE_IPCP_DUMP,
614 				    imsg->hdr.peerid, 0, -1,
615 				    dump, offsetof(struct radiusd_ipcp_db_dump,
616 				    records[i]));
617 				i = 0;
618 			}
619 		}
620 		dump->islast = 1;
621 		module_imsg_compose(self->base, IMSG_RADIUSD_MODULE_IPCP_DUMP,
622 		    imsg->hdr.peerid, 0, -1, dump, offsetof(
623 		    struct radiusd_ipcp_db_dump, records[i]));
624 		freezero(dump ,dumpsiz);
625 		break;
626 	case IMSG_RADIUSD_MODULE_IPCP_DISCONNECT:
627 		if (datalen < sizeof(unsigned)) {
628 			log_warn("%s: received "
629 			    "IMSG_RADIUSD_MODULE_IPCP_DISCONNECT message size "
630 			    "is wrong", __func__);
631 			goto fail;
632 		}
633 		seq = *(unsigned *)imsg->data;
634 		RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) {
635 			if (!timespecisset(&assign->start))
636 				/* not started yet */
637 				continue;
638 			if (assign->seq == seq)
639 				break;
640 		}
641 		if (assign == NULL) {
642 			cause = "session not found";
643 			log_warnx("Disconnect seq=%u requested, but the "
644 			    "session is not found", seq);
645 			module_imsg_compose(self->base, IMSG_NG,
646 			    imsg->hdr.peerid, 0, -1, cause, strlen(cause) + 1);
647 		}
648 		else {
649 			if (assign->dae == NULL)
650 				log_warnx("Disconnect seq=%u requested, but "
651 				    "DAE is not configured", assign->seq);
652 			else {
653 				log_info("Disconnect seq=%u requested",
654 				    assign->seq);
655 				if ((client = calloc(1, sizeof(struct
656 				    radiusctl_client))) == NULL) {
657 					log_warn("%s: calloc: %m",
658 					    __func__);
659 					goto fail;
660 				}
661 				client->peerid = imsg->hdr.peerid;
662 				if (assign->dae_ntry == 0)
663 					ipcp_dae_send_disconnect_request(
664 					    assign);
665 				TAILQ_INSERT_TAIL(&assign->dae_clients,
666 				    client, entry);
667 			}
668 		}
669 		break;
670 	}
671 	return;
672  fail:
673 	module_stop(self->base);
674 }
675 
676 int
677 ipcp_notice_startstop(struct module_ipcp *self, struct assigned_ipv4 *assign,
678     int start, struct radiusd_ipcp_statistics *stat)
679 {
680 	struct module_ipcp_ctrlconn	*ctrl;
681 	struct radiusd_ipcp_db_dump	*dump;
682 	size_t				 dumpsiz;
683 	struct iovec			 iov[2];
684 	int				 niov = 0;
685 
686 	dumpsiz = offsetof(struct radiusd_ipcp_db_dump, records[1]);
687 	if ((dump = calloc(1, dumpsiz)) == NULL) {
688 		log_warn("%s: calloc()", __func__);
689 		return (-1);
690 	}
691 	dump->islast = 1;
692 	ipcp_db_dump_fill_record(dump, 0, assign);
693 
694 	iov[niov].iov_base = dump;
695 	iov[niov].iov_len = dumpsiz;
696 	if (start == 0) {
697 		iov[++niov].iov_base = stat;
698 		iov[niov].iov_len = sizeof(struct radiusd_ipcp_statistics);
699 	}
700 	TAILQ_FOREACH(ctrl, &self->ctrls, next)
701 		module_imsg_composev(self->base,
702 		    (start)? IMSG_RADIUSD_MODULE_IPCP_START :
703 		    IMSG_RADIUSD_MODULE_IPCP_STOP, ctrl->peerid, 0, -1, iov,
704 		    niov + 1);
705 	freezero(dump, dumpsiz);
706 	return (0);
707 }
708 
709 void
710 ipcp_resdeco(void *ctx, u_int q_id, const u_char *req, size_t reqlen,
711     const u_char *res, size_t reslen)
712 {
713 	struct module_ipcp	*self = ctx;
714 	RADIUS_PACKET		*radres = NULL, *radreq = NULL;
715 	struct in_addr		 addr4;
716 	const struct in_addr	 mask4 = { .s_addr = 0xffffffffUL };
717 	int			 res_code, msraserr = 935;
718 	struct ipcp_address	*addr;
719 	int			 i, j, n;
720 	bool			 found = false;
721 	char			 username[256], buf[128];
722 	struct user		*user = NULL;
723 	struct assigned_ipv4	*assigned = NULL, *assign;
724 
725 	ipcp_update_time(self);
726 
727 	if ((radres = radius_convert_packet(res, reslen)) == NULL) {
728 		log_warn("%s: radius_convert_packet() failed", __func__);
729 		goto fatal;
730 	}
731 	res_code = radius_get_code(radres);
732 	if (res_code != RADIUS_CODE_ACCESS_ACCEPT)
733 		goto accept;
734 
735 	if ((radreq = radius_convert_packet(req, reqlen)) == NULL) {
736 		log_warn("%s: radius_convert_packet() failed", __func__);
737 		goto fatal;
738 	}
739 
740 	/*
741 	 * prefer User-Name of the response rather than the request,
742 	 * since it must be the authenticated user.
743 	 */
744 	if (radius_get_string_attr(radres, RADIUS_TYPE_USER_NAME, username,
745 	    sizeof(username)) != 0 &&
746 	    radius_get_string_attr(radreq, RADIUS_TYPE_USER_NAME, username,
747 	    sizeof(username)) != 0) {
748 		log_warnx("q=%u unexpected request: no user-name", q_id);
749 		goto fatal;
750 	}
751 
752 	if ((addr = TAILQ_FIRST(&self->addrs)) != NULL) {
753 		/* The address assignment is configured */
754 
755 		if ((user = ipcp_user_get(self, username)) == NULL) {
756 			log_warn("%s: ipcp_user_get()", __func__);
757 			goto fatal;
758 		}
759 
760 		msraserr = 935;
761 		if (self->max_sessions != 0) {
762 			if (self->nsessions >= self->max_sessions) {
763 				log_info("q=%u rejected: number of "
764 				    "sessions reached the limit(%d)", q_id,
765 				    self->max_sessions);
766 				goto reject;
767 			}
768 		}
769 		if (self->user_max_sessions != 0) {
770 			n = 0;
771 			TAILQ_FOREACH(assign, &user->ipv4s, next)
772 				n++;
773 			if (n >= self->user_max_sessions) {
774 				log_info("q=%u rejected: number of "
775 				    "sessions per a user reached the limit(%d)",
776 				    q_id, self->user_max_sessions);
777 				goto reject;
778 			}
779 		}
780 
781 		msraserr = 716;
782 		if (radius_get_ipv4_attr(radres,
783 		    RADIUS_TYPE_FRAMED_IP_ADDRESS, &addr4) == 0) {
784 			if (ipcp_ipv4_find(self, addr4) != NULL)
785 				log_info("q=%u rejected: server requested IP "
786 				    "address is busy", q_id);
787 			else {
788 				/* compare in host byte order */
789 				addr4.s_addr = ntohl(addr4.s_addr);
790 				TAILQ_FOREACH(addr, &self->addrs, next) {
791 					if (addr->type != ADDRESS_TYPE_STATIC &&
792 					    addr->type != ADDRESS_TYPE_POOL)
793 						continue;
794 					if (addr->start.s_addr <= addr4.s_addr
795 					    && addr4.s_addr <= addr->end.s_addr)
796 						break;
797 				}
798 				if (addr == NULL)
799 					log_info("q=%u rejected: server "
800 					    "requested IP address is out of "
801 					    "the range", q_id);
802 				else
803 					found = true;
804 				/* revert the addr to the network byte order */
805 				addr4.s_addr = htonl(addr4.s_addr);
806 			}
807 			if (!found)
808 				goto reject;
809 		} else {
810 			n = arc4random_uniform(self->npools);
811 			i = 0;
812 			TAILQ_FOREACH(addr, &self->addrs, next) {
813 				if (addr->type == ADDRESS_TYPE_POOL) {
814 					if (i <= n && n < i + addr->naddrs) {
815 						j = n - i;
816 						break;
817 					}
818 					i += addr->naddrs;
819 				}
820 			}
821 			for (i = 0; i < self->npools; i++, j++) {
822 				if (addr == NULL)
823 					break;
824 				if (j >= addr->naddrs) { /* next pool */
825 					if ((addr = TAILQ_NEXT(addr, next))
826 					    == NULL)
827 						addr = TAILQ_FIRST(
828 						    &self->addrs);
829 					j = 0;
830 				}
831 				addr4.s_addr = htonl(addr->start.s_addr + j);
832 				if (ipcp_ipv4_find(self, addr4) == NULL) {
833 					found = true;
834 					break;
835 				}
836 			}
837 			if (!found) {
838 				log_info("q=%u rejected: ran out of the "
839 				    "address pool", q_id);
840 				goto reject;
841 			}
842 		}
843 		if ((assigned = ipcp_ipv4_assign(self, user, addr4)) == NULL) {
844 			log_warn("%s: ipcp_ipv4_assign()", __func__);
845 			goto fatal;
846 		}
847 		radius_set_ipv4_attr(radres, RADIUS_TYPE_FRAMED_IP_NETMASK,
848 		    mask4);
849 		radius_del_attr_all(radres, RADIUS_TYPE_FRAMED_IP_ADDRESS);
850 		radius_put_ipv4_attr(radres, RADIUS_TYPE_FRAMED_IP_ADDRESS,
851 		    addr4);
852 		log_info("q=%u Assign %s for %s", q_id,
853 		    inet_ntop(AF_INET, &addr4, buf, sizeof(buf)), username);
854 		if (radius_has_attr(radreq, RADIUS_TYPE_USER_PASSWORD))
855 			strlcpy(assigned->auth_method, "PAP",
856 			    sizeof(assigned->auth_method));
857 		else if (radius_has_attr(radreq, RADIUS_TYPE_CHAP_PASSWORD))
858 			strlcpy(assigned->auth_method, "CHAP",
859 			    sizeof(assigned->auth_method));
860 		else if (radius_has_vs_attr(radreq, RADIUS_VENDOR_MICROSOFT,
861 		    RADIUS_VTYPE_MS_CHAP_RESPONSE))
862 			strlcpy(assigned->auth_method, "MS-CHAP",
863 			    sizeof(assigned->auth_method));
864 		else if (radius_has_vs_attr(radreq, RADIUS_VENDOR_MICROSOFT,
865 		    RADIUS_VTYPE_MS_CHAP2_RESPONSE))
866 			strlcpy(assigned->auth_method, "MS-CHAP-V2",
867 			    sizeof(assigned->auth_method));
868 		else if (radius_has_attr(radreq, RADIUS_TYPE_EAP_MESSAGE))
869 			strlcpy(assigned->auth_method, "EAP",
870 			    sizeof(assigned->auth_method));
871 	}
872 
873 	if (self->name_server[0].s_addr != 0) {
874 		addr4.s_addr = htonl(self->name_server[0].s_addr);
875 		radius_del_vs_attr_all(radres,
876 		    RADIUS_VENDOR_MICROSOFT,
877 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER);
878 		radius_put_vs_ipv4_attr(radres,
879 		    RADIUS_VENDOR_MICROSOFT,
880 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, self->name_server[0]);
881 	}
882 	if (self->name_server[1].s_addr != 0) {
883 		addr4.s_addr = htonl(self->name_server[1].s_addr);
884 		radius_del_vs_attr_all(radres,
885 		    RADIUS_VENDOR_MICROSOFT,
886 		    RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER);
887 		radius_put_vs_ipv4_attr(radres,
888 		    RADIUS_VENDOR_MICROSOFT,
889 		    RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER, self->name_server[1]);
890 	}
891 	if (self->netbios_server[0].s_addr != 0) {
892 		addr4.s_addr = htonl(self->netbios_server[0].s_addr);
893 		radius_del_vs_attr_all(radres,
894 		    RADIUS_VENDOR_MICROSOFT,
895 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER);
896 		radius_put_vs_ipv4_attr(radres,
897 		    RADIUS_VENDOR_MICROSOFT,
898 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER,
899 		    self->netbios_server[0]);
900 	}
901 	if (self->netbios_server[1].s_addr != 0) {
902 		addr4.s_addr = htonl(self->netbios_server[1].s_addr);
903 		radius_del_vs_attr_all(radres,
904 		    RADIUS_VENDOR_MICROSOFT,
905 		    RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER);
906 		radius_put_vs_ipv4_attr(radres,
907 		    RADIUS_VENDOR_MICROSOFT,
908 		    RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER,
909 		    self->netbios_server[1]);
910 	}
911 	if (!self->no_session_timeout &&
912 	    radius_has_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT)) {
913 		radius_get_uint32_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT,
914 		    &assigned->session_timeout);
915 		/* we handle this session-timeout */
916 		radius_del_attr_all(radres, RADIUS_TYPE_SESSION_TIMEOUT);
917 	}
918 
919  accept:
920 	if (module_resdeco_done(self->base, q_id, radius_get_data(radres),
921 	    radius_get_length(radres)) == -1) {
922 		log_warn("%s: module_resdeco_done() failed", __func__);
923 		module_stop(self->base);
924 	}
925 	if (radreq != NULL)
926 		radius_delete_packet(radreq);
927 	radius_delete_packet(radres);
928 	return;
929  reject:
930 	ipcp_reject(self, radreq, q_id, radres, msraserr);
931 	radius_delete_packet(radreq);
932 	radius_delete_packet(radres);
933 	return;
934  fatal:
935 	if (radreq != NULL)
936 		radius_delete_packet(radreq);
937 	if (radres != NULL)
938 		radius_delete_packet(radres);
939 	module_stop(self->base);
940 }
941 
942 void
943 ipcp_reject(struct module_ipcp *self, RADIUS_PACKET *reqp, unsigned int q_id,
944     RADIUS_PACKET *orig_resp, int mserr)
945 {
946 	bool			 is_eap, is_mschap, is_mschap2;
947 	uint8_t			 attr[256];
948 	size_t			 attrlen;
949 	RADIUS_PACKET		*resp;
950 	struct {
951 		uint8_t		 code;
952 		uint8_t		 id;
953 		uint16_t	 length;
954 	} __packed		 eap;
955 
956 	resp = radius_new_response_packet(RADIUS_CODE_ACCESS_REJECT, reqp);
957 	if (resp == NULL) {
958 		log_warn("%s: radius_new_response_packet() failed", __func__);
959 		module_accsreq_aborted(self->base, q_id);
960 		return;
961 	}
962 
963 	is_eap = radius_has_attr(reqp, RADIUS_TYPE_EAP_MESSAGE);
964 	if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT,
965 	    RADIUS_VTYPE_MS_CHAP_RESPONSE, attr, &attrlen) == 0)
966 		is_mschap = true;
967 	else if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT,
968 	    RADIUS_VTYPE_MS_CHAP2_RESPONSE, attr, &attrlen) == 0)
969 		is_mschap2 = true;
970 
971 	if (is_eap) {
972 		memset(&eap, 0, sizeof(eap));	/* just in case */
973 		eap.code = 1;	/* EAP Request */
974 		attrlen = sizeof(attr);
975 		if (orig_resp != NULL && radius_get_raw_attr(orig_resp,
976 		    RADIUS_TYPE_EAP_MESSAGE, &attr, &attrlen) == 0)
977 			eap.id = attr[1];
978 		else
979 			eap.id = 0;
980 		eap.length = htons(sizeof(eap));
981 		radius_put_raw_attr(resp, RADIUS_TYPE_EAP_MESSAGE, &eap,
982 		    ntohs(eap.length));
983 	} else if (is_mschap || is_mschap2) {
984 		attr[0] = attr[1];	/* Copy the ident of the request */
985 		snprintf(attr + 1, sizeof(attr) - 1, "E=%d R=0 V=3", mserr);
986 		radius_put_vs_raw_attr(resp, RADIUS_VENDOR_MICROSOFT,
987 		    RADIUS_VTYPE_MS_CHAP_ERROR, attr, strlen(attr + 1) + 1);
988 	}
989 
990 	module_resdeco_done(self->base, q_id, radius_get_data(resp),
991 	    radius_get_length(resp));
992 	radius_delete_packet(resp);
993 }
994 
995 /***********************************************************************
996  * RADIUS Accounting
997  ***********************************************************************/
998 void
999 ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt,
1000     size_t pktlen)
1001 {
1002 	RADIUS_PACKET		*radpkt = NULL;
1003 	int			 code, af;
1004 	uint32_t		 type, delay, uval;
1005 	struct in_addr		 addr4, nas_ipv4;
1006 	struct in6_addr		 nas_ipv6, ipv6_zero;
1007 	struct module_ipcp	*self = ctx;
1008 	struct assigned_ipv4	*assign, *assignt;
1009 	char			 username[256], nas_id[256], buf[256],
1010 				    buf1[384];
1011 	struct timespec		 dur;
1012 	struct radiusd_ipcp_statistics
1013 				 stat;
1014 	struct module_ipcp_dae	*dae;
1015 
1016 	ipcp_update_time(self);
1017 
1018 	if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) {
1019 		log_warn("%s: radius_convert_packet() failed", __func__);
1020 		module_stop(self->base);
1021 		return;
1022 	}
1023 	code = radius_get_code(radpkt);
1024 	if (code != RADIUS_CODE_ACCOUNTING_REQUEST &&
1025 	    code != RADIUS_CODE_ACCOUNTING_RESPONSE)
1026 		goto out;
1027 
1028 	if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_STATUS_TYPE, &type)
1029 	    != 0)
1030 		goto out;
1031 
1032 	/* identifier for the NAS */
1033 	memset(&ipv6_zero, 0, sizeof(ipv6_zero));
1034 	memset(&nas_ipv4, 0, sizeof(nas_ipv4));
1035 	memset(&nas_ipv6, 0, sizeof(nas_ipv6));
1036 	memset(&nas_id, 0, sizeof(nas_id));
1037 
1038 	radius_get_ipv4_attr(radpkt, RADIUS_TYPE_NAS_IP_ADDRESS, &nas_ipv4);
1039 	radius_get_ipv6_attr(radpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS, &nas_ipv6);
1040 	radius_get_string_attr(radpkt, RADIUS_TYPE_NAS_IDENTIFIER, nas_id,
1041 	    sizeof(nas_id));
1042 
1043 	if (nas_ipv4.s_addr == 0 && IN6_ARE_ADDR_EQUAL(&nas_ipv6, &ipv6_zero) &&
1044 	    nas_id[0] == '\0') {
1045 		log_warnx("q=%u no NAS-IP-Address, NAS-IPV6-Address, or "
1046 		    "NAS-Identifier", q_id);
1047 		goto out;
1048 	}
1049 
1050 	if (type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON ||
1051 	    type == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) {
1052 		/*
1053 		 * NAS or daemon is restarted.  Delete all assigned records
1054 		 * from it
1055 		 */
1056 		RB_FOREACH_SAFE(assign, assigned_ipv4_tree, &self->ipv4s,
1057 		    assignt) {
1058 			if (assign->nas_ipv4.s_addr != nas_ipv4.s_addr ||
1059 			    !IN6_ARE_ADDR_EQUAL(&assign->nas_ipv6, &nas_ipv6) ||
1060 			    strcmp(assign->nas_id, nas_id) != 0)
1061 				continue;
1062 			log_info("Delete record for %s", inet_ntop(AF_INET,
1063 			    &assign->ipv4, buf, sizeof(buf)));
1064 			ipcp_del_db(self, assign);
1065 			ipcp_ipv4_release(self, assign);
1066 		}
1067 		return;
1068 	}
1069 
1070 	if (radius_get_ipv4_attr(radpkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, &addr4)
1071 	    != 0)
1072 		goto out;
1073 	if (radius_get_string_attr(radpkt, RADIUS_TYPE_USER_NAME, username,
1074 	    sizeof(username)) != 0)
1075 		goto out;
1076 	if ((assign = ipcp_ipv4_find(self, addr4)) == NULL)
1077 		/* not assigned by this */
1078 		goto out;
1079 
1080 	if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_DELAY_TIME, &delay)
1081 	    != 0)
1082 		delay = 0;
1083 
1084 	if (type == RADIUS_ACCT_STATUS_TYPE_START) {
1085 		assign->start = self->uptime;
1086 		assign->start.tv_sec -= delay;
1087 
1088 		if (!self->no_session_timeout && (self->session_timeout > 0 ||
1089 		    assign->session_timeout > 0)) {
1090 			assign->timeout = assign->start;
1091 			if (self->session_timeout > 0)
1092 				assign->timeout.tv_sec += self->session_timeout;
1093 			else
1094 				assign->timeout.tv_sec +=
1095 				    assign->session_timeout;
1096 		}
1097 		assign->nas_ipv4 = nas_ipv4;
1098 		assign->nas_ipv6 = nas_ipv6;
1099 		strlcpy(assign->nas_id, nas_id, sizeof(assign->nas_id));
1100 
1101 		if (radius_get_string_attr(radpkt, RADIUS_TYPE_ACCT_SESSION_ID,
1102 		    assign->session_id, sizeof(assign->session_id)) != 0)
1103 			assign->session_id[0] = '\0';
1104 		if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_TUNNEL_TYPE,
1105 		    &uval) == 0)
1106 			assign->tun_type = radius_tunnel_type_string(uval,
1107 			    NULL);
1108 		if (assign->tun_type == NULL)
1109 			assign->tun_type = "";
1110 
1111 		/*
1112 		 * Get "tunnel from" from Tunnel-Client-Endpoint or Calling-
1113 		 * Station-Id
1114 		 */
1115 		af = AF_UNSPEC;
1116 		if (radius_get_string_attr(radpkt,
1117 		    RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT, buf, sizeof(buf)) == 0)
1118 		    {
1119 			if (radius_get_uint32_attr(radpkt,
1120 			    RADIUS_TYPE_TUNNEL_MEDIUM_TYPE, &uval) == 0) {
1121 				if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV4)
1122 					af = AF_INET;
1123 				else if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV6)
1124 					af = AF_INET6;
1125 			}
1126 			parse_addr(buf, af, (struct sockaddr *)
1127 			    &assign->tun_client, sizeof(assign->tun_client));
1128 		}
1129 		if (assign->tun_client.sin4.sin_family == 0 &&
1130 		    radius_get_string_attr(radpkt,
1131 		    RADIUS_TYPE_CALLING_STATION_ID, buf, sizeof(buf)) == 0)
1132 			parse_addr(buf, af, (struct sockaddr *)
1133 			    &assign->tun_client, sizeof(assign->tun_client));
1134 
1135 		TAILQ_FOREACH(dae, &self->daes, next) {
1136 			if (dae->nas_id[0] == '\0' ||
1137 			    strcmp(dae->nas_id, assign->nas_id) == 0)
1138 				break;
1139 		}
1140 		assign->dae = dae;
1141 
1142 		ipcp_put_db(self, assign);
1143 		ipcp_schedule_timer(self);
1144 
1145 		if (ipcp_notice_startstop(self, assign, 1, NULL) != 0)
1146 			goto fail;
1147 		log_info("Start seq=%u user=%s duration=%dsec session=%s "
1148 		    "tunnel=%s from=%s auth=%s ip=%s", assign->seq,
1149 		    assign->user->name, delay, assign->session_id,
1150 		    assign->tun_type, print_addr((struct sockaddr *)
1151 		    &assign->tun_client, buf1, sizeof(buf1)),
1152 		    assign->auth_method, inet_ntop(AF_INET, &addr4, buf,
1153 		    sizeof(buf)));
1154 	} else if (type == RADIUS_ACCT_STATUS_TYPE_STOP) {
1155 		memset(&stat, 0, sizeof(stat));
1156 
1157 		dur = self->uptime;
1158 		dur.tv_sec -= delay;
1159 		timespecsub(&dur, &assign->start, &dur);
1160 
1161 		if (radius_get_uint32_attr(radpkt,
1162 		    RADIUS_TYPE_ACCT_INPUT_OCTETS, &uval) == 0)
1163 			stat.ibytes = uval;
1164 		if (radius_get_uint32_attr(radpkt,
1165 		    RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, &uval) == 0)
1166 			stat.ibytes = ((uint64_t)uval << 32) | stat.ibytes;
1167 		if (radius_get_uint32_attr(radpkt,
1168 		    RADIUS_TYPE_ACCT_OUTPUT_OCTETS, &uval) == 0)
1169 			stat.obytes = uval;
1170 		if (radius_get_uint32_attr(radpkt,
1171 		    RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, &uval) == 0)
1172 			stat.obytes = ((uint64_t)uval << 32) | stat.obytes;
1173 		radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_INPUT_PACKETS,
1174 		    &stat.ipackets);
1175 		radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS,
1176 		    &stat.opackets);
1177 
1178 		if (radius_get_uint32_attr(radpkt,
1179 		    RADIUS_TYPE_ACCT_TERMINATE_CAUSE, &uval) == 0)
1180 			strlcpy(stat.cause, radius_terminate_cause_string(uval),
1181 			    sizeof(stat.cause));
1182 
1183 		log_info("Stop seq=%u user=%s duration=%lldsec session=%s "
1184 		    "tunnel=%s from=%s auth=%s ip=%s datain=%"PRIu64"bytes,%"
1185 		    PRIu32"packets dataout=%"PRIu64"bytes,%"PRIu32"packets "
1186 		    "cause=\"%s\"",
1187 		    assign->seq, assign->user->name, dur.tv_sec,
1188 		    assign->session_id, assign->tun_type, print_addr(
1189 		    (struct sockaddr *)&assign->tun_client, buf1, sizeof(buf1)),
1190 		    assign->auth_method, inet_ntop(AF_INET, &addr4, buf,
1191 		    sizeof(buf)), stat.ibytes, stat.ipackets, stat.obytes,
1192 		    stat.opackets, stat.cause);
1193 
1194 		ipcp_del_db(self, assign);
1195 		if (ipcp_notice_startstop(self, assign, 0, &stat) != 0)
1196 			goto fail;
1197 		ipcp_ipv4_release(self, ipcp_ipv4_find(self, addr4));
1198 	}
1199  out:
1200 	radius_delete_packet(radpkt);
1201 	return;
1202  fail:
1203 	module_stop(self->base);
1204 	radius_delete_packet(radpkt);
1205 	return;
1206 }
1207 
1208 /***********************************************************************
1209  * On memory database to manage IP address assignment
1210  ***********************************************************************/
1211 struct assigned_ipv4 *
1212 ipcp_ipv4_assign(struct module_ipcp *self, struct user *user,
1213     struct in_addr ina)
1214 {
1215 	struct assigned_ipv4 *ip;
1216 
1217 	ip = calloc(1, sizeof(struct assigned_ipv4));
1218 	if (ip == NULL) {
1219 		log_warn("%s: calloc()", __func__);
1220 		return (NULL);
1221 	}
1222 	ip->ipv4 = ina;
1223 	ip->user = user;
1224 	ip->authtime = self->uptime;
1225 	RB_INSERT(assigned_ipv4_tree, &self->ipv4s, ip);
1226 	TAILQ_INSERT_TAIL(&user->ipv4s, ip, next);
1227 	TAILQ_INIT(&ip->dae_clients);
1228 	self->nsessions++;
1229 	ip->seq = self->seq++;
1230 
1231 	return (ip);
1232 }
1233 
1234 struct assigned_ipv4 *
1235 ipcp_ipv4_find(struct module_ipcp *self, struct in_addr ina)
1236 {
1237 	struct assigned_ipv4	 key, *ret;
1238 	struct timespec		 dif;
1239 
1240 	key.ipv4 = ina;
1241 	ret = RB_FIND(assigned_ipv4_tree, &self->ipv4s, &key);
1242 	if (ret != NULL && ret->start.tv_sec == 0) {
1243 		/* not yet assigned */
1244 		timespecsub(&self->uptime, &ret->authtime, &dif);
1245 		if (dif.tv_sec >= self->start_wait) {
1246 			/* assumed NAS finally didn't use the address */
1247 			TAILQ_REMOVE(&ret->user->ipv4s, ret, next);
1248 			RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, ret);
1249 			free(ret);
1250 			ret = NULL;
1251 			self->nsessions--;
1252 		}
1253 	}
1254 	return (ret);
1255 }
1256 
1257 void
1258 ipcp_ipv4_release(struct module_ipcp *self, struct assigned_ipv4 *assign)
1259 {
1260 	if (assign != NULL) {
1261 		TAILQ_REMOVE(&assign->user->ipv4s, assign, next);
1262 		RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, assign);
1263 		self->nsessions--;
1264 		ipcp_dae_reset_request(assign);
1265 		free(assign);
1266 	}
1267 }
1268 
1269 int
1270 assigned_ipv4_compar(struct assigned_ipv4 *a, struct assigned_ipv4 *b)
1271 {
1272 	return (b->ipv4.s_addr - a->ipv4.s_addr);
1273 }
1274 
1275 struct user *
1276 ipcp_user_get(struct module_ipcp *self, const char *username)
1277 {
1278 	struct {
1279 		struct user	 user;
1280 		char		 name[256];
1281 	} key;
1282 	struct user		*elm;
1283 
1284 	strlcpy(key.user.name, username, 256);
1285 	elm = RB_FIND(user_tree, &self->users, &key.user);
1286 	if (elm == NULL) {
1287 		if ((elm = calloc(1, offsetof(struct user, name[
1288 		    strlen(username) + 1]))) == NULL)
1289 			return (NULL);
1290 		memcpy(elm->name, username, strlen(username));
1291 		RB_INSERT(user_tree, &self->users, elm);
1292 		TAILQ_INIT(&elm->ipv4s);
1293 	}
1294 
1295 	return (elm);
1296 }
1297 
1298 int
1299 user_compar(struct user *a, struct user *b)
1300 {
1301 	return (strcmp(a->name, b->name));
1302 }
1303 
1304 RB_GENERATE_STATIC(assigned_ipv4_tree, assigned_ipv4, tree,
1305     assigned_ipv4_compar);
1306 RB_GENERATE_STATIC(user_tree, user, tree, user_compar);
1307 
1308 /***********************************************************************
1309  * DB for the persistent over processes
1310  ***********************************************************************/
1311 int
1312 ipcp_prepare_db(void)
1313 {
1314 	struct passwd	*pw;
1315 	DB		*db;
1316 
1317 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_CREAT | O_RDWR | O_EXLOCK,
1318 	    0600, DB_BTREE, NULL)) == NULL)
1319 		return (-1);
1320 	if ((pw = getpwnam(RADIUSD_USER)) == NULL)
1321 		return (-1);
1322 	fchown(db->fd(db), pw->pw_uid, pw->pw_gid);
1323 	db->close(db);
1324 
1325 	return (0);
1326 }
1327 
1328 int
1329 ipcp_restore_from_db(struct module_ipcp *self)
1330 {
1331 	DB			*db;
1332 	DBT			 key, val;
1333 	char			 keybuf[128];
1334 	struct user		*user;
1335 	struct radiusd_ipcp_db_record
1336 				*record;
1337 	struct assigned_ipv4	*assigned;
1338 	struct in_addr		 ipv4;
1339 	struct module_ipcp_dae	*dae;
1340 
1341 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDONLY | O_SHLOCK, 0600,
1342 	    DB_BTREE, NULL)) == NULL)
1343 		return (-1);
1344 
1345 	key.data = "ipv4/";
1346 	key.size = 5;
1347 	if (db->seq(db, &key, &val, R_CURSOR) == 0) {
1348 		do {
1349 			if (key.size >= sizeof(keybuf))
1350 				break;
1351 			memcpy(keybuf, key.data, key.size);
1352 			keybuf[key.size] = '\0';
1353 			if (strncmp(keybuf, "ipv4/", 5) != 0)
1354 				break;
1355 			inet_pton(AF_INET, keybuf + 5, &ipv4);
1356 			record = (struct radiusd_ipcp_db_record *)val.data;
1357 			if ((user = ipcp_user_get(self, record->username))
1358 			    == NULL)
1359 				return (-1);
1360 			if ((assigned = ipcp_ipv4_assign(self, user, ipv4))
1361 			    == NULL)
1362 				return (-1);
1363 			assigned->seq = record->seq;
1364 			self->seq = MAXIMUM(assigned->seq + 1, self->seq);
1365 			strlcpy(assigned->auth_method, record->auth_method,
1366 			    sizeof(assigned->auth_method));
1367 			strlcpy(assigned->session_id, record->session_id,
1368 			    sizeof(assigned->session_id));
1369 			assigned->start = record->start;
1370 			assigned->timeout = record->timeout;
1371 			assigned->nas_ipv4 = record->nas_ipv4;
1372 			assigned->nas_ipv6 = record->nas_ipv6;
1373 			strlcpy(assigned->nas_id, record->nas_id,
1374 			    sizeof(assigned->nas_id));
1375 			assigned->tun_type = radius_tunnel_type_string(0,
1376 			    record->tun_type);
1377 			memcpy(&assigned->tun_client, &record->tun_client,
1378 			    sizeof(assigned->tun_client));
1379 
1380 			TAILQ_FOREACH(dae, &self->daes, next) {
1381 				if (dae->nas_id[0] == '\0' ||
1382 				    strcmp(dae->nas_id, assigned->nas_id) == 0)
1383 					break;
1384 			}
1385 			assigned->dae = dae;
1386 		} while (db->seq(db, &key, &val, R_NEXT) == 0);
1387 	}
1388 	db->close(db);
1389 
1390 	return (0);
1391 }
1392 
1393 void
1394 ipcp_put_db(struct module_ipcp *self, struct assigned_ipv4 *assigned)
1395 {
1396 	DB			*db;
1397 	DBT			 key, val;
1398 	char			 keybuf[128];
1399 	struct radiusd_ipcp_db_record
1400 				 record;
1401 
1402 	strlcpy(keybuf, "ipv4/", sizeof(keybuf));
1403 	inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5);
1404 	key.data = keybuf;
1405 	key.size = strlen(keybuf);
1406 	strlcpy(record.session_id, assigned->session_id,
1407 	    sizeof(record.session_id));
1408 	strlcpy(record.auth_method, assigned->auth_method,
1409 	    sizeof(record.auth_method));
1410 	strlcpy(record.username, assigned->user->name, sizeof(record.username));
1411 	record.seq = assigned->seq;
1412 	record.start = assigned->start;
1413 	record.timeout = assigned->timeout;
1414 	record.nas_ipv4 = assigned->nas_ipv4;
1415 	record.nas_ipv6 = assigned->nas_ipv6;
1416 	strlcpy(record.nas_id, assigned->nas_id, sizeof(record.nas_id));
1417 	if (assigned->tun_type != NULL)
1418 		strlcpy(record.tun_type, assigned->tun_type,
1419 		    sizeof(record.tun_type));
1420 	memcpy(&record.tun_client, &assigned->tun_client,
1421 	    sizeof(record.tun_client));
1422 
1423 	val.data = &record;
1424 	val.size = sizeof(record);
1425 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600,
1426 	    DB_BTREE, NULL)) == NULL)
1427 		return;
1428 	db->put(db, &key, &val, 0);
1429 	db->close(db);
1430 }
1431 
1432 void
1433 ipcp_del_db(struct module_ipcp *self, struct assigned_ipv4 *assigned)
1434 {
1435 	DB			*db;
1436 	DBT			 key;
1437 	char			 keybuf[128];
1438 
1439 	strlcpy(keybuf, "ipv4/", sizeof(keybuf));
1440 	inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5);
1441 	key.data = keybuf;
1442 	key.size = strlen(keybuf);
1443 
1444 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600,
1445 	    DB_BTREE, NULL)) == NULL)
1446 		return;
1447 	db->del(db, &key, 0);
1448 	db->close(db);
1449 }
1450 
1451 void
1452 ipcp_db_dump_fill_record(struct radiusd_ipcp_db_dump *dump, int idx,
1453     struct assigned_ipv4 *assign)
1454 {
1455 	dump->records[idx].af = AF_INET;
1456 	dump->records[idx].addr.ipv4 = assign->ipv4;
1457 	dump->records[idx].rec.seq = assign->seq;
1458 	strlcpy(dump->records[idx].rec.session_id, assign->session_id,
1459 	    sizeof(dump->records[idx].rec.session_id));
1460 	strlcpy(dump->records[idx].rec.auth_method, assign->auth_method,
1461 	    sizeof(dump->records[idx].rec.auth_method));
1462 	strlcpy(dump->records[idx].rec.username, assign->user->name,
1463 	    sizeof(dump->records[idx].rec.username));
1464 	dump->records[idx].rec.start = assign->start;
1465 	dump->records[idx].rec.timeout = assign->timeout;
1466 	dump->records[idx].rec.nas_ipv4 = assign->nas_ipv4;
1467 	dump->records[idx].rec.nas_ipv6 = assign->nas_ipv6;
1468 	strlcpy(dump->records[idx].rec.nas_id, assign->nas_id,
1469 	    sizeof(dump->records[idx].rec.nas_id));
1470 	if (assign->tun_type != NULL)
1471 		strlcpy(dump->records[idx].rec.tun_type, assign->tun_type,
1472 		    sizeof(dump->records[idx].rec.tun_type));
1473 	memcpy(&dump->records[idx].rec.tun_client, &assign->tun_client,
1474 	    sizeof(dump->records[idx].rec.tun_client));
1475 }
1476 
1477 /***********************************************************************
1478  * Timer
1479  ***********************************************************************/
1480 void
1481 ipcp_update_time(struct module_ipcp *self)
1482 {
1483 	clock_gettime(CLOCK_BOOTTIME, &self->uptime);
1484 }
1485 
1486 void
1487 ipcp_on_timer(int fd, short ev, void *ctx)
1488 {
1489 	struct module_ipcp *self = ctx;
1490 
1491 	ipcp_update_time(self);
1492 	ipcp_schedule_timer(self);
1493 }
1494 
1495 void
1496 ipcp_schedule_timer(struct module_ipcp *self)
1497 {
1498 	struct assigned_ipv4	*assign, *min_assign = NULL;
1499 	struct timespec		 tsd;
1500 	struct timeval		 tv;
1501 
1502 	/* check session timeout */
1503 	RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) {
1504 		if (assign->timeout.tv_sec == 0)
1505 			continue;
1506 		if (timespeccmp(&assign->timeout, &self->uptime, <=)) {
1507 			log_info("Reached session timeout seq=%u", assign->seq);
1508 			ipcp_dae_send_disconnect_request(assign);
1509 			memset(&assign->timeout, 0, sizeof(assign->timeout));
1510 			ipcp_put_db(self, assign);
1511 		}
1512 		if (min_assign == NULL ||
1513 		    timespeccmp(&min_assign->timeout, &assign->timeout, >))
1514 			min_assign = assign;
1515 	}
1516 	if (evtimer_pending(&self->ev_timer, NULL))
1517 		evtimer_del(&self->ev_timer);
1518 
1519 	if (min_assign != NULL) {
1520 		timespecsub(&min_assign->timeout, &self->uptime, &tsd);
1521 		TIMESPEC_TO_TIMEVAL(&tv, &tsd);
1522 		evtimer_set(&self->ev_timer, ipcp_on_timer, self);
1523 		evtimer_add(&self->ev_timer, &tv);
1524 	}
1525 }
1526 
1527 /***********************************************************************
1528  * Dynamic Authorization Extension for RAIDUS (RFC 5176)
1529  ***********************************************************************/
1530 static const int dae_request_timeouts[] = { 2, 4, 8, 8 };
1531 
1532 void
1533 ipcp_dae_send_disconnect_request(struct assigned_ipv4 *assign)
1534 {
1535 	RADIUS_PACKET		*reqpkt = NULL;
1536 	struct timeval		 tv;
1537 	char			 buf[80];
1538 
1539 	if (assign->dae == NULL)
1540 		return;		/* DAE is not configured */
1541 
1542 	if (assign->dae_reqpkt == NULL) {
1543 		if ((reqpkt = radius_new_request_packet(
1544 		    RADIUS_CODE_DISCONNECT_REQUEST)) == NULL) {
1545 			log_warn("%s: radius_new_request_packet(): %m",
1546 			    __func__);
1547 			return;
1548 		}
1549 		radius_put_string_attr(reqpkt, RADIUS_TYPE_ACCT_SESSION_ID,
1550 		    assign->session_id);
1551 		/*
1552 		 * RFC 5176 Section 3, "either the User-Name or
1553 		 * Chargeable-User-Identity attribute SHOULD be present in
1554 		 * Disconnect-Request and CoA-Request packets."
1555 		 */
1556 		radius_put_string_attr(reqpkt, RADIUS_TYPE_USER_NAME,
1557 		    assign->user->name);
1558 		if (assign->nas_id[0] != '\0')
1559 			radius_put_string_attr(reqpkt,
1560 			    RADIUS_TYPE_NAS_IDENTIFIER, assign->nas_id);
1561 		if (ntohl(assign->nas_ipv4.s_addr) != 0)
1562 			radius_put_ipv4_attr(reqpkt,
1563 			    RADIUS_TYPE_NAS_IP_ADDRESS, assign->nas_ipv4);
1564 		if (!IN6_IS_ADDR_UNSPECIFIED(&assign->nas_ipv6))
1565 			radius_put_ipv6_attr(reqpkt,
1566 			    RADIUS_TYPE_NAS_IPV6_ADDRESS, &assign->nas_ipv6);
1567 		radius_set_accounting_request_authenticator(reqpkt,
1568 		    assign->dae->secret);
1569 		assign->dae_reqpkt = reqpkt;
1570 	}
1571 
1572 	if (assign->dae_ntry == 0) {
1573 		log_info("Sending Disconnect-Request seq=%u to %s",
1574 		    assign->seq, print_addr((struct sockaddr *)
1575 		    &assign->dae->nas_addr, buf, sizeof(buf)));
1576 		TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next);
1577 	}
1578 
1579 	if (radius_send(assign->dae->sock, assign->dae_reqpkt, 0) < 0)
1580 		log_warn("%s: sendto: %m", __func__);
1581 
1582 	tv.tv_sec = dae_request_timeouts[assign->dae_ntry++];
1583 	tv.tv_usec = 0;
1584 	evtimer_set(&assign->dae_evtimer, ipcp_dae_request_on_timeout, assign);
1585 	evtimer_add(&assign->dae_evtimer, &tv);
1586 }
1587 
1588 void
1589 ipcp_dae_request_on_timeout(int fd, short ev, void *ctx)
1590 {
1591 	struct assigned_ipv4	*assign = ctx;
1592 	char			 buf[80];
1593 	struct radiusctl_client	*client;
1594 
1595 	if (assign->dae_ntry >= (int)nitems(dae_request_timeouts)) {
1596 		log_warnx("No answer for Disconnect-Request seq=%u from %s",
1597 		    assign->seq, print_addr((struct sockaddr *)
1598 		    &assign->dae->nas_addr, buf, sizeof(buf)));
1599 		TAILQ_FOREACH(client, &assign->dae_clients, entry)
1600 			module_imsg_compose(assign->dae->ipcp->base, IMSG_NG,
1601 			    client->peerid, 0, -1, NULL, 0);
1602 		ipcp_dae_reset_request(assign);
1603 	} else
1604 		ipcp_dae_send_disconnect_request(assign);
1605 }
1606 
1607 void
1608 ipcp_dae_on_event(int fd, short ev, void *ctx)
1609 {
1610 	struct module_ipcp_dae	*dae = ctx;
1611 	struct module_ipcp	*self = dae->ipcp;
1612 	RADIUS_PACKET		*radres = NULL;
1613 	int			 code;
1614 	uint32_t		 u32;
1615 	struct assigned_ipv4	*assign;
1616 	char			 buf[80], causestr[80];
1617 	const char		*cause = "";
1618 	struct radiusctl_client	*client;
1619 
1620 	ipcp_update_time(self);
1621 
1622 	if ((ev & EV_READ) == 0)
1623 		return;
1624 
1625 	if ((radres = radius_recv(dae->sock, 0)) == NULL) {
1626 		if (errno == EAGAIN)
1627 			return;
1628 		log_warn("Failed to receive from %s", print_addr(
1629 		    (struct sockaddr *)&dae->nas_addr, buf, sizeof(buf)));
1630 		return;
1631 	}
1632 	TAILQ_FOREACH(assign, &dae->reqs, dae_next) {
1633 		if (radius_get_id(assign->dae_reqpkt) == radius_get_id(radres))
1634 			break;
1635 	}
1636 	if (assign == NULL) {
1637 		log_warnx("Received RADIUS packet from %s has unknown id=%d",
1638 		    print_addr((struct sockaddr *)&dae->nas_addr, buf,
1639 		    sizeof(buf)), radius_get_id(radres));
1640 		goto out;
1641 	}
1642 
1643 	radius_set_request_packet(radres, assign->dae_reqpkt);
1644 	if ((radius_check_response_authenticator(radres, dae->secret)) != 0) {
1645 		log_warnx("Received RADIUS packet for seq=%u from %s has a bad "
1646 		    "authenticator", assign->seq, print_addr(
1647 			(struct sockaddr *)&dae->nas_addr, buf,
1648 		    sizeof(buf)));
1649 		goto out;
1650 	}
1651 	causestr[0] = '\0';
1652 	if (radius_get_uint32_attr(radres, RADIUS_TYPE_ERROR_CAUSE, &u32) == 0){
1653 		cause = radius_error_cause_string(u32);
1654 		if (cause != NULL)
1655 			snprintf(causestr, sizeof(causestr), " cause=%u(%s)",
1656 			    u32, cause);
1657 		else
1658 			snprintf(causestr, sizeof(causestr), " cause=%u", u32);
1659 		cause = causestr;
1660 	}
1661 
1662 	code = radius_get_code(radres);
1663 	switch (code) {
1664 	case RADIUS_CODE_DISCONNECT_ACK:
1665 		log_info("Received Disconnect-ACK for seq=%u from %s%s",
1666 		    assign->seq, print_addr((struct sockaddr *)
1667 		    &dae->nas_addr, buf, sizeof(buf)), cause);
1668 		break;
1669 	case RADIUS_CODE_DISCONNECT_NAK:
1670 		log_warnx("Received Disconnect-NAK for seq=%u from %s%s",
1671 		    assign->seq, print_addr((struct sockaddr *)
1672 		    &dae->nas_addr, buf, sizeof(buf)), cause);
1673 		break;
1674 	default:
1675 		log_warn("Received unknown code=%d for id=%u from %s",
1676 		    code, assign->seq, print_addr((struct sockaddr *)
1677 		    &dae->nas_addr, buf, sizeof(buf)));
1678 		break;
1679 	}
1680 
1681 	TAILQ_FOREACH(client, &assign->dae_clients, entry) {
1682 		if (*cause != '\0')
1683 			module_imsg_compose(self->base,
1684 			    (code == RADIUS_CODE_DISCONNECT_ACK)
1685 			    ? IMSG_OK : IMSG_NG, client->peerid, 0, -1,
1686 			    cause + 1, strlen(cause + 1) + 1);
1687 		else
1688 			module_imsg_compose(self->base,
1689 			    (code == RADIUS_CODE_DISCONNECT_ACK)
1690 			    ? IMSG_OK : IMSG_NG, client->peerid, 0, -1,
1691 			    NULL, 0);
1692 	}
1693 	ipcp_dae_reset_request(assign);
1694  out:
1695 	if (radres != NULL)
1696 		radius_delete_packet(radres);
1697 }
1698 
1699 void
1700 ipcp_dae_reset_request(struct assigned_ipv4 *assign)
1701 {
1702 	struct radiusctl_client		*client, *clientt;
1703 
1704 	if (assign->dae != NULL) {
1705 		if (assign->dae_ntry > 0)
1706 			TAILQ_REMOVE(&assign->dae->reqs, assign, dae_next);
1707 	}
1708 	if (assign->dae_reqpkt != NULL)
1709 		radius_delete_packet(assign->dae_reqpkt);
1710 	assign->dae_reqpkt = NULL;
1711 	if (evtimer_pending(&assign->dae_evtimer, NULL))
1712 		evtimer_del(&assign->dae_evtimer);
1713 	TAILQ_FOREACH_SAFE(client, &assign->dae_clients, entry, clientt) {
1714 		TAILQ_REMOVE(&assign->dae_clients, client, entry);
1715 		free(client);
1716 	}
1717 	assign->dae_ntry = 0;
1718 }
1719 
1720 /***********************************************************************
1721  * Miscellaneous functions
1722  ***********************************************************************/
1723 struct ipcp_address *
1724 parse_address_range(const char *range)
1725 {
1726 	char			*buf, *sep;
1727 	int			 masklen;
1728 	uint32_t		 mask;
1729 	struct in_addr		 start, end;
1730 	struct ipcp_address	*ret;
1731 	const char		*errstr;
1732 
1733 	buf = strdup(range);
1734 	if (buf == NULL)
1735 		goto error;
1736 	if ((sep = strchr(buf, '-')) != NULL) {
1737 		*sep = '\0';
1738 		if (inet_pton(AF_INET, buf, &start) != 1)
1739 			goto error;
1740 		else if (inet_pton(AF_INET, ++sep, &end) != 1)
1741 			goto error;
1742 		start.s_addr = ntohl(start.s_addr);
1743 		end.s_addr = ntohl(end.s_addr);
1744 	} else {
1745 		if ((sep = strchr(buf, '/')) != NULL) {
1746 			*sep = '\0';
1747 			if (inet_pton(AF_INET, buf, &start) != 1)
1748 				goto error;
1749 			masklen = strtonum(++sep, 0, 32, &errstr);
1750 			if (errstr != NULL)
1751 				goto error;
1752 		} else {
1753 			if (inet_pton(AF_INET, buf, &start) != 1)
1754 				goto error;
1755 			masklen = 32;
1756 		}
1757 		mask = 0xFFFFFFFFUL;
1758 		if (masklen < 32)
1759 			mask <<= (32 - masklen);
1760 		start.s_addr = ntohl(start.s_addr) & mask;
1761 		if (masklen == 32)
1762 			end = start;
1763 		else if (masklen == 31)
1764 			end.s_addr = start.s_addr + 1;
1765 		else {
1766 			end.s_addr = start.s_addr + (1 << (32 - masklen)) - 2;
1767 			start.s_addr = start.s_addr + 1;
1768 		}
1769 	}
1770 	free(buf);
1771 	if ((ret = calloc(1, sizeof(struct ipcp_address))) == NULL)
1772 		return (NULL);
1773 	ret->start = start;
1774 	ret->end = end;
1775 	ret->naddrs = end.s_addr - start.s_addr + 1;
1776 	return (ret);
1777  error:
1778 	free(buf);
1779 	return (NULL);
1780 }
1781 
1782 const char *
1783 radius_tunnel_type_string(unsigned val, const char *label)
1784 {
1785 	unsigned int		 i;
1786 	struct {
1787 		const unsigned	 constval;
1788 		const char	*label;
1789 	} tunnel_types[] = {
1790 		{ RADIUS_TUNNEL_TYPE_PPTP,	"PPTP" },
1791 		{ RADIUS_TUNNEL_TYPE_L2F,	"L2F" },
1792 		{ RADIUS_TUNNEL_TYPE_L2TP,	"L2TP" },
1793 		{ RADIUS_TUNNEL_TYPE_ATMP,	"ATMP" },
1794 		{ RADIUS_TUNNEL_TYPE_VTP,	"VTP" },
1795 		{ RADIUS_TUNNEL_TYPE_AH,	"AH" },
1796 		{ RADIUS_TUNNEL_TYPE_IP,	"IP" },
1797 		{ RADIUS_TUNNEL_TYPE_MOBILE,	"MIN-IP-IP" },
1798 		{ RADIUS_TUNNEL_TYPE_ESP,	"ESP" },
1799 		{ RADIUS_TUNNEL_TYPE_GRE,	"GRE" },
1800 		{ RADIUS_TUNNEL_TYPE_VDS,	"DVS" },
1801 		/* [MS-RNAS] 3.3.5.1.9 Tunnel-Type */
1802 		{ RADIUS_VENDOR_MICROSOFT << 8 | 1,
1803 						"SSTP" }
1804 	};
1805 
1806 	if (label != NULL) {	/* for conversion to the const value */
1807 		for (i = 0; i < nitems(tunnel_types); i++) {
1808 			if (strcmp(tunnel_types[i].label, label) == 0)
1809 				return (tunnel_types[i].label);
1810 		}
1811 	}
1812 
1813 	for (i = 0; i < nitems(tunnel_types); i++) {
1814 		if (tunnel_types[i].constval == val)
1815 			return (tunnel_types[i].label);
1816 	}
1817 
1818 	return (NULL);
1819 }
1820 
1821 const char *
1822 radius_terminate_cause_string(unsigned val)
1823 {
1824 	unsigned int		 i;
1825 	struct {
1826 		const unsigned	 constval;
1827 		const char	*label;
1828 	} terminate_causes[] = {
1829 	    { RADIUS_TERMNATE_CAUSE_USER_REQUEST,	"User Request" },
1830 	    { RADIUS_TERMNATE_CAUSE_LOST_CARRIER,	"Lost Carrier" },
1831 	    { RADIUS_TERMNATE_CAUSE_LOST_SERVICE,	"Lost Service" },
1832 	    { RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT,	"Idle Timeout" },
1833 	    { RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT,	"Session Timeout" },
1834 	    { RADIUS_TERMNATE_CAUSE_ADMIN_RESET,	"Admin Reset" },
1835 	    { RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT,	"Admin Reboot" },
1836 	    { RADIUS_TERMNATE_CAUSE_PORT_ERROR,		"Port Error" },
1837 	    { RADIUS_TERMNATE_CAUSE_NAS_ERROR,		"NAS Error" },
1838 	    { RADIUS_TERMNATE_CAUSE_NAS_RESET,		"NAS Request" },
1839 	    { RADIUS_TERMNATE_CAUSE_NAS_REBOOT,		"NAS Reboot" },
1840 	    { RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED,	"Port Unneeded" },
1841 	    { RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED,	"Port Preempted" },
1842 	    { RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED,	"Port Suspended" },
1843 	    { RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL,	"Service Unavailable" },
1844 	    { RADIUS_TERMNATE_CAUSE_CALLBACK,		"Callback" },
1845 	    { RADIUS_TERMNATE_CAUSE_USER_ERROR,		"User Error" },
1846 	    { RADIUS_TERMNATE_CAUSE_HOST_REQUEST,	"Host Request" },
1847 	};
1848 
1849 	for (i = 0; i < nitems(terminate_causes); i++) {
1850 		if (terminate_causes[i].constval == val)
1851 			return (terminate_causes[i].label);
1852 	}
1853 
1854 	return (NULL);
1855 }
1856 
1857 const char *
1858 radius_error_cause_string(unsigned val)
1859 {
1860 	unsigned int		 i;
1861 	struct {
1862 		const unsigned	 constval;
1863 		const char	*label;
1864 	} error_causes[] = {
1865 	    { RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_REMOVED,
1866 	      "Residual Session Context Removed" },
1867 	    { RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET,
1868 	      "Invalid EAP Packet (Ignored)" },
1869 	    { RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE,
1870 	      "Unsupported Attribute" },
1871 	    { RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE,
1872 	      "Missing Attribute" },
1873 	    { RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH,
1874 	      "NAS Identification Mismatch" },
1875 	    { RADIUS_ERROR_CAUSE_INVALID_REQUEST,
1876 	      "Invalid Request" },
1877 	    { RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE,
1878 	      "Unsupported Service" },
1879 	    { RADIUS_ERROR_CAUSE_UNSUPPORTED_EXTENSION,
1880 	      "Unsupported Extension" },
1881 	    { RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE,
1882 	      "Invalid Attribute Value" },
1883 	    { RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED,
1884 	      "Administratively Prohibited" },
1885 	    { RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE,
1886 	      "Request Not Routable (Proxy)" },
1887 	    { RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND,
1888 	      "Session Context Not Found" },
1889 	    { RADIUS_ERROR_CAUSE_SESSION_NOT_REMOVABLE,
1890 	      "Session Context Not Removable" },
1891 	    { RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR,
1892 	      "Other Proxy Processing Error" },
1893 	    { RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE,
1894 	      "Resources Unavailable" },
1895 	    { RADIUS_ERROR_CAUSE_REQUEST_INITIATED,
1896 	      "equest Initiated" },
1897 	    { RADIUS_ERROR_CAUSE_MULTI_SELECTION_UNSUPPORTED,
1898 	      "Multiple Session Selection Unsupported" }
1899 	};
1900 
1901 	for (i = 0; i < nitems(error_causes); i++) {
1902 		if (error_causes[i].constval == val)
1903 			return (error_causes[i].label);
1904 	}
1905 
1906 	return (NULL);
1907 }
1908 
1909 int
1910 parse_addr(const char *str0, int af, struct sockaddr *sa, socklen_t salen)
1911 {
1912 	int		 error;
1913 	char		*str, *end, *colon, *colon0, *addr = NULL, *port = NULL;
1914 	char		*sb, *sb0;
1915 	struct addrinfo	 hints, *ai;
1916 
1917 	if ((str = strdup(str0)) == NULL)
1918 		return (-1);
1919 	if (*str == '[' && (end = strchr(str + 1, ']')) != NULL) {
1920 		addr = str + 1;
1921 		*end = '\0';
1922 		if (*(end + 1) == ':')
1923 			port = end + 2;
1924 		else if (*(end + 1) == '[' && (sb = strrchr(end + 2, ']'))
1925 		    != NULL) {
1926 			port = end + 2;
1927 			*sb = '\0';
1928 		}
1929 	} else if ((sb0 = strchr(str, '[')) != NULL &&
1930 	    (sb = strrchr(sb0 + 1, ']')) != NULL && sb0 < sb) {
1931 		addr = str;
1932 		*sb0 = '\0';
1933 		port = sb0 + 1;
1934 		*sb = '\0';
1935 	} else if ((colon0 = strchr(str, ':')) != NULL &&
1936 	    (colon = strrchr(str, ':')) != NULL && colon0 == colon) {
1937 		/* has one : */
1938 		addr = str;
1939 		*colon = '\0';
1940 		port = colon + 1;
1941 	} else {
1942 		addr = str;
1943 		port = NULL;
1944 	}
1945 
1946 	memset(&hints, 0, sizeof(hints));
1947 	hints.ai_family = af;
1948 	hints.ai_socktype = SOCK_DGRAM;
1949 	hints.ai_flags = AI_NUMERICHOST;
1950 	if (port != NULL)
1951 		hints.ai_flags |= AI_NUMERICSERV;
1952 	if ((error = getaddrinfo(addr, port, &hints, &ai)) != 0) {
1953 		free(str);
1954 		return (-1);
1955 	}
1956 	free(str);
1957 	if (salen < ai->ai_addrlen) {
1958 		freeaddrinfo(ai);
1959 		return (-1);
1960 	}
1961 	memcpy(sa, ai->ai_addr, ai->ai_addrlen);
1962 	freeaddrinfo(ai);
1963 
1964 	return (0);
1965 }
1966 
1967 const char *
1968 print_addr(struct sockaddr *sa, char *buf, size_t bufsiz)
1969 {
1970 	int	noport, ret;
1971 	char	hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
1972 
1973 	if (ntohs(((struct sockaddr_in *)sa)->sin_port) == 0) {
1974 		noport = 1;
1975 		ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
1976 		    NI_NUMERICHOST);
1977 	} else {
1978 		noport = 0;
1979 		ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
1980 		    sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
1981 	}
1982 	if (ret != 0)
1983 		return "";
1984 	if (noport)
1985 		strlcpy(buf, hbuf, bufsiz);
1986 	else if (sa->sa_family == AF_INET6)
1987 		snprintf(buf, bufsiz, "[%s]:%s", hbuf, sbuf);
1988 	else
1989 		snprintf(buf, bufsiz, "%s:%s", hbuf, sbuf);
1990 
1991 	return (buf);
1992 }
1993