1 /* 2 * Copyright 1999 Internet Business Solutions Ltd., Switzerland 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 * 28 */ 29 30 #include <sys/param.h> 31 #include <sys/socket.h> 32 #include <netinet/in_systm.h> 33 #include <netinet/in.h> 34 #include <netinet/ip.h> 35 #include <arpa/inet.h> 36 #include <sys/un.h> 37 #include <net/route.h> 38 39 #ifdef LOCALRAD 40 #include "radlib.h" 41 #else 42 #include <radlib.h> 43 #endif 44 45 #include <errno.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <sys/time.h> 50 #include <termios.h> 51 #include <ttyent.h> 52 #include <unistd.h> 53 #include <netdb.h> 54 55 #include "layer.h" 56 #include "defs.h" 57 #include "log.h" 58 #include "descriptor.h" 59 #include "prompt.h" 60 #include "timer.h" 61 #include "fsm.h" 62 #include "iplist.h" 63 #include "slcompress.h" 64 #include "throughput.h" 65 #include "lqr.h" 66 #include "hdlc.h" 67 #include "mbuf.h" 68 #include "ipcp.h" 69 #include "route.h" 70 #include "command.h" 71 #include "filter.h" 72 #include "lcp.h" 73 #include "ccp.h" 74 #include "link.h" 75 #include "mp.h" 76 #include "radius.h" 77 #include "auth.h" 78 #include "async.h" 79 #include "physical.h" 80 #include "chat.h" 81 #include "cbcp.h" 82 #include "chap.h" 83 #include "datalink.h" 84 #include "bundle.h" 85 86 /* 87 * rad_continue_send_request() has given us `got' (non-zero). Deal with it. 88 */ 89 static void 90 radius_Process(struct radius *r, int got) 91 { 92 char *argv[MAXARGS], *nuke; 93 struct bundle *bundle; 94 int argc, addrs; 95 size_t len; 96 struct in_range dest; 97 struct in_addr gw; 98 const void *data; 99 100 r->cx.fd = -1; /* Stop select()ing */ 101 102 switch (got) { 103 case RAD_ACCESS_ACCEPT: 104 log_Printf(LogPHASE, "Radius: ACCEPT received\n"); 105 break; 106 107 case RAD_ACCESS_REJECT: 108 log_Printf(LogPHASE, "Radius: REJECT received\n"); 109 auth_Failure(r->cx.auth); 110 rad_close(r->cx.rad); 111 return; 112 113 case RAD_ACCESS_CHALLENGE: 114 /* we can't deal with this (for now) ! */ 115 log_Printf(LogPHASE, "Radius: CHALLENGE received (can't handle yet)\n"); 116 auth_Failure(r->cx.auth); 117 rad_close(r->cx.rad); 118 return; 119 120 case RAD_ACCOUNTING_RESPONSE: 121 log_Printf(LogPHASE, "Radius: Accounting response received\n"); 122 /* No further processing for accounting requests, please */ 123 rad_close(r->cx.rad); 124 return; 125 126 case -1: 127 log_Printf(LogPHASE, "radius: %s\n", rad_strerror(r->cx.rad)); 128 auth_Failure(r->cx.auth); 129 rad_close(r->cx.rad); 130 return; 131 132 default: 133 log_Printf(LogERROR, "rad_send_request: Failed %d: %s\n", 134 got, rad_strerror(r->cx.rad)); 135 auth_Failure(r->cx.auth); 136 rad_close(r->cx.rad); 137 return; 138 } 139 140 /* So we've been accepted ! Let's see what we've got in our reply :-I */ 141 r->ip.s_addr = r->mask.s_addr = INADDR_NONE; 142 r->mtu = 0; 143 r->vj = 0; 144 while ((got = rad_get_attr(r->cx.rad, &data, &len)) > 0) { 145 switch (got) { 146 case RAD_FRAMED_IP_ADDRESS: 147 r->ip = rad_cvt_addr(data); 148 log_Printf(LogPHASE, " IP %s\n", inet_ntoa(r->ip)); 149 break; 150 151 case RAD_FRAMED_IP_NETMASK: 152 r->mask = rad_cvt_addr(data); 153 log_Printf(LogPHASE, " Netmask %s\n", inet_ntoa(r->mask)); 154 break; 155 156 case RAD_FRAMED_MTU: 157 r->mtu = rad_cvt_int(data); 158 log_Printf(LogPHASE, " MTU %lu\n", r->mtu); 159 break; 160 161 case RAD_FRAMED_ROUTING: 162 /* Disabled for now - should we automatically set up some filters ? */ 163 /* rad_cvt_int(data); */ 164 /* bit 1 = Send routing packets */ 165 /* bit 2 = Receive routing packets */ 166 break; 167 168 case RAD_FRAMED_COMPRESSION: 169 r->vj = rad_cvt_int(data) == 1 ? 1 : 0; 170 log_Printf(LogPHASE, " VJ %sabled\n", r->vj ? "en" : "dis"); 171 break; 172 173 case RAD_FRAMED_ROUTE: 174 /* 175 * We expect a string of the format ``dest[/bits] gw [metrics]'' 176 * Any specified metrics are ignored. MYADDR and HISADDR are 177 * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same 178 * as ``HISADDR''. 179 */ 180 181 if ((nuke = rad_cvt_string(data, len)) == NULL) { 182 log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad)); 183 rad_close(r->cx.rad); 184 return; 185 } 186 187 log_Printf(LogPHASE, " Route: %s\n", nuke); 188 bundle = r->cx.auth->physical->dl->bundle; 189 dest.ipaddr.s_addr = dest.mask.s_addr = INADDR_ANY; 190 dest.width = 0; 191 argc = command_Interpret(nuke, strlen(nuke), argv); 192 if (argc < 0) 193 log_Printf(LogWARN, "radius: %s: Syntax error\n", 194 argc == 1 ? argv[0] : "\"\""); 195 else if (argc < 2) 196 log_Printf(LogWARN, "radius: %s: Invalid route\n", 197 argc == 1 ? argv[0] : "\"\""); 198 else if ((strcasecmp(argv[0], "default") != 0 && 199 !ParseAddr(&bundle->ncp.ipcp, argv[0], &dest.ipaddr, 200 &dest.mask, &dest.width)) || 201 !ParseAddr(&bundle->ncp.ipcp, argv[1], &gw, NULL, NULL)) 202 log_Printf(LogWARN, "radius: %s %s: Invalid route\n", 203 argv[0], argv[1]); 204 else { 205 if (dest.width == 32 && strchr(argv[0], '/') == NULL) 206 /* No mask specified - use the natural mask */ 207 dest.mask = addr2mask(dest.ipaddr); 208 addrs = 0; 209 210 if (!strncasecmp(argv[0], "HISADDR", 7)) 211 addrs = ROUTE_DSTHISADDR; 212 else if (!strncasecmp(argv[0], "MYADDR", 6)) 213 addrs = ROUTE_DSTMYADDR; 214 215 if (gw.s_addr == INADDR_ANY) { 216 addrs |= ROUTE_GWHISADDR; 217 gw = bundle->ncp.ipcp.peer_ip; 218 } else if (strcasecmp(argv[1], "HISADDR") == 0) 219 addrs |= ROUTE_GWHISADDR; 220 221 route_Add(&r->routes, addrs, dest.ipaddr, dest.mask, gw); 222 } 223 free(nuke); 224 break; 225 } 226 } 227 228 if (got == -1) { 229 log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n", 230 rad_strerror(r->cx.rad)); 231 auth_Failure(r->cx.auth); 232 rad_close(r->cx.rad); 233 } else { 234 r->valid = 1; 235 auth_Success(r->cx.auth); 236 rad_close(r->cx.rad); 237 } 238 } 239 240 /* 241 * We've either timed out or select()ed on the read descriptor 242 */ 243 static void 244 radius_Continue(struct radius *r, int sel) 245 { 246 struct timeval tv; 247 int got; 248 249 timer_Stop(&r->cx.timer); 250 if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) { 251 log_Printf(LogPHASE, "Radius: Request re-sent\n"); 252 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 253 timer_Start(&r->cx.timer); 254 return; 255 } 256 257 radius_Process(r, got); 258 } 259 260 /* 261 * Time to call rad_continue_send_request() - timed out. 262 */ 263 static void 264 radius_Timeout(void *v) 265 { 266 radius_Continue((struct radius *)v, 0); 267 } 268 269 /* 270 * Time to call rad_continue_send_request() - something to read. 271 */ 272 static void 273 radius_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 274 { 275 radius_Continue(descriptor2radius(d), 1); 276 } 277 278 /* 279 * Behave as a struct fdescriptor (descriptor.h) 280 */ 281 static int 282 radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 283 { 284 struct radius *rad = descriptor2radius(d); 285 286 if (r && rad->cx.fd != -1) { 287 FD_SET(rad->cx.fd, r); 288 if (*n < rad->cx.fd + 1) 289 *n = rad->cx.fd + 1; 290 log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd); 291 return 1; 292 } 293 294 return 0; 295 } 296 297 /* 298 * Behave as a struct fdescriptor (descriptor.h) 299 */ 300 static int 301 radius_IsSet(struct fdescriptor *d, const fd_set *fdset) 302 { 303 struct radius *r = descriptor2radius(d); 304 305 return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset); 306 } 307 308 /* 309 * Behave as a struct fdescriptor (descriptor.h) 310 */ 311 static int 312 radius_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 313 { 314 /* We never want to write here ! */ 315 log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n"); 316 return 0; 317 } 318 319 /* 320 * Initialise ourselves 321 */ 322 void 323 radius_Init(struct radius *r) 324 { 325 r->valid = 0; 326 r->cx.fd = -1; 327 *r->cfg.file = '\0';; 328 r->desc.type = RADIUS_DESCRIPTOR; 329 r->desc.UpdateSet = radius_UpdateSet; 330 r->desc.IsSet = radius_IsSet; 331 r->desc.Read = radius_Read; 332 r->desc.Write = radius_Write; 333 memset(&r->cx.timer, '\0', sizeof r->cx.timer); 334 log_Printf(LogDEBUG, "Radius: radius_Init\n"); 335 } 336 337 /* 338 * Forget everything and go back to initialised state. 339 */ 340 void 341 radius_Destroy(struct radius *r) 342 { 343 r->valid = 0; 344 log_Printf(LogDEBUG, "Radius: radius_Destroy\n"); 345 timer_Stop(&r->cx.timer); 346 route_DeleteAll(&r->routes); 347 if (r->cx.fd != -1) { 348 r->cx.fd = -1; 349 rad_close(r->cx.rad); 350 } 351 } 352 353 /* 354 * Start an authentication request to the RADIUS server. 355 */ 356 void 357 radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name, 358 const char *key, const char *challenge) 359 { 360 struct ttyent *ttyp; 361 struct timeval tv; 362 int got, slot; 363 char hostname[MAXHOSTNAMELEN]; 364 struct hostent *hp; 365 struct in_addr hostaddr; 366 367 if (!*r->cfg.file) 368 return; 369 370 if (r->cx.fd != -1) 371 /* 372 * We assume that our name/key/challenge is the same as last time, 373 * and just continue to wait for the RADIUS server(s). 374 */ 375 return; 376 377 radius_Destroy(r); 378 379 if ((r->cx.rad = rad_auth_open()) == NULL) { 380 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 381 return; 382 } 383 384 if (rad_config(r->cx.rad, r->cfg.file) != 0) { 385 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 386 rad_close(r->cx.rad); 387 return; 388 } 389 390 if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) { 391 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 392 rad_close(r->cx.rad); 393 return; 394 } 395 396 if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 || 397 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 398 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) { 399 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 400 rad_close(r->cx.rad); 401 return; 402 } 403 404 if (challenge != NULL) { 405 /* We're talking CHAP */ 406 if (rad_put_string(r->cx.rad, RAD_CHAP_PASSWORD, key) != 0 || 407 rad_put_string(r->cx.rad, RAD_CHAP_CHALLENGE, challenge) != 0) { 408 log_Printf(LogERROR, "CHAP: rad_put_string: %s\n", 409 rad_strerror(r->cx.rad)); 410 rad_close(r->cx.rad); 411 return; 412 } 413 } else if (rad_put_string(r->cx.rad, RAD_USER_PASSWORD, key) != 0) { 414 /* We're talking PAP */ 415 log_Printf(LogERROR, "PAP: rad_put_string: %s\n", rad_strerror(r->cx.rad)); 416 rad_close(r->cx.rad); 417 return; 418 } 419 420 if (gethostname(hostname, sizeof hostname) != 0) 421 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 422 else { 423 if ((hp = gethostbyname(hostname)) != NULL) { 424 hostaddr.s_addr = *(u_long *)hp->h_addr; 425 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 426 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 427 rad_strerror(r->cx.rad)); 428 rad_close(r->cx.rad); 429 return; 430 } 431 } 432 if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 433 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 434 rad_strerror(r->cx.rad)); 435 rad_close(r->cx.rad); 436 return; 437 } 438 } 439 440 if (authp->physical->handler && 441 authp->physical->handler->type == TTY_DEVICE) { 442 setttyent(); 443 for (slot = 1; (ttyp = getttyent()); ++slot) 444 if (!strcmp(ttyp->ty_name, authp->physical->name.base)) { 445 if(rad_put_int(r->cx.rad, RAD_NAS_PORT, slot) != 0) { 446 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 447 rad_strerror(r->cx.rad)); 448 rad_close(r->cx.rad); 449 endttyent(); 450 return; 451 } 452 break; 453 } 454 endttyent(); 455 } 456 457 458 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 459 radius_Process(r, got); 460 else { 461 log_Printf(LogPHASE, "Radius: Request sent\n"); 462 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 463 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 464 r->cx.timer.func = radius_Timeout; 465 r->cx.timer.name = "radius"; 466 r->cx.timer.arg = r; 467 r->cx.auth = authp; 468 timer_Start(&r->cx.timer); 469 } 470 } 471 472 /* 473 * Send an accounting request to the RADIUS server 474 */ 475 void 476 radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl, 477 int acct_type, struct in_addr *peer_ip, struct in_addr *netmask, 478 struct pppThroughput *stats) 479 { 480 struct ttyent *ttyp; 481 struct timeval tv; 482 int got, slot; 483 char hostname[MAXHOSTNAMELEN]; 484 struct hostent *hp; 485 struct in_addr hostaddr; 486 487 if (!*r->cfg.file) 488 return; 489 490 if (r->cx.fd != -1) 491 /* 492 * We assume that our name/key/challenge is the same as last time, 493 * and just continue to wait for the RADIUS server(s). 494 */ 495 return; 496 497 radius_Destroy(r); 498 499 if ((r->cx.rad = rad_acct_open()) == NULL) { 500 log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno)); 501 return; 502 } 503 504 if (rad_config(r->cx.rad, r->cfg.file) != 0) { 505 log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad)); 506 rad_close(r->cx.rad); 507 return; 508 } 509 510 if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) { 511 log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad)); 512 rad_close(r->cx.rad); 513 return; 514 } 515 516 /* Grab some accounting data and initialize structure */ 517 if (acct_type == RAD_START) { 518 ac->rad_parent = r; 519 /* Fetch username from datalink */ 520 strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name); 521 ac->user_name[AUTHLEN-1] = '\0'; 522 523 ac->authentic = 2; /* Assume RADIUS verified auth data */ 524 525 /* Generate a session ID */ 526 snprintf(ac->session_id, sizeof ac->session_id, "%s%d-%s%lu", 527 dl->bundle->cfg.auth.name, (int)getpid(), 528 dl->peer.authname, (unsigned long)stats->uptime); 529 530 /* And grab our MP socket name */ 531 snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s", 532 dl->bundle->ncp.mp.active ? 533 dl->bundle->ncp.mp.server.socket.sun_path : ""); 534 535 /* Fetch IP, netmask from IPCP */ 536 memcpy(&ac->ip, peer_ip, sizeof(ac->ip)); 537 memcpy(&ac->mask, netmask, sizeof(ac->mask)); 538 }; 539 540 if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 || 541 rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 || 542 rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0 || 543 rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS, ac->ip) != 0 || 544 rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK, ac->mask) != 0) { 545 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 546 rad_close(r->cx.rad); 547 return; 548 } 549 550 if (gethostname(hostname, sizeof hostname) != 0) 551 log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno)); 552 else { 553 if ((hp = gethostbyname(hostname)) != NULL) { 554 hostaddr.s_addr = *(u_long *)hp->h_addr; 555 if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) { 556 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 557 rad_strerror(r->cx.rad)); 558 rad_close(r->cx.rad); 559 return; 560 } 561 } 562 if (rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) { 563 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 564 rad_strerror(r->cx.rad)); 565 rad_close(r->cx.rad); 566 return; 567 } 568 } 569 570 if (dl->physical->handler && 571 dl->physical->handler->type == TTY_DEVICE) { 572 setttyent(); 573 for (slot = 1; (ttyp = getttyent()); ++slot) 574 if (!strcmp(ttyp->ty_name, dl->physical->name.base)) { 575 if(rad_put_int(r->cx.rad, RAD_NAS_PORT, slot) != 0) { 576 log_Printf(LogERROR, "rad_put: rad_put_string: %s\n", 577 rad_strerror(r->cx.rad)); 578 rad_close(r->cx.rad); 579 endttyent(); 580 return; 581 } 582 break; 583 } 584 endttyent(); 585 } 586 587 if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 || 588 rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 || 589 rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID, 590 ac->multi_session_id) != 0 || 591 rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) { 592 /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */ 593 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 594 rad_close(r->cx.rad); 595 return; 596 } 597 598 if (acct_type == RAD_STOP) 599 /* Show some statistics */ 600 if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn) != 0 || 601 rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 || 602 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut) != 0 || 603 rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut) 604 != 0 || 605 rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats)) 606 != 0) { 607 log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad)); 608 rad_close(r->cx.rad); 609 return; 610 } 611 612 if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv))) 613 radius_Process(r, got); 614 else { 615 log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout); 616 r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS; 617 r->cx.timer.func = radius_Timeout; 618 r->cx.timer.name = "radius"; 619 r->cx.timer.arg = r; 620 r->cx.auth = NULL; /* Not valid for accounting requests */ 621 timer_Start(&r->cx.timer); 622 } 623 } 624 625 /* 626 * How do things look at the moment ? 627 */ 628 void 629 radius_Show(struct radius *r, struct prompt *p) 630 { 631 prompt_Printf(p, " Radius config: %s", *r->cfg.file ? r->cfg.file : "none"); 632 if (r->valid) { 633 prompt_Printf(p, "\n IP: %s\n", inet_ntoa(r->ip)); 634 prompt_Printf(p, " Netmask: %s\n", inet_ntoa(r->mask)); 635 prompt_Printf(p, " MTU: %lu\n", r->mtu); 636 prompt_Printf(p, " VJ: %sabled\n", r->vj ? "en" : "dis"); 637 if (r->routes) 638 route_ShowSticky(p, r->routes, " Routes", 16); 639 } else 640 prompt_Printf(p, " (not authenticated)\n"); 641 } 642