Added RADCLIENT* pointer to the REQUEST structure. It makes some
[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,
302                         request->client->secret);
303 }
304
305
306 /*
307  *      Send an accounting response packet (or not)
308  */
309 static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
310 {
311         rad_assert(request->listener == listener);
312         rad_assert(listener->send == acct_socket_send);
313
314         /*
315          *      Accounting reject's are silently dropped.
316          *
317          *      We do it here to avoid polluting the rest of the
318          *      code with this knowledge
319          */
320         if (request->reply->code == 0) return 0;
321
322         return rad_send(request->reply, request->packet,
323                         request->client->secret);
324 }
325
326
327 /*
328  *      Send a packet to a home server.
329  *
330  *      FIXME: have different code for proxy auth & acct!
331  */
332 static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
333 {
334         listen_socket_t *sock = listener->data;
335
336         rad_assert(request->proxy_listener == listener);
337         rad_assert(listener->send == proxy_socket_send);
338
339         request->proxy->src_ipaddr = sock->ipaddr;
340         request->proxy->src_port = sock->port;
341
342         return rad_send(request->proxy, request->packet,
343                         request->home_server->secret);
344 }
345
346
347 /*
348  *      Check if an incoming request is "ok"
349  *
350  *      It takes packets, not requests.  It sees if the packet looks
351  *      OK.  If so, it does a number of sanity checks on it.
352   */
353 static int auth_socket_recv(rad_listen_t *listener,
354                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
355 {
356         ssize_t         rcode;
357         int             code, src_port;
358         RADIUS_PACKET   *packet;
359         RAD_REQUEST_FUNP fun = NULL;
360         char            buffer[128];
361         RADCLIENT       *client;
362         lrad_ipaddr_t   src_ipaddr;
363
364         rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
365         if (rcode < 0) return 0;
366
367         RAD_SNMP_TYPE_INC(listener, total_requests);
368
369         if (rcode < 20) {       /* AUTH_HDR_LEN */
370                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
371                 return 0;
372         }
373
374         if ((client = client_listener_find(listener,
375                                            &src_ipaddr)) == NULL) {
376                 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
377                 
378                 /*
379                  *      This is debugging rather than logging, so that
380                  *      DoS attacks don't affect us.
381                  */
382                 DEBUG("Ignoring request from unknown client %s port %d",
383                       inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr,
384                                 buffer, sizeof(buffer)), src_port);
385                 return 0;
386         }
387
388         /*
389          *      Some sanity checks, based on the packet code.
390          */
391         switch(code) {
392         case PW_AUTHENTICATION_REQUEST:
393                 RAD_SNMP_CLIENT_INC(listener, client, requests);
394                 fun = rad_authenticate;
395                 break;
396                 
397         case PW_STATUS_SERVER:
398                 if (!mainconfig.status_server) {
399                         RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
400                         RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
401                         DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
402                         return 0;
403                 }
404                 fun = rad_status_server;
405                 break;
406
407         default:
408                 RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
409                 RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
410                 
411                 DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
412                       code, client->shortname, src_port);
413                 return 0;
414                 break;
415         } /* switch over packet types */
416         
417         /*
418          *      Now that we've sanity checked everything, receive the
419          *      packet.
420          */
421         packet = rad_recv(listener->fd);
422         if (!packet) {
423                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
424                 radlog(L_ERR, "%s", librad_errstr);
425                 return 0;
426         }
427         
428         if (!received_request(listener, packet, prequest, client)) {
429                 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
430                 RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
431                 rad_free(&packet);
432                 return 0;
433         }
434
435         *pfun = fun;
436         return 1;
437 }
438
439
440 /*
441  *      Receive packets from an accounting socket
442  */
443 static int acct_socket_recv(rad_listen_t *listener,
444                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
445 {
446         ssize_t         rcode;
447         int             code, src_port;
448         RADIUS_PACKET   *packet;
449         RAD_REQUEST_FUNP fun = NULL;
450         char            buffer[128];
451         RADCLIENT       *client;
452         lrad_ipaddr_t   src_ipaddr;
453         
454         rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
455         if (rcode < 0) return 0;
456
457         RAD_SNMP_TYPE_INC(listener, total_requests);
458
459         if (rcode < 20) {       /* AUTH_HDR_LEN */
460                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
461                 return 0;
462         }
463
464         if ((client = client_listener_find(listener,
465                                            &src_ipaddr)) == NULL) {
466                 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
467                 
468                 /*
469                  *      This is debugging rather than logging, so that
470                  *      DoS attacks don't affect us.
471                  */
472                 DEBUG("Ignoring request from unknown client %s port %d",
473                       inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr,
474                                 buffer, sizeof(buffer)), src_port);
475                 return 0;
476         }
477
478         /*
479          *      Some sanity checks, based on the packet code.
480          */
481         switch(packet->code) {
482         case PW_ACCOUNTING_REQUEST:
483                 RAD_SNMP_CLIENT_INC(listener, client, requests);
484                 fun = rad_accounting;
485                 break;
486                 
487         case PW_STATUS_SERVER:
488                 if (!mainconfig.status_server) {
489                         RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
490                         RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
491
492                         DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
493                         return 0;
494                 }
495                 fun = rad_status_server;
496                 break;
497
498         default:
499                 /*
500                  *      FIXME: Update MIB for packet types?
501                  */
502                 RAD_SNMP_TYPE_INC(listener, total_unknown_types);
503                 RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
504
505                 DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
506                       code, client->shortname, src_port);
507                 return 0;
508         } /* switch over packet types */
509
510         /*
511          *      Now that we've sanity checked everything, receive the
512          *      packet.
513          */
514         packet = rad_recv(listener->fd);
515         if (!packet) {
516                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
517                 radlog(L_ERR, "%s", librad_errstr);
518                 return 0;
519         }
520         
521         /*
522          *      There can be no duplicate accounting packets.
523          */
524         if (!received_request(listener, packet, prequest, client)) {
525                 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
526                 RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
527                 rad_free(&packet);
528                 return 0;
529         }
530
531         *pfun = fun;
532         return 1;
533 }
534
535
536 /*
537  *      Recieve packets from a proxy socket.
538  */
539 static int proxy_socket_recv(rad_listen_t *listener,
540                               RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
541 {
542         REQUEST         *request;
543         RADIUS_PACKET   *packet;
544         RAD_REQUEST_FUNP fun = NULL;
545         char            buffer[128];
546         
547         packet = rad_recv(listener->fd);
548         if (!packet) {
549                 radlog(L_ERR, "%s", librad_errstr);
550                 return 0;
551         }
552
553         /*
554          *      FIXME: Client MIB updates?
555          */
556         switch(packet->code) {
557         case PW_AUTHENTICATION_ACK:
558         case PW_ACCESS_CHALLENGE:
559         case PW_AUTHENTICATION_REJECT:
560                 fun = rad_authenticate;
561                 break;
562                 
563         case PW_ACCOUNTING_RESPONSE:
564                 fun = rad_accounting;
565                 break;
566                 
567         default:
568                 /*
569                  *      FIXME: Update MIB for packet types?
570                  */
571                 radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
572                        "from home server %s port %d - ID %d : IGNORED",
573                        packet->code,
574                        ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
575                        packet->src_port, packet->id);
576                 rad_free(&packet);
577                 return 0;
578         }
579
580         request = received_proxy_response(packet);
581         if (!request) {
582                 return 0;
583         }
584
585         rad_assert(fun != NULL);
586         *pfun = fun;
587         *prequest = request;
588
589         return 1;
590 }
591
592
593 static int client_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
594 {
595         if (!request->reply->code) return 0;
596
597         rad_encode(request->reply, request->packet,
598                    request->client->secret);
599         rad_sign(request->reply, request->packet,
600                  request->client->secret);
601
602         return 0;
603 }
604
605
606 static int client_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
607 {
608         if (rad_verify(request->packet, NULL,
609                        request->client->secret) < 0) {
610                 return -1;
611         }
612
613         return rad_decode(request->packet, NULL,
614                           request->client->secret);
615 }
616
617 static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
618 {
619         rad_encode(request->proxy, NULL, request->home_server->secret);
620         rad_sign(request->proxy, NULL, request->home_server->secret);
621
622         return 0;
623 }
624
625
626 static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
627 {
628         if (rad_verify(request->proxy_reply, request->proxy,
629                        request->home_server->secret) < 0) {
630                 return -1;
631         }
632
633         return rad_decode(request->proxy_reply, request->proxy,
634                            request->home_server->secret);
635 }
636
637
638 #define STATE_UNOPENED  (0)
639 #define STATE_UNLOCKED  (1)
640 #define STATE_HEADER    (2)
641 #define STATE_READING   (3)
642 #define STATE_DONE      (4)
643 #define STATE_WAITING   (5)
644
645 /*
646  *      If we're limiting outstanding packets, then mark the response
647  *      as being sent.
648  */
649 static int detail_send(rad_listen_t *listener, REQUEST *request)
650 {
651         listen_detail_t *data = listener->data;
652
653         rad_assert(request->listener == listener);
654         rad_assert(listener->send == detail_send);
655
656         if (request->simul_max >= 0) {
657                 rad_assert(data->outstanding != NULL);
658                 rad_assert(request->simul_max < data->max_outstanding);
659
660                 data->outstanding[request->simul_max] = 0;
661         }
662
663         return 0;
664 }
665
666
667 /*
668  *      Open the detail file..
669  *
670  *      FIXME: create it, if it's not already there, so that the main
671  *      server select() will wake us up if there's anything to read.
672  */
673 static int detail_open(rad_listen_t *this)
674 {
675         struct stat st;
676         char buffer[2048];
677         listen_detail_t *data = this->data;
678
679         rad_assert(data->state == STATE_UNOPENED);
680         snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
681         
682         /*
683          *      FIXME: Have "one-shot" configuration, where it
684          *      will read the detail file, and exit once it's
685          *      done.
686          *
687          *      FIXME: Try harder to open the detail file.
688          *      Maybe sleep for X usecs if it doesn't exist?
689          */
690
691         /*
692          *      Open detail.work first, so we don't lose
693          *      accounting packets.  It's probably better to
694          *      duplicate them than to lose them.
695          *
696          *      Note that we're not writing to the file, but
697          *      we've got to open it for writing in order to
698          *      establish the lock, to prevent rlm_detail from
699          *      writing to it.
700          */
701         this->fd = open(buffer, O_RDWR);
702         if (this->fd < 0) {
703                 /*
704                  *      Try reading the detail file.  If it
705                  *      doesn't exist, we can't do anything.
706                  *
707                  *      Doing the stat will tell us if the file
708                  *      exists, even if we don't have permissions
709                  *      to read it.
710                  */
711                 if (stat(data->detail, &st) < 0) {
712                         return 0;
713                 }
714                 
715                 /*
716                  *      Open it BEFORE we rename it, just to
717                  *      be safe...
718                  */
719                 this->fd = open(data->detail, O_RDWR);
720                 if (this->fd < 0) {
721                         radlog(L_ERR, "Failed to open %s: %s",
722                                data->detail, strerror(errno));
723                         return 0;
724                 }
725                 
726                 /*
727                  *      Rename detail to detail.work
728                  */
729                 if (rename(data->detail, buffer) < 0) {
730                         close(this->fd);
731                         this->fd = -1;
732                         return 0;
733                 }
734         } /* else detail.work existed, and we opened it */
735         
736         rad_assert(data->vps == NULL);
737         
738         rad_assert(data->fp == NULL);
739         data->fp = fdopen(this->fd, "r");
740         if (!data->fp) {
741                 radlog(L_ERR, "Failed to re-open %s: %s",
742                        data->detail, strerror(errno));
743                 return 0;
744         }
745
746         data->state = STATE_UNLOCKED;
747
748         data->client_ip.af = AF_UNSPEC;
749         data->timestamp = 0;
750         
751         return 1;
752 }
753
754 /*
755  *      This is a bad hack, just so complaints have meaningful text.
756  */
757 static const RADCLIENT detail_client = {
758         {               /* ipaddr */
759                 AF_INET,
760                 {{ INADDR_NONE }}
761         },
762         32,
763         "<detail-file>",
764         "secret",
765         "UNKNOWN-CLIENT",
766         "other",
767         "",
768         "",
769         -1
770 };
771
772 static int detail_recv(rad_listen_t *listener,
773                        RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
774 {
775         int             free_slot = -1;
776         char            key[256], value[1024];
777         VALUE_PAIR      *vp, **tail;
778         RADIUS_PACKET   *packet;
779         char            buffer[2048];
780         listen_detail_t *data = listener->data;
781
782         if (data->state == STATE_UNOPENED) {
783                 rad_assert(listener->fd < 0);
784                 if (!detail_open(listener)) return 0;
785         }
786         rad_assert(listener->fd >= 0);
787
788         /*
789          *      Try to lock fd.  If we can't, return.  If we can,
790          *      continue.  This means that the server doesn't block
791          *      while waiting for the lock to open...
792          */
793         if (data->state == STATE_UNLOCKED) {
794                 /*
795                  *      Note that we do NOT block waiting for the
796                  *      lock.  We've re-named the file above, so we've
797                  *      already guaranteed that any *new* detail
798                  *      writer will not be opening this file.  The
799                  *      only purpose of the lock is to catch a race
800                  *      condition where the execution "ping-pongs"
801                  *      between radiusd & radrelay.
802                  */
803                 if (rad_lockfd_nonblock(listener->fd, 0) < 0) {
804                         return 0;
805                 }
806                 /*
807                  *      Look for the header
808                  */
809                 data->state = STATE_HEADER;
810         }
811
812         /*
813          *      Catch an out of memory condition which will most likely
814          *      never be met.
815          */
816         if (data->state == STATE_DONE) goto alloc_packet;
817
818         /*
819          *      If we're in another state, then it means that we read
820          *      a partial packet, which is bad.
821          */
822         rad_assert(data->state == STATE_HEADER);
823         rad_assert(data->vps == NULL);
824
825         /*
826          *      We read the last packet, and returned it for
827          *      processing.  We later come back here to shut
828          *      everything down, and unlink the file.
829          */
830         if (feof(data->fp)) {
831                 rad_assert(data->state == STATE_HEADER);
832
833                 /*
834                  *      Don't unlink the file until we've received
835                  *      all of the responses.
836                  */
837                 if (data->max_outstanding > 0) {
838                         int i;
839
840                         for (i = 0; i < data->max_outstanding; i++) {
841                                 /*
842                                  *      FIXME: close the file?
843                                  */
844                                 if (data->outstanding[i]) {
845                                         data->state = STATE_WAITING;
846                                         return 0;
847                                 }
848                         }
849                 }
850
851         cleanup:
852                 rad_assert(data->vps == NULL);
853
854                 snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
855                 unlink(buffer);
856                 fclose(data->fp); /* closes listener->fd */
857                 data->fp = NULL;
858                 listener->fd = -1;
859                 data->state = STATE_UNOPENED;
860
861                 /*
862                  *      Try to open "detail" again.  If we're on a
863                  *      busy RADIUS server, odds are that it will
864                  *      now exist.
865                  */
866                 detail_open(listener);
867                 return 0;
868         }
869
870         tail = &data->vps;
871
872         /*
873          *      Fill the buffer...
874          */
875         while (fgets(buffer, sizeof(buffer), data->fp)) {
876                 /*
877                  *      No CR, die.
878                  */
879                 if (!strchr(buffer, '\n')) {
880                         pairfree(&data->vps);
881                         goto cleanup;
882                 }
883
884                 /*
885                  *      We've read a header, possibly packet contents,
886                  *      and are now at the end of the packet.
887                  */
888                 if ((data->state == STATE_READING) &&
889                     (buffer[0] == '\n')) {
890                         data->state = STATE_DONE;
891                         break;
892                 }
893
894                 /*
895                  *      Look for date/time header, and read VP's if
896                  *      found.  If not, keep reading lines until we
897                  *      find one.
898                  */
899                 if (data->state == STATE_HEADER) {
900                         int y;
901                         
902                         if (sscanf(buffer, "%*s %*s %*d %*d:%*d:%*d %d", &y)) {
903                                 data->state = STATE_READING;
904                         }
905                         continue;
906                 }
907
908                 /*
909                  *      We have a full "attribute = value" line.
910                  *      If it doesn't look reasonable, skip it.
911                  */
912                 if (sscanf(buffer, "%255s = %1023s", key, value) != 2) {
913                         continue;
914                 }
915
916                 /*
917                  *      Skip non-protocol attributes.
918                  */
919                 if (!strcasecmp(key, "Request-Authenticator")) continue;
920
921                 /*
922                  *      Set the original client IP address, based on
923                  *      what's in the detail file.
924                  *
925                  *      Hmm... we don't set the server IP address.
926                  *      or port.  Oh well.
927                  */
928                 if (!strcasecmp(key, "Client-IP-Address")) {
929                         data->client_ip.af = AF_INET;
930                         ip_hton(value, AF_INET, &data->client_ip);
931                         continue;
932                 }
933
934                 /*
935                  *      The original time at which we received the
936                  *      packet.  We need this to properly calculate
937                  *      Acct-Delay-Time.
938                  */
939                 if (!strcasecmp(key, "Timestamp")) {
940                         data->timestamp = atoi(value);
941                         continue;
942                 }
943
944                 /*
945                  *      Read one VP.
946                  *
947                  *      FIXME: do we want to check for non-protocol
948                  *      attributes like radsqlrelay does?
949                  */
950                 vp = NULL;
951                 if ((userparse(buffer, &vp) > 0) &&
952                     (vp != NULL)) {
953                         *tail = vp;
954                         tail = &(vp->next);
955                 }               
956         }
957
958         /*
959          *      We got to EOF,  If we're in STATE_HEADER, it's OK.
960          *      Otherwise it's a problem.  In any case, nuke the file
961          *      and start over from scratch,
962          */
963         if (feof(data->fp)) {
964                 goto cleanup;
965         }
966
967         /*
968          *      FIXME: Do load management.
969          */
970
971         /*
972          *      If we're not done, then there's a problem.  The checks
973          *      above for EOF
974          */
975         rad_assert(data->state == STATE_DONE);
976
977         /*
978          *      The packet we read was empty, re-set the state to look
979          *      for a header, and don't return anything.
980          */
981         if (!data->vps) {
982                 data->state = STATE_HEADER;
983                 return 0;
984         }
985
986         /*
987          *      Allocate the packet.  If we fail, it's a serious
988          *      problem.
989          */
990  alloc_packet:
991         /*
992          *      If we keep track of the outstanding requests, do so
993          *      here.  Note that to minimize potential work, we do
994          *      so only once the file is opened & locked.
995          */
996         if (data->max_outstanding) {
997                 int i;
998
999                 for (i = 0; i < data->max_outstanding; i++) {
1000                         if (!data->outstanding[i]) {
1001                                 free_slot = i;
1002                                 break;
1003                         }
1004                 }
1005
1006                 /*
1007                  *      All of the slots are full.  Put the LF back,
1008                  *      so select will say that data is ready, and set
1009                  *      the state back to reading.  Then, return so
1010                  *      that we don't overload the server.
1011                  */
1012                 if (free_slot < 0) {
1013                         ungetc('\n', data->fp);
1014                         data->state = STATE_READING;
1015                         return 0;
1016                 }
1017         }
1018
1019         packet = rad_alloc(1);
1020         if (!packet) {
1021                 return 0;       /* maybe memory will magically free up... */
1022         }
1023
1024         memset(packet, 0, sizeof(*packet));
1025         packet->sockfd = -1;
1026         packet->src_ipaddr.af = AF_INET;
1027         packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1028         packet->code = PW_ACCOUNTING_REQUEST;
1029         packet->timestamp = time(NULL);
1030
1031         /*
1032          *      Look for Acct-Delay-Time, and update
1033          *      based on Acct-Delay-Time += (time(NULL) - timestamp)
1034          */
1035         vp = pairfind(packet->vps, PW_ACCT_DELAY_TIME);
1036         if (!vp) {
1037                 vp = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
1038                 rad_assert(vp != NULL);
1039         }
1040         if (data->timestamp != 0) {
1041                 vp->vp_integer += time(NULL) - data->timestamp;
1042         }
1043
1044         /*
1045          *      Remember where it came from, so that we don't
1046          *      proxy it to the place it came from...
1047          */
1048         if (data->client_ip.af != AF_UNSPEC) {
1049                 packet->src_ipaddr = data->client_ip;
1050         }
1051
1052         vp = pairfind(packet->vps, PW_PACKET_SRC_IP_ADDRESS);
1053         if (vp) {
1054                 packet->src_ipaddr.af = AF_INET;
1055                 packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1056         } else {
1057                 vp = pairfind(packet->vps, PW_PACKET_SRC_IPV6_ADDRESS);
1058                 if (vp) {
1059                         packet->src_ipaddr.af = AF_INET6;
1060                         memcpy(&packet->src_ipaddr.ipaddr.ip6addr,
1061                                &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
1062                 }
1063         }
1064
1065         vp = pairfind(packet->vps, PW_PACKET_DST_IP_ADDRESS);
1066         if (vp) {
1067                 packet->dst_ipaddr.af = AF_INET;
1068                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
1069         } else {
1070                 vp = pairfind(packet->vps, PW_PACKET_DST_IPV6_ADDRESS);
1071                 if (vp) {
1072                         packet->dst_ipaddr.af = AF_INET6;
1073                         memcpy(&packet->dst_ipaddr.ipaddr.ip6addr,
1074                                &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
1075                 }
1076         }
1077
1078         /*
1079          *      We've got to give SOME value for Id & ports, so that
1080          *      the packets can be added to the request queue.
1081          *      However, we don't want to keep track of used/unused
1082          *      id's and ports, as that's a lot of work.  This hack
1083          *      ensures that (if we have real random numbers), that
1084          *      there will be a collision on every 2^(16+15+15+24 - 1)
1085          *      packets, on average.  That means we can read 2^37
1086          *      packets before having a collision, which means it's
1087          *      effectively impossible.
1088          */
1089         packet->id = lrad_rand() & 0xffff;
1090         packet->src_port = 1024 + (lrad_rand() & 0x7fff);
1091         packet->dst_port = 1024 + (lrad_rand() & 0x7fff);
1092
1093         packet->dst_ipaddr.af = AF_INET;
1094         packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl((INADDR_LOOPBACK & ~0xffffff) | (lrad_rand() & 0xffffff));
1095
1096         packet->vps = data->vps;
1097
1098         /*
1099          *      Re-set the state.
1100          */
1101         data->vps = NULL;
1102         data->state = STATE_HEADER;
1103
1104         /*
1105          *      Keep track of free slots, as a hack, in an otherwise
1106          *      unused 'int'
1107          */
1108         (*prequest)->simul_max = free_slot;
1109         data->outstanding[free_slot] = 1;
1110
1111         *pfun = rad_accounting;
1112
1113         if (debug_flag) {
1114                 printf("detail_recv: Read packet from %s\n", data->detail);
1115                 for (vp = packet->vps; vp; vp = vp->next) {
1116                         putchar('\t');
1117                         vp_print(stdout, vp);
1118                         putchar('\n');
1119                 }
1120         }
1121
1122         /*
1123          *      FIXME: many of these checks may not be necessary when
1124          *      reading from the detail file.
1125          */
1126         if (!received_request(listener, packet, prequest, &detail_client)) {
1127                 rad_free(&packet);
1128                 return 0;
1129         }
1130
1131         return 1;
1132 }
1133
1134
1135 /*
1136  *      Free detail-specific stuff.
1137  */
1138 static void detail_free(rad_listen_t *this)
1139 {
1140         listen_detail_t *data = this->data;
1141
1142         free(data->detail);
1143         pairfree(&data->vps);
1144         free(data->outstanding);
1145
1146         if (data->fp != NULL) fclose(data->fp);
1147 }
1148
1149
1150 static int detail_print(rad_listen_t *this, char *buffer, size_t bufsize)
1151 {
1152         return snprintf(buffer, bufsize, "%s",
1153                         ((listen_detail_t *)(this->data))->detail);
1154 }
1155
1156 static int detail_encode(UNUSED rad_listen_t *this, UNUSED REQUEST *request)
1157 {
1158         /*
1159          *      We never encode responses "sent to" the detail file.
1160          */
1161         return 0;
1162 }
1163
1164 static int detail_decode(UNUSED rad_listen_t *this, UNUSED REQUEST *request)
1165 {
1166         /*
1167          *      We never decode responses read from the detail file.
1168          */
1169         return 0;
1170 }
1171
1172
1173 static const CONF_PARSER detail_config[] = {
1174         { "detail",   PW_TYPE_STRING_PTR,
1175           offsetof(listen_detail_t, detail), NULL,  NULL },
1176         { "max_outstanding",  PW_TYPE_INTEGER,
1177            offsetof(listen_detail_t, max_outstanding), NULL, "100" },
1178
1179         { NULL, -1, 0, NULL, NULL }             /* end the list */
1180 };
1181
1182
1183 /*
1184  *      Parse a detail section.
1185  */
1186 static int detail_parse(const char *filename, int lineno,
1187                         const CONF_SECTION *cs, rad_listen_t *this)
1188 {
1189         int             rcode;
1190         listen_detail_t *data;
1191
1192         data = this->data;
1193
1194         rcode = cf_section_parse(cs, data, detail_config);
1195         if (rcode < 0) {
1196                 radlog(L_ERR, "%s[%d]: Failed parsing listen section",
1197                        filename, lineno);
1198                 return -1;
1199         }
1200
1201         if (!data->detail) {
1202                 radlog(L_ERR, "%s[%d]: No detail file specified in listen section",
1203                        filename, lineno);
1204                 return -1;
1205         }
1206         
1207         data->vps = NULL;
1208         data->fp = NULL;
1209         data->state = STATE_UNOPENED;
1210
1211         if (data->max_outstanding > 32768) data->max_outstanding = 32768;
1212
1213         if (data->max_outstanding > 0) {
1214                 data->outstanding = rad_malloc(sizeof(int) * data->max_outstanding);
1215         }
1216         
1217         detail_open(this);
1218
1219         return 0;
1220 }
1221
1222
1223 #ifdef WITH_SNMP
1224 static int radius_snmp_recv(rad_listen_t *listener,
1225                             UNUSED RAD_REQUEST_FUNP *pfun,
1226                             UNUSED REQUEST **prequest)
1227 {
1228         if (!mainconfig.do_snmp) return 0;
1229
1230         if ((rad_snmp.smux_fd >= 0) &&
1231             (rad_snmp.smux_event == SMUX_READ)) {
1232                 smux_read();
1233         }
1234         
1235         /*
1236          *  If we've got to re-connect, then do so now,
1237          *  before calling select again.
1238          */
1239         if (rad_snmp.smux_event == SMUX_CONNECT) {
1240                 smux_connect();
1241         }
1242
1243         /*
1244          *      Reset this every time, as the smux connect may have
1245          *      opened a new socket.
1246          */
1247         listener->fd = rad_snmp.smux_fd;
1248
1249         return 0;
1250 }
1251
1252
1253 static int radius_snmp_print(rad_listen_t *this, char *buffer, size_t bufsize)
1254 {
1255         return snprintf(buffer, bufsize, "SMUX with OID .1.3.6.1.4.1.3317.1.3.1");
1256 }
1257
1258 #endif
1259
1260 static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
1261         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},    /* RAD_LISTEN_NONE */
1262
1263         /* authentication */
1264         { common_socket_parse, NULL,
1265           auth_socket_recv, auth_socket_send,
1266           socket_print, client_socket_encode, client_socket_decode },
1267
1268         /* accounting */
1269         { common_socket_parse, NULL,
1270           acct_socket_recv, acct_socket_send,
1271           socket_print, client_socket_encode, client_socket_decode},
1272
1273         /* proxying */
1274         { NULL, NULL,
1275           proxy_socket_recv, proxy_socket_send,
1276           socket_print, proxy_socket_encode, proxy_socket_decode },
1277
1278         /* detail */
1279         { detail_parse, detail_free,
1280           detail_recv, detail_send,
1281           detail_print, detail_encode, detail_decode },
1282
1283         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},    /* RAD_LISTEN_SNMP */
1284 };
1285
1286
1287
1288 /*
1289  *      Binds a listener to a socket.
1290  */
1291 static int listen_bind(rad_listen_t *this)
1292 {
1293         rad_listen_t    **last;
1294         listen_socket_t *sock = this->data;
1295
1296         /*
1297          *      If the port is zero, then it means the appropriate
1298          *      thing from /etc/services.
1299          */
1300         if (sock->port == 0) {
1301                 struct servent  *svp;
1302
1303                 switch (this->type) {
1304                 case RAD_LISTEN_AUTH:
1305                         svp = getservbyname ("radius", "udp");
1306                         if (svp != NULL) {
1307                                 sock->port = ntohs(svp->s_port);
1308                         } else {
1309                                 sock->port = PW_AUTH_UDP_PORT;
1310                         }
1311                         break;
1312
1313                 case RAD_LISTEN_ACCT:
1314                         svp = getservbyname ("radacct", "udp");
1315                         if (svp != NULL) {
1316                                 sock->port = ntohs(svp->s_port);
1317                         } else {
1318                                 sock->port = PW_ACCT_UDP_PORT;
1319                         }
1320                         break;
1321
1322                 default:
1323                         radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
1324                         return -1;
1325                 }
1326         }
1327
1328         /*
1329          *      Find it in the old list, AFTER updating the port.  If
1330          *      it's there, use that, rather than creating a new
1331          *      socket.  This allows HUP's to re-use the old sockets,
1332          *      which means that packets waiting in the socket queue
1333          *      don't get lost.
1334          */
1335         for (last = &mainconfig.listen;
1336              *last != NULL;
1337              last = &((*last)->next)) {
1338                 if ((this->type == (*last)->type) &&
1339                     (sock->port == ((listen_socket_t *)((*last)->data))->port) &&
1340                     (sock->ipaddr.af == ((listen_socket_t *)((*last)->data))->ipaddr.af)) {
1341                         int equal;
1342
1343                         if (sock->ipaddr.af == AF_INET) {
1344                                 equal = (sock->ipaddr.ipaddr.ip4addr.s_addr == ((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip4addr.s_addr);
1345                         } else if (sock->ipaddr.af == AF_INET6) {
1346                                 equal = IN6_ARE_ADDR_EQUAL(&(sock->ipaddr.ipaddr.ip6addr), &(((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip6addr));
1347                         } else {
1348                                 equal = 0;
1349                         }
1350                         
1351                         if (equal) {
1352                                 this->fd = (*last)->fd;
1353                                 (*last)->fd = -1;
1354                                 return 0;
1355                         }
1356                 }
1357         }
1358
1359         this->fd = lrad_socket(&sock->ipaddr, sock->port);
1360         if (this->fd < 0) {
1361                 radlog(L_ERR|L_CONS, "ERROR: Failed to open socket: %s",
1362                        librad_errstr);
1363                 return -1;
1364         }
1365
1366 #if 0
1367 #ifdef O_NONBLOCK
1368         if ((flags = fcntl(this->fd, F_GETFL, NULL)) < 0)  { 
1369                 radlog(L_ERR, "Failure in fcntl: %s)\n", strerror(errno)); 
1370                 return -1;
1371         }
1372
1373         flags |= O_NONBLOCK; 
1374         if( fcntl(this->fd, F_SETFL, flags) < 0) { 
1375                 radlog(L_ERR, "Failure in fcntl: %s)\n", strerror(errno)); 
1376                 return -1;
1377         }
1378 #endif
1379 #endif
1380
1381         return 0;
1382 }
1383
1384
1385 /*
1386  *      Allocate & initialize a new listener.
1387  */
1388 static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
1389 {
1390         rad_listen_t *this;
1391
1392         this = rad_malloc(sizeof(*this));
1393         memset(this, 0, sizeof(*this));
1394
1395         this->type = type;
1396         this->recv = master_listen[this->type].recv;
1397         this->send = master_listen[this->type].send;
1398         this->print = master_listen[this->type].print;
1399         this->encode = master_listen[this->type].encode;
1400         this->decode = master_listen[this->type].decode;
1401
1402         switch (type) {
1403         case RAD_LISTEN_AUTH:
1404         case RAD_LISTEN_ACCT:
1405         case RAD_LISTEN_PROXY:
1406                 this->data = rad_malloc(sizeof(listen_socket_t));
1407                 memset(this->data, 0, sizeof(listen_socket_t));
1408                 break;
1409
1410         case RAD_LISTEN_DETAIL:
1411                 this->data = rad_malloc(sizeof(listen_detail_t));
1412                 memset(this->data, 0, sizeof(listen_detail_t));
1413                 
1414         default:
1415                 break;
1416         }
1417
1418         return this;
1419 }
1420
1421
1422 /*
1423  *      Externally visible function for creating a new proxy LISTENER.
1424  *
1425  *      For now, don't take ipaddr or port.
1426  *
1427  *      Not thread-safe, but all calls to it are protected by the
1428  *      proxy mutex in request_list.c
1429  */
1430 rad_listen_t *proxy_new_listener()
1431 {
1432         int last_proxy_port, port;
1433         rad_listen_t *this, *tmp, **last;
1434         listen_socket_t *sock, *old;
1435
1436         this = listen_alloc(RAD_LISTEN_PROXY);
1437
1438         /*
1439          *      Find an existing proxy socket to copy.
1440          *
1441          *      FIXME: Make it per-realm, or per-home server!
1442          */
1443         last_proxy_port = 0;
1444         old = NULL;
1445         last = &mainconfig.listen;
1446         for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {
1447                 if (tmp->type == RAD_LISTEN_PROXY) {
1448                         sock = tmp->data;
1449                         if (sock->port > last_proxy_port) {
1450                                 last_proxy_port = sock->port + 1;
1451                         }
1452                         if (!old) old = sock;
1453                 }
1454
1455                 last = &(tmp->next);
1456         }
1457
1458         if (!old) return NULL;  /* This is a serious error. */
1459
1460         /*
1461          *      FIXME: find a new IP address to listen on?
1462          */
1463         sock = this->data;
1464         memcpy(&sock->ipaddr, &old->ipaddr, sizeof(sock->ipaddr));
1465
1466         /*
1467          *      Keep going until we find an unused port.
1468          */
1469         for (port = last_proxy_port; port < 64000; port++) {
1470                 sock->port = port;
1471                 if (listen_bind(this) == 0) {
1472                         /*
1473                          *      Add the new listener to the list of
1474                          *      listeners.
1475                          */
1476                         *last = this;
1477                         return this;
1478                 }
1479         }
1480
1481         return NULL;
1482 }
1483
1484
1485 static const LRAD_NAME_NUMBER listen_compare[] = {
1486         { "auth",       RAD_LISTEN_AUTH },
1487         { "acct",       RAD_LISTEN_ACCT },
1488         { "detail",     RAD_LISTEN_DETAIL },
1489         { NULL, 0 },
1490 };
1491
1492
1493 /*
1494  *      Generate a list of listeners.  Takes an input list of
1495  *      listeners, too, so we don't close sockets with waiting packets.
1496  */
1497 int listen_init(const char *filename, rad_listen_t **head)
1498 {
1499         int             rcode;
1500         CONF_SECTION    *cs;
1501         rad_listen_t    **last;
1502         rad_listen_t    *this;
1503         lrad_ipaddr_t   server_ipaddr;
1504         int             auth_port = 0;
1505
1506         /*
1507          *      We shouldn't be called with a pre-existing list.
1508          */
1509         rad_assert(head && (*head == NULL));
1510         
1511         if (start_time != 0) start_time = time(NULL);
1512
1513         last = head;
1514         server_ipaddr.af = AF_UNSPEC;
1515
1516         /*
1517          *      If the port is specified on the command-line,
1518          *      it over-rides the configuration file.
1519          */
1520         if (mainconfig.port >= 0) {
1521                 auth_port = mainconfig.port;
1522         } else {
1523                 rcode = cf_item_parse(mainconfig.config, "port",
1524                                       PW_TYPE_INTEGER, &auth_port,
1525                                       Stringify(PW_AUTH_UDP_PORT));
1526                 if (rcode < 0) return -1; /* error parsing it */
1527
1528                 if (rcode == 0)
1529                         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'.");
1530         }
1531
1532         /*
1533          *      If the IP address was configured on the command-line,
1534          *      use that as the "bind_address"
1535          */
1536         if (mainconfig.myip.af != AF_UNSPEC) {
1537                 memcpy(&server_ipaddr, &mainconfig.myip,
1538                        sizeof(server_ipaddr));
1539                 goto bind_it;
1540         }
1541
1542         /*
1543          *      Else look for bind_address and/or listen sections.
1544          */
1545         server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1546         rcode = cf_item_parse(mainconfig.config, "bind_address",
1547                               PW_TYPE_IPADDR,
1548                               &server_ipaddr.ipaddr.ip4addr, NULL);
1549         if (rcode < 0) return -1; /* error parsing it */
1550         
1551         if (rcode == 0) { /* successfully parsed IPv4 */
1552                 listen_socket_t *sock;
1553                 server_ipaddr.af = AF_INET;
1554
1555                 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'.");
1556
1557         bind_it:
1558                 this = listen_alloc(RAD_LISTEN_AUTH);
1559                 sock = this->data;
1560
1561                 sock->ipaddr = server_ipaddr;
1562                 sock->port = auth_port;
1563                 
1564                 if (listen_bind(this) < 0) {
1565                         listen_free(&this);
1566                         listen_free(head);
1567                         radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->port);
1568                         return -1;
1569                 }
1570                 auth_port = sock->port; /* may have been updated in listen_bind */
1571                 *last = this;
1572                 last = &(this->next);
1573                 
1574                 /*
1575                  *      Open Accounting Socket.
1576                  *
1577                  *      If we haven't already gotten acct_port from
1578                  *      /etc/services, then make it auth_port + 1.
1579                  */
1580                 this = listen_alloc(RAD_LISTEN_ACCT);
1581                 sock = this->data;
1582                 
1583                 /*
1584                  *      Create the accounting socket.
1585                  *
1586                  *      The accounting port is always the
1587                  *      authentication port + 1
1588                  */
1589                 sock->ipaddr = server_ipaddr;
1590                 sock->port = auth_port + 1;
1591                 
1592                 if (listen_bind(this) < 0) {
1593                         listen_free(&this);
1594                         listen_free(head);
1595                         radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->port);
1596                         return -1;
1597                 }
1598
1599                 *last = this;
1600                 last = &(this->next);
1601
1602         } else if (mainconfig.port > 0) { /* no bind address, but a port */
1603                 radlog(L_CONS|L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",
1604                        mainconfig.port);
1605                 return -1;
1606         }
1607
1608         /*
1609          *      They specified an IP on the command-line, ignore
1610          *      all listen sections.
1611          */
1612         if (mainconfig.myip.af != AF_UNSPEC) goto do_proxy;
1613
1614         /*
1615          *      Walk through the "listen" sections, if they exist.
1616          */
1617         for (cs = cf_subsection_find_next(mainconfig.config, NULL, "listen");
1618              cs != NULL;
1619              cs = cf_subsection_find_next(mainconfig.config, cs, "listen")) {
1620                 int             type;
1621                 char            *listen_type, *identity;
1622                 int             lineno = cf_section_lineno(cs);
1623
1624                 listen_type = identity = NULL;
1625                 
1626                 rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,
1627                                       &listen_type, "");
1628                 if (rcode < 0) return -1;
1629                 if (rcode == 1) {
1630                         listen_free(head);
1631                         free(listen_type);
1632                         radlog(L_ERR, "%s[%d]: No type specified in listen section",
1633                                filename, lineno);
1634                         return -1;
1635                 }
1636
1637                 /*
1638                  *      See if there's an identity.
1639                  */
1640                 rcode = cf_item_parse(cs, "identity", PW_TYPE_STRING_PTR,
1641                                       &identity, NULL);
1642                 if (rcode < 0) {
1643                         listen_free(head);
1644                         free(identity);
1645                         return -1;
1646                 }
1647
1648                 type = lrad_str2int(listen_compare, listen_type,
1649                                     RAD_LISTEN_NONE);
1650                 free(listen_type);
1651                 if (type == RAD_LISTEN_NONE) {
1652                         listen_free(head);
1653                         radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
1654                                filename, lineno);
1655                         return -1;
1656                 }
1657
1658                 /*
1659                  *      Set up cross-type data.
1660                  */
1661                 this = listen_alloc(type);
1662                 this->identity = identity;
1663                 this->fd = -1;
1664                 
1665                 /*
1666                  *      Call per-type parser.
1667                  */
1668                 if (master_listen[type].parse(filename, lineno,
1669                                               cs, this) < 0) {
1670                         listen_free(&this);
1671                         listen_free(head);
1672                         return -1;
1673                 }
1674
1675                 *last = this;
1676                 last = &(this->next);   
1677         }
1678
1679         /*
1680          *      If we're proxying requests, open the proxy FD.
1681          *      Otherwise, don't do anything.
1682          */
1683  do_proxy:
1684         if (mainconfig.proxy_requests == TRUE) {
1685                 int             port = -1;
1686                 listen_socket_t *sock = NULL;
1687
1688                 /*
1689                  *      No sockets to receive packets, therefore
1690                  *      proxying is pointless.
1691                  */
1692                 if (!*head) return -1;
1693
1694                 /*
1695                  *      If we previously had proxy sockets, copy them
1696                  *      to the new config.
1697                  */
1698                 if (mainconfig.listen != NULL) {
1699                         rad_listen_t *old, *next, **tail;
1700
1701                         tail = &mainconfig.listen;
1702                         for (old = mainconfig.listen;
1703                              old != NULL;
1704                              old = next) {
1705                                 next = old->next;
1706
1707                                 if (old->type != RAD_LISTEN_PROXY) {
1708                                         tail = &((*tail)->next);
1709                                         continue;
1710                                 }
1711
1712                                 *last = old;
1713                                 *tail = next;
1714                                 old->next = NULL;
1715                                 last = &(old->next);
1716                         }
1717
1718                         goto do_snmp;
1719                 }
1720
1721                 /*
1722                  *      Find the first authentication port,
1723                  *      and use it
1724                  */
1725                 for (this = *head; this != NULL; this = this->next) {
1726                         if (this->type == RAD_LISTEN_AUTH) {
1727                                 sock = this->data;
1728                                 if (server_ipaddr.af == AF_UNSPEC) {
1729                                         server_ipaddr = sock->ipaddr;
1730                                 }
1731                                 port = sock->port + 2; /* skip acct port */
1732                                 break;
1733                         }
1734                 }
1735
1736                 if (port < 0) port = 1024 + (lrad_rand() & 0x1ff);
1737
1738                 /*
1739                  *      Address is still unspecified, use IPv4.
1740                  */
1741                 if (server_ipaddr.af == AF_UNSPEC) {
1742                         server_ipaddr.af = AF_INET;
1743                         server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
1744                 }
1745
1746                 this = listen_alloc(RAD_LISTEN_PROXY);
1747                 sock = this->data;
1748
1749                 /*
1750                  *      Create the first proxy socket.
1751                  */
1752                 sock->ipaddr = server_ipaddr;
1753
1754                 /*
1755                  *      Try to find a proxy port (value doesn't matter)
1756                  */
1757                 for (sock->port = port;
1758                      sock->port < 64000;
1759                      sock->port++) {
1760                         if (listen_bind(this) == 0) {
1761                                 *last = this;
1762                                 last = &(this->next); /* just in case */
1763                                 break;
1764                         }
1765                 }
1766
1767                 if (sock->port >= 64000) {
1768                         listen_free(head);
1769                         listen_free(&this);
1770                         radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
1771                         return -1;
1772                 }
1773         }
1774         
1775  do_snmp:
1776 #ifdef WITH_SNMP
1777         if (mainconfig.do_snmp) {
1778                 radius_snmp_init();
1779
1780                 /*
1781                  *      Forget about the old one.
1782                  */
1783                 for (this = mainconfig.listen;
1784                      this != NULL;
1785                      this = this->next) {
1786                         if (this->type != RAD_LISTEN_SNMP) continue;
1787                         this->fd = -1;
1788                 }
1789
1790                 this = rad_malloc(sizeof(*this));
1791                 memset(this, 0, sizeof(*this));
1792                 
1793                 this->type = RAD_LISTEN_SNMP;
1794                 this->fd = rad_snmp.smux_fd;
1795                 
1796                 this->recv = radius_snmp_recv;
1797                 this->print = radius_snmp_print;
1798
1799                 *last = this;
1800                 last = &(this->next);
1801         }
1802 #endif
1803
1804         /*
1805          *      Sanity check the configuration.
1806          */
1807         rcode = 0;
1808         if (mainconfig.listen != NULL) for (this = *head;
1809                                             this != NULL;
1810                                             this = this->next) {
1811                 if (((this->type == RAD_LISTEN_ACCT) &&
1812                      (rcode == RAD_LISTEN_DETAIL)) ||
1813                     ((this->type == RAD_LISTEN_DETAIL) &&
1814                      (rcode == RAD_LISTEN_ACCT))) {
1815                         rad_assert(0 == 1); /* FIXME: configuration error */
1816                 }
1817
1818                 if (rcode != 0) continue;
1819
1820                 if ((this->type == RAD_LISTEN_ACCT) ||
1821                     (this->type == RAD_LISTEN_DETAIL)) {
1822                         rcode = this->type;
1823                 }
1824         }
1825
1826  done:
1827         return 0;
1828 }
1829
1830 /*
1831  *      Free a linked list of listeners;
1832  */
1833 void listen_free(rad_listen_t **head)
1834 {
1835         rad_listen_t *this;
1836
1837         if (!head || !*head) return;
1838
1839         this = *head;
1840         while (this) {
1841                 rad_listen_t *next = this->next;
1842                 
1843                 free(this->identity);
1844
1845                 /*
1846                  *      Other code may have eaten the FD.
1847                  */
1848                 if (this->fd >= 0) close(this->fd);
1849
1850                 if (master_listen[this->type].free) {
1851                         master_listen[this->type].free(this);
1852                 }
1853                 free(this->data);
1854                 free(this);
1855                 
1856                 this = next;
1857         }
1858
1859         *head = NULL;
1860 }