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