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