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