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