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