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