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