Home | History | Annotate | Download | only in src
      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: src/usr.sbin/ppp/radius.c,v 1.54.14.1 2010/12/21 17:10:29 kensmith Exp $
     27  *
     28  */
     29 
     30 #include <stdint.h>
     31 #include <sys/param.h>
     32 
     33 #include <sys/select.h>
     34 #include <sys/socket.h>
     35 #include <netinet/in_systm.h>
     36 #include <netinet/in.h>
     37 #include <netinet/ip.h>
     38 #include <arpa/inet.h>
     39 #include <sys/un.h>
     40 #include <net/route.h>
     41 
     42 #ifdef LOCALRAD
     43 #include "radlib.h"
     44 #include "radlib_vs.h"
     45 #else
     46 #include <radlib.h>
     47 #include <radlib_vs.h>
     48 #endif
     49 
     50 #include <errno.h>
     51 #ifndef NODES
     52 #include <md5.h>
     53 #endif
     54 #include <stdarg.h>
     55 #include <stdio.h>
     56 #include <stdlib.h>
     57 #include <string.h>
     58 #include <sys/time.h>
     59 #include <termios.h>
     60 #include <unistd.h>
     61 #include <netdb.h>
     62 
     63 #include "layer.h"
     64 #include "defs.h"
     65 #include "log.h"
     66 #include "descriptor.h"
     67 #include "prompt.h"
     68 #include "timer.h"
     69 #include "fsm.h"
     70 #include "iplist.h"
     71 #include "slcompress.h"
     72 #include "throughput.h"
     73 #include "lqr.h"
     74 #include "hdlc.h"
     75 #include "mbuf.h"
     76 #include "ncpaddr.h"
     77 #include "ip.h"
     78 #include "ipcp.h"
     79 #include "ipv6cp.h"
     80 #include "route.h"
     81 #include "command.h"
     82 #include "filter.h"
     83 #include "lcp.h"
     84 #include "ccp.h"
     85 #include "link.h"
     86 #include "mp.h"
     87 #include "radius.h"
     88 #include "auth.h"
     89 #include "async.h"
     90 #include "physical.h"
     91 #include "chat.h"
     92 #include "cbcp.h"
     93 #include "chap.h"
     94 #include "datalink.h"
     95 #include "ncp.h"
     96 #include "bundle.h"
     97 #include "proto.h"
     98 #include "iface.h"
     99 
    100 #ifndef NODES
    101 struct mschap_response {
    102   u_char ident;
    103   u_char flags;
    104   u_char lm_response[24];
    105   u_char nt_response[24];
    106 };
    107 
    108 struct mschap2_response {
    109   u_char ident;
    110   u_char flags;
    111   u_char pchallenge[16];
    112   u_char reserved[8];
    113   u_char response[24];
    114 };
    115 
    116 #define	AUTH_LEN	16
    117 #define	SALT_LEN	2
    118 #endif
    119 
    120 static const char *
    121 radius_policyname(int policy)
    122 {
    123   switch(policy) {
    124   case MPPE_POLICY_ALLOWED:
    125     return "Allowed";
    126   case MPPE_POLICY_REQUIRED:
    127     return "Required";
    128   }
    129   return NumStr(policy, NULL, 0);
    130 }
    131 
    132 static const char *
    133 radius_typesname(int types)
    134 {
    135   switch(types) {
    136   case MPPE_TYPE_40BIT:
    137     return "40 bit";
    138   case MPPE_TYPE_128BIT:
    139     return "128 bit";
    140   case MPPE_TYPE_40BIT|MPPE_TYPE_128BIT:
    141     return "40 or 128 bit";
    142   }
    143   return NumStr(types, NULL, 0);
    144 }
    145 
    146 #ifndef NODES
    147 static void
    148 demangle(struct radius *r, const void *mangled, size_t mlen,
    149          char **buf, size_t *len)
    150 {
    151   char R[AUTH_LEN];		/* variable names as per rfc2548 */
    152   const char *S;
    153   u_char b[16];
    154   const u_char *A, *C;
    155   MD5_CTX Context;
    156   int Slen, i, Clen, Ppos;
    157   u_char *P;
    158 
    159   if (mlen % 16 != SALT_LEN) {
    160     log_Printf(LogWARN, "Cannot interpret mangled data of length %ld\n",
    161                (u_long)mlen);
    162     *buf = NULL;
    163     *len = 0;
    164     return;
    165   }
    166 
    167   /* We need the RADIUS Request-Authenticator */
    168   if (rad_request_authenticator(r->cx.rad, R, sizeof R) != AUTH_LEN) {
    169     log_Printf(LogWARN, "Cannot obtain the RADIUS request authenticator\n");
    170     *buf = NULL;
    171     *len = 0;
    172     return;
    173   }
    174 
    175   A = (const u_char *)mangled;			/* Salt comes first */
    176   C = (const u_char *)mangled + SALT_LEN;	/* Then the ciphertext */
    177   Clen = mlen - SALT_LEN;
    178   S = rad_server_secret(r->cx.rad);		/* We need the RADIUS secret */
    179   Slen = strlen(S);
    180   P = alloca(Clen);				/* We derive our plaintext */
    181 
    182   MD5Init(&Context);
    183   MD5Update(&Context, S, Slen);
    184   MD5Update(&Context, R, AUTH_LEN);
    185   MD5Update(&Context, A, SALT_LEN);
    186   MD5Final(b, &Context);
    187   Ppos = 0;
    188 
    189   while (Clen) {
    190     Clen -= 16;
    191 
    192     for (i = 0; i < 16; i++)
    193       P[Ppos++] = C[i] ^ b[i];
    194 
    195     if (Clen) {
    196       MD5Init(&Context);
    197       MD5Update(&Context, S, Slen);
    198       MD5Update(&Context, C, 16);
    199       MD5Final(b, &Context);
    200     }
    201 
    202     C += 16;
    203   }
    204 
    205   /*
    206    * The resulting plain text consists of a one-byte length, the text and
    207    * maybe some padding.
    208    */
    209   *len = *P;
    210   if (*len > mlen - 1) {
    211     log_Printf(LogWARN, "Mangled data seems to be garbage\n");
    212     *buf = NULL;
    213     *len = 0;
    214     return;
    215   }
    216 
    217   if ((*buf = malloc(*len)) == NULL) {
    218     log_Printf(LogWARN, "demangle: Out of memory (%lu bytes)\n", (u_long)*len);
    219     *len = 0;
    220   } else
    221     memcpy(*buf, P + 1, *len);
    222 }
    223 #endif
    224 
    225 /* XXX: This should go into librarius. */
    226 #ifndef NOINET6
    227 static uint8_t *
    228 rad_cvt_ipv6prefix(const void *data, size_t len)
    229 {
    230 	const size_t ipv6len = sizeof(struct in6_addr) + 2;
    231 	uint8_t *s;
    232 
    233 	if (len > ipv6len)
    234 		return NULL;
    235 	s = malloc(ipv6len);
    236 	if (s != NULL) {
    237 		memset(s, 0, ipv6len);
    238 		memcpy(s, data, len);
    239 	}
    240 	return s;
    241 }
    242 #endif
    243 
    244 /*
    245  * rad_continue_send_request() has given us `got' (non-zero).  Deal with it.
    246  */
    247 static void
    248 radius_Process(struct radius *r, int got)
    249 {
    250   char *argv[MAXARGS], *nuke;
    251   struct bundle *bundle;
    252   int argc, addrs, res, width;
    253   size_t len;
    254   struct ncprange dest;
    255   struct ncpaddr gw;
    256   const void *data;
    257   const char *stype;
    258   u_int32_t ipaddr, vendor;
    259   struct in_addr ip;
    260 #ifndef NOINET6
    261   uint8_t ipv6addr[INET6_ADDRSTRLEN];
    262   struct in6_addr ip6;
    263 #endif
    264 
    265   r->cx.fd = -1;		/* Stop select()ing */
    266   stype = r->cx.auth ? "auth" : "acct";
    267 
    268   switch (got) {
    269     case RAD_ACCESS_ACCEPT:
    270       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    271 		 "Radius(%s): ACCEPT received\n", stype);
    272       if (!r->cx.auth) {
    273         rad_close(r->cx.rad);
    274         return;
    275       }
    276       break;
    277 
    278     case RAD_ACCESS_REJECT:
    279       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    280 		 "Radius(%s): REJECT received\n", stype);
    281       if (!r->cx.auth) {
    282         rad_close(r->cx.rad);
    283         return;
    284       }
    285       break;
    286 
    287     case RAD_ACCESS_CHALLENGE:
    288       /* we can't deal with this (for now) ! */
    289       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    290 		 "Radius: CHALLENGE received (can't handle yet)\n");
    291       if (r->cx.auth)
    292         auth_Failure(r->cx.auth);
    293       rad_close(r->cx.rad);
    294       return;
    295 
    296     case RAD_ACCOUNTING_RESPONSE:
    297       /*
    298        * It's probably not ideal to log this at PHASE level as we'll see
    299        * too much stuff going to the log when ``set rad_alive'' is used.
    300        * So we differ from older behaviour (ppp version 3.1 and before)
    301        * and just log accounting responses to LogRADIUS.
    302        */
    303       log_Printf(LogRADIUS, "Radius(%s): Accounting response received\n",
    304 		 stype);
    305       if (r->cx.auth)
    306         auth_Failure(r->cx.auth);		/* unexpected !!! */
    307 
    308       /* No further processing for accounting requests, please */
    309       rad_close(r->cx.rad);
    310       return;
    311 
    312     case -1:
    313       log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    314 		 "radius(%s): %s\n", stype, rad_strerror(r->cx.rad));
    315       if (r->cx.auth)
    316         auth_Failure(r->cx.auth);
    317       rad_close(r->cx.rad);
    318       return;
    319 
    320     default:
    321       log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype,
    322                  got, rad_strerror(r->cx.rad));
    323       if (r->cx.auth)
    324         auth_Failure(r->cx.auth);
    325       rad_close(r->cx.rad);
    326       return;
    327   }
    328 
    329   /* Let's see what we've got in our reply */
    330   r->ip.s_addr = r->mask.s_addr = INADDR_NONE;
    331   r->mtu = 0;
    332   r->vj = 0;
    333   while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
    334     switch (res) {
    335       case RAD_FRAMED_IP_ADDRESS:
    336         r->ip = rad_cvt_addr(data);
    337 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    338 		   " IP %s\n", inet_ntoa(r->ip));
    339         break;
    340 
    341       case RAD_FILTER_ID:
    342         free(r->filterid);
    343         if ((r->filterid = rad_cvt_string(data, len)) == NULL) {
    344           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
    345           auth_Failure(r->cx.auth);
    346           rad_close(r->cx.rad);
    347           return;
    348         }
    349 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    350 		   " Filter \"%s\"\n", r->filterid);
    351         break;
    352 
    353       case RAD_SESSION_TIMEOUT:
    354         r->sessiontime = rad_cvt_int(data);
    355 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    356 		   " Session-Timeout %lu\n", r->sessiontime);
    357         break;
    358 
    359       case RAD_FRAMED_IP_NETMASK:
    360         r->mask = rad_cvt_addr(data);
    361 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    362 		   " Netmask %s\n", inet_ntoa(r->mask));
    363         break;
    364 
    365       case RAD_FRAMED_MTU:
    366         r->mtu = rad_cvt_int(data);
    367 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    368 		   " MTU %lu\n", r->mtu);
    369         break;
    370 
    371       case RAD_FRAMED_ROUTING:
    372         /* Disabled for now - should we automatically set up some filters ? */
    373         /* rad_cvt_int(data); */
    374         /* bit 1 = Send routing packets */
    375         /* bit 2 = Receive routing packets */
    376         break;
    377 
    378       case RAD_FRAMED_COMPRESSION:
    379         r->vj = rad_cvt_int(data) == 1 ? 1 : 0;
    380 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    381 		   " VJ %sabled\n", r->vj ? "en" : "dis");
    382         break;
    383 
    384       case RAD_FRAMED_ROUTE:
    385         /*
    386          * We expect a string of the format ``dest[/bits] gw [metrics]''
    387          * Any specified metrics are ignored.  MYADDR and HISADDR are
    388          * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same
    389          * as ``HISADDR''.
    390          */
    391 
    392         if ((nuke = rad_cvt_string(data, len)) == NULL) {
    393           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
    394           auth_Failure(r->cx.auth);
    395           rad_close(r->cx.rad);
    396           return;
    397         }
    398 
    399 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    400 		   " Route: %s\n", nuke);
    401         bundle = r->cx.auth->physical->dl->bundle;
    402         ip.s_addr = INADDR_ANY;
    403         ncpaddr_setip4(&gw, ip);
    404         ncprange_setip4host(&dest, ip);
    405         argc = command_Interpret(nuke, strlen(nuke), argv);
    406         if (argc < 0)
    407           log_Printf(LogWARN, "radius: %s: Syntax error\n",
    408                      argc == 1 ? argv[0] : "\"\"");
    409         else if (argc < 2)
    410           log_Printf(LogWARN, "radius: %s: Invalid route\n",
    411                      argc == 1 ? argv[0] : "\"\"");
    412         else if ((strcasecmp(argv[0], "default") != 0 &&
    413                   !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
    414                  !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
    415           log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
    416                      argv[0], argv[1]);
    417         else {
    418           ncprange_getwidth(&dest, &width);
    419           if (width == 32 && strchr(argv[0], '/') == NULL) {
    420             /* No mask specified - use the natural mask */
    421             ncprange_getip4addr(&dest, &ip);
    422             ncprange_setip4mask(&dest, addr2mask(ip));
    423           }
    424           addrs = 0;
    425 
    426           if (!strncasecmp(argv[0], "HISADDR", 7))
    427             addrs = ROUTE_DSTHISADDR;
    428           else if (!strncasecmp(argv[0], "MYADDR", 6))
    429             addrs = ROUTE_DSTMYADDR;
    430 
    431           if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) {
    432             addrs |= ROUTE_GWHISADDR;
    433             ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip);
    434           } else if (strcasecmp(argv[1], "HISADDR") == 0)
    435             addrs |= ROUTE_GWHISADDR;
    436 
    437           route_Add(&r->routes, addrs, &dest, &gw);
    438         }
    439         free(nuke);
    440         break;
    441 
    442       case RAD_REPLY_MESSAGE:
    443         free(r->repstr);
    444         if ((r->repstr = rad_cvt_string(data, len)) == NULL) {
    445           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
    446           auth_Failure(r->cx.auth);
    447           rad_close(r->cx.rad);
    448           return;
    449         }
    450 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    451 		   " Reply-Message \"%s\"\n", r->repstr);
    452         break;
    453 
    454 #ifndef NOINET6
    455       case RAD_FRAMED_IPV6_PREFIX:
    456 	free(r->ipv6prefix);
    457 	if ((r->ipv6prefix = rad_cvt_ipv6prefix(data, len)) == NULL) {
    458 	  log_Printf(LogERROR, "rad_cvt_ipv6prefix: %s\n",
    459 		     "Malformed attribute in response");
    460 	  auth_Failure(r->cx.auth);
    461 	  rad_close(r->cx.rad);
    462 	  return;
    463 	}
    464 	inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr));
    465 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    466 		   " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]);
    467         break;
    468 
    469       case RAD_FRAMED_IPV6_ROUTE:
    470         /*
    471          * We expect a string of the format ``dest[/bits] gw [metrics]''
    472          * Any specified metrics are ignored.  MYADDR6 and HISADDR6 are
    473          * understood for ``dest'' and ``gw'' and ``::'' is the same
    474          * as ``HISADDR6''.
    475          */
    476 
    477         if ((nuke = rad_cvt_string(data, len)) == NULL) {
    478           log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
    479           auth_Failure(r->cx.auth);
    480           rad_close(r->cx.rad);
    481           return;
    482         }
    483 
    484 	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    485 		   " IPv6 Route: %s\n", nuke);
    486         bundle = r->cx.auth->physical->dl->bundle;
    487 	ncpaddr_setip6(&gw, &in6addr_any);
    488 	ncprange_set(&dest, &gw, 0);
    489         argc = command_Interpret(nuke, strlen(nuke), argv);
    490         if (argc < 0)
    491           log_Printf(LogWARN, "radius: %s: Syntax error\n",
    492                      argc == 1 ? argv[0] : "\"\"");
    493         else if (argc < 2)
    494           log_Printf(LogWARN, "radius: %s: Invalid route\n",
    495                      argc == 1 ? argv[0] : "\"\"");
    496         else if ((strcasecmp(argv[0], "default") != 0 &&
    497                   !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
    498                  !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
    499           log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
    500                      argv[0], argv[1]);
    501         else {
    502           addrs = 0;
    503 
    504           if (!strncasecmp(argv[0], "HISADDR6", 8))
    505             addrs = ROUTE_DSTHISADDR6;
    506           else if (!strncasecmp(argv[0], "MYADDR6", 7))
    507             addrs = ROUTE_DSTMYADDR6;
    508 
    509           if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) {
    510             addrs |= ROUTE_GWHISADDR6;
    511             ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr);
    512           } else if (strcasecmp(argv[1], "HISADDR6") == 0)
    513             addrs |= ROUTE_GWHISADDR6;
    514 
    515           route_Add(&r->ipv6routes, addrs, &dest, &gw);
    516         }
    517         free(nuke);
    518         break;
    519 #endif
    520 
    521       case RAD_VENDOR_SPECIFIC:
    522         if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) {
    523           log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n",
    524                      rad_strerror(r->cx.rad));
    525           auth_Failure(r->cx.auth);
    526           rad_close(r->cx.rad);
    527           return;
    528         }
    529 
    530 	switch (vendor) {
    531           case RAD_VENDOR_MICROSOFT:
    532             switch (res) {
    533 #ifndef NODES
    534               case RAD_MICROSOFT_MS_CHAP_ERROR:
    535                 free(r->errstr);
    536                 if (len == 0)
    537                   r->errstr = NULL;
    538                 else {
    539                   if (len < 3 || ((const char *)data)[1] != '=') {
    540                     /*
    541                      * Only point at the String field if we don't think the
    542                      * peer has misformatted the response.
    543                      */
    544                     data = (const char *)data + 1;
    545                     len--;
    546                   } else
    547                     log_Printf(LogWARN, "Warning: The MS-CHAP-Error "
    548                                "attribute is mis-formatted.  Compensating\n");
    549                   if ((r->errstr = rad_cvt_string((const char *)data,
    550                                                   len)) == NULL) {
    551                     log_Printf(LogERROR, "rad_cvt_string: %s\n",
    552                                rad_strerror(r->cx.rad));
    553                     auth_Failure(r->cx.auth);
    554                     rad_close(r->cx.rad);
    555                     return;
    556                   }
    557 		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    558 			     " MS-CHAP-Error \"%s\"\n", r->errstr);
    559                 }
    560                 break;
    561 
    562               case RAD_MICROSOFT_MS_CHAP2_SUCCESS:
    563                 free(r->msrepstr);
    564                 if (len == 0)
    565                   r->msrepstr = NULL;
    566                 else {
    567                   if (len < 3 || ((const char *)data)[1] != '=') {
    568                     /*
    569                      * Only point at the String field if we don't think the
    570                      * peer has misformatted the response.
    571                      */
    572                     data = (const char *)data + 1;
    573                     len--;
    574                   } else
    575                     log_Printf(LogWARN, "Warning: The MS-CHAP2-Success "
    576                                "attribute is mis-formatted.  Compensating\n");
    577                   if ((r->msrepstr = rad_cvt_string((const char *)data,
    578                                                     len)) == NULL) {
    579                     log_Printf(LogERROR, "rad_cvt_string: %s\n",
    580                                rad_strerror(r->cx.rad));
    581                     auth_Failure(r->cx.auth);
    582                     rad_close(r->cx.rad);
    583                     return;
    584                   }
    585 		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    586 			     " MS-CHAP2-Success \"%s\"\n", r->msrepstr);
    587                 }
    588                 break;
    589 
    590               case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
    591                 r->mppe.policy = rad_cvt_int(data);
    592 		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    593 			   " MS-MPPE-Encryption-Policy %s\n",
    594                            radius_policyname(r->mppe.policy));
    595                 break;
    596 
    597               case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
    598                 r->mppe.types = rad_cvt_int(data);
    599 		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    600 			   " MS-MPPE-Encryption-Types %s\n",
    601                            radius_typesname(r->mppe.types));
    602                 break;
    603 
    604               case RAD_MICROSOFT_MS_MPPE_RECV_KEY:
    605                 free(r->mppe.recvkey);
    606 		demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen);
    607 		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    608 			   " MS-MPPE-Recv-Key ********\n");
    609                 break;
    610 
    611               case RAD_MICROSOFT_MS_MPPE_SEND_KEY:
    612 		demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen);
    613 		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    614 			   " MS-MPPE-Send-Key ********\n");
    615                 break;
    616 #endif
    617 
    618               default:
    619                 log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
    620                            "RADIUS attribute %d\n", res);
    621                 break;
    622             }
    623             break;
    624 
    625           default:
    626             log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n",
    627                        (unsigned long)vendor, res);
    628             break;
    629         }
    630         break;
    631 
    632       default:
    633         log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res);
    634         break;
    635     }
    636   }
    637 
    638   if (res == -1) {
    639     log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n",
    640                rad_strerror(r->cx.rad));
    641     auth_Failure(r->cx.auth);
    642   } else if (got == RAD_ACCESS_REJECT)
    643     auth_Failure(r->cx.auth);
    644   else {
    645     r->valid = 1;
    646     auth_Success(r->cx.auth);
    647   }
    648   rad_close(r->cx.rad);
    649 }
    650 
    651 /*
    652  * We've either timed out or select()ed on the read descriptor
    653  */
    654 static void
    655 radius_Continue(struct radius *r, int sel)
    656 {
    657   struct timeval tv;
    658   int got;
    659 
    660   timer_Stop(&r->cx.timer);
    661   if ((got = rad_continue_send_request(r->cx.rad, sel, &r->cx.fd, &tv)) == 0) {
    662     log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
    663 	       "Radius: Request re-sent\n");
    664     r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
    665     timer_Start(&r->cx.timer);
    666     return;
    667   }
    668 
    669   radius_Process(r, got);
    670 }
    671 
    672 /*
    673  * Time to call rad_continue_send_request() - timed out.
    674  */
    675 static void
    676 radius_Timeout(void *v)
    677 {
    678   radius_Continue((struct radius *)v, 0);
    679 }
    680 
    681 /*
    682  * Time to call rad_continue_send_request() - something to read.
    683  */
    684 static void
    685 radius_Read(struct fdescriptor *d, struct bundle *bundle __unused,
    686 	    const fd_set *fdset __unused)
    687 {
    688   radius_Continue(descriptor2radius(d), 1);
    689 }
    690 
    691 /*
    692  * Flush any pending transactions
    693  */
    694 void
    695 radius_Flush(struct radius *r)
    696 {
    697   struct timeval tv;
    698   fd_set s;
    699 
    700   while (r->cx.fd != -1) {
    701     FD_ZERO(&s);
    702     FD_SET(r->cx.fd, &s);
    703     tv.tv_sec = 0;
    704     tv.tv_usec = TICKUNIT;
    705     select(r->cx.fd + 1, &s, NULL, NULL, &tv);
    706     radius_Continue(r, 1);
    707   }
    708 }
    709 
    710 /*
    711  * Behave as a struct fdescriptor (descriptor.h)
    712  */
    713 static int
    714 radius_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w __unused,
    715 		 fd_set *e __unused, int *n)
    716 {
    717   struct radius *rad = descriptor2radius(d);
    718 
    719   if (r && rad->cx.fd != -1) {
    720     FD_SET(rad->cx.fd, r);
    721     if (*n < rad->cx.fd + 1)
    722       *n = rad->cx.fd + 1;
    723     log_Printf(LogTIMER, "Radius: fdset(r) %d\n", rad->cx.fd);
    724     return 1;
    725   }
    726 
    727   return 0;
    728 }
    729 
    730 /*
    731  * Behave as a struct fdescriptor (descriptor.h)
    732  */
    733 static int
    734 radius_IsSet(struct fdescriptor *d, const fd_set *fdset)
    735 {
    736   struct radius *r = descriptor2radius(d);
    737 
    738   return r && r->cx.fd != -1 && FD_ISSET(r->cx.fd, fdset);
    739 }
    740 
    741 /*
    742  * Behave as a struct fdescriptor (descriptor.h)
    743  */
    744 static int
    745 radius_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused,
    746 	     const fd_set *fdset __unused)
    747 {
    748   /* We never want to write here ! */
    749   log_Printf(LogALERT, "radius_Write: Internal error: Bad call !\n");
    750   return 0;
    751 }
    752 
    753 /*
    754  * Initialise ourselves
    755  */
    756 void
    757 radius_Init(struct radius *r)
    758 {
    759   r->desc.type = RADIUS_DESCRIPTOR;
    760   r->desc.UpdateSet = radius_UpdateSet;
    761   r->desc.IsSet = radius_IsSet;
    762   r->desc.Read = radius_Read;
    763   r->desc.Write = radius_Write;
    764   r->cx.fd = -1;
    765   r->cx.rad = NULL;
    766   memset(&r->cx.timer, '\0', sizeof r->cx.timer);
    767   r->cx.auth = NULL;
    768   r->valid = 0;
    769   r->vj = 0;
    770   r->ip.s_addr = INADDR_ANY;
    771   r->mask.s_addr = INADDR_NONE;
    772   r->routes = NULL;
    773   r->mtu = DEF_MTU;
    774   r->msrepstr = NULL;
    775   r->repstr = NULL;
    776 #ifndef NOINET6
    777   r->ipv6prefix = NULL;
    778   r->ipv6routes = NULL;
    779 #endif
    780   r->errstr = NULL;
    781   r->mppe.policy = 0;
    782   r->mppe.types = 0;
    783   r->mppe.recvkey = NULL;
    784   r->mppe.recvkeylen = 0;
    785   r->mppe.sendkey = NULL;
    786   r->mppe.sendkeylen = 0;
    787   *r->cfg.file = '\0';;
    788   log_Printf(LogDEBUG, "Radius: radius_Init\n");
    789 }
    790 
    791 /*
    792  * Forget everything and go back to initialised state.
    793  */
    794 void
    795 radius_Destroy(struct radius *r)
    796 {
    797   r->valid = 0;
    798   log_Printf(LogDEBUG, "Radius: radius_Destroy\n");
    799   timer_Stop(&r->cx.timer);
    800   route_DeleteAll(&r->routes);
    801 #ifndef NOINET6
    802   route_DeleteAll(&r->ipv6routes);
    803 #endif
    804   free(r->filterid);
    805   r->filterid = NULL;
    806   free(r->msrepstr);
    807   r->msrepstr = NULL;
    808   free(r->repstr);
    809   r->repstr = NULL;
    810 #ifndef NOINET6
    811   free(r->ipv6prefix);
    812   r->ipv6prefix = NULL;
    813 #endif
    814   free(r->errstr);
    815   r->errstr = NULL;
    816   free(r->mppe.recvkey);
    817   r->mppe.recvkey = NULL;
    818   r->mppe.recvkeylen = 0;
    819   free(r->mppe.sendkey);
    820   r->mppe.sendkey = NULL;
    821   r->mppe.sendkeylen = 0;
    822   if (r->cx.fd != -1) {
    823     r->cx.fd = -1;
    824     rad_close(r->cx.rad);
    825   }
    826 }
    827 
    828 static int
    829 radius_put_physical_details(struct radius *rad, struct physical *p)
    830 {
    831   int slot, type;
    832 
    833   type = RAD_VIRTUAL;
    834   if (p->handler)
    835     switch (p->handler->type) {
    836       case I4B_DEVICE:
    837         type = RAD_ISDN_SYNC;
    838         break;
    839 
    840       case TTY_DEVICE:
    841         type = RAD_ASYNC;
    842         break;
    843 
    844       case ETHER_DEVICE:
    845         type = RAD_ETHERNET;
    846         break;
    847 
    848       case TCP_DEVICE:
    849       case UDP_DEVICE:
    850       case EXEC_DEVICE:
    851       case ATM_DEVICE:
    852       case NG_DEVICE:
    853         type = RAD_VIRTUAL;
    854         break;
    855     }
    856 
    857   if (rad_put_int(rad->cx.rad, RAD_NAS_PORT_TYPE, type) != 0) {
    858     log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad->cx.rad));
    859     rad_close(rad->cx.rad);
    860     return 0;
    861   }
    862 
    863   switch (rad->port_id_type) {
    864     case RPI_PID:
    865       slot = (int)getpid();
    866       break;
    867     case RPI_IFNUM:
    868       slot = p->dl->bundle->iface->index;
    869       break;
    870     case RPI_TUNNUM:
    871       slot = p->dl->bundle->unit;
    872       break;
    873     case RPI_DEFAULT:
    874     default:
    875       slot = physical_Slot(p);
    876       break;
    877   }
    878 
    879   if (slot >= 0)
    880     if (rad_put_int(rad->cx.rad, RAD_NAS_PORT, slot) != 0) {
    881       log_Printf(LogERROR, "rad_put: rad_put_int: %s\n", rad_strerror(rad->cx.rad));
    882       rad_close(rad->cx.rad);
    883       return 0;
    884     }
    885 
    886   return 1;
    887 }
    888 
    889 /*
    890  * Start an authentication request to the RADIUS server.
    891  */
    892 int
    893 radius_Authenticate(struct radius *r, struct authinfo *authp, const char *name,
    894                     const char *key, int klen, const char *nchallenge,
    895                     int nclen)
    896 {
    897   char hostname[MAXHOSTNAMELEN];
    898   struct timeval tv;
    899   const char *what = "questionable";	/* silence warnings! */
    900   char *mac_addr;
    901   int got;
    902   struct hostent *hp;
    903   struct in_addr hostaddr;
    904 #ifndef NODES
    905   struct mschap_response msresp;
    906   struct mschap2_response msresp2;
    907   const struct MSCHAPv2_resp *keyv2;
    908 #endif
    909 
    910   if (!*r->cfg.file)
    911     return 0;
    912 
    913   if (r->cx.fd != -1)
    914     /*
    915      * We assume that our name/key/challenge is the same as last time,
    916      * and just continue to wait for the RADIUS server(s).
    917      */
    918     return 1;
    919 
    920   radius_Destroy(r);
    921 
    922   if ((r->cx.rad = rad_auth_open()) == NULL) {
    923     log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
    924     return 0;
    925   }
    926 
    927   if (rad_config(r->cx.rad, r->cfg.file) != 0) {
    928     log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
    929     rad_close(r->cx.rad);
    930     return 0;
    931   }
    932 
    933   if (rad_create_request(r->cx.rad, RAD_ACCESS_REQUEST) != 0) {
    934     log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
    935     rad_close(r->cx.rad);
    936     return 0;
    937   }
    938 
    939   if (rad_put_string(r->cx.rad, RAD_USER_NAME, name) != 0 ||
    940       rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
    941       rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
    942     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
    943     rad_close(r->cx.rad);
    944     return 0;
    945   }
    946 
    947   switch (authp->physical->link.lcp.want_auth) {
    948   case PROTO_PAP:
    949     /* We're talking PAP */
    950     if (rad_put_attr(r->cx.rad, RAD_USER_PASSWORD, key, klen) != 0) {
    951       log_Printf(LogERROR, "PAP: rad_put_string: %s\n",
    952                  rad_strerror(r->cx.rad));
    953       rad_close(r->cx.rad);
    954       return 0;
    955     }
    956     what = "PAP";
    957     break;
    958 
    959   case PROTO_CHAP:
    960     switch (authp->physical->link.lcp.want_authtype) {
    961     case 0x5:
    962       if (rad_put_attr(r->cx.rad, RAD_CHAP_PASSWORD, key, klen) != 0 ||
    963           rad_put_attr(r->cx.rad, RAD_CHAP_CHALLENGE, nchallenge, nclen) != 0) {
    964         log_Printf(LogERROR, "CHAP: rad_put_string: %s\n",
    965                    rad_strerror(r->cx.rad));
    966         rad_close(r->cx.rad);
    967         return 0;
    968       }
    969       what = "CHAP";
    970       break;
    971 
    972 #ifndef NODES
    973     case 0x80:
    974       if (klen != 50) {
    975         log_Printf(LogERROR, "CHAP80: Unrecognised key length %d\n", klen);
    976         rad_close(r->cx.rad);
    977         return 0;
    978       }
    979 
    980       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
    981                           RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
    982       msresp.ident = *key;
    983       msresp.flags = 0x01;
    984       memcpy(msresp.lm_response, key + 1, 24);
    985       memcpy(msresp.nt_response, key + 25, 24);
    986       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
    987                           RAD_MICROSOFT_MS_CHAP_RESPONSE, &msresp,
    988                           sizeof msresp);
    989       what = "MSCHAP";
    990       break;
    991 
    992     case 0x81:
    993       if (klen != sizeof(*keyv2) + 1) {
    994         log_Printf(LogERROR, "CHAP81: Unrecognised key length %d\n", klen);
    995         rad_close(r->cx.rad);
    996         return 0;
    997       }
    998 
    999       keyv2 = (const struct MSCHAPv2_resp *)(key + 1);
   1000       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
   1001                           RAD_MICROSOFT_MS_CHAP_CHALLENGE, nchallenge, nclen);
   1002       msresp2.ident = *key;
   1003       msresp2.flags = keyv2->Flags;
   1004       memcpy(msresp2.response, keyv2->NTResponse, sizeof msresp2.response);
   1005       memset(msresp2.reserved, '\0', sizeof msresp2.reserved);
   1006       memcpy(msresp2.pchallenge, keyv2->PeerChallenge,
   1007              sizeof msresp2.pchallenge);
   1008       rad_put_vendor_attr(r->cx.rad, RAD_VENDOR_MICROSOFT,
   1009                           RAD_MICROSOFT_MS_CHAP2_RESPONSE, &msresp2,
   1010                           sizeof msresp2);
   1011       what = "MSCHAPv2";
   1012       break;
   1013 #endif
   1014     default:
   1015       log_Printf(LogERROR, "CHAP: Unrecognised type 0x%02x\n",
   1016                  authp->physical->link.lcp.want_authtype);
   1017       rad_close(r->cx.rad);
   1018       return 0;
   1019     }
   1020   }
   1021 
   1022   if (gethostname(hostname, sizeof hostname) != 0)
   1023     log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
   1024   else {
   1025     if (Enabled(authp->physical->dl->bundle, OPT_NAS_IP_ADDRESS) &&
   1026         (hp = gethostbyname(hostname)) != NULL) {
   1027       hostaddr.s_addr = *(u_long *)hp->h_addr;
   1028       if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
   1029         log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
   1030                    rad_strerror(r->cx.rad));
   1031         rad_close(r->cx.rad);
   1032         return 0;
   1033       }
   1034     }
   1035     if (Enabled(authp->physical->dl->bundle, OPT_NAS_IDENTIFIER) &&
   1036         rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
   1037       log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
   1038                  rad_strerror(r->cx.rad));
   1039       rad_close(r->cx.rad);
   1040       return 0;
   1041     }
   1042   }
   1043 
   1044   if ((mac_addr = getenv("HISMACADDR")) != NULL &&
   1045       rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) {
   1046     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
   1047     rad_close(r->cx.rad);
   1048     return 0;
   1049   }
   1050 
   1051   radius_put_physical_details(r, authp->physical);
   1052 
   1053   log_Printf(LogRADIUS, "Radius(auth): %s data sent for %s\n", what, name);
   1054 
   1055   r->cx.auth = authp;
   1056   if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
   1057     radius_Process(r, got);
   1058   else {
   1059     log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
   1060 	       "Radius: Request sent\n");
   1061     log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
   1062     r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
   1063     r->cx.timer.func = radius_Timeout;
   1064     r->cx.timer.name = "radius auth";
   1065     r->cx.timer.arg = r;
   1066     timer_Start(&r->cx.timer);
   1067   }
   1068 
   1069   return 1;
   1070 }
   1071 
   1072 /* Fetch IP, netmask from IPCP */
   1073 void
   1074 radius_Account_Set_Ip(struct radacct *ac, struct in_addr *peer_ip,
   1075 		      struct in_addr *netmask)
   1076 {
   1077   ac->proto = PROTO_IPCP;
   1078   memcpy(&ac->peer.ip.addr, peer_ip, sizeof(ac->peer.ip.addr));
   1079   memcpy(&ac->peer.ip.mask, netmask, sizeof(ac->peer.ip.mask));
   1080 }
   1081 
   1082 #ifndef NOINET6
   1083 /* Fetch interface-id from IPV6CP */
   1084 void
   1085 radius_Account_Set_Ipv6(struct radacct *ac, u_char *ifid)
   1086 {
   1087   ac->proto = PROTO_IPV6CP;
   1088   memcpy(&ac->peer.ipv6.ifid, ifid, sizeof(ac->peer.ipv6.ifid));
   1089 }
   1090 #endif
   1091 
   1092 /*
   1093  * Send an accounting request to the RADIUS server
   1094  */
   1095 void
   1096 radius_Account(struct radius *r, struct radacct *ac, struct datalink *dl,
   1097                int acct_type, struct pppThroughput *stats)
   1098 {
   1099   struct timeval tv;
   1100   int got;
   1101   char hostname[MAXHOSTNAMELEN];
   1102   char *mac_addr;
   1103   struct hostent *hp;
   1104   struct in_addr hostaddr;
   1105 
   1106   if (!*r->cfg.file)
   1107     return;
   1108 
   1109   if (r->cx.fd != -1)
   1110     /*
   1111      * We assume that our name/key/challenge is the same as last time,
   1112      * and just continue to wait for the RADIUS server(s).
   1113      */
   1114     return;
   1115 
   1116   timer_Stop(&r->cx.timer);
   1117 
   1118   if ((r->cx.rad = rad_acct_open()) == NULL) {
   1119     log_Printf(LogERROR, "rad_auth_open: %s\n", strerror(errno));
   1120     return;
   1121   }
   1122 
   1123   if (rad_config(r->cx.rad, r->cfg.file) != 0) {
   1124     log_Printf(LogERROR, "rad_config: %s\n", rad_strerror(r->cx.rad));
   1125     rad_close(r->cx.rad);
   1126     return;
   1127   }
   1128 
   1129   if (rad_create_request(r->cx.rad, RAD_ACCOUNTING_REQUEST) != 0) {
   1130     log_Printf(LogERROR, "rad_create_request: %s\n", rad_strerror(r->cx.rad));
   1131     rad_close(r->cx.rad);
   1132     return;
   1133   }
   1134 
   1135   /* Grab some accounting data and initialize structure */
   1136   if (acct_type == RAD_START) {
   1137     ac->rad_parent = r;
   1138     /* Fetch username from datalink */
   1139     strncpy(ac->user_name, dl->peer.authname, sizeof ac->user_name);
   1140     ac->user_name[AUTHLEN-1] = '\0';
   1141 
   1142     ac->authentic = 2;		/* Assume RADIUS verified auth data */
   1143 
   1144     /* Generate a session ID */
   1145     snprintf(ac->session_id, sizeof ac->session_id, "%s%ld-%s%lu",
   1146              dl->bundle->cfg.auth.name, (long)getpid(),
   1147              dl->peer.authname, (unsigned long)stats->uptime);
   1148 
   1149     /* And grab our MP socket name */
   1150     snprintf(ac->multi_session_id, sizeof ac->multi_session_id, "%s",
   1151              dl->bundle->ncp.mp.active ?
   1152              dl->bundle->ncp.mp.server.socket.sun_path : "");
   1153   };
   1154 
   1155   if (rad_put_string(r->cx.rad, RAD_USER_NAME, ac->user_name) != 0 ||
   1156       rad_put_int(r->cx.rad, RAD_SERVICE_TYPE, RAD_FRAMED) != 0 ||
   1157       rad_put_int(r->cx.rad, RAD_FRAMED_PROTOCOL, RAD_PPP) != 0) {
   1158     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
   1159     rad_close(r->cx.rad);
   1160     return;
   1161   }
   1162   switch (ac->proto) {
   1163   case PROTO_IPCP:
   1164     if (rad_put_addr(r->cx.rad, RAD_FRAMED_IP_ADDRESS,
   1165 		     ac->peer.ip.addr) != 0 ||
   1166 	rad_put_addr(r->cx.rad, RAD_FRAMED_IP_NETMASK,
   1167 		     ac->peer.ip.mask) != 0) {
   1168       log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
   1169       rad_close(r->cx.rad);
   1170       return;
   1171     }
   1172     break;
   1173 #ifndef NOINET6
   1174   case PROTO_IPV6CP:
   1175     if (rad_put_attr(r->cx.rad, RAD_FRAMED_INTERFACE_ID, ac->peer.ipv6.ifid,
   1176 		     sizeof(ac->peer.ipv6.ifid)) != 0) {
   1177       log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad));
   1178       rad_close(r->cx.rad);
   1179       return;
   1180     }
   1181     if (r->ipv6prefix) {
   1182       /*
   1183        * Since PPP doesn't delegate an IPv6 prefix to a peer,
   1184        * Framed-IPv6-Prefix may be not used, actually.
   1185        */
   1186       if (rad_put_attr(r->cx.rad, RAD_FRAMED_IPV6_PREFIX, r->ipv6prefix,
   1187 		       sizeof(struct in6_addr) + 2) != 0) {
   1188 	log_Printf(LogERROR, "rad_put_attr: %s\n", rad_strerror(r->cx.rad));
   1189 	rad_close(r->cx.rad);
   1190 	return;
   1191       }
   1192     }
   1193     break;
   1194 #endif
   1195   default:
   1196     /* We don't log any protocol specific information */
   1197     break;
   1198   }
   1199 
   1200   if ((mac_addr = getenv("HISMACADDR")) != NULL &&
   1201       rad_put_string(r->cx.rad, RAD_CALLING_STATION_ID, mac_addr) != 0) {
   1202     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
   1203     rad_close(r->cx.rad);
   1204     return;
   1205   }
   1206 
   1207   if (gethostname(hostname, sizeof hostname) != 0)
   1208     log_Printf(LogERROR, "rad_put: gethostname(): %s\n", strerror(errno));
   1209   else {
   1210     if (Enabled(dl->bundle, OPT_NAS_IP_ADDRESS) &&
   1211         (hp = gethostbyname(hostname)) != NULL) {
   1212       hostaddr.s_addr = *(u_long *)hp->h_addr;
   1213       if (rad_put_addr(r->cx.rad, RAD_NAS_IP_ADDRESS, hostaddr) != 0) {
   1214         log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
   1215                    rad_strerror(r->cx.rad));
   1216         rad_close(r->cx.rad);
   1217         return;
   1218       }
   1219     }
   1220     if (Enabled(dl->bundle, OPT_NAS_IDENTIFIER) &&
   1221         rad_put_string(r->cx.rad, RAD_NAS_IDENTIFIER, hostname) != 0) {
   1222       log_Printf(LogERROR, "rad_put: rad_put_string: %s\n",
   1223                  rad_strerror(r->cx.rad));
   1224       rad_close(r->cx.rad);
   1225       return;
   1226     }
   1227   }
   1228 
   1229   radius_put_physical_details(r, dl->physical);
   1230 
   1231   if (rad_put_int(r->cx.rad, RAD_ACCT_STATUS_TYPE, acct_type) != 0 ||
   1232       rad_put_string(r->cx.rad, RAD_ACCT_SESSION_ID, ac->session_id) != 0 ||
   1233       rad_put_string(r->cx.rad, RAD_ACCT_MULTI_SESSION_ID,
   1234                      ac->multi_session_id) != 0 ||
   1235       rad_put_int(r->cx.rad, RAD_ACCT_DELAY_TIME, 0) != 0) {
   1236 /* XXX ACCT_DELAY_TIME should be increased each time a packet is waiting */
   1237     log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
   1238     rad_close(r->cx.rad);
   1239     return;
   1240   }
   1241 
   1242   if (acct_type == RAD_STOP || acct_type == RAD_ALIVE)
   1243     /* Show some statistics */
   1244     if (rad_put_int(r->cx.rad, RAD_ACCT_INPUT_OCTETS, stats->OctetsIn % UINT32_MAX) != 0 ||
   1245         rad_put_int(r->cx.rad, RAD_ACCT_INPUT_GIGAWORDS, stats->OctetsIn / UINT32_MAX) != 0 ||
   1246         rad_put_int(r->cx.rad, RAD_ACCT_INPUT_PACKETS, stats->PacketsIn) != 0 ||
   1247         rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_OCTETS, stats->OctetsOut % UINT32_MAX) != 0 ||
   1248         rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_GIGAWORDS, stats->OctetsOut / UINT32_MAX) != 0 ||
   1249         rad_put_int(r->cx.rad, RAD_ACCT_OUTPUT_PACKETS, stats->PacketsOut)
   1250         != 0 ||
   1251         rad_put_int(r->cx.rad, RAD_ACCT_SESSION_TIME, throughput_uptime(stats))
   1252         != 0) {
   1253       log_Printf(LogERROR, "rad_put: %s\n", rad_strerror(r->cx.rad));
   1254       rad_close(r->cx.rad);
   1255       return;
   1256     }
   1257 
   1258   if (log_IsKept(LogPHASE) || log_IsKept(LogRADIUS)) {
   1259     const char *what;
   1260     int level;
   1261 
   1262     switch (acct_type) {
   1263     case RAD_START:
   1264       what = "START";
   1265       level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
   1266       break;
   1267     case RAD_STOP:
   1268       what = "STOP";
   1269       level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
   1270       break;
   1271     case RAD_ALIVE:
   1272       what = "ALIVE";
   1273       level = LogRADIUS;
   1274       break;
   1275     default:
   1276       what = "<unknown>";
   1277       level = log_IsKept(LogPHASE) ? LogPHASE : LogRADIUS;
   1278       break;
   1279     }
   1280     log_Printf(level, "Radius(acct): %s data sent\n", what);
   1281   }
   1282 
   1283   r->cx.auth = NULL;			/* Not valid for accounting requests */
   1284   if ((got = rad_init_send_request(r->cx.rad, &r->cx.fd, &tv)))
   1285     radius_Process(r, got);
   1286   else {
   1287     log_Printf(LogDEBUG, "Using radius_Timeout [%p]\n", radius_Timeout);
   1288     r->cx.timer.load = tv.tv_usec / TICKUNIT + tv.tv_sec * SECTICKS;
   1289     r->cx.timer.func = radius_Timeout;
   1290     r->cx.timer.name = "radius acct";
   1291     r->cx.timer.arg = r;
   1292     timer_Start(&r->cx.timer);
   1293   }
   1294 }
   1295 
   1296 /*
   1297  * How do things look at the moment ?
   1298  */
   1299 void
   1300 radius_Show(struct radius *r, struct prompt *p)
   1301 {
   1302   prompt_Printf(p, " Radius config:     %s",
   1303                 *r->cfg.file ? r->cfg.file : "none");
   1304   if (r->valid) {
   1305     prompt_Printf(p, "\n                IP: %s\n", inet_ntoa(r->ip));
   1306     prompt_Printf(p, "           Netmask: %s\n", inet_ntoa(r->mask));
   1307     prompt_Printf(p, "               MTU: %lu\n", r->mtu);
   1308     prompt_Printf(p, "                VJ: %sabled\n", r->vj ? "en" : "dis");
   1309     prompt_Printf(p, "           Message: %s\n", r->repstr ? r->repstr : "");
   1310     prompt_Printf(p, "   MPPE Enc Policy: %s\n",
   1311                   radius_policyname(r->mppe.policy));
   1312     prompt_Printf(p, "    MPPE Enc Types: %s\n",
   1313                   radius_typesname(r->mppe.types));
   1314     prompt_Printf(p, "     MPPE Recv Key: %seceived\n",
   1315                   r->mppe.recvkey ? "R" : "Not r");
   1316     prompt_Printf(p, "     MPPE Send Key: %seceived\n",
   1317                   r->mppe.sendkey ? "R" : "Not r");
   1318     prompt_Printf(p, " MS-CHAP2-Response: %s\n",
   1319                   r->msrepstr ? r->msrepstr : "");
   1320     prompt_Printf(p, "     Error Message: %s\n", r->errstr ? r->errstr : "");
   1321     if (r->routes)
   1322       route_ShowSticky(p, r->routes, "            Routes", 16);
   1323 #ifndef NOINET6
   1324     if (r->ipv6routes)
   1325       route_ShowSticky(p, r->ipv6routes, "            IPv6 Routes", 16);
   1326 #endif
   1327   } else
   1328     prompt_Printf(p, " (not authenticated)\n");
   1329 }
   1330 
   1331 static void
   1332 radius_alive(void *v)
   1333 {
   1334   struct bundle *bundle = (struct bundle *)v;
   1335 
   1336   timer_Stop(&bundle->radius.alive.timer);
   1337   bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS;
   1338   if (bundle->radius.alive.timer.load) {
   1339     radius_Account(&bundle->radius, &bundle->radacct,
   1340                    bundle->links, RAD_ALIVE, &bundle->ncp.ipcp.throughput);
   1341     timer_Start(&bundle->radius.alive.timer);
   1342   }
   1343 }
   1344 
   1345 void
   1346 radius_StartTimer(struct bundle *bundle)
   1347 {
   1348   if (bundle->radius.cfg.file && bundle->radius.alive.interval) {
   1349     bundle->radius.alive.timer.func = radius_alive;
   1350     bundle->radius.alive.timer.name = "radius alive";
   1351     bundle->radius.alive.timer.load = bundle->radius.alive.interval * SECTICKS;
   1352     bundle->radius.alive.timer.arg = bundle;
   1353     radius_alive(bundle);
   1354   }
   1355 }
   1356 
   1357 void
   1358 radius_StopTimer(struct radius *r)
   1359 {
   1360   timer_Stop(&r->alive.timer);
   1361 }
   1362