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