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/autoconf.h>
32 #ifdef HAVE_NETINET_IN_H
33 #include <netinet/in.h>
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
40 #include <sys/resource.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
50 #ifdef HAVE_SYS_STAT_H
55 #include <freeradius-devel/udpfromto.h>
60 #include <freeradius-devel/radiusd.h>
61 #include <freeradius-devel/rad_assert.h>
63 #include <freeradius-devel/radius_snmp.h>
65 static time_t start_time = 0;
68 * FIXME: Delete this crap!
70 extern time_t time_now;
73 * We'll use this below.
75 typedef int (*rad_listen_parse_t)(const char *, int, const CONF_SECTION *, rad_listen_t *);
76 typedef void (*rad_listen_free_t)(rad_listen_t *);
78 typedef struct rad_listen_master_t {
79 rad_listen_parse_t parse;
80 rad_listen_free_t free;
81 rad_listen_recv_t recv;
82 rad_listen_send_t send;
83 rad_listen_print_t print;
84 rad_listen_encode_t encode;
85 rad_listen_decode_t decode;
86 } rad_listen_master_t;
88 typedef struct listen_socket_t {
94 RADCLIENT_LIST *clients;
97 typedef struct listen_detail_t {
103 lrad_ipaddr_t client_ip;
110 * Find a per-socket client.
112 static RADCLIENT *client_listener_find(const rad_listen_t *listener,
113 const lrad_ipaddr_t *ipaddr)
115 const RADCLIENT_LIST *clients;
117 rad_assert(listener != NULL);
118 rad_assert(ipaddr != NULL);
120 rad_assert((listener->type == RAD_LISTEN_AUTH) ||
121 (listener->type == RAD_LISTEN_ACCT));
123 clients = ((listen_socket_t *)listener->data)->clients;
124 if (!clients) clients = mainconfig.clients;
126 rad_assert(clients != NULL);
128 return client_find(clients, ipaddr);
131 static int listen_bind(rad_listen_t *this);
134 * FIXME: have the detail reader use another config "exit when done",
135 * so that it can be used as a one-off tool to update stuff.
139 * Process and reply to a server-status request.
140 * Like rad_authenticate and rad_accounting this should
141 * live in it's own file but it's so small we don't bother.
143 static int rad_status_server(REQUEST *request)
145 switch (request->listener->type) {
146 case RAD_LISTEN_AUTH:
147 request->reply->code = PW_AUTHENTICATION_ACK;
150 * Commented out for now.
159 * Reply with an ACK. We might want to add some more
160 * interesting reply attributes, such as server uptime.
162 t = request->timestamp - start_time;
163 sprintf(reply_msg, "FreeRADIUS STUFF %d day%s, %02d:%02d",
164 (int)(t / 86400), (t / 86400) == 1 ? "" : "s",
165 (int)((t / 3600) % 24), (int)(t / 60) % 60);
167 vp = pairmake("Reply-Message", reply_msg, T_OP_SET);
168 pairadd(&request->reply->vps, vp); /* don't need to check if !vp */
173 case RAD_LISTEN_ACCT:
174 request->reply->code = PW_ACCOUNTING_RESPONSE;
185 static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
188 listen_socket_t *sock = this->data;
190 if ((sock->ipaddr.af == AF_INET) &&
191 (sock->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
194 ip_ntoh(&sock->ipaddr, buffer, bufsize);
197 len = strlen(buffer);
199 return len + snprintf(buffer + len, bufsize - len, " port %d",
205 * Parse an authentication or accounting socket.
207 static int common_socket_parse(const char *filename, int lineno,
208 const CONF_SECTION *cs, rad_listen_t *this)
212 lrad_ipaddr_t ipaddr;
213 listen_socket_t *sock = this->data;
214 const char *section_name = NULL;
215 CONF_SECTION *client_cs;
220 ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
221 rcode = cf_item_parse(cs, "ipaddr", PW_TYPE_IPADDR,
222 &ipaddr.ipaddr.ip4addr, NULL);
223 if (rcode < 0) return -1;
225 if (rcode == 0) { /* successfully parsed IPv4 */
228 } else { /* maybe IPv6? */
229 rcode = cf_item_parse(cs, "ipv6addr", PW_TYPE_IPV6ADDR,
230 &ipaddr.ipaddr.ip6addr, NULL);
231 if (rcode < 0) return -1;
234 radlog(L_ERR, "%s[%d]: No address specified in listen section",
238 ipaddr.af = AF_INET6;
241 rcode = cf_item_parse(cs, "port", PW_TYPE_INTEGER,
243 if (rcode < 0) return -1;
245 sock->ipaddr = ipaddr;
246 sock->port = listen_port;
249 * And bind it to the port.
251 if (listen_bind(this) < 0) {
253 radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s port %d",
254 filename, cf_section_lineno(cs),
255 ip_ntoh(&sock->ipaddr, buffer, sizeof(buffer)),
261 * If we can bind to interfaces, do so,
264 if (cf_pair_find(cs, "interface")) {
265 #ifndef SO_BINDTODEVICE
266 radlog(L_CONS|L_ERR, "%s[%d]: System does not support binding to interfaces, delete this line from the configuration file.",
267 filename, cf_section_lineno(cs));
271 const CONF_PAIR *cp = cf_pair_find(cs, "interface");
274 rad_assert(cp != NULL);
275 value = cf_pair_value(cp);
276 rad_assert(value != NULL);
278 strcpy(ifreq.ifr_name, value);
280 if (setsockopt(this->fd, SOL_SOCKET, SO_BINDTODEVICE,
281 (char *)&ifreq, sizeof(ifreq)) < 0) {
282 radlog(L_CONS|L_ERR, "%s[%d]: Failed binding to interface %s: %s",
283 filename, cf_section_lineno(cs),
284 value, strerror(errno));
286 } /* else it worked. */
291 * Look for the name of a section that holds a list
294 rcode = cf_item_parse(cs, "clients", PW_TYPE_STRING_PTR,
295 §ion_name, NULL);
296 if (rcode < 0) return -1; /* bad string */
297 if (rcode > 0) return 0; /* non-existent is OK. */
299 client_cs = cf_section_find(section_name);
302 radlog(L_CONS|L_ERR, "%s[%d]: Failed to find client section %s",
303 filename, cf_section_lineno(cs), section_name);
307 sock->clients = clients_parse_section(filename, client_cs);
308 if (!sock->clients) {
316 * Send an authentication response packet
318 static int auth_socket_send(rad_listen_t *listener, REQUEST *request)
320 rad_assert(request->listener == listener);
321 rad_assert(listener->send == auth_socket_send);
323 return rad_send(request->reply, request->packet, request->secret);
328 * Send an accounting response packet (or not)
330 static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
332 rad_assert(request->listener == listener);
333 rad_assert(listener->send == acct_socket_send);
336 * Accounting reject's are silently dropped.
338 * We do it here to avoid polluting the rest of the
339 * code with this knowledge
341 if (request->reply->code == 0) return 0;
343 return rad_send(request->reply, request->packet, request->secret);
348 * Send a packet to a home server.
350 * FIXME: have different code for proxy auth & acct!
352 static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
354 listen_socket_t *sock = listener->data;
356 rad_assert(request->proxy_listener == listener);
357 rad_assert(listener->send == proxy_socket_send);
359 request->proxy->src_ipaddr = sock->ipaddr;
360 request->proxy->src_port = sock->port;
362 return rad_send(request->proxy, request->packet,
363 request->home_server->secret);
368 * Check if an incoming request is "ok"
370 * It takes packets, not requests. It sees if the packet looks
371 * OK. If so, it does a number of sanity checks on it.
373 static int auth_socket_recv(rad_listen_t *listener,
374 RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
376 RADIUS_PACKET *packet;
377 RAD_REQUEST_FUNP fun = NULL;
381 packet = rad_recv(listener->fd);
383 radlog(L_ERR, "%s", librad_errstr);
387 RAD_SNMP_TYPE_INC(listener, total_requests); /* FIXME: auth specific */
389 if ((client = client_listener_find(listener,
390 &packet->src_ipaddr)) == NULL) {
391 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
393 radlog(L_ERR, "Ignoring request from unknown client %s port %d",
394 inet_ntop(packet->src_ipaddr.af,
395 &packet->src_ipaddr.ipaddr,
396 buffer, sizeof(buffer)),
403 * Some sanity checks, based on the packet code.
405 switch(packet->code) {
406 case PW_AUTHENTICATION_REQUEST:
407 fun = rad_authenticate;
410 case PW_STATUS_SERVER:
411 if (!mainconfig.status_server) {
412 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
413 DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
417 fun = rad_status_server;
421 RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
423 radlog(L_ERR, "Invalid packet code %d sent to authentication port from client %s port %d "
425 packet->code, client->shortname,
426 packet->src_port, packet->id);
430 } /* switch over packet types */
432 if (!received_request(listener, packet, prequest, client)) {
443 * Receive packets from an accounting socket
445 static int acct_socket_recv(rad_listen_t *listener,
446 RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
448 RADIUS_PACKET *packet;
449 RAD_REQUEST_FUNP fun = NULL;
453 packet = rad_recv(listener->fd);
455 radlog(L_ERR, "%s", librad_errstr);
459 RAD_SNMP_TYPE_INC(listener, total_requests); /* FIXME: acct-specific */
461 if ((client = client_listener_find(listener,
462 &packet->src_ipaddr)) == NULL) {
463 RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
465 radlog(L_ERR, "Ignoring request from unknown client %s port %d",
466 inet_ntop(packet->src_ipaddr.af,
467 &packet->src_ipaddr.ipaddr,
468 buffer, sizeof(buffer)),
474 switch(packet->code) {
475 case PW_ACCOUNTING_REQUEST:
476 fun = rad_accounting;
479 case PW_STATUS_SERVER:
480 if (!mainconfig.status_server) {
481 RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
482 DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
486 fun = rad_status_server;
491 * FIXME: Update MIB for packet types?
493 radlog(L_ERR, "Invalid packet code %d sent to a accounting port "
494 "from client %s port %d - ID %d : IGNORED",
495 packet->code, client->shortname,
496 packet->src_port, packet->id);
502 * FIXME: Accounting duplicates should be handled
503 * differently than authentication duplicates.
505 if (!received_request(listener, packet, prequest, client)) {
516 * Recieve packets from a proxy socket.
518 static int proxy_socket_recv(rad_listen_t *listener,
519 RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
522 RADIUS_PACKET *packet;
523 RAD_REQUEST_FUNP fun = NULL;
526 packet = rad_recv(listener->fd);
528 radlog(L_ERR, "%s", librad_errstr);
533 * FIXME: Client MIB updates?
535 switch(packet->code) {
536 case PW_AUTHENTICATION_ACK:
537 case PW_ACCESS_CHALLENGE:
538 case PW_AUTHENTICATION_REJECT:
539 fun = rad_authenticate;
542 case PW_ACCOUNTING_RESPONSE:
543 fun = rad_accounting;
548 * FIXME: Update MIB for packet types?
550 radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
551 "from home server %s port %d - ID %d : IGNORED",
553 ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
554 packet->src_port, packet->id);
559 request = received_proxy_response(packet);
564 rad_assert(fun != NULL);
572 static int client_socket_encode(rad_listen_t *listener, REQUEST *request)
574 if (!request->reply->code) return 0;
576 rad_encode(request->reply, request->packet, request->secret);
577 rad_sign(request->reply, request->packet, request->secret);
583 static int client_socket_decode(rad_listen_t *listener, REQUEST *request)
585 if (rad_verify(request->packet, NULL, request->secret) < 0) {
589 return rad_decode(request->packet, NULL, request->secret);
592 static int proxy_socket_encode(rad_listen_t *listener, REQUEST *request)
594 rad_encode(request->proxy, NULL, request->home_server->secret);
595 rad_sign(request->proxy, NULL, request->home_server->secret);
601 static int proxy_socket_decode(rad_listen_t *listener, REQUEST *request)
603 if (rad_verify(request->proxy_reply, request->proxy,
604 request->home_server->secret) < 0) {
608 return rad_decode(request->proxy_reply, request->proxy,
609 request->home_server->secret);
613 #define STATE_UNOPENED (0)
614 #define STATE_UNLOCKED (1)
615 #define STATE_HEADER (2)
616 #define STATE_READING (3)
617 #define STATE_DONE (4)
618 #define STATE_WAITING (5)
621 * If we're limiting outstanding packets, then mark the response
624 static int detail_send(rad_listen_t *listener, REQUEST *request)
626 listen_detail_t *data = listener->data;
628 rad_assert(request->listener == listener);
629 rad_assert(listener->send == detail_send);
631 if (request->simul_max >= 0) {
632 rad_assert(data->outstanding != NULL);
633 rad_assert(request->simul_max < data->max_outstanding);
635 data->outstanding[request->simul_max] = 0;
643 * Open the detail file..
645 * FIXME: create it, if it's not already there, so that the main
646 * server select() will wake us up if there's anything to read.
648 static int detail_open(rad_listen_t *this)
652 listen_detail_t *data = this->data;
654 rad_assert(data->state == STATE_UNOPENED);
655 snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
658 * FIXME: Have "one-shot" configuration, where it
659 * will read the detail file, and exit once it's
662 * FIXME: Try harder to open the detail file.
663 * Maybe sleep for X usecs if it doesn't exist?
667 * Open detail.work first, so we don't lose
668 * accounting packets. It's probably better to
669 * duplicate them than to lose them.
671 * Note that we're not writing to the file, but
672 * we've got to open it for writing in order to
673 * establish the lock, to prevent rlm_detail from
676 this->fd = open(buffer, O_RDWR);
679 * Try reading the detail file. If it
680 * doesn't exist, we can't do anything.
682 * Doing the stat will tell us if the file
683 * exists, even if we don't have permissions
686 if (stat(data->detail, &st) < 0) {
691 * Open it BEFORE we rename it, just to
694 this->fd = open(data->detail, O_RDWR);
696 radlog(L_ERR, "Failed to open %s: %s",
697 data->detail, strerror(errno));
702 * Rename detail to detail.work
704 if (rename(data->detail, buffer) < 0) {
709 } /* else detail.work existed, and we opened it */
711 rad_assert(data->vps == NULL);
713 rad_assert(data->fp == NULL);
714 data->fp = fdopen(this->fd, "r");
716 radlog(L_ERR, "Failed to re-open %s: %s",
717 data->detail, strerror(errno));
721 data->state = STATE_UNLOCKED;
723 data->client_ip.af = AF_UNSPEC;
730 * This is a bad hack, just so complaints have meaningful text.
732 static const RADCLIENT detail_client = {
747 static int detail_recv(rad_listen_t *listener,
748 RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
751 char key[256], value[1024];
752 VALUE_PAIR *vp, **tail;
753 RADIUS_PACKET *packet;
755 listen_detail_t *data = listener->data;
757 if (data->state == STATE_UNOPENED) {
758 rad_assert(listener->fd < 0);
759 if (!detail_open(listener)) return 0;
761 rad_assert(listener->fd >= 0);
764 * Try to lock fd. If we can't, return. If we can,
765 * continue. This means that the server doesn't block
766 * while waiting for the lock to open...
768 if (data->state == STATE_UNLOCKED) {
770 * Note that we do NOT block waiting for the
771 * lock. We've re-named the file above, so we've
772 * already guaranteed that any *new* detail
773 * writer will not be opening this file. The
774 * only purpose of the lock is to catch a race
775 * condition where the execution "ping-pongs"
776 * between radiusd & radrelay.
778 if (rad_lockfd_nonblock(listener->fd, 0) < 0) {
782 * Look for the header
784 data->state = STATE_HEADER;
788 * Catch an out of memory condition which will most likely
791 if (data->state == STATE_DONE) goto alloc_packet;
794 * If we're in another state, then it means that we read
795 * a partial packet, which is bad.
797 rad_assert(data->state == STATE_HEADER);
798 rad_assert(data->vps == NULL);
801 * We read the last packet, and returned it for
802 * processing. We later come back here to shut
803 * everything down, and unlink the file.
805 if (feof(data->fp)) {
806 rad_assert(data->state == STATE_HEADER);
809 * Don't unlink the file until we've received
810 * all of the responses.
812 if (data->max_outstanding > 0) {
815 for (i = 0; i < data->max_outstanding; i++) {
817 * FIXME: close the file?
819 if (data->outstanding[i]) {
820 data->state = STATE_WAITING;
827 rad_assert(data->vps == NULL);
829 snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
831 fclose(data->fp); /* closes listener->fd */
834 data->state = STATE_UNOPENED;
837 * Try to open "detail" again. If we're on a
838 * busy RADIUS server, odds are that it will
841 detail_open(listener);
850 while (fgets(buffer, sizeof(buffer), data->fp)) {
854 if (!strchr(buffer, '\n')) {
855 pairfree(&data->vps);
860 * We've read a header, possibly packet contents,
861 * and are now at the end of the packet.
863 if ((data->state == STATE_READING) &&
864 (buffer[0] == '\n')) {
865 data->state = STATE_DONE;
870 * Look for date/time header, and read VP's if
871 * found. If not, keep reading lines until we
874 if (data->state == STATE_HEADER) {
877 if (sscanf(buffer, "%*s %*s %*d %*d:%*d:%*d %d", &y)) {
878 data->state = STATE_READING;
884 * We have a full "attribute = value" line.
885 * If it doesn't look reasonable, skip it.
887 if (sscanf(buffer, "%255s = %1023s", key, value) != 2) {
892 * Skip non-protocol attributes.
894 if (!strcasecmp(key, "Request-Authenticator")) continue;
897 * Set the original client IP address, based on
898 * what's in the detail file.
900 * Hmm... we don't set the server IP address.
903 if (!strcasecmp(key, "Client-IP-Address")) {
904 data->client_ip.af = AF_INET;
905 ip_hton(value, AF_INET, &data->client_ip);
910 * The original time at which we received the
911 * packet. We need this to properly calculate
914 if (!strcasecmp(key, "Timestamp")) {
915 data->timestamp = atoi(value);
922 * FIXME: do we want to check for non-protocol
923 * attributes like radsqlrelay does?
926 if ((userparse(buffer, &vp) > 0) &&
934 * We got to EOF, If we're in STATE_HEADER, it's OK.
935 * Otherwise it's a problem. In any case, nuke the file
936 * and start over from scratch,
938 if (feof(data->fp)) {
943 * FIXME: Do load management.
947 * If we're not done, then there's a problem. The checks
950 rad_assert(data->state == STATE_DONE);
953 * The packet we read was empty, re-set the state to look
954 * for a header, and don't return anything.
957 data->state = STATE_HEADER;
962 * Allocate the packet. If we fail, it's a serious
967 * If we keep track of the outstanding requests, do so
968 * here. Note that to minimize potential work, we do
969 * so only once the file is opened & locked.
971 if (data->max_outstanding) {
974 for (i = 0; i < data->max_outstanding; i++) {
975 if (!data->outstanding[i]) {
982 * All of the slots are full. Put the LF back,
983 * so select will say that data is ready, and set
984 * the state back to reading. Then, return so
985 * that we don't overload the server.
988 ungetc('\n', data->fp);
989 data->state = STATE_READING;
994 packet = rad_alloc(1);
996 return 0; /* maybe memory will magically free up... */
999 memset(packet, 0, sizeof(*packet));
1000 packet->sockfd = -1;
1001 packet->src_ipaddr.af = AF_INET;
1002 packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1003 packet->code = PW_ACCOUNTING_REQUEST;
1004 packet->timestamp = time(NULL);
1007 * Look for Acct-Delay-Time, and update
1008 * based on Acct-Delay-Time += (time(NULL) - timestamp)
1010 vp = pairfind(packet->vps, PW_ACCT_DELAY_TIME);
1012 vp = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
1013 rad_assert(vp != NULL);
1015 if (data->timestamp != 0) {
1016 vp->lvalue += time(NULL) - data->timestamp;
1020 * Remember where it came from, so that we don't
1021 * proxy it to the place it came from...
1023 if (data->client_ip.af != AF_UNSPEC) {
1024 packet->src_ipaddr = data->client_ip;
1027 vp = pairfind(packet->vps, PW_PACKET_SRC_IP_ADDRESS);
1029 packet->src_ipaddr.af = AF_INET;
1030 packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
1032 vp = pairfind(packet->vps, PW_PACKET_SRC_IPV6_ADDRESS);
1034 packet->src_ipaddr.af = AF_INET6;
1035 memcpy(&packet->src_ipaddr.ipaddr.ip6addr,
1036 &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
1040 vp = pairfind(packet->vps, PW_PACKET_DST_IP_ADDRESS);
1042 packet->dst_ipaddr.af = AF_INET;
1043 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
1045 vp = pairfind(packet->vps, PW_PACKET_DST_IPV6_ADDRESS);
1047 packet->dst_ipaddr.af = AF_INET6;
1048 memcpy(&packet->dst_ipaddr.ipaddr.ip6addr,
1049 &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
1054 * We've got to give SOME value for Id & ports, so that
1055 * the packets can be added to the request queue.
1056 * However, we don't want to keep track of used/unused
1057 * id's and ports, as that's a lot of work. This hack
1058 * ensures that (if we have real random numbers), that
1059 * there will be a collision on every 2^(16+15+15+24 - 1)
1060 * packets, on average. That means we can read 2^37
1061 * packets before having a collision, which means it's
1062 * effectively impossible.
1064 packet->id = lrad_rand() & 0xffff;
1065 packet->src_port = 1024 + (lrad_rand() & 0x7fff);
1066 packet->dst_port = 1024 + (lrad_rand() & 0x7fff);
1068 packet->dst_ipaddr.af = AF_INET;
1069 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl((INADDR_LOOPBACK & ~0xffffff) | (lrad_rand() & 0xffffff));
1071 packet->vps = data->vps;
1077 data->state = STATE_HEADER;
1080 * Keep track of free slots, as a hack, in an otherwise
1083 (*prequest)->simul_max = free_slot;
1084 data->outstanding[free_slot] = 1;
1086 *pfun = rad_accounting;
1089 printf("detail_recv: Read packet from %s\n", data->detail);
1090 for (vp = packet->vps; vp; vp = vp->next) {
1092 vp_print(stdout, vp);
1098 * FIXME: many of these checks may not be necessary when
1099 * reading from the detail file.
1101 if (!received_request(listener, packet, prequest, &detail_client)) {
1111 * Free detail-specific stuff.
1113 static void detail_free(rad_listen_t *this)
1115 listen_detail_t *data = this->data;
1118 pairfree(&data->vps);
1119 free(data->outstanding);
1121 if (data->fp != NULL) fclose(data->fp);
1125 static int detail_print(rad_listen_t *this, char *buffer, size_t bufsize)
1127 return snprintf(buffer, bufsize, "%s",
1128 ((listen_detail_t *)(this->data))->detail);
1131 static int detail_encode(rad_listen_t *this, REQUEST *request)
1134 * We never encode responses "sent to" the detail file.
1139 static int detail_decode(rad_listen_t *this, REQUEST *request)
1142 * We never decode responses read from the detail file.
1148 static const CONF_PARSER detail_config[] = {
1149 { "detail", PW_TYPE_STRING_PTR,
1150 offsetof(listen_detail_t, detail), NULL, NULL },
1151 { "max_outstanding", PW_TYPE_INTEGER,
1152 offsetof(listen_detail_t, max_outstanding), NULL, "100" },
1154 { NULL, -1, 0, NULL, NULL } /* end the list */
1159 * Parse a detail section.
1161 static int detail_parse(const char *filename, int lineno,
1162 const CONF_SECTION *cs, rad_listen_t *this)
1165 listen_detail_t *data;
1169 rcode = cf_section_parse(cs, data, detail_config);
1171 radlog(L_ERR, "%s[%d]: Failed parsing listen section",
1176 if (!data->detail) {
1177 radlog(L_ERR, "%s[%d]: No detail file specified in listen section",
1184 data->state = STATE_UNOPENED;
1186 if (data->max_outstanding > 32768) data->max_outstanding = 32768;
1188 if (data->max_outstanding > 0) {
1189 data->outstanding = rad_malloc(sizeof(int) * data->max_outstanding);
1197 static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
1198 { NULL, NULL, NULL, NULL, NULL, NULL, NULL}, /* RAD_LISTEN_NONE */
1200 /* authentication */
1201 { common_socket_parse, NULL,
1202 auth_socket_recv, auth_socket_send,
1203 socket_print, client_socket_encode, client_socket_decode },
1206 { common_socket_parse, NULL,
1207 acct_socket_recv, acct_socket_send,
1208 socket_print, client_socket_encode, client_socket_decode},
1212 proxy_socket_recv, proxy_socket_send,
1213 socket_print, proxy_socket_encode, proxy_socket_decode },
1216 { detail_parse, detail_free,
1217 detail_recv, detail_send,
1218 detail_print, detail_encode, detail_decode }
1224 * Binds a listener to a socket.
1226 static int listen_bind(rad_listen_t *this)
1228 rad_listen_t **last;
1229 listen_socket_t *sock = this->data;
1232 * If the port is zero, then it means the appropriate
1233 * thing from /etc/services.
1235 if (sock->port == 0) {
1236 struct servent *svp;
1238 switch (this->type) {
1239 case RAD_LISTEN_AUTH:
1240 svp = getservbyname ("radius", "udp");
1242 sock->port = ntohs(svp->s_port);
1244 sock->port = PW_AUTH_UDP_PORT;
1248 case RAD_LISTEN_ACCT:
1249 svp = getservbyname ("radacct", "udp");
1251 sock->port = ntohs(svp->s_port);
1253 sock->port = PW_ACCT_UDP_PORT;
1258 radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
1264 * Find it in the old list, AFTER updating the port. If
1265 * it's there, use that, rather than creating a new
1266 * socket. This allows HUP's to re-use the old sockets,
1267 * which means that packets waiting in the socket queue
1270 for (last = &mainconfig.listen;
1272 last = &((*last)->next)) {
1273 if ((this->type == (*last)->type) &&
1274 (sock->port == ((listen_socket_t *)((*last)->data))->port) &&
1275 (sock->ipaddr.af == ((listen_socket_t *)((*last)->data))->ipaddr.af)) {
1278 if (sock->ipaddr.af == AF_INET) {
1279 equal = (sock->ipaddr.ipaddr.ip4addr.s_addr == ((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip4addr.s_addr);
1280 } else if (sock->ipaddr.af == AF_INET6) {
1281 equal = IN6_ARE_ADDR_EQUAL(&(sock->ipaddr.ipaddr.ip6addr), &(((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip6addr));
1287 this->fd = (*last)->fd;
1294 this->fd = lrad_socket(&sock->ipaddr, sock->port);
1296 radlog(L_ERR|L_CONS, "ERROR: Failed to open socket: %s",
1303 if ((flags = fcntl(this->fd, F_GETFL, NULL)) < 0) {
1304 radlog(L_ERR, "Failure in fcntl: %s)\n", strerror(errno));
1308 flags |= O_NONBLOCK;
1309 if( fcntl(this->fd, F_SETFL, flags) < 0) {
1310 radlog(L_ERR, "Failure in fcntl: %s)\n", strerror(errno));
1321 * Allocate & initialize a new listener.
1323 static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
1327 this = rad_malloc(sizeof(*this));
1328 memset(this, 0, sizeof(*this));
1331 this->recv = master_listen[this->type].recv;
1332 this->send = master_listen[this->type].send;
1333 this->print = master_listen[this->type].print;
1334 this->encode = master_listen[this->type].encode;
1335 this->decode = master_listen[this->type].decode;
1338 case RAD_LISTEN_AUTH:
1339 case RAD_LISTEN_ACCT:
1340 case RAD_LISTEN_PROXY:
1341 this->data = rad_malloc(sizeof(listen_socket_t));
1342 memset(this->data, 0, sizeof(listen_socket_t));
1345 case RAD_LISTEN_DETAIL:
1346 this->data = rad_malloc(sizeof(listen_detail_t));
1347 memset(this->data, 0, sizeof(listen_detail_t));
1358 * Externally visible function for creating a new proxy LISTENER.
1360 * For now, don't take ipaddr or port.
1362 * Not thread-safe, but all calls to it are protected by the
1363 * proxy mutex in request_list.c
1365 rad_listen_t *proxy_new_listener()
1367 int last_proxy_port, port;
1368 rad_listen_t *this, *tmp, **last;
1369 listen_socket_t *sock, *old;
1371 this = listen_alloc(RAD_LISTEN_PROXY);
1374 * Find an existing proxy socket to copy.
1376 * FIXME: Make it per-realm, or per-home server!
1378 last_proxy_port = 0;
1380 last = &mainconfig.listen;
1381 for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {
1382 if (tmp->type == RAD_LISTEN_PROXY) {
1384 if (sock->port > last_proxy_port) {
1385 last_proxy_port = sock->port + 1;
1387 if (!old) old = sock;
1390 last = &(tmp->next);
1393 if (!old) return NULL; /* This is a serious error. */
1396 * FIXME: find a new IP address to listen on?
1399 memcpy(&sock->ipaddr, &old->ipaddr, sizeof(sock->ipaddr));
1402 * Keep going until we find an unused port.
1404 for (port = last_proxy_port; port < 64000; port++) {
1406 if (listen_bind(this) == 0) {
1408 * Add the new listener to the list of
1420 static const LRAD_NAME_NUMBER listen_compare[] = {
1421 { "auth", RAD_LISTEN_AUTH },
1422 { "acct", RAD_LISTEN_ACCT },
1423 { "detail", RAD_LISTEN_DETAIL },
1429 * Generate a list of listeners. Takes an input list of
1430 * listeners, too, so we don't close sockets with waiting packets.
1432 int listen_init(const char *filename, rad_listen_t **head)
1436 rad_listen_t **last;
1438 lrad_ipaddr_t server_ipaddr;
1442 * We shouldn't be called with a pre-existing list.
1444 rad_assert(head && (*head == NULL));
1446 if (start_time != 0) start_time = time(NULL);
1449 server_ipaddr.af = AF_UNSPEC;
1452 * If the port is specified on the command-line,
1453 * it over-rides the configuration file.
1455 if (mainconfig.port >= 0) {
1456 auth_port = mainconfig.port;
1458 rcode = cf_item_parse(mainconfig.config, "port",
1459 PW_TYPE_INTEGER, &auth_port,
1460 Stringify(PW_AUTH_UDP_PORT));
1461 if (rcode < 0) return -1; /* error parsing it */
1464 radlog(L_INFO, "WARNING: The directive 'port' is deprecated, and will be removed in future versions of FreeRADIUS. Please edit the configuration files to use the directive 'listen'.");
1468 * If the IP address was configured on the command-line,
1469 * use that as the "bind_address"
1471 if (mainconfig.myip.af != AF_UNSPEC) {
1472 memcpy(&server_ipaddr, &mainconfig.myip,
1473 sizeof(server_ipaddr));
1478 * Else look for bind_address and/or listen sections.
1480 server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
1481 rcode = cf_item_parse(mainconfig.config, "bind_address",
1483 &server_ipaddr.ipaddr.ip4addr, NULL);
1484 if (rcode < 0) return -1; /* error parsing it */
1486 if (rcode == 0) { /* successfully parsed IPv4 */
1487 listen_socket_t *sock;
1488 server_ipaddr.af = AF_INET;
1490 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'.");
1493 this = listen_alloc(RAD_LISTEN_AUTH);
1496 sock->ipaddr = server_ipaddr;
1497 sock->port = auth_port;
1499 if (listen_bind(this) < 0) {
1502 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->port);
1505 auth_port = sock->port; /* may have been updated in listen_bind */
1507 last = &(this->next);
1510 * Open Accounting Socket.
1512 * If we haven't already gotten acct_port from
1513 * /etc/services, then make it auth_port + 1.
1515 this = listen_alloc(RAD_LISTEN_ACCT);
1519 * Create the accounting socket.
1521 * The accounting port is always the
1522 * authentication port + 1
1524 sock->ipaddr = server_ipaddr;
1525 sock->port = auth_port + 1;
1527 if (listen_bind(this) < 0) {
1530 radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->port);
1535 last = &(this->next);
1537 } else if (mainconfig.port > 0) { /* no bind address, but a port */
1538 radlog(L_CONS|L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",
1544 * They specified an IP on the command-line, ignore
1545 * all listen sections.
1547 if (mainconfig.myip.af != AF_UNSPEC) goto do_proxy;
1550 * Walk through the "listen" sections, if they exist.
1552 for (cs = cf_subsection_find_next(mainconfig.config, NULL, "listen");
1554 cs = cf_subsection_find_next(mainconfig.config, cs, "listen")) {
1556 char *listen_type, *identity;
1557 int lineno = cf_section_lineno(cs);
1559 listen_type = identity = NULL;
1561 rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,
1563 if (rcode < 0) return -1;
1567 radlog(L_ERR, "%s[%d]: No type specified in listen section",
1573 * See if there's an identity.
1575 rcode = cf_item_parse(cs, "identity", PW_TYPE_STRING_PTR,
1583 type = lrad_str2int(listen_compare, listen_type,
1586 if (type == RAD_LISTEN_NONE) {
1588 radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
1594 * Set up cross-type data.
1596 this = listen_alloc(type);
1597 this->identity = identity;
1601 * Call per-type parser.
1603 if (master_listen[type].parse(filename, lineno,
1611 last = &(this->next);
1615 * If we're proxying requests, open the proxy FD.
1616 * Otherwise, don't do anything.
1619 if (mainconfig.proxy_requests == TRUE) {
1621 listen_socket_t *sock = NULL;
1624 * No sockets to receive packets, therefore
1625 * proxying is pointless.
1627 if (!*head) return -1;
1630 * If we previously had proxy sockets, copy them
1631 * to the new config.
1633 if (mainconfig.listen != NULL) {
1634 rad_listen_t *old, *next, **tail;
1636 tail = &mainconfig.listen;
1637 for (old = mainconfig.listen;
1642 if (old->type != RAD_LISTEN_PROXY) {
1643 tail = &((*tail)->next);
1650 last = &(old->next);
1657 * Find the first authentication port,
1660 for (this = *head; this != NULL; this = this->next) {
1661 if (this->type == RAD_LISTEN_AUTH) {
1663 if (server_ipaddr.af == AF_UNSPEC) {
1664 server_ipaddr = sock->ipaddr;
1666 port = sock->port + 2; /* skip acct port */
1671 if (port < 0) port = 1024 + (lrad_rand() & 0x1ff);
1674 * Address is still unspecified, use IPv4.
1676 if (server_ipaddr.af == AF_UNSPEC) {
1677 server_ipaddr.af = AF_INET;
1678 server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
1681 this = listen_alloc(RAD_LISTEN_PROXY);
1685 * Create the first proxy socket.
1687 sock->ipaddr = server_ipaddr;
1690 * Try to find a proxy port (value doesn't matter)
1692 for (sock->port = port;
1695 if (listen_bind(this) == 0) {
1697 last = &(this->next); /* just in case */
1702 if (sock->port >= 64000) {
1705 radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
1711 * Sanity check the configuration.
1714 for (this = *head; this != NULL; this = this->next) {
1715 if (((this->type == RAD_LISTEN_ACCT) &&
1716 (rcode == RAD_LISTEN_DETAIL)) ||
1717 ((this->type == RAD_LISTEN_DETAIL) &&
1718 (rcode == RAD_LISTEN_ACCT))) {
1719 rad_assert(0 == 1); /* FIXME: configuration error */
1722 if (rcode != 0) continue;
1724 if ((this->type == RAD_LISTEN_ACCT) ||
1725 (this->type == RAD_LISTEN_DETAIL)) {
1735 * Free a linked list of listeners;
1737 void listen_free(rad_listen_t **head)
1741 if (!head || !*head) return;
1745 rad_listen_t *next = this->next;
1747 free(this->identity);
1750 * Other code may have eaten the FD.
1752 if (this->fd >= 0) close(this->fd);
1754 if (master_listen[this->type].free) {
1755 master_listen[this->type].free(this);