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