The feature everyone's been waiting for.
[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 #include <freeradius-devel/vqp.h>
32 #include <freeradius-devel/dhcp.h>
33
34 #include <freeradius-devel/vmps.h>
35 #include <freeradius-devel/detail.h>
36
37 #ifdef HAVE_SYS_RESOURCE_H
38 #include <sys/resource.h>
39 #endif
40
41 #ifdef HAVE_NET_IF_H
42 #include <net/if.h>
43 #endif
44
45 #ifdef HAVE_FCNTL_H
46 #include <fcntl.h>
47 #endif
48
49
50 /*
51  *      We'll use this below.
52  */
53 typedef int (*rad_listen_parse_t)(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         fr_ipaddr_t     ipaddr;
71         int             port;
72         RADCLIENT_LIST  *clients;
73 } listen_socket_t;
74
75 /*
76  *      Find a per-socket client.
77  */
78 RADCLIENT *client_listener_find(const rad_listen_t *listener,
79                                        const fr_ipaddr_t *ipaddr)
80 {
81 #ifdef WITH_DYNAMIC_CLIENTS
82         int rcode;
83         time_t now;
84         listen_socket_t *sock;
85         REQUEST *request;
86         RADCLIENT *client, *created;
87 #endif
88         RADCLIENT_LIST *clients;
89
90         rad_assert(listener != NULL);
91         rad_assert(ipaddr != NULL);
92
93         rad_assert((listener->type == RAD_LISTEN_AUTH) ||
94                    (listener->type == RAD_LISTEN_ACCT) ||
95                    (listener->type == RAD_LISTEN_VQP) ||
96                    (listener->type == RAD_LISTEN_DHCP));
97
98         clients = ((listen_socket_t *)listener->data)->clients;
99
100         /*
101          *      This HAS to have been initialized previously.
102          */
103         rad_assert(clients != NULL);
104
105 #ifdef WITH_DYNAMIC_CLIENTS
106         client = client_find(clients, ipaddr);
107         if (!client) return NULL;
108
109         /*
110          *      No server defined, and it's not dynamic.  Return it.
111          */
112         if (!client->client_server && !client->dynamic) return client;
113
114         now = time(NULL);
115         
116         /*
117          *      It's a dynamically generated client, check it.
118          */
119         if (client->dynamic) {
120                 /*
121                  *      Lives forever.  Return it.
122                  */
123                 if (client->lifetime == 0) return client;
124                 
125                 /*
126                  *      Rate-limit the deletion of known clients.
127                  *      This makes them last a little longer, but
128                  *      prevents the server from melting down if (say)
129                  *      10k clients all expire at once.
130                  */
131                 if (now == client->last_new_client) return client;
132
133                 /*
134                  *      It's not dead yet.  Return it.
135                  */
136                 if ((client->created + client->lifetime) > now) return client;
137                 
138                 /*
139                  *      It's dead, Jim.  Delete it.
140                  */
141                 client_delete(clients, client);
142
143                 /*
144                  *      Go find the enclosing network again.
145                  */
146                 client = client_find(clients, ipaddr);
147
148                 /*
149                  *      WTF?
150                  */
151                 if (!client) return NULL;
152                 if (!client->client_server) return NULL;
153
154                 /*
155                  *      At this point, 'client' is the enclosing
156                  *      network that configures where dynamic clients
157                  *      can be defined.
158                  */
159                 rad_assert(client->dynamic == 0);
160         } else {
161                 /*
162                  *      The IP is unknown, so we've found an enclosing
163                  *      network.  Enable DoS protection.  We only
164                  *      allow one new client per second.  Known
165                  *      clients aren't subject to this restriction.
166                  */
167                 if (now == client->last_new_client) return NULL;
168         }
169
170         client->last_new_client = now;
171
172         request = request_alloc();
173         if (!request) return NULL;
174
175         request->listener = listener;
176         request->client = client;
177         request->packet = rad_alloc(0);
178         if (!request->packet) {
179                 request_free(&request);
180                 return NULL;
181         }
182         request->reply = rad_alloc(0);
183         if (!request->reply) {
184                 request_free(&request);
185                 return NULL;
186         }
187         request->packet->timestamp = request->timestamp;
188         request->number = 0;
189         request->priority = listener->type;
190         request->server = client->client_server;
191         request->root = &mainconfig;
192
193         /*
194          *      Run a fake request through the given virtual server.
195          *      Look for FreeRADIUS-Client-IP-Address
196          *               FreeRADIUS-Client-Secret
197          *              ...
198          *
199          *      and create the RADCLIENT structure from that.
200          */
201
202         sock = listener->data;
203         request->packet->sockfd = listener->fd;
204         request->packet->src_ipaddr = *ipaddr;
205         request->packet->src_port = 0; /* who cares... */
206         request->packet->dst_ipaddr = sock->ipaddr;
207         request->packet->dst_port = sock->port;
208
209         request->reply->sockfd = request->packet->sockfd;
210         request->reply->dst_ipaddr = request->packet->src_ipaddr;
211         request->reply->src_ipaddr = request->packet->dst_ipaddr;
212         request->reply->dst_port = request->packet->src_port;
213         request->reply->src_port = request->packet->dst_port;
214         request->reply->id = request->packet->id;
215         request->reply->code = 0; /* UNKNOWN code */
216
217         
218         DEBUG("server %s {", request->server);
219
220         rcode = module_authorize(0, request);
221
222         DEBUG("} # server %s", request->server);
223
224         if (rcode != RLM_MODULE_OK) {
225                 request_free(&request);
226                 return NULL;
227         }
228
229         created = client_create(clients, request);
230
231         request_free(&request);
232
233         return created;         /* may be NULL */
234 #else
235         return client_find(clients, ipaddr);
236 #endif
237 }
238
239 static int listen_bind(rad_listen_t *this);
240
241
242 /*
243  *      Process and reply to a server-status request.
244  *      Like rad_authenticate and rad_accounting this should
245  *      live in it's own file but it's so small we don't bother.
246  */
247 static int rad_status_server(REQUEST *request)
248 {
249         int rcode = RLM_MODULE_OK;
250         DICT_VALUE *dval;
251
252         switch (request->listener->type) {
253         case RAD_LISTEN_AUTH:
254                 dval = dict_valbyname(PW_AUTZ_TYPE, "Status-Server");
255                 if (dval) {
256                         rcode = module_authorize(dval->value, request);
257                 } else {
258                         rcode = RLM_MODULE_OK;
259                 }
260
261                 switch (rcode) {
262                 case RLM_MODULE_OK:
263                 case RLM_MODULE_UPDATED:
264                         request->reply->code = PW_AUTHENTICATION_ACK;
265                         break;
266
267                 case RLM_MODULE_FAIL:
268                 case RLM_MODULE_HANDLED:
269                         request->reply->code = 0; /* don't reply */
270                         break;
271
272                 default:
273                 case RLM_MODULE_REJECT:
274                         request->reply->code = PW_AUTHENTICATION_REJECT;
275                         break;
276                 }
277                 break;
278
279 #ifdef WITH_ACCOUNTING
280         case RAD_LISTEN_ACCT:
281                 dval = dict_valbyname(PW_ACCT_TYPE, "Status-Server");
282                 if (dval) {
283                         rcode = module_accounting(dval->value, request);
284                 } else {
285                         rcode = RLM_MODULE_OK;
286                 }
287
288                 switch (rcode) {
289                 case RLM_MODULE_OK:
290                 case RLM_MODULE_UPDATED:
291                         request->reply->code = PW_ACCOUNTING_RESPONSE;
292                         break;
293
294                 default:
295                         request->reply->code = 0; /* don't reply */
296                         break;
297                 }
298                 break;
299 #endif
300
301         default:
302                 return 0;
303         }
304
305         return 0;
306 }
307
308
309 static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
310 {
311         listen_socket_t *sock = this->data;
312         const char *name;
313         char ip_buf[256];
314
315         if ((sock->ipaddr.af == AF_INET) &&
316             (sock->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
317                 strcpy(ip_buf, "*");
318         } else {
319                 ip_ntoh(&sock->ipaddr, ip_buf, sizeof(ip_buf));
320         }
321
322         switch (this->type) {
323         case RAD_LISTEN_AUTH:
324                 name = "authentication";
325                 break;
326
327 #ifdef WITH_ACCOUNTING
328         case RAD_LISTEN_ACCT:
329                 name = "accounting";
330                 break;
331 #endif
332
333 #ifdef WITH_PROXY
334         case RAD_LISTEN_PROXY:
335                 name = "proxy";
336                 break;
337 #endif
338
339 #ifdef WITH_VMPS
340         case RAD_LISTEN_VQP:
341                 name = "vmps";
342                 break;
343 #endif
344
345 #ifdef WITH_DHCP
346         case RAD_LISTEN_DHCP:
347                 name = "dhcp";
348                 break;
349 #endif
350
351         default:
352                 name = "??";
353                 break;
354         }
355
356         if (!this->server) {
357                 return snprintf(buffer, bufsize, "%s address %s port %d",
358                                 name, ip_buf, sock->port);
359         }
360
361         return snprintf(buffer, bufsize, "%s address %s port %d as server %s",
362                         name, ip_buf, sock->port, this->server);
363 }
364
365
366 /*
367  *      Parse an authentication or accounting socket.
368  */
369 static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
370 {
371         int             rcode;
372         int             listen_port;
373         fr_ipaddr_t     ipaddr;
374         listen_socket_t *sock = this->data;
375         char            *section_name = NULL;
376         CONF_SECTION    *client_cs, *parentcs;
377
378         /*
379          *      Try IPv4 first
380          */
381         ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
382         rcode = cf_item_parse(cs, "ipaddr", PW_TYPE_IPADDR,
383                               &ipaddr.ipaddr.ip4addr, NULL);
384         if (rcode < 0) return -1;
385
386         if (rcode == 0) { /* successfully parsed IPv4 */
387                 ipaddr.af = AF_INET;
388
389         } else {        /* maybe IPv6? */
390                 rcode = cf_item_parse(cs, "ipv6addr", PW_TYPE_IPV6ADDR,
391                                       &ipaddr.ipaddr.ip6addr, NULL);
392                 if (rcode < 0) return -1;
393
394                 if (rcode == 1) {
395                         cf_log_err(cf_sectiontoitem(cs),
396                                    "No address specified in listen section");
397                         return -1;
398                 }
399                 ipaddr.af = AF_INET6;
400         }
401
402         rcode = cf_item_parse(cs, "port", PW_TYPE_INTEGER,
403                               &listen_port, "0");
404         if (rcode < 0) return -1;
405
406         if ((listen_port < 0) || (listen_port > 65500)) {
407                         cf_log_err(cf_sectiontoitem(cs),
408                                    "Invalid value for \"port\"");
409                         return -1;
410         }
411
412         sock->ipaddr = ipaddr;
413         sock->port = listen_port;
414
415         /*
416          *      And bind it to the port.
417          */
418         if (listen_bind(this) < 0) {
419                 char buffer[128];
420                 cf_log_err(cf_sectiontoitem(cs),
421                            "Error binding to port for %s port %d",
422                            ip_ntoh(&sock->ipaddr, buffer, sizeof(buffer)),
423                            sock->port);
424                 return -1;
425         }
426
427         /*
428          *      If we can bind to interfaces, do so,
429          *      else don't.
430          */
431         if (cf_pair_find(cs, "interface")) {
432 #ifndef SO_BINDTODEVICE
433                 cf_log_err(cf_sectiontoitem(cs),
434                            "System does not support binding to interfaces.  Delete this line from the configuration file.");
435                 return -1;
436 #else
437                 const char *value;
438                 CONF_PAIR *cp = cf_pair_find(cs, "interface");
439                 struct ifreq ifreq;
440
441                 rad_assert(cp != NULL);
442                 value = cf_pair_value(cp);
443                 if (!value) {
444                         cf_log_err(cf_sectiontoitem(cs),
445                                    "No interface name given");
446                         return -1;
447                 }
448
449                 strcpy(ifreq.ifr_name, value);
450
451                 if (setsockopt(this->fd, SOL_SOCKET, SO_BINDTODEVICE,
452                                (char *)&ifreq, sizeof(ifreq)) < 0) {
453                         cf_log_err(cf_sectiontoitem(cs),
454                                    "Failed binding to interface %s: %s",
455                                    value, strerror(errno));
456                         return -1;
457                 } /* else it worked. */
458 #endif
459         }
460
461 #ifdef WITH_PROXY
462         /*
463          *      Proxy sockets don't have clients.
464          */
465         if (this->type == RAD_LISTEN_PROXY) return 0;
466 #endif
467         
468         /*
469          *      The more specific configurations are preferred to more
470          *      generic ones.
471          */
472         client_cs = NULL;
473         parentcs = cf_top_section(cs);
474         rcode = cf_item_parse(cs, "clients", PW_TYPE_STRING_PTR,
475                               &section_name, NULL);
476         if (rcode < 0) return -1; /* bad string */
477         if (rcode == 0) {
478                 /*
479                  *      Explicit list given: use it.
480                  */
481                 client_cs = cf_section_sub_find_name2(parentcs,
482                                                       "clients",
483                                                       section_name);
484                 if (!client_cs) {
485                         client_cs = cf_section_find(section_name);
486                 }
487                 if (!client_cs) {
488                         cf_log_err(cf_sectiontoitem(cs),
489                                    "Failed to find clients %s {...}",
490                                    section_name);
491                         free(section_name);
492                         return -1;
493                 }
494                 free(section_name);
495         } /* else there was no "clients = " entry. */
496
497         if (!client_cs) {
498                 CONF_SECTION *server_cs;
499
500                 server_cs = cf_section_sub_find_name2(parentcs,
501                                                       "server",
502                                                       this->server);
503                 /*
504                  *      Found a "server foo" section.  If there are clients
505                  *      in it, use them.
506                  */
507                 if (server_cs &&
508                     (cf_section_sub_find(server_cs, "client") != NULL)) {
509                         client_cs = server_cs;
510                 }
511         }
512
513         /*
514          *      Still nothing.  Look for global clients.
515          */
516         if (!client_cs) client_cs = parentcs;
517
518         sock->clients = clients_parse_section(client_cs);
519         if (!sock->clients) {
520                 cf_log_err(cf_sectiontoitem(cs),
521                            "Failed to find any clients for this listen section");
522                 return -1;
523         }
524
525         return 0;
526 }
527
528 /*
529  *      Send an authentication response packet
530  */
531 static int auth_socket_send(rad_listen_t *listener, REQUEST *request)
532 {
533         rad_assert(request->listener == listener);
534         rad_assert(listener->send == auth_socket_send);
535
536         return rad_send(request->reply, request->packet,
537                         request->client->secret);
538 }
539
540
541 #ifdef WITH_ACCOUNTING
542 /*
543  *      Send an accounting response packet (or not)
544  */
545 static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
546 {
547         rad_assert(request->listener == listener);
548         rad_assert(listener->send == acct_socket_send);
549
550         /*
551          *      Accounting reject's are silently dropped.
552          *
553          *      We do it here to avoid polluting the rest of the
554          *      code with this knowledge
555          */
556         if (request->reply->code == 0) return 0;
557
558         return rad_send(request->reply, request->packet,
559                         request->client->secret);
560 }
561 #endif
562
563 #ifdef WITH_PROXY
564 /*
565  *      Send a packet to a home server.
566  *
567  *      FIXME: have different code for proxy auth & acct!
568  */
569 static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
570 {
571         listen_socket_t *sock = listener->data;
572
573         rad_assert(request->proxy_listener == listener);
574         rad_assert(listener->send == proxy_socket_send);
575
576         request->proxy->src_ipaddr = sock->ipaddr;
577         request->proxy->src_port = sock->port;
578
579         return rad_send(request->proxy, request->packet,
580                         request->home_server->secret);
581 }
582 #endif
583
584
585 /*
586  *      Check if an incoming request is "ok"
587  *
588  *      It takes packets, not requests.  It sees if the packet looks
589  *      OK.  If so, it does a number of sanity checks on it.
590   */
591 static int auth_socket_recv(rad_listen_t *listener,
592                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
593 {
594         ssize_t         rcode;
595         int             code, src_port;
596         RADIUS_PACKET   *packet;
597         RAD_REQUEST_FUNP fun = NULL;
598         char            buffer[128];
599         RADCLIENT       *client;
600         fr_ipaddr_t     src_ipaddr;
601
602         rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
603         if (rcode < 0) return 0;
604
605         RAD_SNMP_TYPE_INC(listener, total_requests);
606
607         if (rcode < 20) {       /* AUTH_HDR_LEN */
608                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
609                 return 0;
610         }
611
612         if ((client = client_listener_find(listener,
613                                            &src_ipaddr)) == NULL) {
614                 rad_recv_discard(listener->fd);
615                 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
616
617                 if (debug_flag > 0) {
618                         char name[1024];
619
620                         listener->print(listener, name, sizeof(name));
621
622                         /*
623                          *      This is debugging rather than logging, so that
624                          *      DoS attacks don't affect us.
625                          */
626                         DEBUG("Ignoring request to %s from unknown client %s port %d",
627                               name,
628                               inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr,
629                                         buffer, sizeof(buffer)), src_port);
630                 }
631
632                 return 0;
633         }
634
635         /*
636          *      Some sanity checks, based on the packet code.
637          */
638         switch(code) {
639         case PW_AUTHENTICATION_REQUEST:
640                 RAD_SNMP_CLIENT_INC(listener, client, requests);
641                 fun = rad_authenticate;
642                 break;
643
644         case PW_STATUS_SERVER:
645                 if (!mainconfig.status_server) {
646                         rad_recv_discard(listener->fd);
647                         RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
648                         RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
649                         DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
650                         return 0;
651                 }
652                 fun = rad_status_server;
653                 break;
654
655         default:
656                 rad_recv_discard(listener->fd);
657                 RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
658                 RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
659
660                 DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
661                       code, client->shortname, src_port);
662                 return 0;
663                 break;
664         } /* switch over packet types */
665
666         /*
667          *      Now that we've sanity checked everything, receive the
668          *      packet.
669          */
670         packet = rad_recv(listener->fd, client->message_authenticator);
671         if (!packet) {
672                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
673                 DEBUG("%s", librad_errstr);
674                 return 0;
675         }
676
677         if (!received_request(listener, packet, prequest, client)) {
678                 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
679                 RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
680                 rad_free(&packet);
681                 return 0;
682         }
683
684         *pfun = fun;
685         return 1;
686 }
687
688
689 #ifdef WITH_ACCOUNTING
690 /*
691  *      Receive packets from an accounting socket
692  */
693 static int acct_socket_recv(rad_listen_t *listener,
694                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
695 {
696         ssize_t         rcode;
697         int             code, src_port;
698         RADIUS_PACKET   *packet;
699         RAD_REQUEST_FUNP fun = NULL;
700         char            buffer[128];
701         RADCLIENT       *client;
702         fr_ipaddr_t     src_ipaddr;
703
704         rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
705         if (rcode < 0) return 0;
706
707         RAD_SNMP_TYPE_INC(listener, total_requests);
708
709         if (rcode < 20) {       /* AUTH_HDR_LEN */
710                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
711                 return 0;
712         }
713
714         if ((client = client_listener_find(listener,
715                                            &src_ipaddr)) == NULL) {
716                 rad_recv_discard(listener->fd);
717                 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
718
719                 /*
720                  *      This is debugging rather than logging, so that
721                  *      DoS attacks don't affect us.
722                  */
723                 if (debug_flag > 0) {
724                         char name[1024];
725
726                         listener->print(listener, name, sizeof(name));
727
728                         DEBUG("Ignoring request to %s from unknown client %s port %d",
729                               name,
730                               inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr,
731                                         buffer, sizeof(buffer)), src_port);
732                 }
733
734                 return 0;
735         }
736
737         /*
738          *      Some sanity checks, based on the packet code.
739          */
740         switch(code) {
741         case PW_ACCOUNTING_REQUEST:
742                 RAD_SNMP_CLIENT_INC(listener, client, requests);
743                 fun = rad_accounting;
744                 break;
745
746         case PW_STATUS_SERVER:
747                 if (!mainconfig.status_server) {
748                         rad_recv_discard(listener->fd);
749                         RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
750                         RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
751
752                         DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
753                         return 0;
754                 }
755                 fun = rad_status_server;
756                 break;
757
758         default:
759                 rad_recv_discard(listener->fd);
760                 RAD_SNMP_TYPE_INC(listener, total_unknown_types);
761                 RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
762
763                 DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
764                       code, client->shortname, src_port);
765                 return 0;
766         } /* switch over packet types */
767
768         /*
769          *      Now that we've sanity checked everything, receive the
770          *      packet.
771          */
772         packet = rad_recv(listener->fd, 0);
773         if (!packet) {
774                 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
775                 radlog(L_ERR, "%s", librad_errstr);
776                 return 0;
777         }
778
779         /*
780          *      There can be no duplicate accounting packets.
781          */
782         if (!received_request(listener, packet, prequest, client)) {
783                 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
784                 RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
785                 rad_free(&packet);
786                 return 0;
787         }
788
789         *pfun = fun;
790         return 1;
791 }
792 #endif
793
794 #ifdef WITH_PROXY
795 /*
796  *      Recieve packets from a proxy socket.
797  */
798 static int proxy_socket_recv(rad_listen_t *listener,
799                               RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
800 {
801         REQUEST         *request;
802         RADIUS_PACKET   *packet;
803         RAD_REQUEST_FUNP fun = NULL;
804         char            buffer[128];
805
806         packet = rad_recv(listener->fd, 0);
807         if (!packet) {
808                 radlog(L_ERR, "%s", librad_errstr);
809                 return 0;
810         }
811
812         /*
813          *      FIXME: Client MIB updates?
814          */
815         switch(packet->code) {
816         case PW_AUTHENTICATION_ACK:
817         case PW_ACCESS_CHALLENGE:
818         case PW_AUTHENTICATION_REJECT:
819                 fun = rad_authenticate;
820                 break;
821
822 #ifdef WITH_ACCOUNTING
823         case PW_ACCOUNTING_RESPONSE:
824                 fun = rad_accounting;
825                 break;
826 #endif
827
828         default:
829                 /*
830                  *      FIXME: Update MIB for packet types?
831                  */
832                 radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
833                        "from home server %s port %d - ID %d : IGNORED",
834                        packet->code,
835                        ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
836                        packet->src_port, packet->id);
837                 rad_free(&packet);
838                 return 0;
839         }
840
841         request = received_proxy_response(packet);
842         if (!request) {
843                 return 0;
844         }
845
846         rad_assert(fun != NULL);
847         *pfun = fun;
848         *prequest = request;
849
850         return 1;
851 }
852 #endif
853
854
855 static int client_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
856 {
857         if (!request->reply->code) return 0;
858
859         rad_encode(request->reply, request->packet,
860                    request->client->secret);
861         rad_sign(request->reply, request->packet,
862                  request->client->secret);
863
864         return 0;
865 }
866
867
868 static int client_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
869 {
870         if (rad_verify(request->packet, NULL,
871                        request->client->secret) < 0) {
872                 return -1;
873         }
874
875         return rad_decode(request->packet, NULL,
876                           request->client->secret);
877 }
878
879 #ifdef WITH_PROXY
880 static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
881 {
882         rad_encode(request->proxy, NULL, request->home_server->secret);
883         rad_sign(request->proxy, NULL, request->home_server->secret);
884
885         return 0;
886 }
887
888
889 static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
890 {
891         if (rad_verify(request->proxy_reply, request->proxy,
892                        request->home_server->secret) < 0) {
893                 return -1;
894         }
895
896         return rad_decode(request->proxy_reply, request->proxy,
897                            request->home_server->secret);
898 }
899 #endif
900
901 #ifdef WITH_SNMP
902 static int radius_snmp_recv(rad_listen_t *listener,
903                             UNUSED RAD_REQUEST_FUNP *pfun,
904                             UNUSED REQUEST **prequest)
905 {
906         if ((rad_snmp.smux_fd >= 0) &&
907             (rad_snmp.smux_event == SMUX_READ)) {
908                 smux_read();
909         }
910
911         /*
912          *  If we've got to re-connect, then do so now,
913          *  before calling select again.
914          */
915         if (rad_snmp.smux_event == SMUX_CONNECT) {
916                 smux_connect();
917         }
918
919         /*
920          *      Reset this every time, as the smux connect may have
921          *      opened a new socket.
922          */
923         listener->fd = rad_snmp.smux_fd;
924
925         return 0;
926 }
927
928
929 static int radius_snmp_print(UNUSED rad_listen_t *this, char *buffer, size_t bufsize)
930 {
931         return snprintf(buffer, bufsize, "SMUX with OID .1.3.6.1.4.1.11344.1.1.1");
932 }
933
934 #endif
935
936 #include "dhcpd.c"
937
938 static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
939         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},    /* RAD_LISTEN_NONE */
940
941 #ifdef WITH_PROXY
942         /* proxying */
943         { common_socket_parse, NULL,
944           proxy_socket_recv, proxy_socket_send,
945           socket_print, proxy_socket_encode, proxy_socket_decode },
946 #else
947         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},
948 #endif
949
950         /* authentication */
951         { common_socket_parse, NULL,
952           auth_socket_recv, auth_socket_send,
953           socket_print, client_socket_encode, client_socket_decode },
954
955 #ifdef WITH_ACCOUNTING
956         /* accounting */
957         { common_socket_parse, NULL,
958           acct_socket_recv, acct_socket_send,
959           socket_print, client_socket_encode, client_socket_decode},
960 #else
961         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},
962 #endif
963
964 #ifdef WITH_DETAIL
965         /* detail */
966         { detail_parse, detail_free,
967           detail_recv, detail_send,
968           detail_print, detail_encode, detail_decode },
969 #else
970         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},
971 #endif
972
973 #ifdef WITH_VMPS
974         /* vlan query protocol */
975         { common_socket_parse, NULL,
976           vqp_socket_recv, vqp_socket_send,
977           socket_print, vqp_socket_encode, vqp_socket_decode },
978 #else
979         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},
980 #endif
981
982 #ifdef WITH_DHCP
983         /* dhcp query protocol */
984         { dhcp_socket_parse, NULL,
985           dhcp_socket_recv, dhcp_socket_send,
986           socket_print, dhcp_socket_encode, dhcp_socket_decode },
987 #else
988         { NULL, NULL, NULL, NULL, NULL, NULL, NULL},
989 #endif
990
991         { NULL, NULL, NULL, NULL, NULL, NULL, NULL}     /* RAD_LISTEN_SNMP */
992 };
993
994
995
996 /*
997  *      Binds a listener to a socket.
998  */
999 static int listen_bind(rad_listen_t *this)
1000 {
1001         listen_socket_t *sock = this->data;
1002
1003         /*
1004          *      If the port is zero, then it means the appropriate
1005          *      thing from /etc/services.
1006          */
1007         if (sock->port == 0) {
1008                 struct servent  *svp;
1009
1010                 switch (this->type) {
1011                 case RAD_LISTEN_AUTH:
1012                         svp = getservbyname ("radius", "udp");
1013                         if (svp != NULL) {
1014                                 sock->port = ntohs(svp->s_port);
1015                         } else {
1016                                 sock->port = PW_AUTH_UDP_PORT;
1017                         }
1018                         break;
1019
1020 #ifdef WITH_ACCOUNTING
1021                 case RAD_LISTEN_ACCT:
1022                         svp = getservbyname ("radacct", "udp");
1023                         if (svp != NULL) {
1024                                 sock->port = ntohs(svp->s_port);
1025                         } else {
1026                                 sock->port = PW_ACCT_UDP_PORT;
1027                         }
1028                         break;
1029 #endif
1030
1031 #ifdef WITH_PROXY
1032                 case RAD_LISTEN_PROXY:
1033                         sock->port = 0;
1034                         break;
1035 #endif
1036
1037 #ifdef WITH_VMPS
1038                 case RAD_LISTEN_VQP:
1039                         sock->port = 1589;
1040                         break;
1041 #endif
1042
1043                 default:
1044                         radlog(L_ERR, "ERROR: Non-fatal internal sanity check failed in bind.");
1045                         return -1;
1046                 }
1047         }
1048
1049         this->fd = fr_socket(&sock->ipaddr, sock->port);
1050         if (this->fd < 0) {
1051                 radlog(L_ERR, "ERROR: Failed to open socket: %s",
1052                        librad_errstr);
1053                 return -1;
1054         }
1055
1056         /*
1057          *      FreeBSD jail issues.  We bind to 0.0.0.0, but the
1058          *      kernel instead binds us to a 1.2.3.4.  If this
1059          *      happens, notice, and remember our real IP.
1060          */
1061         {
1062                 struct sockaddr_storage src;
1063                 socklen_t               sizeof_src = sizeof(src);
1064
1065                 memset(&src, 0, sizeof_src);
1066                 if (getsockname(this->fd, (struct sockaddr *) &src,
1067                                 &sizeof_src) < 0) {
1068                         radlog(L_ERR, "Failed getting socket name: %s",
1069                                strerror(errno));
1070                         return -1;
1071                 }
1072
1073                 if (!fr_sockaddr2ipaddr(&src, sizeof_src,
1074                                         &sock->ipaddr, &sock->port)) {
1075                         radlog(L_ERR, "Socket has unsupported address family");
1076                         return -1;
1077                 }
1078         }
1079
1080 #ifdef O_NONBLOCK
1081         {
1082                 int flags;
1083                 
1084                 if ((flags = fcntl(this->fd, F_GETFL, NULL)) < 0)  {
1085                         radlog(L_ERR, "Failure getting socket flags: %s)\n",
1086                                strerror(errno));
1087                         return -1;
1088                 }
1089                 
1090                 flags |= O_NONBLOCK;
1091                 if( fcntl(this->fd, F_SETFL, flags) < 0) {
1092                         radlog(L_ERR, "Failure setting socket flags: %s)\n",
1093                                strerror(errno));
1094                         return -1;
1095                 }
1096         }
1097 #endif
1098
1099         return 0;
1100 }
1101
1102
1103 /*
1104  *      Allocate & initialize a new listener.
1105  */
1106 static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
1107 {
1108         rad_listen_t *this;
1109
1110         this = rad_malloc(sizeof(*this));
1111         memset(this, 0, sizeof(*this));
1112
1113         this->type = type;
1114         this->recv = master_listen[this->type].recv;
1115         this->send = master_listen[this->type].send;
1116         this->print = master_listen[this->type].print;
1117         this->encode = master_listen[this->type].encode;
1118         this->decode = master_listen[this->type].decode;
1119
1120         switch (type) {
1121         case RAD_LISTEN_AUTH:
1122         case RAD_LISTEN_ACCT:
1123         case RAD_LISTEN_PROXY:
1124         case RAD_LISTEN_VQP:
1125         case RAD_LISTEN_DHCP:
1126                 this->data = rad_malloc(sizeof(listen_socket_t));
1127                 memset(this->data, 0, sizeof(listen_socket_t));
1128                 break;
1129
1130 #ifdef WITH_DETAIL
1131         case RAD_LISTEN_DETAIL:
1132                 this->data = NULL;
1133                 break;
1134 #endif
1135
1136         default:
1137                 rad_assert("Unsupported option!" == NULL);
1138                 break;
1139         }
1140
1141         return this;
1142 }
1143
1144
1145 #ifdef WITH_PROXY
1146 /*
1147  *      Externally visible function for creating a new proxy LISTENER.
1148  *
1149  *      For now, don't take ipaddr or port.
1150  *
1151  *      Not thread-safe, but all calls to it are protected by the
1152  *      proxy mutex in request_list.c
1153  */
1154 rad_listen_t *proxy_new_listener()
1155 {
1156         int last_proxy_port, port;
1157         rad_listen_t *this, *tmp, **last;
1158         listen_socket_t *sock, *old;
1159
1160         this = listen_alloc(RAD_LISTEN_PROXY);
1161
1162         /*
1163          *      Find an existing proxy socket to copy.
1164          *
1165          *      FIXME: Make it per-realm, or per-home server!
1166          */
1167         last_proxy_port = 0;
1168         old = NULL;
1169         last = &mainconfig.listen;
1170         for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {
1171                 if (tmp->type == RAD_LISTEN_PROXY) {
1172                         sock = tmp->data;
1173                         if (sock->port > last_proxy_port) {
1174                                 last_proxy_port = sock->port + 1;
1175                         }
1176                         if (!old) old = sock;
1177                 }
1178
1179                 last = &(tmp->next);
1180         }
1181
1182         if (!old) {
1183                 listen_free(&this);
1184                 return NULL;    /* This is a serious error. */
1185         }
1186
1187         /*
1188          *      FIXME: find a new IP address to listen on?
1189          *
1190          *      This could likely be done in the "home server"
1191          *      configuration, to have per-home-server source IP's.
1192          */
1193         sock = this->data;
1194         memcpy(&sock->ipaddr, &old->ipaddr, sizeof(sock->ipaddr));
1195
1196         /*
1197          *      Keep going until we find an unused port.
1198          */
1199         for (port = last_proxy_port; port < 64000; port++) {
1200                 sock->port = port;
1201                 if (listen_bind(this) == 0) {
1202                         /*
1203                          *      Add the new listener to the list of
1204                          *      listeners.
1205                          */
1206                         *last = this;
1207                         return this;
1208                 }
1209         }
1210
1211         listen_free(&this);
1212         return NULL;
1213 }
1214 #endif
1215
1216 static const FR_NAME_NUMBER listen_compare[] = {
1217         { "auth",       RAD_LISTEN_AUTH },
1218 #ifdef WITH_ACCOUNTING
1219         { "acct",       RAD_LISTEN_ACCT },
1220 #endif
1221 #ifdef WITH_DETAIL
1222         { "detail",     RAD_LISTEN_DETAIL },
1223 #endif
1224 #ifdef WITH_PROXY
1225         { "proxy",      RAD_LISTEN_PROXY },
1226 #endif
1227 #ifdef WITH_VMPS
1228         { "vmps",       RAD_LISTEN_VQP },
1229 #endif
1230 #ifdef WITH_DHCP
1231         { "dhcp",       RAD_LISTEN_DHCP },
1232 #else
1233         { "dhcp",       RAD_LISTEN_NONE },
1234 #endif
1235         { NULL, 0 },
1236 };
1237
1238
1239 static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
1240 {
1241         int             type, rcode;
1242         char            *listen_type;
1243         rad_listen_t    *this;
1244
1245         listen_type = NULL;
1246         
1247         cf_log_info(cs, "listen {");
1248
1249         rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,
1250                               &listen_type, "");
1251         if (rcode < 0) return NULL;
1252         if (rcode == 1) {
1253                 free(listen_type);
1254                 cf_log_err(cf_sectiontoitem(cs),
1255                            "No type specified in listen section");
1256                 return NULL;
1257         }
1258
1259         type = fr_str2int(listen_compare, listen_type,
1260                             RAD_LISTEN_NONE);
1261         if (type == RAD_LISTEN_NONE) {
1262                 cf_log_err(cf_sectiontoitem(cs),
1263                            "Invalid type \"%s\" in listen section.",
1264                            listen_type);
1265                 free(listen_type);
1266                 return NULL;
1267         }
1268         free(listen_type);
1269         
1270         /*
1271          *      Allow listen sections in the default config to
1272          *      refer to a server.
1273          */
1274         if (!server) {
1275                 rcode = cf_item_parse(cs, "virtual_server", PW_TYPE_STRING_PTR,
1276                                       &server, NULL);
1277                 if (rcode == 1) { /* compatiblity with 2.0-pre */
1278                         rcode = cf_item_parse(cs, "server", PW_TYPE_STRING_PTR,
1279                                               &server, NULL);
1280                 }
1281                 if (rcode < 0) return NULL;
1282         }
1283
1284         /*
1285          *      Set up cross-type data.
1286          */
1287         this = listen_alloc(type);
1288         this->server = server;
1289         this->fd = -1;
1290
1291         /*
1292          *      Call per-type parser.
1293          */
1294         if (master_listen[type].parse(cs, this) < 0) {
1295                 listen_free(&this);
1296                 return NULL;
1297         }
1298
1299         cf_log_info(cs, "}");
1300
1301         return this;
1302 }
1303
1304 /*
1305  *      Generate a list of listeners.  Takes an input list of
1306  *      listeners, too, so we don't close sockets with waiting packets.
1307  */
1308 int listen_init(CONF_SECTION *config, rad_listen_t **head)
1309 {
1310         int             override = FALSE;
1311         int             rcode;
1312         CONF_SECTION    *cs;
1313         rad_listen_t    **last;
1314         rad_listen_t    *this;
1315         fr_ipaddr_t     server_ipaddr;
1316         int             auth_port = 0;
1317 #ifdef WITH_PROXY
1318         int             defined_proxy = 0;
1319 #endif
1320
1321         /*
1322          *      We shouldn't be called with a pre-existing list.
1323          */
1324         rad_assert(head && (*head == NULL));
1325
1326         last = head;
1327         server_ipaddr.af = AF_UNSPEC;
1328
1329         /*
1330          *      If the port is specified on the command-line,
1331          *      it over-rides the configuration file.
1332          *
1333          *      FIXME: If argv[0] == "vmpsd", then don't listen on auth/acct!
1334          */
1335         if (mainconfig.port >= 0) auth_port = mainconfig.port;
1336
1337         /*
1338          *      If the IP address was configured on the command-line,
1339          *      use that as the "bind_address"
1340          */
1341         if (mainconfig.myip.af != AF_UNSPEC) {
1342                 memcpy(&server_ipaddr, &mainconfig.myip,
1343                        sizeof(server_ipaddr));
1344                 override = TRUE;
1345                 goto bind_it;
1346         }
1347
1348         /*
1349          *      Else look for bind_address and/or listen sections.
1350          */
1351         server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1352         rcode = cf_item_parse(config, "bind_address",
1353                               PW_TYPE_IPADDR,
1354                               &server_ipaddr.ipaddr.ip4addr, NULL);
1355         if (rcode < 0) return -1; /* error parsing it */
1356
1357         if (rcode == 0) { /* successfully parsed IPv4 */
1358                 listen_socket_t *sock;
1359                 server_ipaddr.af = AF_INET;
1360
1361                 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'.");
1362
1363         bind_it:
1364 #ifdef WITH_VMPS
1365                 if (strcmp(progname, "vmpsd") == 0) {
1366                         this = listen_alloc(RAD_LISTEN_VQP);
1367                         if (!auth_port) auth_port = 1589;
1368                 } else
1369 #endif
1370                         this = listen_alloc(RAD_LISTEN_AUTH);
1371
1372                 sock = this->data;
1373
1374                 sock->ipaddr = server_ipaddr;
1375                 sock->port = auth_port;
1376
1377                 sock->clients = clients_parse_section(config);
1378                 if (!sock->clients) {
1379                         cf_log_err(cf_sectiontoitem(config),
1380                                    "Failed to find any clients for this listen section");
1381                         return -1;
1382                 }
1383
1384                 if (listen_bind(this) < 0) {
1385                         listen_free(&this);
1386                         listen_free(head);
1387                         radlog(L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->port);
1388                         return -1;
1389                 }
1390                 auth_port = sock->port; /* may have been updated in listen_bind */
1391                 if (override) {
1392                         cs = cf_section_sub_find_name2(config, "server",
1393                                                        mainconfig.name);
1394                         if (cs) this->server = mainconfig.name;
1395                 }
1396
1397                 *last = this;
1398                 last = &(this->next);
1399
1400 #ifdef WITH_VMPS
1401                 /*
1402                  *      No acct for vmpsd
1403                  */
1404                 if (strcmp(progname, "vmpsd") == 0) goto do_proxy;
1405 #endif
1406
1407 #ifdef WITH_ACCOUNTING
1408                 /*
1409                  *      Open Accounting Socket.
1410                  *
1411                  *      If we haven't already gotten acct_port from
1412                  *      /etc/services, then make it auth_port + 1.
1413                  */
1414                 this = listen_alloc(RAD_LISTEN_ACCT);
1415                 sock = this->data;
1416
1417                 /*
1418                  *      Create the accounting socket.
1419                  *
1420                  *      The accounting port is always the
1421                  *      authentication port + 1
1422                  */
1423                 sock->ipaddr = server_ipaddr;
1424                 sock->port = auth_port + 1;
1425
1426                 sock->clients = clients_parse_section(config);
1427                 if (!sock->clients) {
1428                         cf_log_err(cf_sectiontoitem(config),
1429                                    "Failed to find any clients for this listen section");
1430                         return -1;
1431                 }
1432
1433                 if (listen_bind(this) < 0) {
1434                         listen_free(&this);
1435                         listen_free(head);
1436                         radlog(L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->port);
1437                         return -1;
1438                 }
1439
1440                 if (override) {
1441                         cs = cf_section_sub_find_name2(config, "server",
1442                                                        mainconfig.name);
1443                         if (cs) this->server = mainconfig.name;
1444                 }
1445
1446                 *last = this;
1447                 last = &(this->next);
1448 #endif
1449         } else if (mainconfig.port > 0) { /* no bind address, but a port */
1450                 radlog(L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",
1451                        mainconfig.port);
1452                 return -1;
1453         }
1454
1455         /*
1456          *      They specified an IP on the command-line, ignore
1457          *      all listen sections except the one in '-n'.
1458          */
1459         if (mainconfig.myip.af != AF_UNSPEC) {
1460                 CONF_SECTION *subcs;
1461                 const char *name2 = cf_section_name2(cs);
1462
1463                 cs = cf_section_sub_find_name2(config, "server",
1464                                                mainconfig.name);
1465                 if (!cs) goto do_proxy;
1466
1467                 /*
1468                  *      Should really abstract this code...
1469                  */
1470                 for (subcs = cf_subsection_find_next(cs, NULL, "listen");
1471                      subcs != NULL;
1472                      subcs = cf_subsection_find_next(cs, subcs, "listen")) {
1473                         this = listen_parse(subcs, name2);
1474                         if (!this) {
1475                                 listen_free(head);
1476                                 return -1;
1477                         }
1478
1479 #ifdef WITH_PROXY
1480                         if (this->type == RAD_LISTEN_PROXY) defined_proxy = 1;
1481 #endif
1482                         
1483                         *last = this;
1484                         last = &(this->next);
1485                 } /* loop over "listen" directives in server <foo> */
1486
1487                 goto do_proxy;
1488         }
1489
1490         /*
1491          *      Walk through the "listen" sections, if they exist.
1492          */
1493         for (cs = cf_subsection_find_next(config, NULL, "listen");
1494              cs != NULL;
1495              cs = cf_subsection_find_next(config, cs, "listen")) {
1496                 this = listen_parse(cs, NULL);
1497                 if (!this) {
1498                         listen_free(head);
1499                         return -1;
1500                 }
1501
1502 #ifdef WITH_PROXY
1503                 if (this->type == RAD_LISTEN_PROXY) defined_proxy = 1;
1504 #endif
1505
1506                 *last = this;
1507                 last = &(this->next);
1508         }
1509
1510         /*
1511          *      Check virtual servers for "listen" sections, too.
1512          *
1513          *      FIXME: Move to virtual server init?
1514          */
1515         for (cs = cf_subsection_find_next(config, NULL, "server");
1516              cs != NULL;
1517              cs = cf_subsection_find_next(config, cs, "server")) {
1518                 CONF_SECTION *subcs;
1519                 const char *name2 = cf_section_name2(cs);
1520                 
1521                 for (subcs = cf_subsection_find_next(cs, NULL, "listen");
1522                      subcs != NULL;
1523                      subcs = cf_subsection_find_next(cs, subcs, "listen")) {
1524                         this = listen_parse(subcs, name2);
1525                         if (!this) {
1526                                 listen_free(head);
1527                                 return -1;
1528                         }
1529                         
1530 #ifdef WITH_PROXY
1531                         if (this->type == RAD_LISTEN_PROXY) {
1532                                 radlog(L_ERR, "Error: listen type \"proxy\" Cannot appear in a virtual server section");
1533                                 listen_free(head);
1534                                 return -1;
1535                         }
1536 #endif
1537
1538                         *last = this;
1539                         last = &(this->next);
1540                 } /* loop over "listen" directives in virtual servers */
1541         } /* loop over virtual servers */
1542
1543         /*
1544          *      If we're proxying requests, open the proxy FD.
1545          *      Otherwise, don't do anything.
1546          */
1547  do_proxy:
1548 #ifdef WITH_PROXY
1549         if (mainconfig.proxy_requests == TRUE) {
1550                 int             port = -1;
1551                 listen_socket_t *sock = NULL;
1552
1553                 /*
1554                  *      No sockets to receive packets, therefore
1555                  *      proxying is pointless.
1556                  */
1557                 if (!*head) return -1;
1558
1559                 if (defined_proxy) goto do_snmp;
1560
1561                 /*
1562                  *      Find the first authentication port,
1563                  *      and use it
1564                  */
1565                 for (this = *head; this != NULL; this = this->next) {
1566                         if (this->type == RAD_LISTEN_AUTH) {
1567                                 sock = this->data;
1568                                 if (server_ipaddr.af == AF_UNSPEC) {
1569                                         server_ipaddr = sock->ipaddr;
1570                                 }
1571                                 port = sock->port + 2; /* skip acct port */
1572                                 break;
1573                         }
1574                         if (this->type == RAD_LISTEN_VQP) {
1575                                 sock = this->data;
1576                                 if (server_ipaddr.af == AF_UNSPEC) {
1577                                         server_ipaddr = sock->ipaddr;
1578                                 }
1579                                 port = sock->port + 1;
1580                                 break;
1581                         }
1582                 }
1583
1584                 if (port < 0) port = 1024 + (fr_rand() & 0x1ff);
1585
1586                 /*
1587                  *      Address is still unspecified, use IPv4.
1588                  */
1589                 if (server_ipaddr.af == AF_UNSPEC) {
1590                         server_ipaddr.af = AF_INET;
1591                         server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
1592                 }
1593
1594                 this = listen_alloc(RAD_LISTEN_PROXY);
1595                 sock = this->data;
1596
1597                 /*
1598                  *      Create the first proxy socket.
1599                  */
1600                 sock->ipaddr = server_ipaddr;
1601
1602                 /*
1603                  *      Try to find a proxy port (value doesn't matter)
1604                  */
1605                 for (sock->port = port;
1606                      sock->port < 64000;
1607                      sock->port++) {
1608                         if (listen_bind(this) == 0) {
1609                                 *last = this;
1610                                 last = &(this->next); /* just in case */
1611                                 break;
1612                         }
1613                 }
1614
1615                 if (sock->port >= 64000) {
1616                         listen_free(head);
1617                         listen_free(&this);
1618                         radlog(L_ERR, "Failed to open socket for proxying");
1619                         return -1;
1620                 }
1621         }
1622
1623  do_snmp:                       /* used only in proxy code. */
1624 #endif
1625
1626 #ifdef WITH_SNMP
1627         if (radius_snmp_init(config)) {
1628                 this = rad_malloc(sizeof(*this));
1629                 memset(this, 0, sizeof(*this));
1630
1631                 this->type = RAD_LISTEN_SNMP;
1632                 this->fd = rad_snmp.smux_fd;
1633
1634                 this->recv = radius_snmp_recv;
1635                 this->print = radius_snmp_print;
1636
1637                 *last = this;
1638                 last = &(this->next);
1639         }
1640 #endif
1641
1642         return 0;
1643 }
1644
1645 /*
1646  *      Free a linked list of listeners;
1647  */
1648 void listen_free(rad_listen_t **head)
1649 {
1650         rad_listen_t *this;
1651
1652         if (!head || !*head) return;
1653
1654         this = *head;
1655         while (this) {
1656                 rad_listen_t *next = this->next;
1657
1658                 /*
1659                  *      Other code may have eaten the FD.
1660                  */
1661                 if (this->fd >= 0) close(this->fd);
1662
1663                 if (master_listen[this->type].free) {
1664                         master_listen[this->type].free(this);
1665                 }
1666                 free(this->data);
1667                 free(this);
1668
1669                 this = next;
1670         }
1671
1672         *head = NULL;
1673 }