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