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