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