xref: /openbsd-src/usr.sbin/radiusd/radiusd_ipcp.c (revision 53555c846a0a6f917dbd0a191f826da995ab1c42)
1 /*	$OpenBSD: radiusd_ipcp.c,v 1.21 2024/11/28 11:51:45 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 
902 	if (self->name_server[0].s_addr != 0) {
903 		addr4.s_addr = htonl(self->name_server[0].s_addr);
904 		radius_del_vs_attr_all(radres,
905 		    RADIUS_VENDOR_MICROSOFT,
906 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER);
907 		radius_put_vs_ipv4_attr(radres,
908 		    RADIUS_VENDOR_MICROSOFT,
909 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER, self->name_server[0]);
910 	}
911 	if (self->name_server[1].s_addr != 0) {
912 		addr4.s_addr = htonl(self->name_server[1].s_addr);
913 		radius_del_vs_attr_all(radres,
914 		    RADIUS_VENDOR_MICROSOFT,
915 		    RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER);
916 		radius_put_vs_ipv4_attr(radres,
917 		    RADIUS_VENDOR_MICROSOFT,
918 		    RADIUS_VTYPE_MS_SECONDARY_DNS_SERVER, self->name_server[1]);
919 	}
920 	if (self->netbios_server[0].s_addr != 0) {
921 		addr4.s_addr = htonl(self->netbios_server[0].s_addr);
922 		radius_del_vs_attr_all(radres,
923 		    RADIUS_VENDOR_MICROSOFT,
924 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER);
925 		radius_put_vs_ipv4_attr(radres,
926 		    RADIUS_VENDOR_MICROSOFT,
927 		    RADIUS_VTYPE_MS_PRIMARY_DNS_SERVER,
928 		    self->netbios_server[0]);
929 	}
930 	if (self->netbios_server[1].s_addr != 0) {
931 		addr4.s_addr = htonl(self->netbios_server[1].s_addr);
932 		radius_del_vs_attr_all(radres,
933 		    RADIUS_VENDOR_MICROSOFT,
934 		    RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER);
935 		radius_put_vs_ipv4_attr(radres,
936 		    RADIUS_VENDOR_MICROSOFT,
937 		    RADIUS_VTYPE_MS_SECONDARY_NBNS_SERVER,
938 		    self->netbios_server[1]);
939 	}
940 	if (!self->no_session_timeout &&
941 	    radius_has_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT)) {
942 		radius_get_uint32_attr(radres, RADIUS_TYPE_SESSION_TIMEOUT,
943 		    &assigned->session_timeout);
944 		/* we handle this session-timeout */
945 		radius_del_attr_all(radres, RADIUS_TYPE_SESSION_TIMEOUT);
946 	}
947 
948  accept:
949 	if (module_resdeco_done(self->base, q_id, radius_get_data(radres),
950 	    radius_get_length(radres)) == -1) {
951 		log_warn("%s: module_resdeco_done() failed", __func__);
952 		module_stop(self->base);
953 	}
954 	if (radreq != NULL)
955 		radius_delete_packet(radreq);
956 	radius_delete_packet(radres);
957 	return;
958  reject:
959 	ipcp_reject(self, radreq, q_id, radres, msraserr);
960 	radius_delete_packet(radreq);
961 	radius_delete_packet(radres);
962 	return;
963  fatal:
964 	if (radreq != NULL)
965 		radius_delete_packet(radreq);
966 	if (radres != NULL)
967 		radius_delete_packet(radres);
968 	module_stop(self->base);
969 }
970 
971 void
972 ipcp_reject(struct module_ipcp *self, RADIUS_PACKET *reqp, unsigned int q_id,
973     RADIUS_PACKET *orig_resp, int mserr)
974 {
975 	bool			 is_eap, is_mschap, is_mschap2;
976 	uint8_t			 attr[256];
977 	size_t			 attrlen;
978 	RADIUS_PACKET		*resp;
979 	struct {
980 		uint8_t		 code;
981 		uint8_t		 id;
982 		uint16_t	 length;
983 	} __packed		 eap;
984 
985 	resp = radius_new_response_packet(RADIUS_CODE_ACCESS_REJECT, reqp);
986 	if (resp == NULL) {
987 		log_warn("%s: radius_new_response_packet() failed", __func__);
988 		module_accsreq_aborted(self->base, q_id);
989 		return;
990 	}
991 
992 	is_eap = radius_has_attr(reqp, RADIUS_TYPE_EAP_MESSAGE);
993 	if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT,
994 	    RADIUS_VTYPE_MS_CHAP_RESPONSE, attr, &attrlen) == 0)
995 		is_mschap = true;
996 	else if (radius_get_vs_raw_attr(reqp, RADIUS_VENDOR_MICROSOFT,
997 	    RADIUS_VTYPE_MS_CHAP2_RESPONSE, attr, &attrlen) == 0)
998 		is_mschap2 = true;
999 
1000 	if (is_eap) {
1001 		memset(&eap, 0, sizeof(eap));	/* just in case */
1002 		eap.code = 1;	/* EAP Request */
1003 		attrlen = sizeof(attr);
1004 		if (orig_resp != NULL && radius_get_raw_attr(orig_resp,
1005 		    RADIUS_TYPE_EAP_MESSAGE, &attr, &attrlen) == 0)
1006 			eap.id = attr[1];
1007 		else
1008 			eap.id = 0;
1009 		eap.length = htons(sizeof(eap));
1010 		radius_put_raw_attr(resp, RADIUS_TYPE_EAP_MESSAGE, &eap,
1011 		    ntohs(eap.length));
1012 	} else if (is_mschap || is_mschap2) {
1013 		attr[0] = attr[1];	/* Copy the ident of the request */
1014 		snprintf(attr + 1, sizeof(attr) - 1, "E=%d R=0 V=3", mserr);
1015 		radius_put_vs_raw_attr(resp, RADIUS_VENDOR_MICROSOFT,
1016 		    RADIUS_VTYPE_MS_CHAP_ERROR, attr, strlen(attr + 1) + 1);
1017 	}
1018 
1019 	module_resdeco_done(self->base, q_id, radius_get_data(resp),
1020 	    radius_get_length(resp));
1021 	radius_delete_packet(resp);
1022 }
1023 
1024 /***********************************************************************
1025  * RADIUS Accounting
1026  ***********************************************************************/
1027 void
1028 ipcp_accounting_request(void *ctx, u_int q_id, const u_char *pkt,
1029     size_t pktlen)
1030 {
1031 	RADIUS_PACKET		*radpkt = NULL;
1032 	int			 code, af;
1033 	uint32_t		 type, delay, uval;
1034 	struct in_addr		 addr4, nas_ipv4;
1035 	struct in6_addr		 nas_ipv6, ipv6_zero;
1036 	struct module_ipcp	*self = ctx;
1037 	struct assigned_ipv4	*assign, *assignt;
1038 	char			 username[256], nas_id[256], buf[256],
1039 				    buf1[384];
1040 	struct timespec		 dur;
1041 	struct radiusd_ipcp_statistics
1042 				 stat;
1043 	struct module_ipcp_dae	*dae;
1044 
1045 	ipcp_update_time(self);
1046 
1047 	if ((radpkt = radius_convert_packet(pkt, pktlen)) == NULL) {
1048 		log_warn("%s: radius_convert_packet() failed", __func__);
1049 		module_stop(self->base);
1050 		return;
1051 	}
1052 	code = radius_get_code(radpkt);
1053 	if (code != RADIUS_CODE_ACCOUNTING_REQUEST &&
1054 	    code != RADIUS_CODE_ACCOUNTING_RESPONSE)
1055 		goto out;
1056 
1057 	if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_STATUS_TYPE, &type)
1058 	    != 0)
1059 		goto out;
1060 
1061 	/* identifier for the NAS */
1062 	memset(&ipv6_zero, 0, sizeof(ipv6_zero));
1063 	memset(&nas_ipv4, 0, sizeof(nas_ipv4));
1064 	memset(&nas_ipv6, 0, sizeof(nas_ipv6));
1065 	memset(&nas_id, 0, sizeof(nas_id));
1066 
1067 	radius_get_ipv4_attr(radpkt, RADIUS_TYPE_NAS_IP_ADDRESS, &nas_ipv4);
1068 	radius_get_ipv6_attr(radpkt, RADIUS_TYPE_NAS_IPV6_ADDRESS, &nas_ipv6);
1069 	radius_get_string_attr(radpkt, RADIUS_TYPE_NAS_IDENTIFIER, nas_id,
1070 	    sizeof(nas_id));
1071 
1072 	if (nas_ipv4.s_addr == 0 && IN6_ARE_ADDR_EQUAL(&nas_ipv6, &ipv6_zero) &&
1073 	    nas_id[0] == '\0') {
1074 		log_warnx("q=%u no NAS-IP-Address, NAS-IPV6-Address, or "
1075 		    "NAS-Identifier", q_id);
1076 		goto out;
1077 	}
1078 
1079 	if (type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON ||
1080 	    type == RADIUS_ACCT_STATUS_TYPE_ACCT_OFF) {
1081 		/*
1082 		 * NAS or daemon is restarted.  Delete all assigned records
1083 		 * from it
1084 		 */
1085 		RB_FOREACH_SAFE(assign, assigned_ipv4_tree, &self->ipv4s,
1086 		    assignt) {
1087 			if (assign->nas_ipv4.s_addr != nas_ipv4.s_addr ||
1088 			    !IN6_ARE_ADDR_EQUAL(&assign->nas_ipv6, &nas_ipv6) ||
1089 			    strcmp(assign->nas_id, nas_id) != 0)
1090 				continue;
1091 			log_info("q=%u Delete record for %s", q_id,
1092 			    inet_ntop(AF_INET, &assign->ipv4, buf,
1093 			    sizeof(buf)));
1094 			ipcp_ipv4_delete(self, assign,
1095 			    (type == RADIUS_ACCT_STATUS_TYPE_ACCT_ON)
1096 			    ? "Receive Acct-On" : "Receive Acct-Off");
1097 		}
1098 		return;
1099 	}
1100 
1101 	if (radius_get_ipv4_attr(radpkt, RADIUS_TYPE_FRAMED_IP_ADDRESS, &addr4)
1102 	    != 0) {
1103 		log_warnx("q=%u no Framed-IP-Address-Address attribute", q_id);
1104 		goto out;
1105 	}
1106 	if (radius_get_string_attr(radpkt, RADIUS_TYPE_USER_NAME, username,
1107 	    sizeof(username)) != 0) {
1108 		log_warnx("q=%u no User-Name attribute", q_id);
1109 		goto out;
1110 	}
1111 	if ((assign = ipcp_ipv4_find(self, addr4)) == NULL) {
1112 		/* not assigned by this */
1113 		log_warnx("q=%u %s is not assigned by us", q_id,
1114 		    inet_ntop(AF_INET, &addr4, buf, sizeof(buf)));
1115 		goto out;
1116 	}
1117 
1118 	if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_DELAY_TIME, &delay)
1119 	    != 0)
1120 		delay = 0;
1121 
1122 	if (type == RADIUS_ACCT_STATUS_TYPE_START) {
1123 		assign->start = self->uptime;
1124 		assign->start.tv_sec -= delay;
1125 
1126 		if (!self->no_session_timeout && (self->session_timeout > 0 ||
1127 		    assign->session_timeout > 0)) {
1128 			assign->timeout = assign->start;
1129 			if (self->session_timeout > 0)
1130 				assign->timeout.tv_sec += self->session_timeout;
1131 			else
1132 				assign->timeout.tv_sec +=
1133 				    assign->session_timeout;
1134 		}
1135 		assign->nas_ipv4 = nas_ipv4;
1136 		assign->nas_ipv6 = nas_ipv6;
1137 		strlcpy(assign->nas_id, nas_id, sizeof(assign->nas_id));
1138 
1139 		if (radius_get_string_attr(radpkt, RADIUS_TYPE_ACCT_SESSION_ID,
1140 		    assign->session_id, sizeof(assign->session_id)) != 0)
1141 			assign->session_id[0] = '\0';
1142 		if (radius_get_uint32_attr(radpkt, RADIUS_TYPE_TUNNEL_TYPE,
1143 		    &uval) == 0)
1144 			assign->tun_type = radius_tunnel_type_string(uval,
1145 			    NULL);
1146 		if (assign->tun_type == NULL)
1147 			assign->tun_type = "";
1148 
1149 		/*
1150 		 * Get "tunnel from" from Tunnel-Client-Endpoint or Calling-
1151 		 * Station-Id
1152 		 */
1153 		af = AF_UNSPEC;
1154 		if (radius_get_string_attr(radpkt,
1155 		    RADIUS_TYPE_TUNNEL_CLIENT_ENDPOINT, buf, sizeof(buf)) == 0)
1156 		    {
1157 			if (radius_get_uint32_attr(radpkt,
1158 			    RADIUS_TYPE_TUNNEL_MEDIUM_TYPE, &uval) == 0) {
1159 				if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV4)
1160 					af = AF_INET;
1161 				else if (uval == RADIUS_TUNNEL_MEDIUM_TYPE_IPV6)
1162 					af = AF_INET6;
1163 			}
1164 			parse_addr(buf, af, (struct sockaddr *)
1165 			    &assign->tun_client, sizeof(assign->tun_client));
1166 		}
1167 		if (assign->tun_client.sin4.sin_family == 0 &&
1168 		    radius_get_string_attr(radpkt,
1169 		    RADIUS_TYPE_CALLING_STATION_ID, buf, sizeof(buf)) == 0)
1170 			parse_addr(buf, af, (struct sockaddr *)
1171 			    &assign->tun_client, sizeof(assign->tun_client));
1172 
1173 		TAILQ_FOREACH(dae, &self->daes, next) {
1174 			if (dae->nas_id[0] == '\0' ||
1175 			    strcmp(dae->nas_id, assign->nas_id) == 0)
1176 				break;
1177 		}
1178 		assign->dae = dae;
1179 
1180 		ipcp_put_db(self, assign);
1181 		ipcp_schedule_timer(self);
1182 
1183 		if (ipcp_notice_startstop(self, assign, 1, NULL) != 0)
1184 			goto fail;
1185 		log_info("q=%u Start seq=%u user=%s duration=%dsec "
1186 		    "session=%s tunnel=%s from=%s auth=%s ip=%s", q_id,
1187 		    assign->seq, assign->user->name, delay, assign->session_id,
1188 		    assign->tun_type, print_addr((struct sockaddr *)
1189 		    &assign->tun_client, buf1, sizeof(buf1)),
1190 		    assign->auth_method, inet_ntop(AF_INET, &addr4, buf,
1191 		    sizeof(buf)));
1192 	} else if (type == RADIUS_ACCT_STATUS_TYPE_STOP) {
1193 		memset(&stat, 0, sizeof(stat));
1194 
1195 		dur = self->uptime;
1196 		dur.tv_sec -= delay;
1197 		timespecsub(&dur, &assign->start, &dur);
1198 
1199 		if (radius_get_uint32_attr(radpkt,
1200 		    RADIUS_TYPE_ACCT_INPUT_OCTETS, &uval) == 0)
1201 			stat.ibytes = uval;
1202 		if (radius_get_uint32_attr(radpkt,
1203 		    RADIUS_TYPE_ACCT_INPUT_GIGAWORDS, &uval) == 0)
1204 			stat.ibytes = ((uint64_t)uval << 32) | stat.ibytes;
1205 		if (radius_get_uint32_attr(radpkt,
1206 		    RADIUS_TYPE_ACCT_OUTPUT_OCTETS, &uval) == 0)
1207 			stat.obytes = uval;
1208 		if (radius_get_uint32_attr(radpkt,
1209 		    RADIUS_TYPE_ACCT_OUTPUT_GIGAWORDS, &uval) == 0)
1210 			stat.obytes = ((uint64_t)uval << 32) | stat.obytes;
1211 		radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_INPUT_PACKETS,
1212 		    &stat.ipackets);
1213 		radius_get_uint32_attr(radpkt, RADIUS_TYPE_ACCT_OUTPUT_PACKETS,
1214 		    &stat.opackets);
1215 
1216 		if (radius_get_uint32_attr(radpkt,
1217 		    RADIUS_TYPE_ACCT_TERMINATE_CAUSE, &uval) == 0)
1218 			strlcpy(stat.cause, radius_terminate_cause_string(uval),
1219 			    sizeof(stat.cause));
1220 
1221 		log_info("q=%u Stop seq=%u user=%s duration=%lldsec "
1222 		    "session=%s tunnel=%s from=%s auth=%s ip=%s "
1223 		    "datain=%"PRIu64"bytes,%" PRIu32"packets dataout=%"PRIu64
1224 		    "bytes,%"PRIu32"packets cause=\"%s\"", q_id,
1225 		    assign->seq, assign->user->name, dur.tv_sec,
1226 		    assign->session_id, assign->tun_type, print_addr(
1227 		    (struct sockaddr *)&assign->tun_client, buf1, sizeof(buf1)),
1228 		    assign->auth_method, inet_ntop(AF_INET, &addr4, buf,
1229 		    sizeof(buf)), stat.ibytes, stat.ipackets, stat.obytes,
1230 		    stat.opackets, stat.cause);
1231 
1232 		ipcp_del_db(self, assign);
1233 		if (ipcp_notice_startstop(self, assign, 0, &stat) != 0)
1234 			goto fail;
1235 		ipcp_ipv4_release(self, ipcp_ipv4_find(self, addr4));
1236 	}
1237  out:
1238 	radius_delete_packet(radpkt);
1239 	return;
1240  fail:
1241 	module_stop(self->base);
1242 	radius_delete_packet(radpkt);
1243 	return;
1244 }
1245 
1246 /***********************************************************************
1247  * On memory database to manage IP address assignment
1248  ***********************************************************************/
1249 struct assigned_ipv4 *
1250 ipcp_ipv4_assign(struct module_ipcp *self, struct user *user,
1251     struct in_addr ina)
1252 {
1253 	struct assigned_ipv4 *ip;
1254 
1255 	ip = calloc(1, sizeof(struct assigned_ipv4));
1256 	if (ip == NULL) {
1257 		log_warn("%s: calloc()", __func__);
1258 		return (NULL);
1259 	}
1260 	ip->ipv4 = ina;
1261 	ip->user = user;
1262 	ip->authtime = self->uptime;
1263 	RB_INSERT(assigned_ipv4_tree, &self->ipv4s, ip);
1264 	TAILQ_INSERT_TAIL(&user->ipv4s, ip, next);
1265 	TAILQ_INIT(&ip->dae_clients);
1266 	self->nsessions++;
1267 	ip->seq = self->seq++;
1268 
1269 	return (ip);
1270 }
1271 
1272 struct assigned_ipv4 *
1273 ipcp_ipv4_find(struct module_ipcp *self, struct in_addr ina)
1274 {
1275 	struct assigned_ipv4	 key, *ret;
1276 	struct timespec		 dif;
1277 
1278 	key.ipv4 = ina;
1279 	ret = RB_FIND(assigned_ipv4_tree, &self->ipv4s, &key);
1280 	if (ret != NULL && ret->start.tv_sec == 0) {
1281 		/* not yet assigned */
1282 		timespecsub(&self->uptime, &ret->authtime, &dif);
1283 		if (dif.tv_sec >= self->start_wait) {
1284 			/* assumed NAS finally didn't use the address */
1285 			TAILQ_REMOVE(&ret->user->ipv4s, ret, next);
1286 			RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, ret);
1287 			free(ret);
1288 			ret = NULL;
1289 			self->nsessions--;
1290 		}
1291 	}
1292 	return (ret);
1293 }
1294 
1295 void
1296 ipcp_ipv4_delete(struct module_ipcp *self, struct assigned_ipv4 *assign,
1297     const char *cause)
1298 {
1299 	struct radiusd_ipcp_statistics stat;
1300 
1301 	memset(&stat, 0, sizeof(stat));
1302 	strlcpy(stat.cause, cause, sizeof(stat.cause));
1303 
1304 	ipcp_del_db(self, assign);
1305 	ipcp_notice_startstop(self, assign, 0, &stat);
1306 	ipcp_ipv4_release(self, assign);
1307 }
1308 
1309 void
1310 ipcp_ipv4_release(struct module_ipcp *self, struct assigned_ipv4 *assign)
1311 {
1312 	if (assign != NULL) {
1313 		TAILQ_REMOVE(&assign->user->ipv4s, assign, next);
1314 		RB_REMOVE(assigned_ipv4_tree, &self->ipv4s, assign);
1315 		self->nsessions--;
1316 		ipcp_dae_reset_request(assign);
1317 		free(assign);
1318 	}
1319 }
1320 
1321 int
1322 assigned_ipv4_compar(struct assigned_ipv4 *a, struct assigned_ipv4 *b)
1323 {
1324 	if (a->ipv4.s_addr > b->ipv4.s_addr)
1325 		return (1);
1326 	else if (a->ipv4.s_addr < b->ipv4.s_addr)
1327 		return (-1);
1328 	return (0);
1329 }
1330 
1331 struct user *
1332 ipcp_user_get(struct module_ipcp *self, const char *username)
1333 {
1334 	struct {
1335 		struct user	 user;
1336 		char		 name[256];
1337 	} key;
1338 	struct user		*elm;
1339 
1340 	strlcpy(key.user.name, username, 256);
1341 	elm = RB_FIND(user_tree, &self->users, &key.user);
1342 	if (elm == NULL) {
1343 		if ((elm = calloc(1, offsetof(struct user, name[
1344 		    strlen(username) + 1]))) == NULL)
1345 			return (NULL);
1346 		memcpy(elm->name, username, strlen(username));
1347 		RB_INSERT(user_tree, &self->users, elm);
1348 		TAILQ_INIT(&elm->ipv4s);
1349 	}
1350 
1351 	return (elm);
1352 }
1353 
1354 int
1355 user_compar(struct user *a, struct user *b)
1356 {
1357 	return (strcmp(a->name, b->name));
1358 }
1359 
1360 RB_GENERATE_STATIC(assigned_ipv4_tree, assigned_ipv4, tree,
1361     assigned_ipv4_compar);
1362 RB_GENERATE_STATIC(user_tree, user, tree, user_compar);
1363 
1364 /***********************************************************************
1365  * DB for the persistent over processes
1366  ***********************************************************************/
1367 int
1368 ipcp_prepare_db(void)
1369 {
1370 	struct passwd	*pw;
1371 	DB		*db;
1372 
1373 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_CREAT | O_RDWR | O_EXLOCK,
1374 	    0600, DB_BTREE, NULL)) == NULL)
1375 		return (-1);
1376 	if ((pw = getpwnam(RADIUSD_USER)) == NULL)
1377 		return (-1);
1378 	fchown(db->fd(db), pw->pw_uid, pw->pw_gid);
1379 	db->close(db);
1380 
1381 	return (0);
1382 }
1383 
1384 int
1385 ipcp_restore_from_db(struct module_ipcp *self)
1386 {
1387 	DB			*db;
1388 	DBT			 key, val;
1389 	char			 keybuf[128];
1390 	struct user		*user;
1391 	struct radiusd_ipcp_db_record
1392 				*record;
1393 	struct assigned_ipv4	*assigned;
1394 	struct in_addr		 ipv4;
1395 	struct module_ipcp_dae	*dae;
1396 
1397 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDONLY | O_SHLOCK, 0600,
1398 	    DB_BTREE, NULL)) == NULL)
1399 		return (-1);
1400 
1401 	key.data = "ipv4/";
1402 	key.size = 5;
1403 	if (db->seq(db, &key, &val, R_CURSOR) == 0) {
1404 		do {
1405 			if (key.size >= sizeof(keybuf))
1406 				break;
1407 			memcpy(keybuf, key.data, key.size);
1408 			keybuf[key.size] = '\0';
1409 			if (strncmp(keybuf, "ipv4/", 5) != 0)
1410 				break;
1411 			inet_pton(AF_INET, keybuf + 5, &ipv4);
1412 			record = (struct radiusd_ipcp_db_record *)val.data;
1413 			if ((user = ipcp_user_get(self, record->username))
1414 			    == NULL)
1415 				return (-1);
1416 			if ((assigned = ipcp_ipv4_assign(self, user, ipv4))
1417 			    == NULL)
1418 				return (-1);
1419 			assigned->seq = record->seq;
1420 			self->seq = MAXIMUM(assigned->seq + 1, self->seq);
1421 			strlcpy(assigned->auth_method, record->auth_method,
1422 			    sizeof(assigned->auth_method));
1423 			strlcpy(assigned->session_id, record->session_id,
1424 			    sizeof(assigned->session_id));
1425 			assigned->start = record->start;
1426 			assigned->timeout = record->timeout;
1427 			assigned->nas_ipv4 = record->nas_ipv4;
1428 			assigned->nas_ipv6 = record->nas_ipv6;
1429 			strlcpy(assigned->nas_id, record->nas_id,
1430 			    sizeof(assigned->nas_id));
1431 			assigned->tun_type = radius_tunnel_type_string(0,
1432 			    record->tun_type);
1433 			memcpy(&assigned->tun_client, &record->tun_client,
1434 			    sizeof(assigned->tun_client));
1435 
1436 			TAILQ_FOREACH(dae, &self->daes, next) {
1437 				if (dae->nas_id[0] == '\0' ||
1438 				    strcmp(dae->nas_id, assigned->nas_id) == 0)
1439 					break;
1440 			}
1441 			assigned->dae = dae;
1442 		} while (db->seq(db, &key, &val, R_NEXT) == 0);
1443 	}
1444 	db->close(db);
1445 
1446 	return (0);
1447 }
1448 
1449 void
1450 ipcp_put_db(struct module_ipcp *self, struct assigned_ipv4 *assigned)
1451 {
1452 	DB			*db;
1453 	DBT			 key, val;
1454 	char			 keybuf[128];
1455 	struct radiusd_ipcp_db_record
1456 				 record;
1457 
1458 	strlcpy(keybuf, "ipv4/", sizeof(keybuf));
1459 	inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5);
1460 	key.data = keybuf;
1461 	key.size = strlen(keybuf);
1462 	strlcpy(record.session_id, assigned->session_id,
1463 	    sizeof(record.session_id));
1464 	strlcpy(record.auth_method, assigned->auth_method,
1465 	    sizeof(record.auth_method));
1466 	strlcpy(record.username, assigned->user->name, sizeof(record.username));
1467 	record.seq = assigned->seq;
1468 	record.start = assigned->start;
1469 	record.timeout = assigned->timeout;
1470 	record.nas_ipv4 = assigned->nas_ipv4;
1471 	record.nas_ipv6 = assigned->nas_ipv6;
1472 	strlcpy(record.nas_id, assigned->nas_id, sizeof(record.nas_id));
1473 	if (assigned->tun_type != NULL)
1474 		strlcpy(record.tun_type, assigned->tun_type,
1475 		    sizeof(record.tun_type));
1476 	memcpy(&record.tun_client, &assigned->tun_client,
1477 	    sizeof(record.tun_client));
1478 
1479 	val.data = &record;
1480 	val.size = sizeof(record);
1481 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600,
1482 	    DB_BTREE, NULL)) == NULL)
1483 		return;
1484 	db->put(db, &key, &val, 0);
1485 	db->close(db);
1486 }
1487 
1488 void
1489 ipcp_del_db(struct module_ipcp *self, struct assigned_ipv4 *assigned)
1490 {
1491 	DB			*db;
1492 	DBT			 key;
1493 	char			 keybuf[128];
1494 
1495 	strlcpy(keybuf, "ipv4/", sizeof(keybuf));
1496 	inet_ntop(AF_INET, &assigned->ipv4, keybuf + 5, sizeof(keybuf) - 5);
1497 	key.data = keybuf;
1498 	key.size = strlen(keybuf);
1499 
1500 	if ((db = dbopen(_PATH_RADIUSD_IPCP_DB, O_RDWR | O_EXLOCK, 0600,
1501 	    DB_BTREE, NULL)) == NULL)
1502 		return;
1503 	db->del(db, &key, 0);
1504 	db->close(db);
1505 }
1506 
1507 void
1508 ipcp_db_dump_fill_record(struct radiusd_ipcp_db_dump *dump, int idx,
1509     struct assigned_ipv4 *assign)
1510 {
1511 	dump->records[idx].af = AF_INET;
1512 	dump->records[idx].addr.ipv4 = assign->ipv4;
1513 	dump->records[idx].rec.seq = assign->seq;
1514 	strlcpy(dump->records[idx].rec.session_id, assign->session_id,
1515 	    sizeof(dump->records[idx].rec.session_id));
1516 	strlcpy(dump->records[idx].rec.auth_method, assign->auth_method,
1517 	    sizeof(dump->records[idx].rec.auth_method));
1518 	strlcpy(dump->records[idx].rec.username, assign->user->name,
1519 	    sizeof(dump->records[idx].rec.username));
1520 	dump->records[idx].rec.start = assign->start;
1521 	dump->records[idx].rec.timeout = assign->timeout;
1522 	dump->records[idx].rec.nas_ipv4 = assign->nas_ipv4;
1523 	dump->records[idx].rec.nas_ipv6 = assign->nas_ipv6;
1524 	strlcpy(dump->records[idx].rec.nas_id, assign->nas_id,
1525 	    sizeof(dump->records[idx].rec.nas_id));
1526 	if (assign->tun_type != NULL)
1527 		strlcpy(dump->records[idx].rec.tun_type, assign->tun_type,
1528 		    sizeof(dump->records[idx].rec.tun_type));
1529 	memcpy(&dump->records[idx].rec.tun_client, &assign->tun_client,
1530 	    sizeof(dump->records[idx].rec.tun_client));
1531 }
1532 
1533 /***********************************************************************
1534  * Timer
1535  ***********************************************************************/
1536 void
1537 ipcp_update_time(struct module_ipcp *self)
1538 {
1539 	clock_gettime(CLOCK_BOOTTIME, &self->uptime);
1540 }
1541 
1542 void
1543 ipcp_on_timer(int fd, short ev, void *ctx)
1544 {
1545 	struct module_ipcp *self = ctx;
1546 
1547 	ipcp_update_time(self);
1548 	ipcp_schedule_timer(self);
1549 }
1550 
1551 void
1552 ipcp_schedule_timer(struct module_ipcp *self)
1553 {
1554 	struct assigned_ipv4	*assign, *min_assign = NULL;
1555 	struct timespec		 tsd;
1556 	struct timeval		 tv;
1557 
1558 	/* check session timeout */
1559 	RB_FOREACH(assign, assigned_ipv4_tree, &self->ipv4s) {
1560 		if (assign->timeout.tv_sec == 0)
1561 			continue;
1562 		if (timespeccmp(&assign->timeout, &self->uptime, <=)) {
1563 			log_info("Reached session timeout seq=%u", assign->seq);
1564 			ipcp_dae_send_disconnect_request(assign);
1565 			memset(&assign->timeout, 0, sizeof(assign->timeout));
1566 			ipcp_put_db(self, assign);
1567 		}
1568 		if (min_assign == NULL ||
1569 		    timespeccmp(&min_assign->timeout, &assign->timeout, >))
1570 			min_assign = assign;
1571 	}
1572 	if (evtimer_pending(&self->ev_timer, NULL))
1573 		evtimer_del(&self->ev_timer);
1574 
1575 	if (min_assign != NULL) {
1576 		timespecsub(&min_assign->timeout, &self->uptime, &tsd);
1577 		TIMESPEC_TO_TIMEVAL(&tv, &tsd);
1578 		evtimer_set(&self->ev_timer, ipcp_on_timer, self);
1579 		evtimer_add(&self->ev_timer, &tv);
1580 	}
1581 }
1582 
1583 /***********************************************************************
1584  * Dynamic Authorization Extension for RAIDUS (RFC 5176)
1585  ***********************************************************************/
1586 static const int dae_request_timeouts[] = { 2, 4, 8, 8 };
1587 
1588 void
1589 ipcp_dae_send_disconnect_request(struct assigned_ipv4 *assign)
1590 {
1591 	RADIUS_PACKET		*reqpkt = NULL;
1592 	struct timeval		 tv;
1593 	char			 buf[80];
1594 
1595 	if (assign->dae == NULL)
1596 		return;		/* DAE is not configured */
1597 
1598 	if (assign->dae_reqpkt == NULL) {
1599 		if ((reqpkt = radius_new_request_packet(
1600 		    RADIUS_CODE_DISCONNECT_REQUEST)) == NULL) {
1601 			log_warn("%s: radius_new_request_packet(): %m",
1602 			    __func__);
1603 			return;
1604 		}
1605 		radius_put_string_attr(reqpkt, RADIUS_TYPE_ACCT_SESSION_ID,
1606 		    assign->session_id);
1607 		/*
1608 		 * RFC 5176 Section 3, "either the User-Name or
1609 		 * Chargeable-User-Identity attribute SHOULD be present in
1610 		 * Disconnect-Request and CoA-Request packets."
1611 		 */
1612 		radius_put_string_attr(reqpkt, RADIUS_TYPE_USER_NAME,
1613 		    assign->user->name);
1614 		if (assign->nas_id[0] != '\0')
1615 			radius_put_string_attr(reqpkt,
1616 			    RADIUS_TYPE_NAS_IDENTIFIER, assign->nas_id);
1617 		if (ntohl(assign->nas_ipv4.s_addr) != 0)
1618 			radius_put_ipv4_attr(reqpkt,
1619 			    RADIUS_TYPE_NAS_IP_ADDRESS, assign->nas_ipv4);
1620 		if (!IN6_IS_ADDR_UNSPECIFIED(&assign->nas_ipv6))
1621 			radius_put_ipv6_attr(reqpkt,
1622 			    RADIUS_TYPE_NAS_IPV6_ADDRESS, &assign->nas_ipv6);
1623 		radius_set_accounting_request_authenticator(reqpkt,
1624 		    assign->dae->secret);
1625 		assign->dae_reqpkt = reqpkt;
1626 		TAILQ_INSERT_TAIL(&assign->dae->reqs, assign, dae_next);
1627 	}
1628 
1629 	if (assign->dae_ntry == 0) {
1630 		if (assign->dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT)
1631 			return;
1632 		log_info("Sending Disconnect-Request seq=%u to %s",
1633 		    assign->seq, print_addr((struct sockaddr *)
1634 		    &assign->dae->nas_addr, buf, sizeof(buf)));
1635 	}
1636 
1637 	if (radius_send(assign->dae->sock, assign->dae_reqpkt, 0) < 0)
1638 		log_warn("%s: sendto: %m", __func__);
1639 
1640 	tv.tv_sec = dae_request_timeouts[assign->dae_ntry];
1641 	tv.tv_usec = 0;
1642 	evtimer_set(&assign->dae_evtimer, ipcp_dae_request_on_timeout, assign);
1643 	evtimer_add(&assign->dae_evtimer, &tv);
1644 	if (assign->dae_ntry == 0)
1645 		assign->dae->ninflight++;
1646 	assign->dae_ntry++;
1647 }
1648 
1649 void
1650 ipcp_dae_request_on_timeout(int fd, short ev, void *ctx)
1651 {
1652 	struct assigned_ipv4	*assign = ctx;
1653 	char			 buf[80];
1654 	struct radiusctl_client	*client;
1655 
1656 	if (assign->dae_ntry >= (int)nitems(dae_request_timeouts)) {
1657 		log_warnx("No answer for Disconnect-Request seq=%u from %s",
1658 		    assign->seq, print_addr((struct sockaddr *)
1659 		    &assign->dae->nas_addr, buf, sizeof(buf)));
1660 		TAILQ_FOREACH(client, &assign->dae_clients, entry)
1661 			module_imsg_compose(assign->dae->ipcp->base, IMSG_NG,
1662 			    client->peerid, 0, -1, NULL, 0);
1663 		ipcp_dae_reset_request(assign);
1664 	} else
1665 		ipcp_dae_send_disconnect_request(assign);
1666 }
1667 
1668 void
1669 ipcp_dae_on_event(int fd, short ev, void *ctx)
1670 {
1671 	struct module_ipcp_dae	*dae = ctx;
1672 	struct module_ipcp	*self = dae->ipcp;
1673 	RADIUS_PACKET		*radres = NULL;
1674 	int			 code;
1675 	uint32_t		 u32;
1676 	struct assigned_ipv4	*assign;
1677 	char			 buf[80], causestr[80];
1678 	const char		*cause = "";
1679 	struct radiusctl_client	*client;
1680 
1681 	ipcp_update_time(self);
1682 
1683 	if ((ev & EV_READ) == 0)
1684 		return;
1685 
1686 	if ((radres = radius_recv(dae->sock, 0)) == NULL) {
1687 		if (errno == EAGAIN)
1688 			return;
1689 		log_warn("%s: Failed to receive from %s", __func__, print_addr(
1690 		    (struct sockaddr *)&dae->nas_addr, buf, sizeof(buf)));
1691 		return;
1692 	}
1693 	TAILQ_FOREACH(assign, &dae->reqs, dae_next) {
1694 		if (radius_get_id(assign->dae_reqpkt) == radius_get_id(radres))
1695 			break;
1696 	}
1697 	if (assign == NULL) {
1698 		log_warnx("%s: Received RADIUS packet from %s has unknown "
1699 		    "id=%d", __func__, print_addr((struct sockaddr *)
1700 		    &dae->nas_addr, buf, sizeof(buf)), radius_get_id(radres));
1701 		goto out;
1702 	}
1703 
1704 	radius_set_request_packet(radres, assign->dae_reqpkt);
1705 	if ((radius_check_response_authenticator(radres, dae->secret)) != 0) {
1706 		log_warnx("%s: Received RADIUS packet for seq=%u from %s has "
1707 		    "a bad authenticator", __func__, assign->seq, print_addr(
1708 			(struct sockaddr *)&dae->nas_addr, buf,
1709 		    sizeof(buf)));
1710 		goto out;
1711 	}
1712 	causestr[0] = '\0';
1713 	if (radius_get_uint32_attr(radres, RADIUS_TYPE_ERROR_CAUSE, &u32) == 0){
1714 		cause = radius_error_cause_string(u32);
1715 		if (cause != NULL)
1716 			snprintf(causestr, sizeof(causestr), " cause=%u(%s)",
1717 			    u32, cause);
1718 		else
1719 			snprintf(causestr, sizeof(causestr), " cause=%u", u32);
1720 		cause = causestr;
1721 	}
1722 
1723 	code = radius_get_code(radres);
1724 	switch (code) {
1725 	case RADIUS_CODE_DISCONNECT_ACK:
1726 		log_info("Received Disconnect-ACK for seq=%u from %s%s",
1727 		    assign->seq, print_addr((struct sockaddr *)
1728 		    &dae->nas_addr, buf, sizeof(buf)), cause);
1729 		break;
1730 	case RADIUS_CODE_DISCONNECT_NAK:
1731 		log_info("Received Disconnect-NAK for seq=%u from %s%s",
1732 		    assign->seq, print_addr((struct sockaddr *)
1733 		    &dae->nas_addr, buf, sizeof(buf)), cause);
1734 		break;
1735 	default:
1736 		log_warn("%s: Received unknown code=%d for id=%u from %s",
1737 		    __func__, code, assign->seq, print_addr((struct sockaddr *)
1738 		    &dae->nas_addr, buf, sizeof(buf)));
1739 		break;
1740 	}
1741 
1742 	TAILQ_FOREACH(client, &assign->dae_clients, entry) {
1743 		if (*cause != '\0')
1744 			module_imsg_compose(self->base,
1745 			    (code == RADIUS_CODE_DISCONNECT_ACK)
1746 			    ? IMSG_OK : IMSG_NG, client->peerid, 0, -1,
1747 			    cause + 1, strlen(cause + 1) + 1);
1748 		else
1749 			module_imsg_compose(self->base,
1750 			    (code == RADIUS_CODE_DISCONNECT_ACK)
1751 			    ? IMSG_OK : IMSG_NG, client->peerid, 0, -1,
1752 			    NULL, 0);
1753 	}
1754 	ipcp_dae_reset_request(assign);
1755  out:
1756 	if (radres != NULL)
1757 		radius_delete_packet(radres);
1758 }
1759 
1760 void
1761 ipcp_dae_reset_request(struct assigned_ipv4 *assign)
1762 {
1763 	struct radiusctl_client		*client, *clientt;
1764 	const struct timeval		 zero = { 0, 0 };
1765 
1766 	if (assign->dae != NULL) {
1767 		if (assign->dae_reqpkt != NULL)
1768 			TAILQ_REMOVE(&assign->dae->reqs, assign, dae_next);
1769 		if (assign->dae_ntry > 0) {
1770 			assign->dae->ninflight--;
1771 			if (!evtimer_pending(&assign->dae->ev_reqs, NULL))
1772 				evtimer_add(&assign->dae->ev_reqs, &zero);
1773 		}
1774 	}
1775 	if (assign->dae_reqpkt != NULL)
1776 		radius_delete_packet(assign->dae_reqpkt);
1777 	assign->dae_reqpkt = NULL;
1778 	if (evtimer_pending(&assign->dae_evtimer, NULL))
1779 		evtimer_del(&assign->dae_evtimer);
1780 	TAILQ_FOREACH_SAFE(client, &assign->dae_clients, entry, clientt) {
1781 		TAILQ_REMOVE(&assign->dae_clients, client, entry);
1782 		free(client);
1783 	}
1784 	assign->dae_ntry = 0;
1785 }
1786 
1787 void
1788 ipcp_dae_send_pending_requests(int fd, short ev, void *ctx)
1789 {
1790 	struct module_ipcp_dae	*dae = ctx;
1791 	struct module_ipcp	*self = dae->ipcp;
1792 	struct assigned_ipv4	*assign, *assignt;
1793 
1794 	ipcp_update_time(self);
1795 
1796 	TAILQ_FOREACH_SAFE(assign, &dae->reqs, dae_next, assignt) {
1797 		if (dae->ninflight >= RADIUSD_IPCP_DAE_MAX_INFLIGHT)
1798 			break;
1799 		if (assign->dae_ntry == 0)	/* pending */
1800 			ipcp_dae_send_disconnect_request(assign);
1801 	}
1802 }
1803 
1804 /***********************************************************************
1805  * Miscellaneous functions
1806  ***********************************************************************/
1807 struct ipcp_address *
1808 parse_address_range(const char *range)
1809 {
1810 	char			*buf, *sep;
1811 	int			 masklen;
1812 	uint32_t		 mask;
1813 	struct in_addr		 start, end;
1814 	struct ipcp_address	*ret;
1815 	const char		*errstr;
1816 
1817 	buf = strdup(range);
1818 	if (buf == NULL)
1819 		goto error;
1820 	if ((sep = strchr(buf, '-')) != NULL) {
1821 		*sep = '\0';
1822 		if (inet_pton(AF_INET, buf, &start) != 1)
1823 			goto error;
1824 		else if (inet_pton(AF_INET, ++sep, &end) != 1)
1825 			goto error;
1826 		start.s_addr = ntohl(start.s_addr);
1827 		end.s_addr = ntohl(end.s_addr);
1828 		if (end.s_addr < start.s_addr)
1829 			goto error;
1830 	} else {
1831 		if ((sep = strchr(buf, '/')) != NULL) {
1832 			*sep = '\0';
1833 			if (inet_pton(AF_INET, buf, &start) != 1)
1834 				goto error;
1835 			masklen = strtonum(++sep, 0, 32, &errstr);
1836 			if (errstr != NULL)
1837 				goto error;
1838 		} else {
1839 			if (inet_pton(AF_INET, buf, &start) != 1)
1840 				goto error;
1841 			masklen = 32;
1842 		}
1843 		mask = 0xFFFFFFFFUL;
1844 		if (masklen < 32)
1845 			mask <<= (32 - masklen);
1846 		start.s_addr = ntohl(start.s_addr) & mask;
1847 		if (masklen == 32)
1848 			end = start;
1849 		else if (masklen == 31)
1850 			end.s_addr = start.s_addr + 1;
1851 		else {
1852 			end.s_addr = start.s_addr + (1 << (32 - masklen)) - 2;
1853 			start.s_addr = start.s_addr + 1;
1854 		}
1855 	}
1856 	free(buf);
1857 	if ((ret = calloc(1, sizeof(struct ipcp_address))) == NULL)
1858 		return (NULL);
1859 	ret->start = start;
1860 	ret->end = end;
1861 	ret->naddrs = end.s_addr - start.s_addr + 1;
1862 	return (ret);
1863  error:
1864 	free(buf);
1865 	return (NULL);
1866 }
1867 
1868 const char *
1869 radius_tunnel_type_string(unsigned val, const char *label)
1870 {
1871 	unsigned int		 i;
1872 	struct {
1873 		const unsigned	 constval;
1874 		const char	*label;
1875 	} tunnel_types[] = {
1876 		{ RADIUS_TUNNEL_TYPE_PPTP,	"PPTP" },
1877 		{ RADIUS_TUNNEL_TYPE_L2F,	"L2F" },
1878 		{ RADIUS_TUNNEL_TYPE_L2TP,	"L2TP" },
1879 		{ RADIUS_TUNNEL_TYPE_ATMP,	"ATMP" },
1880 		{ RADIUS_TUNNEL_TYPE_VTP,	"VTP" },
1881 		{ RADIUS_TUNNEL_TYPE_AH,	"AH" },
1882 		{ RADIUS_TUNNEL_TYPE_IP,	"IP" },
1883 		{ RADIUS_TUNNEL_TYPE_MOBILE,	"MIN-IP-IP" },
1884 		{ RADIUS_TUNNEL_TYPE_ESP,	"ESP" },
1885 		{ RADIUS_TUNNEL_TYPE_GRE,	"GRE" },
1886 		{ RADIUS_TUNNEL_TYPE_VDS,	"DVS" },
1887 		/* [MS-RNAS] 3.3.5.1.9 Tunnel-Type */
1888 		{ RADIUS_VENDOR_MICROSOFT << 8 | 1,
1889 						"SSTP" }
1890 	};
1891 
1892 	if (label != NULL) {	/* for conversion to the const value */
1893 		for (i = 0; i < nitems(tunnel_types); i++) {
1894 			if (strcmp(tunnel_types[i].label, label) == 0)
1895 				return (tunnel_types[i].label);
1896 		}
1897 	}
1898 
1899 	for (i = 0; i < nitems(tunnel_types); i++) {
1900 		if (tunnel_types[i].constval == val)
1901 			return (tunnel_types[i].label);
1902 	}
1903 
1904 	return (NULL);
1905 }
1906 
1907 const char *
1908 radius_terminate_cause_string(unsigned val)
1909 {
1910 	unsigned int		 i;
1911 	struct {
1912 		const unsigned	 constval;
1913 		const char	*label;
1914 	} terminate_causes[] = {
1915 	    { RADIUS_TERMNATE_CAUSE_USER_REQUEST,	"User Request" },
1916 	    { RADIUS_TERMNATE_CAUSE_LOST_CARRIER,	"Lost Carrier" },
1917 	    { RADIUS_TERMNATE_CAUSE_LOST_SERVICE,	"Lost Service" },
1918 	    { RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT,	"Idle Timeout" },
1919 	    { RADIUS_TERMNATE_CAUSE_SESSION_TIMEOUT,	"Session Timeout" },
1920 	    { RADIUS_TERMNATE_CAUSE_ADMIN_RESET,	"Admin Reset" },
1921 	    { RADIUS_TERMNATE_CAUSE_ADMIN_REBOOT,	"Admin Reboot" },
1922 	    { RADIUS_TERMNATE_CAUSE_PORT_ERROR,		"Port Error" },
1923 	    { RADIUS_TERMNATE_CAUSE_NAS_ERROR,		"NAS Error" },
1924 	    { RADIUS_TERMNATE_CAUSE_NAS_RESET,		"NAS Request" },
1925 	    { RADIUS_TERMNATE_CAUSE_NAS_REBOOT,		"NAS Reboot" },
1926 	    { RADIUS_TERMNATE_CAUSE_PORT_UNNEEDED,	"Port Unneeded" },
1927 	    { RADIUS_TERMNATE_CAUSE_PORT_PREEMPTED,	"Port Preempted" },
1928 	    { RADIUS_TERMNATE_CAUSE_PORT_SUSPENDED,	"Port Suspended" },
1929 	    { RADIUS_TERMNATE_CAUSE_SERVICE_UNAVAIL,	"Service Unavailable" },
1930 	    { RADIUS_TERMNATE_CAUSE_CALLBACK,		"Callback" },
1931 	    { RADIUS_TERMNATE_CAUSE_USER_ERROR,		"User Error" },
1932 	    { RADIUS_TERMNATE_CAUSE_HOST_REQUEST,	"Host Request" },
1933 	};
1934 
1935 	for (i = 0; i < nitems(terminate_causes); i++) {
1936 		if (terminate_causes[i].constval == val)
1937 			return (terminate_causes[i].label);
1938 	}
1939 
1940 	return (NULL);
1941 }
1942 
1943 const char *
1944 radius_error_cause_string(unsigned val)
1945 {
1946 	unsigned int		 i;
1947 	struct {
1948 		const unsigned	 constval;
1949 		const char	*label;
1950 	} error_causes[] = {
1951 	    { RADIUS_ERROR_CAUSE_RESIDUAL_SESSION_REMOVED,
1952 	      "Residual Session Context Removed" },
1953 	    { RADIUS_ERROR_CAUSE_INVALID_EAP_PACKET,
1954 	      "Invalid EAP Packet (Ignored)" },
1955 	    { RADIUS_ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE,
1956 	      "Unsupported Attribute" },
1957 	    { RADIUS_ERROR_CAUSE_MISSING_ATTRIBUTE,
1958 	      "Missing Attribute" },
1959 	    { RADIUS_ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH,
1960 	      "NAS Identification Mismatch" },
1961 	    { RADIUS_ERROR_CAUSE_INVALID_REQUEST,
1962 	      "Invalid Request" },
1963 	    { RADIUS_ERROR_CAUSE_UNSUPPORTED_SERVICE,
1964 	      "Unsupported Service" },
1965 	    { RADIUS_ERROR_CAUSE_UNSUPPORTED_EXTENSION,
1966 	      "Unsupported Extension" },
1967 	    { RADIUS_ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE,
1968 	      "Invalid Attribute Value" },
1969 	    { RADIUS_ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED,
1970 	      "Administratively Prohibited" },
1971 	    { RADIUS_ERROR_CAUSE_REQUEST_NOT_ROUTABLE,
1972 	      "Request Not Routable (Proxy)" },
1973 	    { RADIUS_ERROR_CAUSE_SESSION_NOT_FOUND,
1974 	      "Session Context Not Found" },
1975 	    { RADIUS_ERROR_CAUSE_SESSION_NOT_REMOVABLE,
1976 	      "Session Context Not Removable" },
1977 	    { RADIUS_ERROR_CAUSE_OTHER_PROXY_PROCESSING_ERROR,
1978 	      "Other Proxy Processing Error" },
1979 	    { RADIUS_ERROR_CAUSE_RESOURCES_UNAVAILABLE,
1980 	      "Resources Unavailable" },
1981 	    { RADIUS_ERROR_CAUSE_REQUEST_INITIATED,
1982 	      "equest Initiated" },
1983 	    { RADIUS_ERROR_CAUSE_MULTI_SELECTION_UNSUPPORTED,
1984 	      "Multiple Session Selection Unsupported" }
1985 	};
1986 
1987 	for (i = 0; i < nitems(error_causes); i++) {
1988 		if (error_causes[i].constval == val)
1989 			return (error_causes[i].label);
1990 	}
1991 
1992 	return (NULL);
1993 }
1994 
1995 int
1996 parse_addr(const char *str0, int af, struct sockaddr *sa, socklen_t salen)
1997 {
1998 	int		 error;
1999 	char		*str, *end, *colon, *colon0, *addr = NULL, *port = NULL;
2000 	char		*sb, *sb0;
2001 	struct addrinfo	 hints, *ai;
2002 
2003 	if ((str = strdup(str0)) == NULL)
2004 		return (-1);
2005 	if (*str == '[' && (end = strchr(str + 1, ']')) != NULL) {
2006 		addr = str + 1;
2007 		*end = '\0';
2008 		if (*(end + 1) == ':')
2009 			port = end + 2;
2010 		else if (*(end + 1) == '[' && (sb = strrchr(end + 2, ']'))
2011 		    != NULL) {
2012 			port = end + 2;
2013 			*sb = '\0';
2014 		}
2015 	} else if ((sb0 = strchr(str, '[')) != NULL &&
2016 	    (sb = strrchr(sb0 + 1, ']')) != NULL && sb0 < sb) {
2017 		addr = str;
2018 		*sb0 = '\0';
2019 		port = sb0 + 1;
2020 		*sb = '\0';
2021 	} else if ((colon0 = strchr(str, ':')) != NULL &&
2022 	    (colon = strrchr(str, ':')) != NULL && colon0 == colon) {
2023 		/* has one : */
2024 		addr = str;
2025 		*colon = '\0';
2026 		port = colon + 1;
2027 	} else {
2028 		addr = str;
2029 		port = NULL;
2030 	}
2031 
2032 	memset(&hints, 0, sizeof(hints));
2033 	hints.ai_family = af;
2034 	hints.ai_socktype = SOCK_DGRAM;
2035 	hints.ai_flags = AI_NUMERICHOST;
2036 	if (port != NULL)
2037 		hints.ai_flags |= AI_NUMERICSERV;
2038 	if ((error = getaddrinfo(addr, port, &hints, &ai)) != 0) {
2039 		free(str);
2040 		return (-1);
2041 	}
2042 	free(str);
2043 	if (salen < ai->ai_addrlen) {
2044 		freeaddrinfo(ai);
2045 		return (-1);
2046 	}
2047 	memcpy(sa, ai->ai_addr, ai->ai_addrlen);
2048 	freeaddrinfo(ai);
2049 
2050 	return (0);
2051 }
2052 
2053 const char *
2054 print_addr(struct sockaddr *sa, char *buf, size_t bufsiz)
2055 {
2056 	int	noport, ret;
2057 	char	hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
2058 
2059 	if (ntohs(((struct sockaddr_in *)sa)->sin_port) == 0) {
2060 		noport = 1;
2061 		ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
2062 		    NI_NUMERICHOST);
2063 	} else {
2064 		noport = 0;
2065 		ret = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
2066 		    sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
2067 	}
2068 	if (ret != 0)
2069 		return "";
2070 	if (noport)
2071 		strlcpy(buf, hbuf, bufsiz);
2072 	else if (sa->sa_family == AF_INET6)
2073 		snprintf(buf, bufsiz, "[%s]:%s", hbuf, sbuf);
2074 	else
2075 		snprintf(buf, bufsiz, "%s:%s", hbuf, sbuf);
2076 
2077 	return (buf);
2078 }
2079