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