Massively cleaned up #include's, so they're in a consistent
[freeradius.git] / src / main / listen.c
1 /*
2  * listen.c     Handle socket stuff
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2005,2006  The FreeRADIUS server project
21  * Copyright 2005  Alan DeKok <aland@ox.org>
22  */
23
24 #include <freeradius-devel/ident.h>
25 RCSID("$Id$")
26
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/radius_snmp.h>
29 #include <freeradius-devel/rad_assert.h>
30
31 #include <sys/resource.h>
32
33 #ifdef HAVE_NET_IF_H
34 #include <net/if.h>
35 #endif
36
37 #ifdef HAVE_SYS_STAT_H
38 #include <sys/stat.h>
39 #endif
40
41 #include <fcntl.h>
42
43 static time_t start_time = 0;
44
45 /*
46  *      FIXME: Delete this crap!
47  */
48 extern time_t time_now;
49
50 /*
51  *      We'll use this below.
52  */
53 typedef int (*rad_listen_parse_t)(const char *, int, const CONF_SECTION *, rad_listen_t *);
54 typedef void (*rad_listen_free_t)(rad_listen_t *);
55
56 typedef struct rad_listen_master_t {
57         rad_listen_parse_t      parse;
58         rad_listen_free_t       free;
59         rad_listen_recv_t       recv;
60         rad_listen_send_t       send;
61         rad_listen_print_t      print;
62         rad_listen_encode_t     encode;
63         rad_listen_decode_t     decode;
64 } rad_listen_master_t;
65
66 typedef struct listen_socket_t {
67         /*
68          *      For normal sockets.
69          */
70         lrad_ipaddr_t   ipaddr;
71         int             port;
72         RADCLIENT_LIST  *clients;
73 } listen_socket_t;
74
75 typedef struct listen_detail_t {
76         const char      *detail;
77         VALUE_PAIR      *vps;
78         FILE            *fp;
79         int             state;
80         time_t          timestamp;
81         lrad_ipaddr_t   client_ip;
82         int             max_outstanding;
83         int             *outstanding;
84 } listen_detail_t;
85                                
86
87 /*
88  *      Find a per-socket client.
89  */
90 static RADCLIENT *client_listener_find(const rad_listen_t *listener,
91                                        const lrad_ipaddr_t *ipaddr)
92 {
93         const RADCLIENT_LIST *clients;
94
95         rad_assert(listener != NULL);
96         rad_assert(ipaddr != NULL);
97
98         rad_assert((listener->type == RAD_LISTEN_AUTH) ||
99                    (listener->type == RAD_LISTEN_ACCT));
100
101         clients = ((listen_socket_t *)listener->data)->clients;
102         if (!clients) clients = mainconfig.clients;
103
104         rad_assert(clients != NULL);
105         
106         return client_find(clients, ipaddr);
107 }
108
109 static int listen_bind(rad_listen_t *this);
110
111 /*
112  *      FIXME: have the detail reader use another config "exit when done",
113  *      so that it can be used as a one-off tool to update stuff.
114  */
115
116 /*
117  *      Process and reply to a server-status request.
118  *      Like rad_authenticate and rad_accounting this should
119  *      live in it's own file but it's so small we don't bother.
120  */
121 static int rad_status_server(REQUEST *request)
122 {
123         switch (request->listener->type) {
124         case RAD_LISTEN_AUTH:
125                 request->reply->code = PW_AUTHENTICATION_ACK;
126
127                 /*
128                  *      Commented out for now.
129                  */
130 #if 0
131  { 
132                 char            reply_msg[64];
133                 time_t          t;
134                 VALUE_PAIR      *vp;
135                 
136                 /*
137                  *      Reply with an ACK. We might want to add some more
138                  *      interesting reply attributes, such as server uptime.
139                  */
140                 t = request->timestamp - start_time;
141                 sprintf(reply_msg, "FreeRADIUS STUFF %d day%s, %02d:%02d",
142                         (int)(t / 86400), (t / 86400) == 1 ? "" : "s",
143                         (int)((t / 3600) % 24), (int)(t / 60) % 60);
144                 
145                 vp = pairmake("Reply-Message", reply_msg, T_OP_SET);
146                 pairadd(&request->reply->vps, vp); /* don't need to check if !vp */
147  }
148 #endif
149                 break;
150
151         case RAD_LISTEN_ACCT:
152                 request->reply->code = PW_ACCOUNTING_RESPONSE;
153                 break;
154
155         default:
156                 return 0;
157         }
158         
159
160         return 0;
161 }
162
163 static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
164 {
165         size_t len;
166         listen_socket_t *sock = this->data;
167
168         if ((sock->ipaddr.af == AF_INET) &&
169             (sock->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
170                 strcpy(buffer, "*");
171         } else {
172                 ip_ntoh(&sock->ipaddr, buffer, bufsize);
173         }
174
175         len = strlen(buffer);
176
177         return len + snprintf(buffer + len, bufsize - len, " port %d",
178                               sock->port);
179 }
180
181
182 /*
183  *      Parse an authentication or accounting socket.
184  */
185 static int common_socket_parse(const char *filename, int lineno,
186                              const CONF_SECTION *cs, rad_listen_t *this)
187 {
188         int             rcode;
189         int             listen_port;
190         lrad_ipaddr_t   ipaddr;
191         listen_socket_t *sock = this->data;
192         const char      *section_name = NULL;
193         CONF_SECTION    *client_cs;
194
195         /*
196          *      Try IPv4 first
197          */
198         ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
199         rcode = cf_item_parse(cs, "ipaddr", PW_TYPE_IPADDR,
200                               &ipaddr.ipaddr.ip4addr, NULL);
201         if (rcode < 0) return -1;
202         
203         if (rcode == 0) { /* successfully parsed IPv4 */
204                 ipaddr.af = AF_INET;
205                 
206         } else {        /* maybe IPv6? */
207                 rcode = cf_item_parse(cs, "ipv6addr", PW_TYPE_IPV6ADDR,
208                                       &ipaddr.ipaddr.ip6addr, NULL);
209                 if (rcode < 0) return -1;
210                 
211                 if (rcode == 1) {
212                         radlog(L_ERR, "%s[%d]: No address specified in listen section",
213                                filename, lineno);
214                         return -1;
215                 }
216                 ipaddr.af = AF_INET6;
217         }
218         
219         rcode = cf_item_parse(cs, "port", PW_TYPE_INTEGER,
220                               &listen_port, "0");
221         if (rcode < 0) return -1;
222         
223         sock->ipaddr = ipaddr;
224         sock->port = listen_port;
225
226         /*
227          *      And bind it to the port.
228          */
229         if (listen_bind(this) < 0) {
230                 char buffer[128];
231                 radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s port %d",
232                        filename, cf_section_lineno(cs),
233                        ip_ntoh(&sock->ipaddr, buffer, sizeof(buffer)),
234                        sock->port);
235                 return -1;
236         }
237
238         /*
239          *      If we can bind to interfaces, do so,
240          *      else don't.
241          */
242         if (cf_pair_find(cs, "interface")) {
243 #ifndef SO_BINDTODEVICE
244                 radlog(L_CONS|L_ERR, "%s[%d]: System does not support binding to interfaces, delete this line from the configuration file.",
245                        filename, cf_section_lineno(cs));
246                 return -1;
247 #else
248                 const char *value;
249                 const CONF_PAIR *cp = cf_pair_find(cs, "interface");
250                 struct ifreq ifreq;
251
252                 rad_assert(cp != NULL);
253                 value = cf_pair_value(cp);
254                 rad_assert(value != NULL);
255                 
256                 strcpy(ifreq.ifr_name, value);
257         
258                 if (setsockopt(this->fd, SOL_SOCKET, SO_BINDTODEVICE,
259                                (char *)&ifreq, sizeof(ifreq)) < 0) {
260                         radlog(L_CONS|L_ERR, "%s[%d]: Failed binding to interface %s: %s",
261                                filename, cf_section_lineno(cs),
262                                value, strerror(errno));
263                         return -1;
264                 } /* else it worked. */
265 #endif
266         }
267
268         /*
269          *      Look for the name of a section that holds a list
270          *      of clients.
271          */
272         rcode = cf_item_parse(cs, "clients", PW_TYPE_STRING_PTR,
273                               &section_name, NULL);
274         if (rcode < 0) return -1; /* bad string */
275         if (rcode > 0) return 0; /* non-existent is OK. */
276
277         client_cs = cf_section_find(section_name);
278         free(section_name);
279         if (!client_cs) {
280                 radlog(L_CONS|L_ERR, "%s[%d]: Failed to find client section %s",
281                        filename, cf_section_lineno(cs), section_name);
282                 return -1;
283         }
284
285         sock->clients = clients_parse_section(filename, client_cs);
286         if (!sock->clients) {
287                 return -1;
288         }
289
290         return 0;
291 }
292
293 /*
294  *      Send an authentication response packet
295  */
296 static int auth_socket_send(rad_listen_t *listener, REQUEST *request)
297 {
298         rad_assert(request->listener == listener);
299         rad_assert(listener->send == auth_socket_send);
300
301         return rad_send(request->reply, request->packet, request->secret);
302 }
303
304
305 /*
306  *      Send an accounting response packet (or not)
307  */
308 static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
309 {
310         rad_assert(request->listener == listener);
311         rad_assert(listener->send == acct_socket_send);
312
313         /*
314          *      Accounting reject's are silently dropped.
315          *
316          *      We do it here to avoid polluting the rest of the
317          *      code with this knowledge
318          */
319         if (request->reply->code == 0) return 0;
320
321         return rad_send(request->reply, request->packet, request->secret);
322 }
323
324
325 /*
326  *      Send a packet to a home server.
327  *
328  *      FIXME: have different code for proxy auth & acct!
329  */
330 static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
331 {
332         listen_socket_t *sock = listener->data;
333
334         rad_assert(request->proxy_listener == listener);
335         rad_assert(listener->send == proxy_socket_send);
336
337         request->proxy->src_ipaddr = sock->ipaddr;
338         request->proxy->src_port = sock->port;
339
340         return rad_send(request->proxy, request->packet,
341                         request->home_server->secret);
342 }
343
344
345 /*
346  *      Check if an incoming request is "ok"
347  *
348  *      It takes packets, not requests.  It sees if the packet looks
349  *      OK.  If so, it does a number of sanity checks on it.
350   */
351 static int auth_socket_recv(rad_listen_t *listener,
352                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
353 {
354         RADIUS_PACKET   *packet;
355         RAD_REQUEST_FUNP fun = NULL;
356         char            buffer[128];
357         RADCLIENT       *client;
358
359         packet = rad_recv(listener->fd);
360         if (!packet) {
361                 radlog(L_ERR, "%s", librad_errstr);
362                 return 0;
363         }
364
365         RAD_SNMP_TYPE_INC(listener, total_requests); /* FIXME: auth specific */
366
367         if ((client = client_listener_find(listener,
368                                            &packet->src_ipaddr)) == NULL) {
369                 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
370                 
371                 radlog(L_ERR, "Ignoring request from unknown client %s port %d",
372                        inet_ntop(packet->src_ipaddr.af,
373                                  &packet->src_ipaddr.ipaddr,
374                                  buffer, sizeof(buffer)),
375                        packet->src_port);
376                 rad_free(&packet);
377                 return 0;
378         }
379
380         /*
381          *      Some sanity checks, based on the packet code.
382          */
383         switch(packet->code) {
384         case PW_AUTHENTICATION_REQUEST:
385                 fun = rad_authenticate;
386                 break;
387                 
388         case PW_STATUS_SERVER:
389                 if (!mainconfig.status_server) {
390                         RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
391                         DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
392                         rad_free(&packet);
393                         return 0;
394                 }
395                 fun = rad_status_server;
396                 break;
397
398         default:
399                 RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
400                 
401                 radlog(L_ERR, "Invalid packet code %d sent to authentication port from client %s port %d "
402                        "- ID %d : IGNORED",
403                        packet->code, client->shortname,
404                        packet->src_port, packet->id);
405                 rad_free(&packet);
406                 return 0;
407                 break;
408         } /* switch over packet types */
409         
410         if (!received_request(listener, packet, prequest, client)) {
411                 rad_free(&packet);
412                 return 0;
413         }
414
415         *pfun = fun;
416         return 1;
417 }
418
419
420 /*
421  *      Receive packets from an accounting socket
422  */
423 static int acct_socket_recv(rad_listen_t *listener,
424         RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
425 {
426         RADIUS_PACKET   *packet;
427         RAD_REQUEST_FUNP fun = NULL;
428         char            buffer[128];
429         RADCLIENT       *client;
430         
431         packet = rad_recv(listener->fd);
432         if (!packet) {
433                 radlog(L_ERR, "%s", librad_errstr);
434                 return 0;
435         }
436         
437         RAD_SNMP_TYPE_INC(listener, total_requests); /* FIXME: acct-specific */
438
439         if ((client = client_listener_find(listener,
440                                            &packet->src_ipaddr)) == NULL) {
441                 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
442                 
443                 radlog(L_ERR, "Ignoring request from unknown client %s port %d",
444                        inet_ntop(packet->src_ipaddr.af,
445                                  &packet->src_ipaddr.ipaddr,
446                                  buffer, sizeof(buffer)),
447                        packet->src_port);
448                 rad_free(&packet);
449                 return 0;
450         }
451
452         switch(packet->code) {
453         case PW_ACCOUNTING_REQUEST:
454                 fun = rad_accounting;
455                 break;
456                 
457         case PW_STATUS_SERVER:
458                 if (!mainconfig.status_server) {
459                         RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
460                         DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
461                         rad_free(&packet);
462                         return 0;
463                 }
464                 fun = rad_status_server;
465                 break;
466
467         default:
468                 /*
469                  *      FIXME: Update MIB for packet types?
470                  */
471                 radlog(L_ERR, "Invalid packet code %d sent to a accounting port "
472                        "from client %s port %d - ID %d : IGNORED",
473                        packet->code, client->shortname,
474                        packet->src_port, packet->id);
475                 rad_free(&packet);
476                 return 0;
477         }
478
479         /*
480          *      FIXME: Accounting duplicates should be handled
481          *      differently than authentication duplicates.
482          */
483         if (!received_request(listener, packet, prequest, client)) {
484                 rad_free(&packet);
485                 return 0;
486         }
487
488         *pfun = fun;
489         return 1;
490 }
491
492
493 /*
494  *      Recieve packets from a proxy socket.
495  */
496 static int proxy_socket_recv(rad_listen_t *listener,
497                               RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
498 {
499         REQUEST         *request;
500         RADIUS_PACKET   *packet;
501         RAD_REQUEST_FUNP fun = NULL;
502         char            buffer[128];
503         
504         packet = rad_recv(listener->fd);
505         if (!packet) {
506                 radlog(L_ERR, "%s", librad_errstr);
507                 return 0;
508         }
509
510         /*
511          *      FIXME: Client MIB updates?
512          */
513         switch(packet->code) {
514         case PW_AUTHENTICATION_ACK:
515         case PW_ACCESS_CHALLENGE:
516         case PW_AUTHENTICATION_REJECT:
517                 fun = rad_authenticate;
518                 break;
519                 
520         case PW_ACCOUNTING_RESPONSE:
521                 fun = rad_accounting;
522                 break;
523                 
524         default:
525                 /*
526                  *      FIXME: Update MIB for packet types?
527                  */
528                 radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
529                        "from home server %s port %d - ID %d : IGNORED",
530                        packet->code,
531                        ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
532                        packet->src_port, packet->id);
533                 rad_free(&packet);
534                 return 0;
535         }
536
537         request = received_proxy_response(packet);
538         if (!request) {
539                 return 0;
540         }
541
542         rad_assert(fun != NULL);
543         *pfun = fun;
544         *prequest = request;
545
546         return 1;
547 }
548
549
550 static int client_socket_encode(rad_listen_t *listener, REQUEST *request)
551 {
552         if (!request->reply->code) return 0;
553
554         rad_encode(request->reply, request->packet, request->secret);
555         rad_sign(request->reply, request->packet, request->secret);
556
557         return 0;
558 }
559
560
561 static int client_socket_decode(rad_listen_t *listener, REQUEST *request)
562 {
563         if (rad_verify(request->packet, NULL, request->secret) < 0) {
564                 return -1;
565         }
566
567         return rad_decode(request->packet, NULL, request->secret);
568 }
569
570 static int proxy_socket_encode(rad_listen_t *listener, REQUEST *request)
571 {
572         rad_encode(request->proxy, NULL, request->home_server->secret);
573         rad_sign(request->proxy, NULL, request->home_server->secret);
574
575         return 0;
576 }
577
578
579 static int proxy_socket_decode(rad_listen_t *listener, REQUEST *request)
580 {
581         if (rad_verify(request->proxy_reply, request->proxy,
582                        request->home_server->secret) < 0) {
583                 return -1;
584         }
585
586         return rad_decode(request->proxy_reply, request->proxy,
587                            request->home_server->secret);
588 }
589
590
591 #define STATE_UNOPENED  (0)
592 #define STATE_UNLOCKED  (1)
593 #define STATE_HEADER    (2)
594 #define STATE_READING   (3)
595 #define STATE_DONE      (4)
596 #define STATE_WAITING   (5)
597
598 /*
599  *      If we're limiting outstanding packets, then mark the response
600  *      as being sent.
601  */
602 static int detail_send(rad_listen_t *listener, REQUEST *request)
603 {
604         listen_detail_t *data = listener->data;
605
606         rad_assert(request->listener == listener);
607         rad_assert(listener->send == detail_send);
608
609         if (request->simul_max >= 0) {
610                 rad_assert(data->outstanding != NULL);
611                 rad_assert(request->simul_max < data->max_outstanding);
612
613                 data->outstanding[request->simul_max] = 0;
614         }
615
616         return 0;
617 }
618
619
620 /*
621  *      Open the detail file..
622  *
623  *      FIXME: create it, if it's not already there, so that the main
624  *      server select() will wake us up if there's anything to read.
625  */
626 static int detail_open(rad_listen_t *this)
627 {
628         struct stat st;
629         char buffer[2048];
630         listen_detail_t *data = this->data;
631
632         rad_assert(data->state == STATE_UNOPENED);
633         snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
634         
635         /*
636          *      FIXME: Have "one-shot" configuration, where it
637          *      will read the detail file, and exit once it's
638          *      done.
639          *
640          *      FIXME: Try harder to open the detail file.
641          *      Maybe sleep for X usecs if it doesn't exist?
642          */
643
644         /*
645          *      Open detail.work first, so we don't lose
646          *      accounting packets.  It's probably better to
647          *      duplicate them than to lose them.
648          *
649          *      Note that we're not writing to the file, but
650          *      we've got to open it for writing in order to
651          *      establish the lock, to prevent rlm_detail from
652          *      writing to it.
653          */
654         this->fd = open(buffer, O_RDWR);
655         if (this->fd < 0) {
656                 /*
657                  *      Try reading the detail file.  If it
658                  *      doesn't exist, we can't do anything.
659                  *
660                  *      Doing the stat will tell us if the file
661                  *      exists, even if we don't have permissions
662                  *      to read it.
663                  */
664                 if (stat(data->detail, &st) < 0) {
665                         return 0;
666                 }
667                 
668                 /*
669                  *      Open it BEFORE we rename it, just to
670                  *      be safe...
671                  */
672                 this->fd = open(data->detail, O_RDWR);
673                 if (this->fd < 0) {
674                         radlog(L_ERR, "Failed to open %s: %s",
675                                data->detail, strerror(errno));
676                         return 0;
677                 }
678                 
679                 /*
680                  *      Rename detail to detail.work
681                  */
682                 if (rename(data->detail, buffer) < 0) {
683                         close(this->fd);
684                         this->fd = -1;
685                         return 0;
686                 }
687         } /* else detail.work existed, and we opened it */
688         
689         rad_assert(data->vps == NULL);
690         
691         rad_assert(data->fp == NULL);
692         data->fp = fdopen(this->fd, "r");
693         if (!data->fp) {
694                 radlog(L_ERR, "Failed to re-open %s: %s",
695                        data->detail, strerror(errno));
696                 return 0;
697         }
698
699         data->state = STATE_UNLOCKED;
700
701         data->client_ip.af = AF_UNSPEC;
702         data->timestamp = 0;
703         
704         return 1;
705 }
706
707 /*
708  *      This is a bad hack, just so complaints have meaningful text.
709  */
710 static const RADCLIENT detail_client = {
711         {               /* ipaddr */
712                 AF_INET,
713                 {{ INADDR_NONE }}
714         },
715         32,
716         "<detail-file>",
717         "secret",
718         "UNKNOWN-CLIENT",
719         "other",
720         "",
721         "",
722         -1
723 };
724
725 static int detail_recv(rad_listen_t *listener,
726                        RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
727 {
728         int             free_slot = -1;
729         char            key[256], value[1024];
730         VALUE_PAIR      *vp, **tail;
731         RADIUS_PACKET   *packet;
732         char            buffer[2048];
733         listen_detail_t *data = listener->data;
734
735         if (data->state == STATE_UNOPENED) {
736                 rad_assert(listener->fd < 0);
737                 if (!detail_open(listener)) return 0;
738         }
739         rad_assert(listener->fd >= 0);
740
741         /*
742          *      Try to lock fd.  If we can't, return.  If we can,
743          *      continue.  This means that the server doesn't block
744          *      while waiting for the lock to open...
745          */
746         if (data->state == STATE_UNLOCKED) {
747                 /*
748                  *      Note that we do NOT block waiting for the
749                  *      lock.  We've re-named the file above, so we've
750                  *      already guaranteed that any *new* detail
751                  *      writer will not be opening this file.  The
752                  *      only purpose of the lock is to catch a race
753                  *      condition where the execution "ping-pongs"
754                  *      between radiusd & radrelay.
755                  */
756                 if (rad_lockfd_nonblock(listener->fd, 0) < 0) {
757                         return 0;
758                 }
759                 /*
760                  *      Look for the header
761                  */
762                 data->state = STATE_HEADER;
763         }
764
765         /*
766          *      Catch an out of memory condition which will most likely
767          *      never be met.
768          */
769         if (data->state == STATE_DONE) goto alloc_packet;
770
771         /*
772          *      If we're in another state, then it means that we read
773          *      a partial packet, which is bad.
774          */
775         rad_assert(data->state == STATE_HEADER);
776         rad_assert(data->vps == NULL);
777
778         /*
779          *      We read the last packet, and returned it for
780          *      processing.  We later come back here to shut
781          *      everything down, and unlink the file.
782          */
783         if (feof(data->fp)) {
784                 rad_assert(data->state == STATE_HEADER);
785
786                 /*
787                  *      Don't unlink the file until we've received
788                  *      all of the responses.
789                  */
790                 if (data->max_outstanding > 0) {
791                         int i;
792
793                         for (i = 0; i < data->max_outstanding; i++) {
794                                 /*
795                                  *      FIXME: close the file?
796                                  */
797                                 if (data->outstanding[i]) {
798                                         data->state = STATE_WAITING;
799                                         return 0;
800                                 }
801                         }
802                 }
803
804         cleanup:
805                 rad_assert(data->vps == NULL);
806
807                 snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
808                 unlink(buffer);
809                 fclose(data->fp); /* closes listener->fd */
810                 data->fp = NULL;
811                 listener->fd = -1;
812                 data->state = STATE_UNOPENED;
813
814                 /*
815                  *      Try to open "detail" again.  If we're on a
816                  *      busy RADIUS server, odds are that it will
817                  *      now exist.
818                  */
819                 detail_open(listener);
820                 return 0;
821         }
822
823         tail = &data->vps;
824
825         /*
826          *      Fill the buffer...
827          */
828         while (fgets(buffer, sizeof(buffer), data->fp)) {
829                 /*
830                  *      No CR, die.
831                  */
832                 if (!strchr(buffer, '\n')) {
833                         pairfree(&data->vps);
834                         goto cleanup;
835                 }
836
837                 /*
838                  *      We've read a header, possibly packet contents,
839                  *      and are now at the end of the packet.
840                  */
841                 if ((data->state == STATE_READING) &&
842                     (buffer[0] == '\n')) {
843                         data->state = STATE_DONE;
844                         break;
845                 }
846
847                 /*
848                  *      Look for date/time header, and read VP's if
849                  *      found.  If not, keep reading lines until we
850                  *      find one.
851                  */
852                 if (data->state == STATE_HEADER) {
853                         int y;
854                         
855                         if (sscanf(buffer, "%*s %*s %*d %*d:%*d:%*d %d", &y)) {
856                                 data->state = STATE_READING;
857                         }
858                         continue;
859                 }
860
861                 /*
862                  *      We have a full "attribute = value" line.
863                  *      If it doesn't look reasonable, skip it.
864                  */
865                 if (sscanf(buffer, "%255s = %1023s", key, value) != 2) {
866                         continue;
867                 }
868
869                 /*
870                  *      Skip non-protocol attributes.
871                  */
872                 if (!strcasecmp(key, "Request-Authenticator")) continue;
873
874                 /*
875                  *      Set the original client IP address, based on
876                  *      what's in the detail file.
877                  *
878                  *      Hmm... we don't set the server IP address.
879                  *      or port.  Oh well.
880                  */
881                 if (!strcasecmp(key, "Client-IP-Address")) {
882                         data->client_ip.af = AF_INET;
883                         ip_hton(value, AF_INET, &data->client_ip);
884                         continue;
885                 }
886
887                 /*
888                  *      The original time at which we received the
889                  *      packet.  We need this to properly calculate
890                  *      Acct-Delay-Time.
891                  */
892                 if (!strcasecmp(key, "Timestamp")) {
893                         data->timestamp = atoi(value);
894                         continue;
895                 }
896
897                 /*
898                  *      Read one VP.
899                  *
900                  *      FIXME: do we want to check for non-protocol
901                  *      attributes like radsqlrelay does?
902                  */
903                 vp = NULL;
904                 if ((userparse(buffer, &vp) > 0) &&
905                     (vp != NULL)) {
906                         *tail = vp;
907                         tail = &(vp->next);
908                 }               
909         }
910
911         /*
912          *      We got to EOF,  If we're in STATE_HEADER, it's OK.
913          *      Otherwise it's a problem.  In any case, nuke the file
914          *      and start over from scratch,
915          */
916         if (feof(data->fp)) {
917                 goto cleanup;
918         }
919
920         /*
921          *      FIXME: Do load management.
922          */
923
924         /*
925          *      If we're not done, then there's a problem.  The checks
926          *      above for EOF
927          */
928         rad_assert(data->state == STATE_DONE);
929
930         /*
931          *      The packet we read was empty, re-set the state to look
932          *      for a header, and don't return anything.
933          */
934         if (!data->vps) {
935                 data->state = STATE_HEADER;
936                 return 0;
937         }
938
939         /*
940          *      Allocate the packet.  If we fail, it's a serious
941          *      problem.
942          */
943  alloc_packet:
944         /*
945          *      If we keep track of the outstanding requests, do so
946          *      here.  Note that to minimize potential work, we do
947          *      so only once the file is opened & locked.
948          */
949         if (data->max_outstanding) {
950                 int i;
951
952                 for (i = 0; i < data->max_outstanding; i++) {
953                         if (!data->outstanding[i]) {
954                                 free_slot = i;
955                                 break;
956                         }
957                 }
958
959                 /*
960                  *      All of the slots are full.  Put the LF back,
961                  *      so select will say that data is ready, and set
962                  *      the state back to reading.  Then, return so
963                  *      that we don't overload the server.
964                  */
965                 if (free_slot < 0) {
966                         ungetc('\n', data->fp);
967                         data->state = STATE_READING;
968                         return 0;
969                 }
970         }
971
972         packet = rad_alloc(1);
973         if (!packet) {
974                 return 0;       /* maybe memory will magically free up... */
975         }
976
977         memset(packet, 0, sizeof(*packet));
978         packet->sockfd = -1;
979         packet->src_ipaddr.af = AF_INET;
980         packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
981         packet->code = PW_ACCOUNTING_REQUEST;
982         packet->timestamp = time(NULL);
983
984         /*
985          *      Look for Acct-Delay-Time, and update
986          *      based on Acct-Delay-Time += (time(NULL) - timestamp)
987          */
988         vp = pairfind(packet->vps, PW_ACCT_DELAY_TIME);
989         if (!vp) {
990                 vp = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
991                 rad_assert(vp != NULL);
992         }
993         if (data->timestamp != 0) {
994                 vp->lvalue += time(NULL) - data->timestamp;
995         }
996
997         /*
998          *      Remember where it came from, so that we don't
999          *      proxy it to the place it came from...
1000          */
1001         if (data->client_ip.af != AF_UNSPEC) {
1002                 packet->src_ipaddr = data->client_ip;
1003         }
1004
1005         vp = pairfind(packet->vps, PW_PACKET_SRC_IP_ADDRESS);
1006         if (vp) {
1007                 packet->src_ipaddr.af = AF_INET;
1008                 packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
1009         } else {
1010                 vp = pairfind(packet->vps, PW_PACKET_SRC_IPV6_ADDRESS);
1011                 if (vp) {
1012                         packet->src_ipaddr.af = AF_INET6;
1013                         memcpy(&packet->src_ipaddr.ipaddr.ip6addr,
1014                                &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
1015                 }
1016         }
1017
1018         vp = pairfind(packet->vps, PW_PACKET_DST_IP_ADDRESS);
1019         if (vp) {
1020                 packet->dst_ipaddr.af = AF_INET;
1021                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
1022         } else {
1023                 vp = pairfind(packet->vps, PW_PACKET_DST_IPV6_ADDRESS);
1024                 if (vp) {
1025                         packet->dst_ipaddr.af = AF_INET6;
1026                         memcpy(&packet->dst_ipaddr.ipaddr.ip6addr,
1027                                &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
1028                 }
1029         }
1030
1031         /*
1032          *      We've got to give SOME value for Id & ports, so that
1033          *      the packets can be added to the request queue.
1034          *      However, we don't want to keep track of used/unused
1035          *      id's and ports, as that's a lot of work.  This hack
1036          *      ensures that (if we have real random numbers), that
1037          *      there will be a collision on every 2^(16+15+15+24 - 1)
1038          *      packets, on average.  That means we can read 2^37
1039          *      packets before having a collision, which means it's
1040          *      effectively impossible.
1041          */
1042         packet->id = lrad_rand() & 0xffff;
1043         packet->src_port = 1024 + (lrad_rand() & 0x7fff);
1044         packet->dst_port = 1024 + (lrad_rand() & 0x7fff);
1045
1046         packet->dst_ipaddr.af = AF_INET;
1047         packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl((INADDR_LOOPBACK & ~0xffffff) | (lrad_rand() & 0xffffff));
1048
1049         packet->vps = data->vps;
1050
1051         /*
1052          *      Re-set the state.
1053          */
1054         data->vps = NULL;
1055         data->state = STATE_HEADER;
1056
1057         /*
1058          *      Keep track of free slots, as a hack, in an otherwise
1059          *      unused 'int'
1060          */
1061         (*prequest)->simul_max = free_slot;
1062         data->outstanding[free_slot] = 1;
1063
1064         *pfun = rad_accounting;
1065
1066         if (debug_flag) {
1067                 printf("detail_recv: Read packet from %s\n", data->detail);
1068                 for (vp = packet->vps; vp; vp = vp->next) {
1069                         putchar('\t');
1070                         vp_print(stdout, vp);
1071                         putchar('\n');
1072                 }
1073         }
1074
1075         /*
1076          *      FIXME: many of these checks may not be necessary when
1077          *      reading from the detail file.
1078          */
1079         if (!received_request(listener, packet, prequest, &detail_client)) {
1080                 rad_free(&packet);
1081                 return 0;
1082         }
1083
1084         return 1;
1085 }
1086
1087
1088 /*
1089  *      Free detail-specific stuff.
1090  */
1091 static void detail_free(rad_listen_t *this)
1092 {
1093         listen_detail_t *data = this->data;
1094
1095         free(data->detail);
1096         pairfree(&data->vps);
1097         free(data->outstanding);
1098
1099         if (data->fp != NULL) fclose(data->fp);
1100 }
1101
1102
1103 static int detail_print(rad_listen_t *this, char *buffer, size_t bufsize)
1104 {
1105         return snprintf(buffer, bufsize, "%s",
1106                         ((listen_detail_t *)(this->data))->detail);
1107 }
1108
1109 static int detail_encode(rad_listen_t *this, REQUEST *request)
1110 {
1111         /*
1112          *      We never encode responses "sent to" the detail file.
1113          */
1114         return 0;
1115 }
1116
1117 static int detail_decode(rad_listen_t *this, REQUEST *request)
1118 {
1119         /*
1120          *      We never decode responses read from the detail file.
1121          */
1122         return 0;
1123 }
1124
1125
1126 static const CONF_PARSER detail_config[] = {
1127         { "detail",   PW_TYPE_STRING_PTR,
1128           offsetof(listen_detail_t, detail), NULL,  NULL },
1129         { "max_outstanding",  PW_TYPE_INTEGER,
1130            offsetof(listen_detail_t, max_outstanding), NULL, "100" },
1131
1132         { NULL, -1, 0, NULL, NULL }             /* end the list */
1133 };
1134
1135
1136 /*
1137  *      Parse a detail section.
1138  */
1139 static int detail_parse(const char *filename, int lineno,
1140                         const CONF_SECTION *cs, rad_listen_t *this)
1141 {
1142         int             rcode;
1143         listen_detail_t *data;
1144
1145         data = this->data;
1146
1147         rcode = cf_section_parse(cs, data, detail_config);
1148         if (rcode < 0) {
1149                 radlog(L_ERR, "%s[%d]: Failed parsing listen section",
1150                        filename, lineno);
1151                 return -1;
1152         }
1153
1154         if (!data->detail) {
1155                 radlog(L_ERR, "%s[%d]: No detail file specified in listen section",
1156                        filename, lineno);
1157                 return -1;
1158         }
1159         
1160         data->vps = NULL;
1161         data->fp = NULL;
1162         data->state = STATE_UNOPENED;
1163
1164         if (data->max_outstanding > 32768) data->max_outstanding = 32768;
1165
1166         if (data->max_outstanding > 0) {
1167                 data->outstanding = rad_malloc(sizeof(int) * data->max_outstanding);
1168         }
1169         
1170         detail_open(this);
1171
1172         return 0;
1173 }
1174
1175 static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
1176         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},    /* RAD_LISTEN_NONE */
1177
1178         /* authentication */
1179         { common_socket_parse, NULL,
1180           auth_socket_recv, auth_socket_send,
1181           socket_print, client_socket_encode, client_socket_decode },
1182
1183         /* accounting */
1184         { common_socket_parse, NULL,
1185           acct_socket_recv, acct_socket_send,
1186           socket_print, client_socket_encode, client_socket_decode},
1187
1188         /* proxying */
1189         { NULL, NULL,
1190           proxy_socket_recv, proxy_socket_send,
1191           socket_print, proxy_socket_encode, proxy_socket_decode },
1192
1193         /* detail */
1194         { detail_parse, detail_free,
1195           detail_recv, detail_send,
1196           detail_print, detail_encode, detail_decode }
1197 };
1198
1199
1200
1201 /*
1202  *      Binds a listener to a socket.
1203  */
1204 static int listen_bind(rad_listen_t *this)
1205 {
1206         rad_listen_t    **last;
1207         listen_socket_t *sock = this->data;
1208
1209         /*
1210          *      If the port is zero, then it means the appropriate
1211          *      thing from /etc/services.
1212          */
1213         if (sock->port == 0) {
1214                 struct servent  *svp;
1215
1216                 switch (this->type) {
1217                 case RAD_LISTEN_AUTH:
1218                         svp = getservbyname ("radius", "udp");
1219                         if (svp != NULL) {
1220                                 sock->port = ntohs(svp->s_port);
1221                         } else {
1222                                 sock->port = PW_AUTH_UDP_PORT;
1223                         }
1224                         break;
1225
1226                 case RAD_LISTEN_ACCT:
1227                         svp = getservbyname ("radacct", "udp");
1228                         if (svp != NULL) {
1229                                 sock->port = ntohs(svp->s_port);
1230                         } else {
1231                                 sock->port = PW_ACCT_UDP_PORT;
1232                         }
1233                         break;
1234
1235                 default:
1236                         radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
1237                         return -1;
1238                 }
1239         }
1240
1241         /*
1242          *      Find it in the old list, AFTER updating the port.  If
1243          *      it's there, use that, rather than creating a new
1244          *      socket.  This allows HUP's to re-use the old sockets,
1245          *      which means that packets waiting in the socket queue
1246          *      don't get lost.
1247          */
1248         for (last = &mainconfig.listen;
1249              *last != NULL;
1250              last = &((*last)->next)) {
1251                 if ((this->type == (*last)->type) &&
1252                     (sock->port == ((listen_socket_t *)((*last)->data))->port) &&
1253                     (sock->ipaddr.af == ((listen_socket_t *)((*last)->data))->ipaddr.af)) {
1254                         int equal;
1255
1256                         if (sock->ipaddr.af == AF_INET) {
1257                                 equal = (sock->ipaddr.ipaddr.ip4addr.s_addr == ((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip4addr.s_addr);
1258                         } else if (sock->ipaddr.af == AF_INET6) {
1259                                 equal = IN6_ARE_ADDR_EQUAL(&(sock->ipaddr.ipaddr.ip6addr), &(((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip6addr));
1260                         } else {
1261                                 equal = 0;
1262                         }
1263                         
1264                         if (equal) {
1265                                 this->fd = (*last)->fd;
1266                                 (*last)->fd = -1;
1267                                 return 0;
1268                         }
1269                 }
1270         }
1271
1272         this->fd = lrad_socket(&sock->ipaddr, sock->port);
1273         if (this->fd < 0) {
1274                 radlog(L_ERR|L_CONS, "ERROR: Failed to open socket: %s",
1275                        librad_errstr);
1276                 return -1;
1277         }
1278
1279 #if 0
1280 #ifdef O_NONBLOCK
1281         if ((flags = fcntl(this->fd, F_GETFL, NULL)) < 0)  { 
1282                 radlog(L_ERR, "Failure in fcntl: %s)\n", strerror(errno)); 
1283                 return -1;
1284         }
1285
1286         flags |= O_NONBLOCK; 
1287         if( fcntl(this->fd, F_SETFL, flags) < 0) { 
1288                 radlog(L_ERR, "Failure in fcntl: %s)\n", strerror(errno)); 
1289                 return -1;
1290         }
1291 #endif
1292 #endif
1293
1294         return 0;
1295 }
1296
1297
1298 /*
1299  *      Allocate & initialize a new listener.
1300  */
1301 static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
1302 {
1303         rad_listen_t *this;
1304
1305         this = rad_malloc(sizeof(*this));
1306         memset(this, 0, sizeof(*this));
1307
1308         this->type = type;
1309         this->recv = master_listen[this->type].recv;
1310         this->send = master_listen[this->type].send;
1311         this->print = master_listen[this->type].print;
1312         this->encode = master_listen[this->type].encode;
1313         this->decode = master_listen[this->type].decode;
1314
1315         switch (type) {
1316         case RAD_LISTEN_AUTH:
1317         case RAD_LISTEN_ACCT:
1318         case RAD_LISTEN_PROXY:
1319                 this->data = rad_malloc(sizeof(listen_socket_t));
1320                 memset(this->data, 0, sizeof(listen_socket_t));
1321                 break;
1322
1323         case RAD_LISTEN_DETAIL:
1324                 this->data = rad_malloc(sizeof(listen_detail_t));
1325                 memset(this->data, 0, sizeof(listen_detail_t));
1326                 
1327         default:
1328                 break;
1329         }
1330
1331         return this;
1332 }
1333
1334
1335 /*
1336  *      Externally visible function for creating a new proxy LISTENER.
1337  *
1338  *      For now, don't take ipaddr or port.
1339  *
1340  *      Not thread-safe, but all calls to it are protected by the
1341  *      proxy mutex in request_list.c
1342  */
1343 rad_listen_t *proxy_new_listener()
1344 {
1345         int last_proxy_port, port;
1346         rad_listen_t *this, *tmp, **last;
1347         listen_socket_t *sock, *old;
1348
1349         this = listen_alloc(RAD_LISTEN_PROXY);
1350
1351         /*
1352          *      Find an existing proxy socket to copy.
1353          *
1354          *      FIXME: Make it per-realm, or per-home server!
1355          */
1356         last_proxy_port = 0;
1357         old = NULL;
1358         last = &mainconfig.listen;
1359         for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {
1360                 if (tmp->type == RAD_LISTEN_PROXY) {
1361                         sock = tmp->data;
1362                         if (sock->port > last_proxy_port) {
1363                                 last_proxy_port = sock->port + 1;
1364                         }
1365                         if (!old) old = sock;
1366                 }
1367
1368                 last = &(tmp->next);
1369         }
1370
1371         if (!old) return NULL;  /* This is a serious error. */
1372
1373         /*
1374          *      FIXME: find a new IP address to listen on?
1375          */
1376         sock = this->data;
1377         memcpy(&sock->ipaddr, &old->ipaddr, sizeof(sock->ipaddr));
1378
1379         /*
1380          *      Keep going until we find an unused port.
1381          */
1382         for (port = last_proxy_port; port < 64000; port++) {
1383                 sock->port = port;
1384                 if (listen_bind(this) == 0) {
1385                         /*
1386                          *      Add the new listener to the list of
1387                          *      listeners.
1388                          */
1389                         *last = this;
1390                         return this;
1391                 }
1392         }
1393
1394         return NULL;
1395 }
1396
1397
1398 static const LRAD_NAME_NUMBER listen_compare[] = {
1399         { "auth",       RAD_LISTEN_AUTH },
1400         { "acct",       RAD_LISTEN_ACCT },
1401         { "detail",     RAD_LISTEN_DETAIL },
1402         { NULL, 0 },
1403 };
1404
1405
1406 /*
1407  *      Generate a list of listeners.  Takes an input list of
1408  *      listeners, too, so we don't close sockets with waiting packets.
1409  */
1410 int listen_init(const char *filename, rad_listen_t **head)
1411 {
1412         int             rcode;
1413         CONF_SECTION    *cs;
1414         rad_listen_t    **last;
1415         rad_listen_t    *this;
1416         lrad_ipaddr_t   server_ipaddr;
1417         int             auth_port = 0;
1418
1419         /*
1420          *      We shouldn't be called with a pre-existing list.
1421          */
1422         rad_assert(head && (*head == NULL));
1423         
1424         if (start_time != 0) start_time = time(NULL);
1425
1426         last = head;
1427         server_ipaddr.af = AF_UNSPEC;
1428
1429         /*
1430          *      If the port is specified on the command-line,
1431          *      it over-rides the configuration file.
1432          */
1433         if (mainconfig.port >= 0) {
1434                 auth_port = mainconfig.port;
1435         } else {
1436                 rcode = cf_item_parse(mainconfig.config, "port",
1437                                       PW_TYPE_INTEGER, &auth_port,
1438                                       Stringify(PW_AUTH_UDP_PORT));
1439                 if (rcode < 0) return -1; /* error parsing it */
1440
1441                 if (rcode == 0)
1442                         radlog(L_INFO, "WARNING: The directive 'port' is deprecated, and will be removed in future versions of FreeRADIUS. Please edit the configuration files to use the directive 'listen'.");
1443         }
1444
1445         /*
1446          *      If the IP address was configured on the command-line,
1447          *      use that as the "bind_address"
1448          */
1449         if (mainconfig.myip.af != AF_UNSPEC) {
1450                 memcpy(&server_ipaddr, &mainconfig.myip,
1451                        sizeof(server_ipaddr));
1452                 goto bind_it;
1453         }
1454
1455         /*
1456          *      Else look for bind_address and/or listen sections.
1457          */
1458         server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1459         rcode = cf_item_parse(mainconfig.config, "bind_address",
1460                               PW_TYPE_IPADDR,
1461                               &server_ipaddr.ipaddr.ip4addr, NULL);
1462         if (rcode < 0) return -1; /* error parsing it */
1463         
1464         if (rcode == 0) { /* successfully parsed IPv4 */
1465                 listen_socket_t *sock;
1466                 server_ipaddr.af = AF_INET;
1467
1468                 radlog(L_INFO, "WARNING: The directive 'bind_adress' is deprecated, and will be removed in future versions of FreeRADIUS. Please edit the configuration files to use the directive 'listen'.");
1469
1470         bind_it:
1471                 this = listen_alloc(RAD_LISTEN_AUTH);
1472                 sock = this->data;
1473
1474                 sock->ipaddr = server_ipaddr;
1475                 sock->port = auth_port;
1476                 
1477                 if (listen_bind(this) < 0) {
1478                         listen_free(&this);
1479                         listen_free(head);
1480                         radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->port);
1481                         return -1;
1482                 }
1483                 auth_port = sock->port; /* may have been updated in listen_bind */
1484                 *last = this;
1485                 last = &(this->next);
1486                 
1487                 /*
1488                  *      Open Accounting Socket.
1489                  *
1490                  *      If we haven't already gotten acct_port from
1491                  *      /etc/services, then make it auth_port + 1.
1492                  */
1493                 this = listen_alloc(RAD_LISTEN_ACCT);
1494                 sock = this->data;
1495                 
1496                 /*
1497                  *      Create the accounting socket.
1498                  *
1499                  *      The accounting port is always the
1500                  *      authentication port + 1
1501                  */
1502                 sock->ipaddr = server_ipaddr;
1503                 sock->port = auth_port + 1;
1504                 
1505                 if (listen_bind(this) < 0) {
1506                         listen_free(&this);
1507                         listen_free(head);
1508                         radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->port);
1509                         return -1;
1510                 }
1511
1512                 *last = this;
1513                 last = &(this->next);
1514
1515         } else if (mainconfig.port > 0) { /* no bind address, but a port */
1516                 radlog(L_CONS|L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",
1517                        mainconfig.port);
1518                 return -1;
1519         }
1520
1521         /*
1522          *      They specified an IP on the command-line, ignore
1523          *      all listen sections.
1524          */
1525         if (mainconfig.myip.af != AF_UNSPEC) goto do_proxy;
1526
1527         /*
1528          *      Walk through the "listen" sections, if they exist.
1529          */
1530         for (cs = cf_subsection_find_next(mainconfig.config, NULL, "listen");
1531              cs != NULL;
1532              cs = cf_subsection_find_next(mainconfig.config, cs, "listen")) {
1533                 int             type;
1534                 char            *listen_type, *identity;
1535                 int             lineno = cf_section_lineno(cs);
1536
1537                 listen_type = identity = NULL;
1538                 
1539                 rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,
1540                                       &listen_type, "");
1541                 if (rcode < 0) return -1;
1542                 if (rcode == 1) {
1543                         listen_free(head);
1544                         free(listen_type);
1545                         radlog(L_ERR, "%s[%d]: No type specified in listen section",
1546                                filename, lineno);
1547                         return -1;
1548                 }
1549
1550                 /*
1551                  *      See if there's an identity.
1552                  */
1553                 rcode = cf_item_parse(cs, "identity", PW_TYPE_STRING_PTR,
1554                                       &identity, NULL);
1555                 if (rcode < 0) {
1556                         listen_free(head);
1557                         free(identity);
1558                         return -1;
1559                 }
1560
1561                 type = lrad_str2int(listen_compare, listen_type,
1562                                     RAD_LISTEN_NONE);
1563                 free(listen_type);
1564                 if (type == RAD_LISTEN_NONE) {
1565                         listen_free(head);
1566                         radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
1567                                filename, lineno);
1568                         return -1;
1569                 }
1570
1571                 /*
1572                  *      Set up cross-type data.
1573                  */
1574                 this = listen_alloc(type);
1575                 this->identity = identity;
1576                 this->fd = -1;
1577                 
1578                 /*
1579                  *      Call per-type parser.
1580                  */
1581                 if (master_listen[type].parse(filename, lineno,
1582                                               cs, this) < 0) {
1583                         listen_free(&this);
1584                         listen_free(head);
1585                         return -1;
1586                 }
1587
1588                 *last = this;
1589                 last = &(this->next);   
1590         }
1591
1592         /*
1593          *      If we're proxying requests, open the proxy FD.
1594          *      Otherwise, don't do anything.
1595          */
1596  do_proxy:
1597         if (mainconfig.proxy_requests == TRUE) {
1598                 int             port = -1;
1599                 listen_socket_t *sock = NULL;
1600
1601                 /*
1602                  *      No sockets to receive packets, therefore
1603                  *      proxying is pointless.
1604                  */
1605                 if (!*head) return -1;
1606
1607                 /*
1608                  *      If we previously had proxy sockets, copy them
1609                  *      to the new config.
1610                  */
1611                 if (mainconfig.listen != NULL) {
1612                         rad_listen_t *old, *next, **tail;
1613
1614                         tail = &mainconfig.listen;
1615                         for (old = mainconfig.listen;
1616                              old != NULL;
1617                              old = next) {
1618                                 next = old->next;
1619
1620                                 if (old->type != RAD_LISTEN_PROXY) {
1621                                         tail = &((*tail)->next);
1622                                         continue;
1623                                 }
1624
1625                                 *last = old;
1626                                 *tail = next;
1627                                 old->next = NULL;
1628                                 last = &(old->next);
1629                         }
1630
1631                         goto done;
1632                 }
1633
1634                 /*
1635                  *      Find the first authentication port,
1636                  *      and use it
1637                  */
1638                 for (this = *head; this != NULL; this = this->next) {
1639                         if (this->type == RAD_LISTEN_AUTH) {
1640                                 sock = this->data;
1641                                 if (server_ipaddr.af == AF_UNSPEC) {
1642                                         server_ipaddr = sock->ipaddr;
1643                                 }
1644                                 port = sock->port + 2; /* skip acct port */
1645                                 break;
1646                         }
1647                 }
1648
1649                 if (port < 0) port = 1024 + (lrad_rand() & 0x1ff);
1650
1651                 /*
1652                  *      Address is still unspecified, use IPv4.
1653                  */
1654                 if (server_ipaddr.af == AF_UNSPEC) {
1655                         server_ipaddr.af = AF_INET;
1656                         server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
1657                 }
1658
1659                 this = listen_alloc(RAD_LISTEN_PROXY);
1660                 sock = this->data;
1661
1662                 /*
1663                  *      Create the first proxy socket.
1664                  */
1665                 sock->ipaddr = server_ipaddr;
1666
1667                 /*
1668                  *      Try to find a proxy port (value doesn't matter)
1669                  */
1670                 for (sock->port = port;
1671                      sock->port < 64000;
1672                      sock->port++) {
1673                         if (listen_bind(this) == 0) {
1674                                 *last = this;
1675                                 last = &(this->next); /* just in case */
1676                                 break;
1677                         }
1678                 }
1679
1680                 if (sock->port >= 64000) {
1681                         listen_free(head);
1682                         listen_free(&this);
1683                         radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
1684                         return -1;
1685                 }
1686         }
1687
1688         /*
1689          *      Sanity check the configuration.
1690          */
1691         rcode = 0;
1692         for (this = *head; this != NULL; this = this->next) {
1693                 if (((this->type == RAD_LISTEN_ACCT) &&
1694                      (rcode == RAD_LISTEN_DETAIL)) ||
1695                     ((this->type == RAD_LISTEN_DETAIL) &&
1696                      (rcode == RAD_LISTEN_ACCT))) {
1697                         rad_assert(0 == 1); /* FIXME: configuration error */
1698                 }
1699
1700                 if (rcode != 0) continue;
1701
1702                 if ((this->type == RAD_LISTEN_ACCT) ||
1703                     (this->type == RAD_LISTEN_DETAIL)) {
1704                         rcode = this->type;
1705                 }
1706         }
1707
1708  done:
1709         return 0;
1710 }
1711
1712 /*
1713  *      Free a linked list of listeners;
1714  */
1715 void listen_free(rad_listen_t **head)
1716 {
1717         rad_listen_t *this;
1718
1719         if (!head || !*head) return;
1720
1721         this = *head;
1722         while (this) {
1723                 rad_listen_t *next = this->next;
1724                 
1725                 free(this->identity);
1726
1727                 /*
1728                  *      Other code may have eaten the FD.
1729                  */
1730                 if (this->fd >= 0) close(this->fd);
1731
1732                 if (master_listen[this->type].free) {
1733                         master_listen[this->type].free(this);
1734                 }
1735                 free(this->data);
1736                 free(this);
1737                 
1738                 this = next;
1739         }
1740
1741         *head = NULL;
1742 }