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