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