354dbb1b5dcf98e8ecdea7304bbd4d829aa0c9cb
[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/modules.h>
29 #include <freeradius-devel/modpriv.h>
30 #include <freeradius-devel/rad_assert.h>
31
32 #ifdef WITH_UDPFROMTO
33 #include <freeradius-devel/udpfromto.h>
34 #endif
35
36 #ifdef HAVE_SYS_RESOURCE_H
37 #include <sys/resource.h>
38 #endif
39
40 #ifdef HAVE_NET_IF_H
41 #include <net/if.h>
42 #endif
43
44 #ifdef HAVE_FCNTL_H
45 #include <fcntl.h>
46 #endif
47
48 /*
49  *      Find a per-socket client.
50  */
51 RADCLIENT *client_listener_find(const rad_listen_t *listener,
52                                 const fr_ipaddr_t *ipaddr, int src_port)
53 {
54 #ifdef WITH_DYNAMIC_CLIENTS
55         int rcode;
56         REQUEST *request;
57         RADCLIENT *created;
58 #endif
59         time_t now;
60         RADCLIENT *client;
61         RADCLIENT_LIST *clients;
62         listen_socket_t *sock;
63
64         rad_assert(listener != NULL);
65         rad_assert(ipaddr != NULL);
66
67         sock = listener->data;
68         clients = sock->clients;
69
70         /*
71          *      This HAS to have been initialized previously.
72          */
73         rad_assert(clients != NULL);
74
75         client = client_find(clients, ipaddr,sock->proto);
76         if (!client) {
77                 char name[256], buffer[128];
78                                         
79 #ifdef WITH_DYNAMIC_CLIENTS
80         unknown:                /* used only for dynamic clients */
81 #endif
82
83                 /*
84                  *      DoS attack quenching, but only in daemon mode.
85                  *      If they're running in debug mode, show them
86                  *      every packet.
87                  */
88                 if (debug_flag == 0) {
89                         static time_t last_printed = 0;
90
91                         now = time(NULL);
92                         if (last_printed == now) return NULL;
93                         
94                         last_printed = now;
95                 }
96
97                 listener->print(listener, name, sizeof(name));
98
99                 radlog(L_ERR, "Ignoring request to %s from unknown client %s port %d"
100 #ifdef WITH_TCP
101                        " proto %s"
102 #endif
103                        , name, inet_ntop(ipaddr->af, &ipaddr->ipaddr,
104                                          buffer, sizeof(buffer)), src_port
105 #ifdef WITH_TCP
106                        , (sock->proto == IPPROTO_UDP) ? "udp" : "tcp"
107 #endif
108                        );
109                 return NULL;
110         }
111
112 #ifndef WITH_DYNAMIC_CLIENTS
113         return client;          /* return the found client. */
114 #else
115
116         /*
117          *      No server defined, and it's not dynamic.  Return it.
118          */
119         if (!client->client_server && !client->dynamic) return client;
120
121         now = time(NULL);
122         
123         /*
124          *      It's a dynamically generated client, check it.
125          */
126         if (client->dynamic && (src_port != 0)) {
127                 /*
128                  *      Lives forever.  Return it.
129                  */
130                 if (client->lifetime == 0) return client;
131                 
132                 /*
133                  *      Rate-limit the deletion of known clients.
134                  *      This makes them last a little longer, but
135                  *      prevents the server from melting down if (say)
136                  *      10k clients all expire at once.
137                  */
138                 if (now == client->last_new_client) return client;
139
140                 /*
141                  *      It's not dead yet.  Return it.
142                  */
143                 if ((client->created + client->lifetime) > now) return client;
144                 
145                 /*
146                  *      This really puts them onto a queue for later
147                  *      deletion.
148                  */
149                 client_delete(clients, client);
150
151                 /*
152                  *      Go find the enclosing network again.
153                  */
154                 client = client_find(clients, ipaddr, sock->proto);
155
156                 /*
157                  *      WTF?
158                  */
159                 if (!client) goto unknown;
160                 if (!client->client_server) goto unknown;
161
162                 /*
163                  *      At this point, 'client' is the enclosing
164                  *      network that configures where dynamic clients
165                  *      can be defined.
166                  */
167                 rad_assert(client->dynamic == 0);
168         } else {
169                 /*
170                  *      The IP is unknown, so we've found an enclosing
171                  *      network.  Enable DoS protection.  We only
172                  *      allow one new client per second.  Known
173                  *      clients aren't subject to this restriction.
174                  */
175                 if (now == client->last_new_client) goto unknown;
176         }
177
178         client->last_new_client = now;
179
180         request = request_alloc();
181         if (!request) goto unknown;
182
183         request->listener = listener;
184         request->client = client;
185         request->packet = rad_recv(listener->fd, 0x02); /* MSG_PEEK */
186         if (!request->packet) {                         /* badly formed, etc */
187                 request_free(&request);
188                 goto unknown;
189         }
190         request->reply = rad_alloc_reply(request->packet);
191         if (!request->reply) {
192                 request_free(&request);
193                 goto unknown;
194         }
195         request->packet->timestamp = request->timestamp;
196         request->number = 0;
197         request->priority = listener->type;
198         request->server = client->client_server;
199         request->root = &mainconfig;
200
201         /*
202          *      Run a fake request through the given virtual server.
203          *      Look for FreeRADIUS-Client-IP-Address
204          *               FreeRADIUS-Client-Secret
205          *              ...
206          *
207          *      and create the RADCLIENT structure from that.
208          */
209         DEBUG("server %s {", request->server);
210
211         rcode = module_authorize(0, request);
212
213         DEBUG("} # server %s", request->server);
214
215         if (rcode != RLM_MODULE_OK) {
216                 request_free(&request);
217                 goto unknown;
218         }
219
220         /*
221          *      If the client was updated by rlm_dynamic_clients,
222          *      don't create the client from attribute-value pairs.
223          */
224         if (request->client == client) {
225                 created = client_create(clients, request);
226         } else {
227                 created = request->client;
228
229                 /*
230                  *      This frees the client if it isn't valid.
231                  */
232                 if (!client_validate(clients, client, created)) goto unknown;
233         }
234         request_free(&request);
235
236         if (!created) goto unknown;
237
238         return created;
239 #endif
240 }
241
242 static int listen_bind(rad_listen_t *this);
243
244
245 int listen_socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
246 {
247         size_t len;
248         listen_socket_t *sock = this->data;
249
250 #define FORWARD len = strlen(buffer); if (len >= (bufsize + 1)) return 0;buffer += len;bufsize -= len
251 #define ADDSTRING(_x) strlcpy(buffer, _x, bufsize);FORWARD
252
253         ADDSTRING(this->frs->name);
254
255 #ifdef SO_BINDTODEVICE
256         if (sock->interface) {
257                 ADDSTRING(" interface ");
258                 ADDSTRING(sock->interface);
259         }
260 #endif
261
262 #ifdef WITH_TCP
263         if (this->recv == auth_tcp_accept) {
264                 ADDSTRING(" proto tcp");
265         }
266 #endif
267
268 #ifdef WITH_TCP
269         /*
270          *      TCP sockets get printed a little differently, to make
271          *      it clear what's going on.
272          */
273         if (sock->client) {
274                 ADDSTRING(" from client (");
275                 ip_ntoh(&sock->other_ipaddr, buffer, bufsize);
276                 FORWARD;
277
278                 ADDSTRING(", ");
279                 snprintf(buffer, bufsize, "%d", sock->other_port);
280                 FORWARD;
281                 ADDSTRING(") -> (");
282
283                 if ((sock->my_ipaddr.af == AF_INET) &&
284                     (sock->my_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
285                         strlcpy(buffer, "*", bufsize);
286                 } else {
287                         ip_ntoh(&sock->my_ipaddr, buffer, bufsize);
288                 }
289                 FORWARD;
290                 
291                 ADDSTRING(", ");
292                 snprintf(buffer, bufsize, "%d", sock->my_port);
293                 FORWARD;
294
295                 if (this->server) {
296                         ADDSTRING(", virtual-server=");
297                         ADDSTRING(this->server);
298                 }
299
300                 ADDSTRING(")");
301
302                 return 1;
303         }
304
305         /*
306          *      Maybe it's a socket that we opened to a home server.
307          */
308         if ((sock->proto == IPPROTO_TCP) &&
309             (this->type == RAD_LISTEN_PROXY)) {
310                 ADDSTRING(" (");
311                 ip_ntoh(&sock->my_ipaddr, buffer, bufsize);
312                 FORWARD;
313
314                 ADDSTRING(", ");
315                 snprintf(buffer, bufsize, "%d", sock->my_port);
316                 FORWARD;
317                 ADDSTRING(") -> home_server (");
318
319                 if ((sock->other_ipaddr.af == AF_INET) &&
320                     (sock->other_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
321                         strlcpy(buffer, "*", bufsize);
322                 } else {
323                         ip_ntoh(&sock->other_ipaddr, buffer, bufsize);
324                 }
325                 FORWARD;
326                 
327                 ADDSTRING(", ");
328                 snprintf(buffer, bufsize, "%d", sock->other_port);
329                 FORWARD;
330
331                 ADDSTRING(")");
332
333                 return 1;
334         }
335 #endif
336
337         ADDSTRING(" address ");
338         
339         if ((sock->my_ipaddr.af == AF_INET) &&
340             (sock->my_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
341                 strlcpy(buffer, "*", bufsize);
342         } else {
343                 ip_ntoh(&sock->my_ipaddr, buffer, bufsize);
344         }
345         FORWARD;
346
347         ADDSTRING(" port ");
348         snprintf(buffer, bufsize, "%d", sock->my_port);
349         FORWARD;
350
351         if (this->server) {
352                 ADDSTRING(" as server ");
353                 ADDSTRING(this->server);
354         }
355
356 #undef ADDSTRING
357 #undef FORWARD
358
359         return 1;
360 }
361
362
363 /*
364  *      Parse an authentication or accounting socket.
365  */
366 int listen_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
367 {
368         int             rcode;
369         int             listen_port;
370         fr_ipaddr_t     ipaddr;
371         listen_socket_t *sock = this->data;
372         char            *section_name = NULL;
373         CONF_SECTION    *client_cs, *parentcs;
374
375         /*
376          *      Try IPv4 first
377          */
378         ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
379         rcode = cf_item_parse(cs, "ipaddr", PW_TYPE_IPADDR,
380                               &ipaddr.ipaddr.ip4addr, NULL);
381         if (rcode < 0) return -1;
382
383         if (rcode == 0) { /* successfully parsed IPv4 */
384                 ipaddr.af = AF_INET;
385
386         } else {        /* maybe IPv6? */
387                 rcode = cf_item_parse(cs, "ipv6addr", PW_TYPE_IPV6ADDR,
388                                       &ipaddr.ipaddr.ip6addr, NULL);
389                 if (rcode < 0) return -1;
390
391                 if (rcode == 1) {
392                         cf_log_err(cf_sectiontoitem(cs),
393                                    "No address specified in listen section");
394                         return -1;
395                 }
396                 ipaddr.af = AF_INET6;
397         }
398
399         rcode = cf_item_parse(cs, "port", PW_TYPE_INTEGER,
400                               &listen_port, "0");
401         if (rcode < 0) return -1;
402
403         if ((listen_port < 0) || (listen_port > 65535)) {
404                         cf_log_err(cf_sectiontoitem(cs),
405                                    "Invalid value for \"port\"");
406                         return -1;
407         }
408
409         sock->proto = IPPROTO_UDP;
410
411         if (cf_pair_find(cs, "proto")) {
412 #ifndef WITH_TCP
413                 cf_log_err(cf_sectiontoitem(cs),
414                            "System does not support the TCP protocol.  Delete this line from the configuration file.");
415                 return -1;
416 #else
417                 char *proto = NULL;
418
419
420                 rcode = cf_item_parse(cs, "proto", PW_TYPE_STRING_PTR,
421                                       &proto, "udp");
422                 if (rcode < 0) return -1;
423
424                 if (strcmp(proto, "udp") == 0) {
425                         sock->proto = IPPROTO_UDP;
426
427                 } else if (strcmp(proto, "tcp") == 0) {
428                         sock->proto = IPPROTO_TCP;
429
430                         rcode = cf_item_parse(cs, "max_connections", PW_TYPE_INTEGER,
431                                               &sock->max_connections, "64");
432                         if (rcode < 0) return -1;
433
434                 } else {
435                         cf_log_err(cf_sectiontoitem(cs),
436                                    "Unknown proto name \"%s\"", proto);
437                         free(proto);
438                         return -1;
439                 }
440                 free(proto);
441
442                 /*
443                  *      TCP requires a destination IP for sockets.
444                  *      UDP doesn't, so it's allowed.
445                  */
446                 if ((this->type == RAD_LISTEN_PROXY) &&
447                     (sock->proto != IPPROTO_UDP)) {
448                         cf_log_err(cf_sectiontoitem(cs),
449                                    "Proxy listeners can only listen on proto = udp");
450                         return -1;
451                 }
452 #endif
453         }
454
455         sock->my_ipaddr = ipaddr;
456         sock->my_port = listen_port;
457
458         /*
459          *      If we can bind to interfaces, do so,
460          *      else don't.
461          */
462         if (cf_pair_find(cs, "interface")) {
463 #ifndef SO_BINDTODEVICE
464                 cf_log_err(cf_sectiontoitem(cs),
465                            "System does not support binding to interfaces.  Delete this line from the configuration file.");
466                 return -1;
467 #else
468                 const char *value;
469                 CONF_PAIR *cp = cf_pair_find(cs, "interface");
470
471                 rad_assert(cp != NULL);
472                 value = cf_pair_value(cp);
473                 if (!value) {
474                         cf_log_err(cf_sectiontoitem(cs),
475                                    "No interface name given");
476                         return -1;
477                 }
478                 sock->interface = value;
479 #endif
480         }
481
482 #ifdef WITH_DHCP
483         /*
484          *      If we can do broadcasts..
485          */
486         if (cf_pair_find(cs, "broadcast")) {
487 #ifndef SO_BROADCAST
488                 cf_log_err(cf_sectiontoitem(cs),
489                            "System does not support broadcast sockets.  Delete this line from the configuration file.");
490                 return -1;
491 #else
492                 const char *value;
493                 CONF_PAIR *cp = cf_pair_find(cs, "broadcast");
494
495                 if (this->type != RAD_LISTEN_DHCP) {
496                         cf_log_err(cf_pairtoitem(cp),
497                                    "Broadcast can only be set for DHCP listeners.  Delete this line from the configuration file.");
498                         return -1;
499                 }
500                 
501                 rad_assert(cp != NULL);
502                 value = cf_pair_value(cp);
503                 if (!value) {
504                         cf_log_err(cf_sectiontoitem(cs),
505                                    "No broadcast value given");
506                         return -1;
507                 }
508
509                 /*
510                  *      Hack... whatever happened to cf_section_parse?
511                  */
512                 sock->broadcast = (strcmp(value, "yes") == 0);
513 #endif
514         }
515 #endif
516
517         /*
518          *      And bind it to the port.
519          */
520         if (listen_bind(this) < 0) {
521                 char buffer[128];
522                 cf_log_err(cf_sectiontoitem(cs),
523                            "Error binding to port for %s port %d",
524                            ip_ntoh(&sock->my_ipaddr, buffer, sizeof(buffer)),
525                            sock->my_port);
526                 return -1;
527         }
528
529 #ifdef WITH_PROXY
530         /*
531          *      Proxy sockets don't have clients.
532          */
533         if (this->type == RAD_LISTEN_PROXY) return 0;
534 #endif
535         
536         /*
537          *      The more specific configurations are preferred to more
538          *      generic ones.
539          */
540         client_cs = NULL;
541         parentcs = cf_top_section(cs);
542         rcode = cf_item_parse(cs, "clients", PW_TYPE_STRING_PTR,
543                               &section_name, NULL);
544         if (rcode < 0) return -1; /* bad string */
545         if (rcode == 0) {
546                 /*
547                  *      Explicit list given: use it.
548                  */
549                 client_cs = cf_section_sub_find_name2(parentcs,
550                                                       "clients",
551                                                       section_name);
552                 if (!client_cs) {
553                         client_cs = cf_section_find(section_name);
554                 }
555                 if (!client_cs) {
556                         cf_log_err(cf_sectiontoitem(cs),
557                                    "Failed to find clients %s {...}",
558                                    section_name);
559                         free(section_name);
560                         return -1;
561                 }
562                 free(section_name);
563         } /* else there was no "clients = " entry. */
564
565         if (!client_cs) {
566                 CONF_SECTION *server_cs;
567
568                 server_cs = cf_section_sub_find_name2(parentcs,
569                                                       "server",
570                                                       this->server);
571                 /*
572                  *      Found a "server foo" section.  If there are clients
573                  *      in it, use them.
574                  */
575                 if (server_cs &&
576                     (cf_section_sub_find(server_cs, "client") != NULL)) {
577                         client_cs = server_cs;
578                 }
579         }
580
581         /*
582          *      Still nothing.  Look for global clients.
583          */
584         if (!client_cs) client_cs = parentcs;
585
586         sock->clients = clients_parse_section(client_cs);
587         if (!sock->clients) {
588                 cf_log_err(cf_sectiontoitem(cs),
589                            "Failed to load clients for this listen section");
590                 return -1;
591         }
592
593 #ifdef WITH_TCP
594         if (sock->proto == IPPROTO_TCP) {
595                 /*
596                  *      Re-write the listener receive function to
597                  *      allow us to accept the socket.
598                  */
599                 this->recv = auth_tcp_accept;
600         }
601 #endif
602
603         return 0;
604 }
605
606
607 /*
608  *      Binds a listener to a socket.
609  */
610 static int listen_bind(rad_listen_t *this)
611 {
612         int rcode;
613         struct sockaddr_storage salocal;
614         socklen_t       salen;
615         listen_socket_t *sock = this->data;
616 #ifndef WITH_TCP
617 #define proto_for_port "udp"
618 #define sock_type SOCK_DGRAM
619 #else
620         const char *proto_for_port = "udp";
621         int sock_type = SOCK_DGRAM;
622         
623         if (sock->proto == IPPROTO_TCP) {
624 #ifdef WITH_VMPS
625                 if (this->type == RAD_LISTEN_VQP) {
626                         radlog(L_ERR, "VQP does not support TCP transport");
627                         return -1;
628                 }
629 #endif
630
631                 proto_for_port = "tcp";
632                 sock_type = SOCK_STREAM;        
633         }
634 #endif
635
636         /*
637          *      If the port is zero, then it means the appropriate
638          *      thing from /etc/services.
639          */
640         if (sock->my_port == 0) {
641                 struct servent  *svp;
642
643                 switch (this->type) {
644                 case RAD_LISTEN_AUTH:
645                         svp = getservbyname ("radius", proto_for_port);
646                         if (svp != NULL) {
647                                 sock->my_port = ntohs(svp->s_port);
648                         } else {
649                                 sock->my_port = PW_AUTH_UDP_PORT;
650                         }
651                         break;
652
653 #ifdef WITH_ACCOUNTING
654                 case RAD_LISTEN_ACCT:
655                         svp = getservbyname ("radacct", proto_for_port);
656                         if (svp != NULL) {
657                                 sock->my_port = ntohs(svp->s_port);
658                         } else {
659                                 sock->my_port = PW_ACCT_UDP_PORT;
660                         }
661                         break;
662 #endif
663
664 #ifdef WITH_PROXY
665                 case RAD_LISTEN_PROXY:
666                         /* leave it at zero */
667                         break;
668 #endif
669
670 #ifdef WITH_VMPS
671                 case RAD_LISTEN_VQP:
672                         sock->my_port = 1589;
673                         break;
674 #endif
675
676 #ifdef WITH_COA
677                 case RAD_LISTEN_COA:
678                         sock->my_port = PW_COA_UDP_PORT;
679                         break;
680 #endif
681                 default:
682                         radlog(L_ERR, "ERROR: Non-fatal internal sanity check failed in bind.");
683                         return -1;
684                 }
685         }
686
687         /*
688          *      Copy fr_socket() here, as we may need to bind to a device.
689          */
690         this->fd = socket(sock->my_ipaddr.af, sock_type, 0);
691         if (this->fd < 0) {
692                 radlog(L_ERR, "Failed opening socket: %s", strerror(errno));
693                 return -1;
694         }
695                 
696 #ifdef SO_BINDTODEVICE
697         /*
698          *      Bind to a device BEFORE touching IP addresses.
699          */
700         if (sock->interface) {
701                 struct ifreq ifreq;
702                 strcpy(ifreq.ifr_name, sock->interface);
703
704                 fr_suid_up();
705                 rcode = setsockopt(this->fd, SOL_SOCKET, SO_BINDTODEVICE,
706                                    (char *)&ifreq, sizeof(ifreq));
707                 fr_suid_down();
708                 if (rcode < 0) {
709                         close(this->fd);
710                         radlog(L_ERR, "Failed binding to interface %s: %s",
711                                sock->interface, strerror(errno));
712                         return -1;
713                 } /* else it worked. */
714         }
715 #endif
716
717 #ifdef WITH_TCP
718         if (sock->proto == IPPROTO_TCP) {
719                 int on = 1;
720
721                 if (setsockopt(this->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
722                         close(this->fd);
723                         radlog(L_ERR, "Failed to reuse address: %s", strerror(errno));
724                         return -1;
725                 }
726         }
727 #endif
728
729 #if defined(WITH_TCP) && defined(WITH_UDPFROMTO)
730         else                    /* UDP sockets get UDPfromto */
731 #endif
732
733 #ifdef WITH_UDPFROMTO
734         /*
735          *      Initialize udpfromto for all sockets.
736          */
737         if (udpfromto_init(this->fd) != 0) {
738                 close(this->fd);
739                 return -1;
740         }
741 #endif
742
743         /*
744          *      Set up sockaddr stuff.
745          */
746         if (!fr_ipaddr2sockaddr(&sock->my_ipaddr, sock->my_port, &salocal, &salen)) {
747                 close(this->fd);
748                 return -1;
749         }
750                 
751 #ifdef HAVE_STRUCT_SOCKADDR_IN6
752         if (sock->my_ipaddr.af == AF_INET6) {
753                 /*
754                  *      Listening on '::' does NOT get you IPv4 to
755                  *      IPv6 mapping.  You've got to listen on an IPv4
756                  *      address, too.  This makes the rest of the server
757                  *      design a little simpler.
758                  */
759 #ifdef IPV6_V6ONLY
760                 
761                 if (IN6_IS_ADDR_UNSPECIFIED(&sock->my_ipaddr.ipaddr.ip6addr)) {
762                         int on = 1;
763                         
764                         setsockopt(this->fd, IPPROTO_IPV6, IPV6_V6ONLY,
765                                    (char *)&on, sizeof(on));
766                 }
767 #endif /* IPV6_V6ONLY */
768         }
769 #endif /* HAVE_STRUCT_SOCKADDR_IN6 */
770
771         if (sock->my_ipaddr.af == AF_INET) {
772                 UNUSED int flag;
773                 
774 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
775                 /*
776                  *      Disable PMTU discovery.  On Linux, this
777                  *      also makes sure that the "don't fragment"
778                  *      flag is zero.
779                  */
780                 flag = IP_PMTUDISC_DONT;
781                 setsockopt(this->fd, IPPROTO_IP, IP_MTU_DISCOVER,
782                            &flag, sizeof(flag));
783 #endif
784
785 #if defined(IP_DONTFRAG)
786                 /*
787                  *      Ensure that the "don't fragment" flag is zero.
788                  */
789                 flag = 0;
790                 setsockopt(this->fd, IPPROTO_IP, IP_DONTFRAG,
791                            &flag, sizeof(flag));
792 #endif
793         }
794
795 #ifdef WITH_DHCP
796 #ifdef SO_BROADCAST
797         if (sock->broadcast) {
798                 int on = 1;
799                 
800                 if (setsockopt(this->fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
801                         radlog(L_ERR, "Can't set broadcast option: %s\n",
802                                strerror(errno));
803                         return -1;
804                 }
805         }
806 #endif
807 #endif
808
809         /*
810          *      May be binding to priviledged ports.
811          */
812         if (sock->my_port != 0) {
813 #ifdef SO_REUSEADDR
814                 int on = 1;
815
816                 if (setsockopt(this->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
817                         radlog(L_ERR, "Can't set re-use address option: %s\n",
818                                strerror(errno));
819                         return -1;
820                 }
821 #endif
822
823                 fr_suid_up();
824                 rcode = bind(this->fd, (struct sockaddr *) &salocal, salen);
825                 fr_suid_down();
826                 if (rcode < 0) {
827                         char buffer[256];
828                         close(this->fd);
829                         
830                         this->print(this, buffer, sizeof(buffer));
831                         radlog(L_ERR, "Failed binding to %s: %s\n",
832                                buffer, strerror(errno));
833                         return -1;
834                 }
835         
836                 /*
837                  *      FreeBSD jail issues.  We bind to 0.0.0.0, but the
838                  *      kernel instead binds us to a 1.2.3.4.  If this
839                  *      happens, notice, and remember our real IP.
840                  */
841                 {
842                         struct sockaddr_storage src;
843                         socklen_t               sizeof_src = sizeof(src);
844                         
845                         memset(&src, 0, sizeof_src);
846                         if (getsockname(this->fd, (struct sockaddr *) &src,
847                                         &sizeof_src) < 0) {
848                                 radlog(L_ERR, "Failed getting socket name: %s",
849                                        strerror(errno));
850                                 return -1;
851                         }
852                         
853                         if (!fr_sockaddr2ipaddr(&src, sizeof_src,
854                                                 &sock->my_ipaddr, &sock->my_port)) {
855                                 radlog(L_ERR, "Socket has unsupported address family");
856                                 return -1;
857                         }
858                 }
859         }
860
861 #ifdef WITH_TCP
862         if (sock->proto == IPPROTO_TCP) {
863                 if (listen(this->fd, 8) < 0) {
864                         close(this->fd);
865                         radlog(L_ERR, "Failed in listen(): %s", strerror(errno));
866                         return -1;
867                 }
868         } else
869 #endif
870
871           if (fr_nonblock(this->fd) < 0) {
872                   close(this->fd);
873                   radlog(L_ERR, "Failed setting non-blocking on socket: %s",
874                          strerror(errno));
875                   return -1;
876           }
877
878         /*
879          *      Mostly for proxy sockets.
880          */
881         sock->other_ipaddr.af = sock->my_ipaddr.af;
882
883 /*
884  *      Don't screw up other people.
885  */
886 #undef proto_for_port
887 #undef sock_type
888
889         return 0;
890 }
891
892 #define MAX_HANDLES (32)
893 static int frs_init = 0;
894 static lt_dlhandle frs_modules[MAX_HANDLES];
895
896
897 /*
898  *      Allocate & initialize a new listener.
899  */
900 rad_listen_t *listen_alloc(const char *type_name)
901 {
902         int i;
903         rad_listen_t *this;
904         const frs_module_t *frs;
905         char buffer[256];
906
907         this = rad_malloc(sizeof(*this));
908         memset(this, 0, sizeof(*this));
909
910         snprintf(buffer, sizeof(buffer), "frs_%s", type_name);
911
912         if (!frs_init) {
913                 memset(frs_modules, 0, sizeof(frs_modules));
914                 frs_init = TRUE;
915         }
916
917         frs = NULL;
918         for (i = 0; i < MAX_HANDLES; i++) {
919                 if (!frs_modules[i]) continue;
920
921                 frs = lt_dlsym(frs_modules[i], buffer);
922                 if (frs) break;
923         }
924         
925         if (!frs) {
926                 lt_dlhandle handle;
927
928                 handle = lt_dlopenext(buffer);
929                 if (!handle) {
930                         radlog(L_ERR, "Failed opening %s: %s",
931                                buffer, lt_dlerror());
932                         return NULL;
933                 }
934                 
935                 frs = lt_dlsym(handle, buffer);
936                 if (!frs) {
937                         lt_dlclose(handle);
938                         radlog(L_ERR, "Failed linking to %s: %s",
939                                buffer, lt_dlerror());
940                         return NULL;
941                 }
942         
943                 if (frs->magic != FRS_MODULE_MAGIC_NUMBER) {
944                         lt_dlclose(handle);
945                         radlog(L_ERR, "Invalid version in %s\n",
946                                buffer);
947                         return NULL;
948                 }
949
950                 for (i = 0; i < MAX_HANDLES; i++) {
951                         if (!frs_modules[i]) {
952                                 frs_modules[i] = handle;
953                                 break;
954                         }
955                 } /* if we run out, we leak the handle.  Too bad. */
956         }
957
958         this->type = frs->type;
959         this->frs = frs;
960         this->recv = frs->recv;
961         this->send = frs->send;
962         this->print = frs->print;
963         this->encode = frs->encode;
964         this->decode = frs->decode;
965
966         switch (this->type) {
967 #ifdef WITH_STATS
968         case RAD_LISTEN_NONE:
969 #endif
970         case RAD_LISTEN_AUTH:
971 #ifdef WITH_ACCOUNTING
972         case RAD_LISTEN_ACCT:
973 #endif
974 #ifdef WITH_PROXY
975         case RAD_LISTEN_PROXY:
976 #endif
977 #ifdef WITH_VMPS
978         case RAD_LISTEN_VQP:
979 #endif
980 #ifdef WITH_COA
981         case RAD_LISTEN_COA:
982 #endif
983                 this->data = rad_malloc(sizeof(listen_socket_t));
984                 memset(this->data, 0, sizeof(listen_socket_t));
985                 break;
986
987 #ifdef WITH_DHCP
988         case RAD_LISTEN_DHCP:
989                 this->data = rad_malloc(sizeof(dhcp_socket_t));
990                 memset(this->data, 0, sizeof(dhcp_socket_t));
991                 break;
992 #endif
993
994 #ifdef WITH_DETAIL
995         case RAD_LISTEN_DETAIL:
996                 this->data = NULL;
997                 break;
998 #endif
999
1000 #ifdef WITH_COMMAND_SOCKET
1001         /*
1002          *      The data here is allocate in the "parse" section.
1003          */
1004         case RAD_LISTEN_COMMAND:
1005                 break;
1006 #endif
1007
1008         default:
1009                 rad_assert("Unsupported option!" == NULL);
1010                 break;
1011         }
1012
1013         return this;
1014 }
1015
1016 #ifdef WITH_PROXY
1017 /*
1018  *      Externally visible function for creating a new proxy LISTENER.
1019  *
1020  *      Not thread-safe, but all calls to it are protected by the
1021  *      proxy mutex in event.c
1022  */
1023 int proxy_new_listener(home_server *home, int src_port)
1024 {
1025         rad_listen_t *this;
1026         listen_socket_t *sock;
1027
1028         if (!home) return 0;
1029
1030         if ((home->max_connections > 0) &&
1031             (home->num_connections >= home->max_connections)) {
1032                 DEBUG("WARNING: Home server has too many open connections (%d)",
1033                       home->max_connections);
1034                 return 0;
1035         }
1036
1037         this = listen_alloc(RAD_LISTEN_PROXY);
1038
1039         sock = this->data;
1040         sock->other_ipaddr = home->ipaddr;
1041         sock->other_port = home->port;
1042         sock->home = home;
1043
1044         sock->my_ipaddr = home->src_ipaddr;
1045         sock->my_port = src_port;
1046         sock->proto = home->proto;
1047
1048 #ifdef WITH_TCP
1049         sock->last_packet = time(NULL);
1050
1051         if (home->proto == IPPROTO_TCP) {
1052                 this->recv = proxy_socket_tcp_recv;
1053
1054                 /*
1055                  *      FIXME: connect() is blocking!
1056                  *      We do this with the proxy mutex locked, which may
1057                  *      cause large delays!
1058                  *
1059                  *      http://www.developerweb.net/forum/showthread.php?p=13486
1060                  */
1061                 this->fd = fr_tcp_client_socket(&home->src_ipaddr,
1062                                                 &home->ipaddr, home->port);
1063         } else
1064 #endif
1065                 this->fd = fr_socket(&home->src_ipaddr, src_port);
1066
1067         if (this->fd < 0) {
1068                 DEBUG("Failed opening client socket: %s", fr_strerror());
1069                 listen_free(&this);
1070                 return 0;
1071         }
1072
1073         /*
1074          *      Figure out which port we were bound to.
1075          */
1076         if (sock->my_port == 0) {
1077                 struct sockaddr_storage src;
1078                 socklen_t               sizeof_src = sizeof(src);
1079                 
1080                 memset(&src, 0, sizeof_src);
1081                 if (getsockname(this->fd, (struct sockaddr *) &src,
1082                                 &sizeof_src) < 0) {
1083                         radlog(L_ERR, "Failed getting socket name: %s",
1084                                strerror(errno));
1085                         listen_free(&this);
1086                         return 0;
1087                 }
1088                 
1089                 if (!fr_sockaddr2ipaddr(&src, sizeof_src,
1090                                         &sock->my_ipaddr, &sock->my_port)) {
1091                         radlog(L_ERR, "Socket has unsupported address family");
1092                         listen_free(&this);
1093                         return 0;
1094                 }
1095         }
1096
1097         /*
1098          *      Tell the event loop that we have a new FD
1099          */
1100         event_new_fd(this);
1101         
1102         return 1;
1103 }
1104 #endif
1105
1106
1107 static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
1108 {
1109         int             rcode;
1110         char            *listen_type;
1111         rad_listen_t    *this;
1112
1113         listen_type = NULL;
1114         
1115         cf_log_info(cs, "listen {");
1116
1117         rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,
1118                               &listen_type, "");
1119         if (rcode < 0) return NULL;
1120         if (rcode == 1) {
1121                 free(listen_type);
1122                 cf_log_err(cf_sectiontoitem(cs),
1123                            "No type specified in listen section");
1124                 return NULL;
1125         }
1126
1127         /*
1128          *      Allow listen sections in the default config to
1129          *      refer to a server.
1130          */
1131         if (!server) {
1132                 rcode = cf_item_parse(cs, "virtual_server", PW_TYPE_STRING_PTR,
1133                                       &server, NULL);
1134                 if (rcode == 1) { /* compatiblity with 2.0-pre */
1135                         rcode = cf_item_parse(cs, "server", PW_TYPE_STRING_PTR,
1136                                               &server, NULL);
1137                 }
1138                 if (rcode < 0) {
1139                         free(listen_type);
1140                         return NULL;
1141                 }
1142         }
1143
1144 #ifdef WITH_PROXY
1145         /*
1146          *      We were passed a virtual server, so the caller is
1147          *      defining a proxy listener inside of a virtual server.
1148          *      This isn't allowed right now.
1149          */
1150         else if (type == RAD_LISTEN_PROXY) {
1151                 radlog(L_ERR, "Error: listen type \"proxy\" Cannot appear in a virtual server section");
1152                 return NULL;
1153         }
1154 #endif
1155
1156         /*
1157          *      Set up cross-type data.
1158          */
1159         this = listen_alloc(listen_type);
1160         if (!this) return NULL;
1161
1162         free(listen_type);
1163         this->server = server;
1164         this->fd = -1;
1165
1166         /*
1167          *      Call per-type parser.
1168          */
1169         if (this->frs->parse(cs, this) < 0) {
1170                 listen_free(&this);
1171                 return NULL;
1172         }
1173
1174         cf_log_info(cs, "}");
1175
1176         return this;
1177 }
1178
1179 /*
1180  *      Generate a list of listeners.  Takes an input list of
1181  *      listeners, too, so we don't close sockets with waiting packets.
1182  */
1183 int listen_init(CONF_SECTION *config, rad_listen_t **head)
1184 {
1185         int             override = FALSE;
1186         int             rcode;
1187         CONF_SECTION    *cs = NULL;
1188         rad_listen_t    **last;
1189         rad_listen_t    *this;
1190         fr_ipaddr_t     server_ipaddr;
1191         int             auth_port = 0;
1192 #ifdef WITH_PROXY
1193         int             defined_proxy = 0;
1194 #endif
1195
1196         /*
1197          *      We shouldn't be called with a pre-existing list.
1198          */
1199         rad_assert(head && (*head == NULL));
1200
1201         last = head;
1202         server_ipaddr.af = AF_UNSPEC;
1203
1204         /*
1205          *      If the port is specified on the command-line,
1206          *      it over-rides the configuration file.
1207          *
1208          *      FIXME: If argv[0] == "vmpsd", then don't listen on auth/acct!
1209          */
1210         if (mainconfig.port >= 0) auth_port = mainconfig.port;
1211
1212         /*
1213          *      If the IP address was configured on the command-line,
1214          *      use that as the "bind_address"
1215          */
1216         if (mainconfig.myip.af != AF_UNSPEC) {
1217                 memcpy(&server_ipaddr, &mainconfig.myip,
1218                        sizeof(server_ipaddr));
1219                 override = TRUE;
1220                 goto bind_it;
1221         }
1222
1223         /*
1224          *      Else look for bind_address and/or listen sections.
1225          */
1226         server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1227         rcode = cf_item_parse(config, "bind_address",
1228                               PW_TYPE_IPADDR,
1229                               &server_ipaddr.ipaddr.ip4addr, NULL);
1230         if (rcode < 0) return -1; /* error parsing it */
1231
1232         if (rcode == 0) { /* successfully parsed IPv4 */
1233                 listen_socket_t *sock;
1234                 server_ipaddr.af = AF_INET;
1235
1236                 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'.");
1237
1238         bind_it:
1239 #ifdef WITH_VMPS
1240                 if (strcmp(progname, "vmpsd") == 0) {
1241                         this = listen_alloc("vmps");
1242                         if (!this) return 0;    /* FIXME: memleak? */
1243                         if (!auth_port) auth_port = 1589;
1244                 } else
1245 #endif
1246                 {
1247                         this = listen_alloc("auth");
1248                         if (!this) return 0;    /* FIXME: memleak? */
1249                 }
1250
1251                 sock = this->data;
1252
1253                 sock->my_ipaddr = server_ipaddr;
1254                 sock->my_port = auth_port;
1255
1256                 sock->clients = clients_parse_section(config);
1257                 if (!sock->clients) {
1258                         cf_log_err(cf_sectiontoitem(config),
1259                                    "Failed to find any clients for this listen section");
1260                         listen_free(&this);
1261                         return -1;
1262                 }
1263
1264                 if (listen_bind(this) < 0) {
1265                         listen_free(head);
1266                         radlog(L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->my_port);
1267                         listen_free(&this);
1268                         return -1;
1269                 }
1270                 auth_port = sock->my_port;      /* may have been updated in listen_bind */
1271                 if (override) {
1272                         cs = cf_section_sub_find_name2(config, "server",
1273                                                        mainconfig.name);
1274                         if (cs) this->server = mainconfig.name;
1275                 }
1276
1277                 *last = this;
1278                 last = &(this->next);
1279
1280 #ifdef WITH_VMPS
1281                 /*
1282                  *      No acct for vmpsd
1283                  */
1284                 if (strcmp(progname, "vmpsd") == 0) goto add_sockets;
1285 #endif
1286
1287 #ifdef WITH_ACCOUNTING
1288                 /*
1289                  *      Open Accounting Socket.
1290                  *
1291                  *      If we haven't already gotten acct_port from
1292                  *      /etc/services, then make it auth_port + 1.
1293                  */
1294                 this = listen_alloc("acct");
1295                 if (!this) return 0;    /* FIXME: memleak? */
1296                 sock = this->data;
1297
1298                 /*
1299                  *      Create the accounting socket.
1300                  *
1301                  *      The accounting port is always the
1302                  *      authentication port + 1
1303                  */
1304                 sock->my_ipaddr = server_ipaddr;
1305                 sock->my_port = auth_port + 1;
1306
1307                 sock->clients = clients_parse_section(config);
1308                 if (!sock->clients) {
1309                         cf_log_err(cf_sectiontoitem(config),
1310                                    "Failed to find any clients for this listen section");
1311                         return -1;
1312                 }
1313
1314                 if (listen_bind(this) < 0) {
1315                         listen_free(&this);
1316                         listen_free(head);
1317                         radlog(L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->my_port);
1318                         return -1;
1319                 }
1320
1321                 if (override) {
1322                         cs = cf_section_sub_find_name2(config, "server",
1323                                                        mainconfig.name);
1324                         if (cs) this->server = mainconfig.name;
1325                 }
1326
1327                 *last = this;
1328                 last = &(this->next);
1329 #endif
1330         } else if (mainconfig.port > 0) { /* no bind address, but a port */
1331                 radlog(L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",
1332                        mainconfig.port);
1333                 return -1;
1334         }
1335
1336         /*
1337          *      They specified an IP on the command-line, ignore
1338          *      all listen sections except the one in '-n'.
1339          */
1340         if (mainconfig.myip.af != AF_UNSPEC) {
1341                 CONF_SECTION *subcs;
1342                 const char *name2 = cf_section_name2(cs);
1343
1344                 cs = cf_section_sub_find_name2(config, "server",
1345                                                mainconfig.name);
1346                 if (!cs) goto add_sockets;
1347
1348                 /*
1349                  *      Should really abstract this code...
1350                  */
1351                 for (subcs = cf_subsection_find_next(cs, NULL, "listen");
1352                      subcs != NULL;
1353                      subcs = cf_subsection_find_next(cs, subcs, "listen")) {
1354                         this = listen_parse(subcs, name2);
1355                         if (!this) {
1356                                 listen_free(head);
1357                                 return -1;
1358                         }
1359
1360                         *last = this;
1361                         last = &(this->next);
1362                 } /* loop over "listen" directives in server <foo> */
1363
1364                 goto add_sockets;
1365         }
1366
1367         /*
1368          *      Walk through the "listen" sections, if they exist.
1369          */
1370         for (cs = cf_subsection_find_next(config, NULL, "listen");
1371              cs != NULL;
1372              cs = cf_subsection_find_next(config, cs, "listen")) {
1373                 this = listen_parse(cs, NULL);
1374                 if (!this) {
1375                         listen_free(head);
1376                         return -1;
1377                 }
1378
1379                 *last = this;
1380                 last = &(this->next);
1381         }
1382
1383         /*
1384          *      Check virtual servers for "listen" sections, too.
1385          *
1386          *      FIXME: Move to virtual server init?
1387          */
1388         for (cs = cf_subsection_find_next(config, NULL, "server");
1389              cs != NULL;
1390              cs = cf_subsection_find_next(config, cs, "server")) {
1391                 CONF_SECTION *subcs;
1392                 const char *name2 = cf_section_name2(cs);
1393                 
1394                 for (subcs = cf_subsection_find_next(cs, NULL, "listen");
1395                      subcs != NULL;
1396                      subcs = cf_subsection_find_next(cs, subcs, "listen")) {
1397                         this = listen_parse(subcs, name2);
1398                         if (!this) {
1399                                 listen_free(head);
1400                                 return -1;
1401                         }
1402                         
1403                         *last = this;
1404                         last = &(this->next);
1405                 } /* loop over "listen" directives in virtual servers */
1406         } /* loop over virtual servers */
1407
1408 add_sockets:
1409         /*
1410          *      Print out which sockets we're listening on, and
1411          *      add them to the event list.
1412          */
1413         for (this = *head; this != NULL; this = this->next) {
1414 #ifdef WITH_PROXY
1415                 if (this->type == RAD_LISTEN_PROXY) {
1416                         defined_proxy = 1;
1417                 }
1418
1419 #endif
1420                 event_new_fd(this);
1421         }
1422
1423         /*
1424          *      If we're proxying requests, open the proxy FD.
1425          *      Otherwise, don't do anything.
1426          */
1427 #ifdef WITH_PROXY
1428         if ((mainconfig.proxy_requests == TRUE) &&
1429             (*head != NULL) && !defined_proxy) {
1430                 listen_socket_t *sock = NULL;
1431                 int             port = 0;
1432                 home_server     home;
1433
1434                 memset(&home, 0, sizeof(home));
1435
1436                 /*
1437                  *      
1438                  */
1439                 home.proto = IPPROTO_UDP;
1440                 home.src_ipaddr = server_ipaddr;
1441
1442                 /*
1443                  *      Find the first authentication port,
1444                  *      and use it
1445                  */
1446                 for (this = *head; this != NULL; this = this->next) {
1447                         if (this->type == RAD_LISTEN_AUTH) {
1448                                 sock = this->data;
1449                                 if (home.src_ipaddr.af == AF_UNSPEC) {
1450                                         home.src_ipaddr = sock->my_ipaddr;
1451                                 }
1452                                 port = sock->my_port + 2;
1453                                 break;
1454                         }
1455 #ifdef WITH_ACCT
1456                         if (this->type == RAD_LISTEN_ACCT) {
1457                                 sock = this->data;
1458                                 if (home.src_ipaddr.af == AF_UNSPEC) {
1459                                         home.src_ipaddr = sock->my_ipaddr;
1460                                 }
1461                                 port = sock->my_port + 1;
1462                                 break;
1463                         }
1464 #endif
1465                 }
1466
1467                 /*
1468                  *      Address is still unspecified, use IPv4.
1469                  */
1470                 if (home.src_ipaddr.af == AF_UNSPEC) {
1471                         home.src_ipaddr.af = AF_INET;
1472                         /* everything else is already set to zero */
1473                 }
1474
1475                 this = listen_alloc("proxy");
1476                 if (!this) return 0;    /* FIXME: memleak? */
1477                 sock = this->data;
1478                 home.ipaddr.af = home.src_ipaddr.af;
1479                 /* everything else is already set to zero */
1480
1481                 if (!proxy_new_listener(&home, port)) {
1482                         listen_free(head);
1483                         return -1;
1484                 }
1485         }
1486 #endif
1487
1488         /*
1489          *      Haven't defined any sockets.  Die.
1490          */
1491         if (!*head) return -1;
1492
1493
1494         return 0;
1495 }
1496
1497 /*
1498  *      Free a linked list of listeners;
1499  */
1500 void listen_free(rad_listen_t **head)
1501 {
1502         rad_listen_t *this;
1503
1504         if (!head || !*head) return;
1505
1506         this = *head;
1507         while (this) {
1508                 rad_listen_t *next = this->next;
1509
1510                 /*
1511                  *      Other code may have eaten the FD.
1512                  */
1513                 if (this->fd >= 0) close(this->fd);
1514
1515                 if (this->frs->free) {
1516                         this->frs->free(this);
1517                 }
1518
1519 #ifdef WITH_TCP
1520                 if ((this->type == RAD_LISTEN_AUTH) ||
1521 #ifdef WITH_ACCT
1522                     (this->type == RAD_LISTEN_ACCT) ||
1523 #endif
1524 #ifdef WITH_PROXY
1525                     (this->type == RAD_LISTEN_PROXY)
1526 #endif
1527                         ) {
1528                         listen_socket_t *sock = this->data;
1529                         rad_free(&sock->packet);
1530                 }
1531 #endif
1532
1533                 free(this->data);
1534                 free(this);
1535
1536                 this = next;
1537         }
1538
1539         *head = NULL;
1540
1541 #ifdef WITH_TCP
1542 fr_tcp_radius_t *fr_listen2tcp(rad_listen_t *this)
1543 {
1544         listen_socket_t *sock;
1545
1546         if (!this || (this->type != RAD_LISTEN_PROXY) || !this->data) {
1547                 return NULL;
1548         }
1549
1550         sock = this->data;
1551         return sock->tcp;
1552 }
1553
1554 rad_listen_t *proxy_new_tcp_listener(home_server *home)
1555 {
1556         int i;
1557         fr_tcp_radius_t *tcp;
1558         struct sockaddr_storage src;
1559         socklen_t sizeof_src = sizeof(src);
1560         rad_listen_t *this;
1561         listen_socket_t *sock;
1562
1563         if (!home ||
1564             ((home->max_connections > 0) &&
1565              (home->num_connections >= home->max_connections))) {
1566                 DEBUG("WARNING: Home server has too many open connections (%d)",
1567                       home->max_connections);
1568                 return NULL;
1569         }
1570
1571         this = NULL;
1572
1573         /*
1574          *      FIXME: Move to RBTrees.
1575          */
1576         for (i = 0; i < home->max_connections; i++) {
1577                 if (home->listeners[i]) continue;
1578
1579                 this = home->listeners[i] = listen_alloc(RAD_LISTEN_PROXY);
1580                 if (!this) {
1581                         DEBUG("WARNING: Failed allocating memory");
1582                         return NULL;
1583                 }
1584                 break;
1585         }
1586
1587         if (!this) {
1588                 DEBUG("WARNING: Failed to find a free connection slot");
1589                 return NULL;
1590         }
1591         sock = this->data;
1592
1593         tcp = sock->tcp = rad_malloc(sizeof(*tcp));
1594         memset(tcp, 0, sizeof(*tcp));
1595
1596         /*
1597          *      Initialize th
1598          *
1599          *      Open a new socket...
1600          *
1601          *      Do stuff...
1602          */
1603         tcp->dst_ipaddr = home->ipaddr;
1604         tcp->dst_port = home->port;
1605         tcp->lifetime = home->lifetime;
1606         tcp->opened = time(NULL);       
1607
1608         /*
1609          *      FIXME: connect() is blocking!
1610          *      We do this with the proxy mutex locked, which may
1611          *      cause large delays!
1612          *
1613          *      http://www.developerweb.net/forum/showthread.php?p=13486
1614          */
1615         this->fd = tcp->fd = fr_tcp_client_socket(&tcp->dst_ipaddr, tcp->dst_port);
1616         if (tcp->fd < 0) {
1617                 listen_free(&this);
1618                 DEBUG("WARNING: Failed opening socket to home server");
1619                 return NULL;
1620         }
1621         memset(&src, 0, sizeof_src);
1622         if (getsockname(tcp->fd, (struct sockaddr *) &src, &sizeof_src) < 0) {
1623                 close(tcp->fd);
1624                 listen_free(&this);
1625                 return NULL;
1626         }
1627
1628         if (!fr_sockaddr2ipaddr(&src, sizeof_src,
1629                                 &tcp->src_ipaddr, &tcp->src_port)) {
1630                 close(tcp->fd);
1631                 listen_free(&this);
1632                 return NULL;
1633         }
1634
1635         /*
1636          *      Fill in socket information.
1637          */
1638         sock->proto = IPPROTO_TCP;
1639         sock->tcp = tcp;
1640
1641         sock->ipaddr = tcp->src_ipaddr;
1642         sock->port = tcp->src_port;
1643
1644         /*
1645          *      Don't ask.  Just don't ask.
1646          */
1647         sock->src_ipaddr = tcp->dst_ipaddr;
1648         sock->src_port = tcp->dst_port;
1649         sock->home = home;
1650         sock->home->num_connections++;
1651
1652 #if 0
1653         this->recv = proxy_socket_tcp_recv;
1654 #endif
1655
1656         /*
1657          *      Tell the event handler about the new socket.
1658          *
1659          *      It keeps track of "this", so we don't have to insert
1660          *      it into the main list of listeners.
1661          */
1662         event_new_fd(this);
1663
1664         return this;
1665 }
1666
1667 void proxy_close_tcp_listener(rad_listen_t *listener)
1668 {
1669         int i;
1670         listen_socket_t *sock = listener->data;
1671         
1672         /*
1673          *      This is the second time around for the socket.  Free
1674          *      the memory now.
1675          */
1676         if (listener->status != RAD_LISTEN_STATUS_KNOWN) {
1677                 listen_free(&listener);
1678                 return;
1679         }
1680
1681         listener->status = RAD_LISTEN_STATUS_CLOSED;
1682         event_new_fd(listener);
1683         
1684         /*
1685          *      Find the home server, and mark this listener as
1686          *      no longer being active.
1687          */
1688         for (i = 0; i < sock->home->max_connections; i++) {
1689                 if (sock->home->listeners[i] == listener) {
1690                         sock->home->listeners[i] = NULL;
1691                         sock->home->num_connections--;
1692                         break;
1693                 }
1694         }
1695
1696         /*
1697          *      There are still one or more requests using this socket.
1698          *      leave it marked as "closed", but don't free it.  When the
1699          *      last requeast using it is cleaned up, it will be deleted.
1700          */
1701         if (sock->tcp->used > 0) return;
1702         
1703         listen_free(&listener);
1704 }
1705 #endif
1706
1707 #ifdef WITH_STATS
1708 rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port)
1709 {
1710         rad_listen_t *this;
1711
1712         for (this = mainconfig.listen; this != NULL; this = this->next) {
1713                 listen_socket_t *sock;
1714
1715                 /*
1716                  *      FIXME: For TCP, ignore the *secondary*
1717                  *      listeners associated with the main socket.
1718                  */
1719                 if ((this->type != RAD_LISTEN_AUTH) &&
1720                     (this->type != RAD_LISTEN_ACCT)) continue;
1721                 
1722                 sock = this->data;
1723
1724                 if ((sock->my_port == port) &&
1725                     (fr_ipaddr_cmp(ipaddr, &sock->my_ipaddr) == 0)) {
1726                         return this;
1727                 }
1728
1729                 if ((sock->my_port == port) &&
1730                     ((sock->my_ipaddr.af == AF_INET) &&
1731                      (sock->my_ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY))) {
1732                         return this;
1733                 }
1734
1735 #ifdef HAVE_STRUCT_SOCKADDR_IN6
1736                 if ((sock->my_port == port) &&
1737                     (sock->my_ipaddr.af == AF_INET6) &&
1738                     (IN6_IS_ADDR_UNSPECIFIED(&sock->my_ipaddr.ipaddr.ip6addr))) {
1739                         return this;
1740                 }
1741 #endif
1742         }
1743
1744         return NULL;
1745 }