2 * listen.c Handle socket stuff
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.
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.
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
20 * Copyright 2005,2006 The FreeRADIUS server project
21 * Copyright 2005 Alan DeKok <aland@ox.org>
24 #include <freeradius-devel/ident.h>
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>
33 #include <freeradius-devel/vmps.h>
34 #include <freeradius-devel/detail.h>
36 #ifdef HAVE_SYS_RESOURCE_H
37 #include <sys/resource.h>
50 * We'll use this below.
52 typedef int (*rad_listen_parse_t)(CONF_SECTION *, rad_listen_t *);
53 typedef void (*rad_listen_free_t)(rad_listen_t *);
55 typedef struct rad_listen_master_t {
56 rad_listen_parse_t parse;
57 rad_listen_free_t free;
58 rad_listen_recv_t recv;
59 rad_listen_send_t send;
60 rad_listen_print_t print;
61 rad_listen_encode_t encode;
62 rad_listen_decode_t decode;
63 } rad_listen_master_t;
65 typedef struct listen_socket_t {
71 RADCLIENT_LIST *clients;
75 * Find a per-socket client.
77 RADCLIENT *client_listener_find(const rad_listen_t *listener,
78 const fr_ipaddr_t *ipaddr)
80 const RADCLIENT_LIST *clients;
82 rad_assert(listener != NULL);
83 rad_assert(ipaddr != NULL);
85 rad_assert((listener->type == RAD_LISTEN_AUTH) ||
86 (listener->type == RAD_LISTEN_ACCT) ||
87 (listener->type == RAD_LISTEN_VQP));
89 clients = ((listen_socket_t *)listener->data)->clients;
92 * This HAS to have been initialized previously.
94 rad_assert(clients != NULL);
96 return client_find(clients, ipaddr);
99 static int listen_bind(rad_listen_t *this);
103 * Process and reply to a server-status request.
104 * Like rad_authenticate and rad_accounting this should
105 * live in it's own file but it's so small we don't bother.
107 static int rad_status_server(REQUEST *request)
109 int rcode = RLM_MODULE_OK;
112 switch (request->listener->type) {
113 case RAD_LISTEN_AUTH:
114 dval = dict_valbyname(PW_AUTZ_TYPE, "Status-Server");
116 rcode = module_authorize(dval->value, request);
118 rcode = RLM_MODULE_OK;
123 case RLM_MODULE_UPDATED:
124 request->reply->code = PW_AUTHENTICATION_ACK;
127 case RLM_MODULE_FAIL:
128 case RLM_MODULE_HANDLED:
129 request->reply->code = 0; /* don't reply */
133 case RLM_MODULE_REJECT:
134 request->reply->code = PW_AUTHENTICATION_REJECT;
139 case RAD_LISTEN_ACCT:
140 dval = dict_valbyname(PW_ACCT_TYPE, "Status-Server");
142 rcode = module_accounting(dval->value, request);
144 rcode = RLM_MODULE_OK;
149 case RLM_MODULE_UPDATED:
150 request->reply->code = PW_ACCOUNTING_RESPONSE;
154 request->reply->code = 0; /* don't reply */
167 static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
169 listen_socket_t *sock = this->data;
173 if ((sock->ipaddr.af == AF_INET) &&
174 (sock->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
177 ip_ntoh(&sock->ipaddr, ip_buf, sizeof(ip_buf));
180 switch (this->type) {
181 case RAD_LISTEN_AUTH:
182 name = "authentication";
185 case RAD_LISTEN_ACCT:
189 case RAD_LISTEN_PROXY:
205 return snprintf(buffer, bufsize, "%s address %s port %d",
206 name, ip_buf, sock->port);
209 return snprintf(buffer, bufsize, "%s address %s port %d as server %s",
210 name, ip_buf, sock->port, this->server);
215 * Parse an authentication or accounting socket.
217 static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
222 listen_socket_t *sock = this->data;
223 char *section_name = NULL;
224 CONF_SECTION *client_cs, *parentcs;
229 ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
230 rcode = cf_item_parse(cs, "ipaddr", PW_TYPE_IPADDR,
231 &ipaddr.ipaddr.ip4addr, NULL);
232 if (rcode < 0) return -1;
234 if (rcode == 0) { /* successfully parsed IPv4 */
237 } else { /* maybe IPv6? */
238 rcode = cf_item_parse(cs, "ipv6addr", PW_TYPE_IPV6ADDR,
239 &ipaddr.ipaddr.ip6addr, NULL);
240 if (rcode < 0) return -1;
243 cf_log_err(cf_sectiontoitem(cs),
244 "No address specified in listen section");
247 ipaddr.af = AF_INET6;
250 rcode = cf_item_parse(cs, "port", PW_TYPE_INTEGER,
252 if (rcode < 0) return -1;
254 if ((listen_port < 0) || (listen_port > 65500)) {
255 cf_log_err(cf_sectiontoitem(cs),
256 "Invalid value for \"port\"");
260 sock->ipaddr = ipaddr;
261 sock->port = listen_port;
264 * And bind it to the port.
266 if (listen_bind(this) < 0) {
268 cf_log_err(cf_sectiontoitem(cs),
269 "Error binding to port for %s port %d",
270 ip_ntoh(&sock->ipaddr, buffer, sizeof(buffer)),
276 * If we can bind to interfaces, do so,
279 if (cf_pair_find(cs, "interface")) {
280 #ifndef SO_BINDTODEVICE
281 cf_log_err(cf_sectiontoitem(cs),
282 "System does not support binding to interfaces. Delete this line from the configuration file.");
286 CONF_PAIR *cp = cf_pair_find(cs, "interface");
289 rad_assert(cp != NULL);
290 value = cf_pair_value(cp);
292 cf_log_err(cf_sectiontoitem(cs),
293 "No interface name given");
297 strcpy(ifreq.ifr_name, value);
299 if (setsockopt(this->fd, SOL_SOCKET, SO_BINDTODEVICE,
300 (char *)&ifreq, sizeof(ifreq)) < 0) {
301 cf_log_err(cf_sectiontoitem(cs),
302 "Failed binding to interface %s: %s",
303 value, strerror(errno));
305 } /* else it worked. */
310 * Proxy sockets don't have clients.
312 if (this->type == RAD_LISTEN_PROXY) return 0;
315 * The more specific configurations are preferred to more
319 parentcs = cf_top_section(cs);
320 rcode = cf_item_parse(cs, "clients", PW_TYPE_STRING_PTR,
321 §ion_name, NULL);
322 if (rcode < 0) return -1; /* bad string */
325 * Explicit list given: use it.
327 client_cs = cf_section_sub_find_name2(parentcs,
331 client_cs = cf_section_find(section_name);
334 cf_log_err(cf_sectiontoitem(cs),
335 "Failed to find clients %s {...}",
341 } /* else there was no "clients = " entry. */
344 CONF_SECTION *server_cs;
346 server_cs = cf_section_sub_find_name2(parentcs,
350 * Found a "server foo" section. If there are clients
354 (cf_section_sub_find(server_cs, "client") != NULL)) {
355 client_cs = server_cs;
360 * Still nothing. Look for global clients.
362 if (!client_cs) client_cs = parentcs;
364 sock->clients = clients_parse_section(client_cs);
365 if (!sock->clients) {
366 cf_log_err(cf_sectiontoitem(cs),
367 "Failed to find any clients for this listen section");
375 * Send an authentication response packet
377 static int auth_socket_send(rad_listen_t *listener, REQUEST *request)
379 rad_assert(request->listener == listener);
380 rad_assert(listener->send == auth_socket_send);
382 return rad_send(request->reply, request->packet,
383 request->client->secret);
388 * Send an accounting response packet (or not)
390 static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
392 rad_assert(request->listener == listener);
393 rad_assert(listener->send == acct_socket_send);
396 * Accounting reject's are silently dropped.
398 * We do it here to avoid polluting the rest of the
399 * code with this knowledge
401 if (request->reply->code == 0) return 0;
403 return rad_send(request->reply, request->packet,
404 request->client->secret);
409 * Send a packet to a home server.
411 * FIXME: have different code for proxy auth & acct!
413 static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
415 listen_socket_t *sock = listener->data;
417 rad_assert(request->proxy_listener == listener);
418 rad_assert(listener->send == proxy_socket_send);
420 request->proxy->src_ipaddr = sock->ipaddr;
421 request->proxy->src_port = sock->port;
423 return rad_send(request->proxy, request->packet,
424 request->home_server->secret);
429 * Check if an incoming request is "ok"
431 * It takes packets, not requests. It sees if the packet looks
432 * OK. If so, it does a number of sanity checks on it.
434 static int auth_socket_recv(rad_listen_t *listener,
435 RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
439 RADIUS_PACKET *packet;
440 RAD_REQUEST_FUNP fun = NULL;
443 fr_ipaddr_t src_ipaddr;
445 rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
446 if (rcode < 0) return 0;
448 RAD_SNMP_TYPE_INC(listener, total_requests);
450 if (rcode < 20) { /* AUTH_HDR_LEN */
451 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
455 if ((client = client_listener_find(listener,
456 &src_ipaddr)) == NULL) {
457 rad_recv_discard(listener->fd);
458 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
460 if (debug_flag > 0) {
463 listener->print(listener, name, sizeof(name));
466 * This is debugging rather than logging, so that
467 * DoS attacks don't affect us.
469 DEBUG("Ignoring request to %s from unknown client %s port %d",
471 inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr,
472 buffer, sizeof(buffer)), src_port);
479 * Some sanity checks, based on the packet code.
482 case PW_AUTHENTICATION_REQUEST:
483 RAD_SNMP_CLIENT_INC(listener, client, requests);
484 fun = rad_authenticate;
487 case PW_STATUS_SERVER:
488 if (!mainconfig.status_server) {
489 rad_recv_discard(listener->fd);
490 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
491 RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
492 DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
495 fun = rad_status_server;
499 rad_recv_discard(listener->fd);
500 RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
501 RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
503 DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
504 code, client->shortname, src_port);
507 } /* switch over packet types */
510 * Now that we've sanity checked everything, receive the
513 packet = rad_recv(listener->fd, client->message_authenticator);
515 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
516 DEBUG("%s", librad_errstr);
520 if (!received_request(listener, packet, prequest, client)) {
521 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
522 RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
533 * Receive packets from an accounting socket
535 static int acct_socket_recv(rad_listen_t *listener,
536 RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
540 RADIUS_PACKET *packet;
541 RAD_REQUEST_FUNP fun = NULL;
544 fr_ipaddr_t src_ipaddr;
546 rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
547 if (rcode < 0) return 0;
549 RAD_SNMP_TYPE_INC(listener, total_requests);
551 if (rcode < 20) { /* AUTH_HDR_LEN */
552 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
556 if ((client = client_listener_find(listener,
557 &src_ipaddr)) == NULL) {
558 rad_recv_discard(listener->fd);
559 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
562 * This is debugging rather than logging, so that
563 * DoS attacks don't affect us.
565 if (debug_flag > 0) {
568 listener->print(listener, name, sizeof(name));
570 DEBUG("Ignoring request to %s from unknown client %s port %d",
572 inet_ntop(src_ipaddr.af, &src_ipaddr.ipaddr,
573 buffer, sizeof(buffer)), src_port);
580 * Some sanity checks, based on the packet code.
583 case PW_ACCOUNTING_REQUEST:
584 RAD_SNMP_CLIENT_INC(listener, client, requests);
585 fun = rad_accounting;
588 case PW_STATUS_SERVER:
589 if (!mainconfig.status_server) {
590 rad_recv_discard(listener->fd);
591 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
592 RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
594 DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
597 fun = rad_status_server;
601 rad_recv_discard(listener->fd);
602 RAD_SNMP_TYPE_INC(listener, total_unknown_types);
603 RAD_SNMP_CLIENT_INC(listener, client, unknown_types);
605 DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
606 code, client->shortname, src_port);
608 } /* switch over packet types */
611 * Now that we've sanity checked everything, receive the
614 packet = rad_recv(listener->fd, 0);
616 RAD_SNMP_TYPE_INC(listener, total_malformed_requests);
617 radlog(L_ERR, "%s", librad_errstr);
622 * There can be no duplicate accounting packets.
624 if (!received_request(listener, packet, prequest, client)) {
625 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
626 RAD_SNMP_CLIENT_INC(listener, client, packets_dropped);
637 * Recieve packets from a proxy socket.
639 static int proxy_socket_recv(rad_listen_t *listener,
640 RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
643 RADIUS_PACKET *packet;
644 RAD_REQUEST_FUNP fun = NULL;
647 packet = rad_recv(listener->fd, 0);
649 radlog(L_ERR, "%s", librad_errstr);
654 * FIXME: Client MIB updates?
656 switch(packet->code) {
657 case PW_AUTHENTICATION_ACK:
658 case PW_ACCESS_CHALLENGE:
659 case PW_AUTHENTICATION_REJECT:
660 fun = rad_authenticate;
663 case PW_ACCOUNTING_RESPONSE:
664 fun = rad_accounting;
669 * FIXME: Update MIB for packet types?
671 radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
672 "from home server %s port %d - ID %d : IGNORED",
674 ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
675 packet->src_port, packet->id);
680 request = received_proxy_response(packet);
685 rad_assert(fun != NULL);
693 static int client_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
695 if (!request->reply->code) return 0;
697 rad_encode(request->reply, request->packet,
698 request->client->secret);
699 rad_sign(request->reply, request->packet,
700 request->client->secret);
706 static int client_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
708 if (rad_verify(request->packet, NULL,
709 request->client->secret) < 0) {
713 return rad_decode(request->packet, NULL,
714 request->client->secret);
717 static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
719 rad_encode(request->proxy, NULL, request->home_server->secret);
720 rad_sign(request->proxy, NULL, request->home_server->secret);
726 static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
728 if (rad_verify(request->proxy_reply, request->proxy,
729 request->home_server->secret) < 0) {
733 return rad_decode(request->proxy_reply, request->proxy,
734 request->home_server->secret);
739 static int radius_snmp_recv(rad_listen_t *listener,
740 UNUSED RAD_REQUEST_FUNP *pfun,
741 UNUSED REQUEST **prequest)
743 if ((rad_snmp.smux_fd >= 0) &&
744 (rad_snmp.smux_event == SMUX_READ)) {
749 * If we've got to re-connect, then do so now,
750 * before calling select again.
752 if (rad_snmp.smux_event == SMUX_CONNECT) {
757 * Reset this every time, as the smux connect may have
758 * opened a new socket.
760 listener->fd = rad_snmp.smux_fd;
766 static int radius_snmp_print(UNUSED rad_listen_t *this, char *buffer, size_t bufsize)
768 return snprintf(buffer, bufsize, "SMUX with OID .1.3.6.1.4.1.11344.1.1.1");
773 static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
774 { NULL, NULL, NULL, NULL, NULL, NULL, NULL}, /* RAD_LISTEN_NONE */
777 { common_socket_parse, NULL,
778 proxy_socket_recv, proxy_socket_send,
779 socket_print, proxy_socket_encode, proxy_socket_decode },
782 { common_socket_parse, NULL,
783 auth_socket_recv, auth_socket_send,
784 socket_print, client_socket_encode, client_socket_decode },
787 { common_socket_parse, NULL,
788 acct_socket_recv, acct_socket_send,
789 socket_print, client_socket_encode, client_socket_decode},
792 { detail_parse, detail_free,
793 detail_recv, detail_send,
794 detail_print, detail_encode, detail_decode },
797 /* vlan query protocol */
798 { common_socket_parse, NULL,
799 vqp_socket_recv, vqp_socket_send,
800 socket_print, vqp_socket_encode, vqp_socket_decode },
802 { NULL, NULL, NULL, NULL, NULL, NULL, NULL},
805 { NULL, NULL, NULL, NULL, NULL, NULL, NULL} /* RAD_LISTEN_SNMP */
811 * Binds a listener to a socket.
813 static int listen_bind(rad_listen_t *this)
815 listen_socket_t *sock = this->data;
818 * If the port is zero, then it means the appropriate
819 * thing from /etc/services.
821 if (sock->port == 0) {
824 switch (this->type) {
825 case RAD_LISTEN_AUTH:
826 svp = getservbyname ("radius", "udp");
828 sock->port = ntohs(svp->s_port);
830 sock->port = PW_AUTH_UDP_PORT;
834 case RAD_LISTEN_ACCT:
835 svp = getservbyname ("radacct", "udp");
837 sock->port = ntohs(svp->s_port);
839 sock->port = PW_ACCT_UDP_PORT;
843 case RAD_LISTEN_PROXY:
854 radlog(L_ERR, "ERROR: Non-fatal internal sanity check failed in bind.");
859 this->fd = fr_socket(&sock->ipaddr, sock->port);
861 radlog(L_ERR, "ERROR: Failed to open socket: %s",
867 * FreeBSD jail issues. We bind to 0.0.0.0, but the
868 * kernel instead binds us to a 1.2.3.4. If this
869 * happens, notice, and remember our real IP.
872 struct sockaddr_storage src;
873 socklen_t sizeof_src = sizeof(src);
875 memset(&src, 0, sizeof_src);
876 if (getsockname(this->fd, (struct sockaddr *) &src,
878 radlog(L_ERR, "Failed getting socket name: %s",
883 if (src.ss_family == AF_INET) {
884 struct sockaddr_in *s4;
886 s4 = (struct sockaddr_in *)&src;
887 sock->ipaddr.ipaddr.ip4addr = s4->sin_addr;
888 sock->port = ntohs(s4->sin_port);
890 #ifdef HAVE_STRUCT_SOCKADDR_IN6
891 } else if (src.ss_family == AF_INET6) {
892 struct sockaddr_in6 *s6;
894 s6 = (struct sockaddr_in6 *)&src;
895 sock->ipaddr.ipaddr.ip6addr = s6->sin6_addr;
896 sock->port = ntohs(s6->sin6_port);
899 radlog(L_ERR, "Socket has unsupported address family");
908 if ((flags = fcntl(this->fd, F_GETFL, NULL)) < 0) {
909 radlog(L_ERR, "Failure getting socket flags: %s)\n",
915 if( fcntl(this->fd, F_SETFL, flags) < 0) {
916 radlog(L_ERR, "Failure setting socket flags: %s)\n",
928 * Allocate & initialize a new listener.
930 static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
934 this = rad_malloc(sizeof(*this));
935 memset(this, 0, sizeof(*this));
938 this->recv = master_listen[this->type].recv;
939 this->send = master_listen[this->type].send;
940 this->print = master_listen[this->type].print;
941 this->encode = master_listen[this->type].encode;
942 this->decode = master_listen[this->type].decode;
945 case RAD_LISTEN_AUTH:
946 case RAD_LISTEN_ACCT:
947 case RAD_LISTEN_PROXY:
949 this->data = rad_malloc(sizeof(listen_socket_t));
950 memset(this->data, 0, sizeof(listen_socket_t));
953 case RAD_LISTEN_DETAIL:
958 rad_assert("Unsupported option!" == NULL);
967 * Externally visible function for creating a new proxy LISTENER.
969 * For now, don't take ipaddr or port.
971 * Not thread-safe, but all calls to it are protected by the
972 * proxy mutex in request_list.c
974 rad_listen_t *proxy_new_listener()
976 int last_proxy_port, port;
977 rad_listen_t *this, *tmp, **last;
978 listen_socket_t *sock, *old;
980 this = listen_alloc(RAD_LISTEN_PROXY);
983 * Find an existing proxy socket to copy.
985 * FIXME: Make it per-realm, or per-home server!
989 last = &mainconfig.listen;
990 for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {
991 if (tmp->type == RAD_LISTEN_PROXY) {
993 if (sock->port > last_proxy_port) {
994 last_proxy_port = sock->port + 1;
996 if (!old) old = sock;
1004 return NULL; /* This is a serious error. */
1008 * FIXME: find a new IP address to listen on?
1010 * This could likely be done in the "home server"
1011 * configuration, to have per-home-server source IP's.
1014 memcpy(&sock->ipaddr, &old->ipaddr, sizeof(sock->ipaddr));
1017 * Keep going until we find an unused port.
1019 for (port = last_proxy_port; port < 64000; port++) {
1021 if (listen_bind(this) == 0) {
1023 * Add the new listener to the list of
1036 static const FR_NAME_NUMBER listen_compare[] = {
1037 { "auth", RAD_LISTEN_AUTH },
1038 { "acct", RAD_LISTEN_ACCT },
1039 { "detail", RAD_LISTEN_DETAIL },
1040 { "proxy", RAD_LISTEN_PROXY },
1042 { "vmps", RAD_LISTEN_VQP },
1048 static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
1056 cf_log_info(cs, "listen {");
1058 rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,
1060 if (rcode < 0) return NULL;
1063 cf_log_err(cf_sectiontoitem(cs),
1064 "No type specified in listen section");
1068 type = fr_str2int(listen_compare, listen_type,
1070 if (type == RAD_LISTEN_NONE) {
1071 cf_log_err(cf_sectiontoitem(cs),
1072 "Invalid type \"%s\" in listen section.",
1080 * Allow listen sections in the default config to
1081 * refer to a server.
1084 rcode = cf_item_parse(cs, "virtual_server", PW_TYPE_STRING_PTR,
1086 if (rcode == 1) { /* compatiblity with 2.0-pre */
1087 rcode = cf_item_parse(cs, "server", PW_TYPE_STRING_PTR,
1090 if (rcode < 0) return NULL;
1094 * Set up cross-type data.
1096 this = listen_alloc(type);
1097 this->server = server;
1101 * Call per-type parser.
1103 if (master_listen[type].parse(cs, this) < 0) {
1108 cf_log_info(cs, "}");
1114 * Generate a list of listeners. Takes an input list of
1115 * listeners, too, so we don't close sockets with waiting packets.
1117 int listen_init(CONF_SECTION *config, rad_listen_t **head)
1119 int override = FALSE;
1122 rad_listen_t **last;
1124 fr_ipaddr_t server_ipaddr;
1126 int defined_proxy = 0;
1129 * We shouldn't be called with a pre-existing list.
1131 rad_assert(head && (*head == NULL));
1134 server_ipaddr.af = AF_UNSPEC;
1137 * If the port is specified on the command-line,
1138 * it over-rides the configuration file.
1140 * FIXME: If argv[0] == "vmpsd", then don't listen on auth/acct!
1142 if (mainconfig.port >= 0) auth_port = mainconfig.port;
1145 * If the IP address was configured on the command-line,
1146 * use that as the "bind_address"
1148 if (mainconfig.myip.af != AF_UNSPEC) {
1149 memcpy(&server_ipaddr, &mainconfig.myip,
1150 sizeof(server_ipaddr));
1156 * Else look for bind_address and/or listen sections.
1158 server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1159 rcode = cf_item_parse(config, "bind_address",
1161 &server_ipaddr.ipaddr.ip4addr, NULL);
1162 if (rcode < 0) return -1; /* error parsing it */
1164 if (rcode == 0) { /* successfully parsed IPv4 */
1165 listen_socket_t *sock;
1166 server_ipaddr.af = AF_INET;
1168 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'.");
1172 if (strcmp(progname, "vmpsd") == 0) {
1173 this = listen_alloc(RAD_LISTEN_VQP);
1174 if (!auth_port) auth_port = 1589;
1177 this = listen_alloc(RAD_LISTEN_AUTH);
1181 sock->ipaddr = server_ipaddr;
1182 sock->port = auth_port;
1184 sock->clients = clients_parse_section(config);
1185 if (!sock->clients) {
1186 cf_log_err(cf_sectiontoitem(config),
1187 "Failed to find any clients for this listen section");
1191 if (listen_bind(this) < 0) {
1194 radlog(L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->port);
1197 auth_port = sock->port; /* may have been updated in listen_bind */
1199 cs = cf_section_sub_find_name2(config, "server",
1201 if (cs) this->server = mainconfig.name;
1205 last = &(this->next);
1211 if (strcmp(progname, "vmpsd") == 0) goto do_proxy;
1215 * Open Accounting Socket.
1217 * If we haven't already gotten acct_port from
1218 * /etc/services, then make it auth_port + 1.
1220 this = listen_alloc(RAD_LISTEN_ACCT);
1224 * Create the accounting socket.
1226 * The accounting port is always the
1227 * authentication port + 1
1229 sock->ipaddr = server_ipaddr;
1230 sock->port = auth_port + 1;
1232 sock->clients = clients_parse_section(config);
1233 if (!sock->clients) {
1234 cf_log_err(cf_sectiontoitem(config),
1235 "Failed to find any clients for this listen section");
1239 if (listen_bind(this) < 0) {
1242 radlog(L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->port);
1247 cs = cf_section_sub_find_name2(config, "server",
1249 if (cs) this->server = mainconfig.name;
1253 last = &(this->next);
1255 } else if (mainconfig.port > 0) { /* no bind address, but a port */
1256 radlog(L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",
1262 * They specified an IP on the command-line, ignore
1263 * all listen sections except the one in '-n'.
1265 if (mainconfig.myip.af != AF_UNSPEC) {
1266 CONF_SECTION *subcs;
1267 const char *name2 = cf_section_name2(cs);
1269 cs = cf_section_sub_find_name2(config, "server",
1271 if (!cs) goto do_proxy;
1274 * Should really abstract this code...
1276 for (subcs = cf_subsection_find_next(cs, NULL, "listen");
1278 subcs = cf_subsection_find_next(cs, subcs, "listen")) {
1279 this = listen_parse(subcs, name2);
1285 if (this->type == RAD_LISTEN_PROXY) defined_proxy = 1;
1288 last = &(this->next);
1289 } /* loop over "listen" directives in server <foo> */
1295 * Walk through the "listen" sections, if they exist.
1297 for (cs = cf_subsection_find_next(config, NULL, "listen");
1299 cs = cf_subsection_find_next(config, cs, "listen")) {
1300 this = listen_parse(cs, NULL);
1306 if (this->type == RAD_LISTEN_PROXY) defined_proxy = 1;
1309 last = &(this->next);
1313 * Check virtual servers for "listen" sections, too.
1315 * FIXME: Move to virtual server init?
1317 for (cs = cf_subsection_find_next(config, NULL, "server");
1319 cs = cf_subsection_find_next(config, cs, "server")) {
1320 CONF_SECTION *subcs;
1321 const char *name2 = cf_section_name2(cs);
1323 for (subcs = cf_subsection_find_next(cs, NULL, "listen");
1325 subcs = cf_subsection_find_next(cs, subcs, "listen")) {
1326 this = listen_parse(subcs, name2);
1332 if (this->type == RAD_LISTEN_PROXY) {
1333 radlog(L_ERR, "Error: listen type \"proxy\" Cannot appear in a virtual server section");
1339 last = &(this->next);
1340 } /* loop over "listen" directives in virtual servers */
1341 } /* loop over virtual servers */
1344 * If we're proxying requests, open the proxy FD.
1345 * Otherwise, don't do anything.
1348 if (mainconfig.proxy_requests == TRUE) {
1350 listen_socket_t *sock = NULL;
1353 * No sockets to receive packets, therefore
1354 * proxying is pointless.
1356 if (!*head) return -1;
1358 if (defined_proxy) goto do_snmp;
1361 * Find the first authentication port,
1364 for (this = *head; this != NULL; this = this->next) {
1365 if (this->type == RAD_LISTEN_AUTH) {
1367 if (server_ipaddr.af == AF_UNSPEC) {
1368 server_ipaddr = sock->ipaddr;
1370 port = sock->port + 2; /* skip acct port */
1373 if (this->type == RAD_LISTEN_VQP) {
1375 if (server_ipaddr.af == AF_UNSPEC) {
1376 server_ipaddr = sock->ipaddr;
1378 port = sock->port + 1;
1383 if (port < 0) port = 1024 + (fr_rand() & 0x1ff);
1386 * Address is still unspecified, use IPv4.
1388 if (server_ipaddr.af == AF_UNSPEC) {
1389 server_ipaddr.af = AF_INET;
1390 server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
1393 this = listen_alloc(RAD_LISTEN_PROXY);
1397 * Create the first proxy socket.
1399 sock->ipaddr = server_ipaddr;
1402 * Try to find a proxy port (value doesn't matter)
1404 for (sock->port = port;
1407 if (listen_bind(this) == 0) {
1409 last = &(this->next); /* just in case */
1414 if (sock->port >= 64000) {
1417 radlog(L_ERR, "Failed to open socket for proxying");
1424 if (radius_snmp_init(config)) {
1425 this = rad_malloc(sizeof(*this));
1426 memset(this, 0, sizeof(*this));
1428 this->type = RAD_LISTEN_SNMP;
1429 this->fd = rad_snmp.smux_fd;
1431 this->recv = radius_snmp_recv;
1432 this->print = radius_snmp_print;
1435 last = &(this->next);
1443 * Free a linked list of listeners;
1445 void listen_free(rad_listen_t **head)
1449 if (!head || !*head) return;
1453 rad_listen_t *next = this->next;
1456 * Other code may have eaten the FD.
1458 if (this->fd >= 0) close(this->fd);
1460 if (master_listen[this->type].free) {
1461 master_listen[this->type].free(this);