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