#include <freeradius-devel/rad_assert.h>
#include <freeradius-devel/vqp.h>
#include <freeradius-devel/dhcp.h>
+#include <freeradius-devel/process.h>
#include <freeradius-devel/vmps.h>
#include <freeradius-devel/detail.h>
request_free(&request);
goto unknown;
}
- request->packet->timestamp = request->timestamp;
+ gettimeofday(&request->packet->timestamp, NULL);
request->number = 0;
request->priority = listener->type;
request->server = client->client_server;
*/
if (!client_validate(clients, client, created)) goto unknown;
}
+
+ request->server = client->server;
+ exec_trigger(request, NULL, "server.client.add");
+
request_free(&request);
if (!created) goto unknown;
* Like rad_authenticate and rad_accounting this should
* live in it's own file but it's so small we don't bother.
*/
-static int rad_status_server(REQUEST *request)
+int rad_status_server(REQUEST *request)
{
int rcode = RLM_MODULE_OK;
DICT_VALUE *dval;
}
#ifdef WITH_TCP
-static int dual_tcp_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int dual_tcp_recv(rad_listen_t *listener)
{
int rcode;
RADIUS_PACKET *packet;
return 0;
}
- RAD_STATS_TYPE_INC(listener, total_requests);
-
/*
* Some sanity checks, based on the packet code.
*/
switch(packet->code) {
case PW_AUTHENTICATION_REQUEST:
- if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
- RAD_STATS_CLIENT_INC(listener, client, total_requests);
+ if (listener->type != RAD_LISTEN_AUTH) goto bad_packet;
+ FR_STATS_INC(auth, total_requests);
fun = rad_authenticate;
break;
#ifdef WITH_ACCOUNTING
case PW_ACCOUNTING_REQUEST:
if (listener->type != RAD_LISTEN_ACCT) goto bad_packet;
- RAD_STATS_CLIENT_INC(listener, client, total_requests);
+ FR_STATS_INC(acct, total_requests);
fun = rad_accounting;
break;
#endif
case PW_STATUS_SERVER:
if (!mainconfig.status_server) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ FR_STATS_INC(auth, total_unknown_types);
DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
rad_free(&sock->packet);
return 0;
default:
bad_packet:
- RAD_STATS_INC(radius_auth_stats.total_unknown_types);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+ FR_STATS_INC(auth, total_unknown_types);
DEBUG("Invalid packet code %d sent from client %s port %d : IGNORED",
packet->code, client->shortname, packet->src_port);
return 0;
} /* switch over packet types */
- if (!received_request(listener, packet, prequest, sock->client)) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, sock->client, total_packets_dropped);
+ if (!request_receive(listener, packet, client, fun)) {
+ FR_STATS_INC(auth, total_packets_dropped);
rad_free(&sock->packet);
return 0;
}
- *pfun = fun;
sock->packet = NULL; /* we have no need for more partial reads */
return 1;
}
-static int dual_tcp_accept(rad_listen_t *listener,
- UNUSED RAD_REQUEST_FUNP *pfun,
- UNUSED REQUEST **prequest)
+static int dual_tcp_accept(rad_listen_t *listener)
{
int newfd, src_port;
rad_listen_t *this;
struct sockaddr_storage src;
listen_socket_t *sock;
fr_ipaddr_t src_ipaddr;
- RADCLIENT *client;
+ RADCLIENT *client = NULL;
salen = sizeof(src);
/*
* Non-blocking sockets must handle this.
*/
+#ifdef EWOULDBLOCK
if (errno == EWOULDBLOCK) {
return 0;
}
+#endif
DEBUG2(" ... failed to accept connection.");
return -1;
if ((client = client_listener_find(listener,
&src_ipaddr, src_port)) == NULL) {
close(newfd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ FR_STATS_INC(auth, total_invalid_requests);
return 0;
}
sock->other_ipaddr = src_ipaddr;
sock->other_port = src_port;
sock->client = client;
+ sock->opened = sock->last_packet = time(NULL);
this->fd = newfd;
this->status = RAD_LISTEN_STATUS_INIT;
this->recv = dual_tcp_recv;
+#ifdef WITH_TLS
+ if (this->tls) {
+ this->recv = dual_tls_recv;
+ this->send = dual_tls_send;
+ }
+#endif
+
/*
* FIXME: set O_NONBLOCK on the accept'd fd.
* See djb's portability rants for details.
snprintf(buffer, bufsize, "%d", sock->my_port);
FORWARD;
+#ifdef WITH_TLS
+ if (this->tls) {
+ ADDSTRING(" (TLS)");
+ FORWARD;
+ }
+#endif
+
if (this->server) {
ADDSTRING(" as server ");
ADDSTRING(this->server);
/*
* Try IPv4 first
*/
+ memset(&ipaddr, 0, sizeof(ipaddr));
ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
rcode = cf_item_parse(cs, "ipaddr", PW_TYPE_IPADDR,
&ipaddr.ipaddr.ip4addr, NULL);
return -1;
#else
char *proto = NULL;
-
+#ifdef WITH_TLS
+ CONF_SECTION *tls;
+#endif
rcode = cf_item_parse(cs, "proto", PW_TYPE_STRING_PTR,
&proto, "udp");
return -1;
}
#endif /* WITH_PROXY */
+
+#ifdef WITH_TLS
+ tls = cf_section_sub_find(cs, "tls");
+
+ /*
+ * Don't allow TLS configurations for UDP sockets.
+ */
+ if (sock->proto != IPPROTO_TCP) {
+ cf_log_err(cf_sectiontoitem(cs),
+ "TLS transport is not available for UDP sockets.");
+ return -1;
+ }
+
+ if (tls) {
+ /*
+ * FIXME: Make this better.
+ */
+ if (listen_port == 0) listen_port = 2083;
+
+ this->tls = tls_server_conf_parse(tls);
+ if (!this->tls) {
+ return -1;
+ }
+
+#ifdef HAVE_PTRHEAD_H
+ if (pthread_mutex_init(&sock->mutex, NULL) < 0) {
+ rad_assert(0 == 1);
+ listen_free(&this);
+ return 0;
+ }
+#endif
+
+ }
+#else /* WITH_TLS */
+ /*
+ * Built without TLS. Disallow it.
+ */
+ if (cf_section_sub_find(cs, "tls")) {
+ cf_log_err(cf_sectiontoitem(cs),
+ "TLS transport is not available in this executable.");
+ return -1;
+ }
+#endif /* WITH_TLS */
+
#endif /* WITH_TCP */
+
+ /*
+ * No "proto" field. Disallow TLS.
+ */
+ } else if (cf_section_sub_find(cs, "tls")) {
+ cf_log_err(cf_sectiontoitem(cs),
+ "TLS transport is not available in this \"listen\" section.");
+ return -1;
}
sock->my_ipaddr = ipaddr;
rad_assert(request->proxy_listener == listener);
rad_assert(listener->send == proxy_socket_send);
- if (rad_send(request->proxy, request->packet,
+ if (rad_send(request->proxy, NULL,
request->home_server->secret) < 0) {
radlog_request(L_ERR, 0, request, "Failed sending proxied request: %s",
fr_strerror());
* It takes packets, not requests. It sees if the packet looks
* OK. If so, it does a number of sanity checks on it.
*/
-static int stats_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int stats_socket_recv(rad_listen_t *listener)
{
ssize_t rcode;
int code, src_port;
RADIUS_PACKET *packet;
- RADCLIENT *client;
+ RADCLIENT *client = NULL;
fr_ipaddr_t src_ipaddr;
rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
if (rcode < 0) return 0;
- RAD_STATS_TYPE_INC(listener, total_requests);
+ FR_STATS_INC(auth, total_requests);
if (rcode < 20) { /* AUTH_HDR_LEN */
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(auth, total_malformed_requests);
return 0;
}
if ((client = client_listener_find(listener,
&src_ipaddr, src_port)) == NULL) {
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ FR_STATS_INC(auth, total_invalid_requests);
return 0;
}
+ FR_STATS_TYPE_INC(client->auth.total_requests);
+
/*
* We only understand Status-Server on this socket.
*/
DEBUG("Ignoring packet code %d sent to Status-Server port",
code);
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_unknown_types);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+ FR_STATS_INC(auth, total_unknown_types);
return 0;
}
*/
packet = rad_recv(listener->fd, 1); /* require message authenticator */
if (!packet) {
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(auth, total_malformed_requests);
DEBUG("%s", fr_strerror());
return 0;
}
- if (!received_request(listener, packet, prequest, client)) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ if (!request_receive(listener, packet, client, rad_status_server)) {
+ FR_STATS_INC(auth, total_packets_dropped);
rad_free(&packet);
return 0;
}
- *pfun = rad_status_server;
return 1;
}
#endif
* It takes packets, not requests. It sees if the packet looks
* OK. If so, it does a number of sanity checks on it.
*/
-static int auth_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int auth_socket_recv(rad_listen_t *listener)
{
ssize_t rcode;
int code, src_port;
RADIUS_PACKET *packet;
RAD_REQUEST_FUNP fun = NULL;
- RADCLIENT *client;
+ RADCLIENT *client = NULL;
fr_ipaddr_t src_ipaddr;
rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
if (rcode < 0) return 0;
- RAD_STATS_TYPE_INC(listener, total_requests);
+ FR_STATS_INC(auth, total_requests);
if (rcode < 20) { /* AUTH_HDR_LEN */
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(auth, total_malformed_requests);
return 0;
}
if ((client = client_listener_find(listener,
&src_ipaddr, src_port)) == NULL) {
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ FR_STATS_INC(auth, total_invalid_requests);
return 0;
}
+ FR_STATS_TYPE_INC(client->auth.total_requests);
+
/*
* Some sanity checks, based on the packet code.
*/
switch(code) {
case PW_AUTHENTICATION_REQUEST:
- RAD_STATS_CLIENT_INC(listener, client, total_requests);
fun = rad_authenticate;
break;
case PW_STATUS_SERVER:
if (!mainconfig.status_server) {
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ FR_STATS_INC(auth, total_unknown_types);
DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
return 0;
}
default:
rad_recv_discard(listener->fd);
- RAD_STATS_INC(radius_auth_stats.total_unknown_types);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+ FR_STATS_INC(auth,total_unknown_types);
DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
code, client->shortname, src_port);
*/
packet = rad_recv(listener->fd, client->message_authenticator);
if (!packet) {
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(auth, total_malformed_requests);
DEBUG("%s", fr_strerror());
return 0;
}
- if (!received_request(listener, packet, prequest, client)) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ if (!request_receive(listener, packet, client, fun)) {
+ FR_STATS_INC(auth, total_packets_dropped);
rad_free(&packet);
return 0;
}
- *pfun = fun;
return 1;
}
/*
* Receive packets from an accounting socket
*/
-static int acct_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int acct_socket_recv(rad_listen_t *listener)
{
ssize_t rcode;
int code, src_port;
RADIUS_PACKET *packet;
RAD_REQUEST_FUNP fun = NULL;
- RADCLIENT *client;
+ RADCLIENT *client = NULL;
fr_ipaddr_t src_ipaddr;
rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
if (rcode < 0) return 0;
- RAD_STATS_TYPE_INC(listener, total_requests);
+ FR_STATS_INC(acct, total_requests);
if (rcode < 20) { /* AUTH_HDR_LEN */
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(acct, total_malformed_requests);
return 0;
}
if ((client = client_listener_find(listener,
&src_ipaddr, src_port)) == NULL) {
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ FR_STATS_INC(acct, total_invalid_requests);
return 0;
}
+ FR_STATS_TYPE_INC(client->acct.total_requests);
+
/*
* Some sanity checks, based on the packet code.
*/
switch(code) {
case PW_ACCOUNTING_REQUEST:
- RAD_STATS_CLIENT_INC(listener, client, total_requests);
fun = rad_accounting;
break;
case PW_STATUS_SERVER:
if (!mainconfig.status_server) {
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+ FR_STATS_INC(acct, total_unknown_types);
DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
return 0;
default:
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_unknown_types);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+ FR_STATS_INC(acct, total_unknown_types);
DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
code, client->shortname, src_port);
*/
packet = rad_recv(listener->fd, 0);
if (!packet) {
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(acct, total_malformed_requests);
radlog(L_ERR, "%s", fr_strerror());
return 0;
}
/*
* There can be no duplicate accounting packets.
*/
- if (!received_request(listener, packet, prequest, client)) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ if (!request_receive(listener, packet, client, fun)) {
+ FR_STATS_INC(acct, total_packets_dropped);
rad_free(&packet);
return 0;
}
- *pfun = fun;
return 1;
}
#endif
#ifdef WITH_COA
-/*
- * For now, all CoA requests are *only* originated, and not
- * proxied. So all of the necessary work is done in the
- * post-proxy section, which is automatically handled by event.c.
- * As a result, we don't have to do anything here.
- */
-static int rad_coa_reply(REQUEST *request)
-{
- VALUE_PAIR *s1, *s2;
-
- /*
- * Inform the user about RFC requirements.
- */
- s1 = pairfind(request->proxy->vps, PW_STATE, 0);
- if (s1) {
- s2 = pairfind(request->proxy_reply->vps, PW_STATE, 0);
-
- if (!s2) {
- DEBUG("WARNING: Client was sent State in CoA, and did not respond with State.");
-
- } else if ((s1->length != s2->length) ||
- (memcmp(s1->vp_octets, s2->vp_octets,
- s1->length) != 0)) {
- DEBUG("WARNING: Client was sent State in CoA, and did not respond with the same State.");
- }
- }
-
- return RLM_MODULE_OK;
-}
-
static int do_proxy(REQUEST *request)
{
VALUE_PAIR *vp;
request->reply->code = ack;
break;
}
- } else {
+ } else if (request->proxy_reply) {
/*
* Start the reply code with the proxy reply
* code.
/*
* We may want to over-ride the reply.
*/
- rcode = module_send_coa(0, request);
- switch (rcode) {
- /*
- * We need to send CoA-NAK back if Service-Type
- * is Authorize-Only. Rely on the user's policy
- * to do that. We're not a real NAS, so this
- * restriction doesn't (ahem) apply to us.
- */
+ if (request->reply->code) {
+ rcode = module_send_coa(0, request);
+ switch (rcode) {
+ /*
+ * We need to send CoA-NAK back if Service-Type
+ * is Authorize-Only. Rely on the user's policy
+ * to do that. We're not a real NAS, so this
+ * restriction doesn't (ahem) apply to us.
+ */
case RLM_MODULE_FAIL:
case RLM_MODULE_INVALID:
case RLM_MODULE_REJECT:
request->reply->code = ack;
}
break;
-
+ }
}
return RLM_MODULE_OK;
* It takes packets, not requests. It sees if the packet looks
* OK. If so, it does a number of sanity checks on it.
*/
-static int coa_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int coa_socket_recv(rad_listen_t *listener)
{
ssize_t rcode;
int code, src_port;
RADIUS_PACKET *packet;
RAD_REQUEST_FUNP fun = NULL;
- RADCLIENT *client;
+ RADCLIENT *client = NULL;
fr_ipaddr_t src_ipaddr;
rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
if (rcode < 0) return 0;
- RAD_STATS_TYPE_INC(listener, total_requests);
-
if (rcode < 20) { /* AUTH_HDR_LEN */
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(coa, total_requests);
+ FR_STATS_INC(coa, total_malformed_requests);
return 0;
}
if ((client = client_listener_find(listener,
&src_ipaddr, src_port)) == NULL) {
rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ FR_STATS_INC(coa, total_requests);
+ FR_STATS_INC(coa, total_invalid_requests);
return 0;
}
*/
switch(code) {
case PW_COA_REQUEST:
+ FR_STATS_INC(coa, total_requests);
+ fun = rad_coa_recv;
+ break;
+
case PW_DISCONNECT_REQUEST:
+ FR_STATS_INC(dsc, total_requests);
fun = rad_coa_recv;
break;
default:
rad_recv_discard(listener->fd);
+ FR_STATS_INC(coa, total_unknown_types);
DEBUG("Invalid packet code %d sent to coa port from client %s port %d : IGNORED",
code, client->shortname, src_port);
return 0;
- break;
} /* switch over packet types */
/*
*/
packet = rad_recv(listener->fd, client->message_authenticator);
if (!packet) {
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ FR_STATS_INC(coa, total_malformed_requests);
DEBUG("%s", fr_strerror());
return 0;
}
- if (!received_request(listener, packet, prequest, client)) {
+ if (!request_receive(listener, packet, client, fun)) {
+ FR_STATS_INC(coa, total_packets_dropped);
rad_free(&packet);
return 0;
}
- *pfun = fun;
return 1;
}
#endif
/*
* Recieve packets from a proxy socket.
*/
-static int proxy_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int proxy_socket_recv(rad_listen_t *listener)
{
- REQUEST *request;
RADIUS_PACKET *packet;
- RAD_REQUEST_FUNP fun = NULL;
char buffer[128];
packet = rad_recv(listener->fd, 0);
case PW_AUTHENTICATION_ACK:
case PW_ACCESS_CHALLENGE:
case PW_AUTHENTICATION_REJECT:
- fun = rad_authenticate;
break;
#ifdef WITH_ACCOUNTING
case PW_ACCOUNTING_RESPONSE:
- fun = rad_accounting;
break;
#endif
case PW_DISCONNECT_NAK:
case PW_COA_ACK:
case PW_COA_NAK:
- fun = rad_coa_reply;
break;
#endif
return 0;
}
- request = received_proxy_response(packet);
- if (!request) {
+ if (!request_proxy_reply(packet)) {
rad_free(&packet);
return 0;
}
-#ifdef WITH_COA
- /*
- * Distinguish proxied CoA requests from ones we
- * originate.
- */
- if ((fun == rad_coa_reply) &&
- (request->packet->code == request->proxy->code)) {
- fun = rad_coa_recv;
- }
-#endif
-
- rad_assert(fun != NULL);
- *pfun = fun;
- *prequest = request;
-
return 1;
}
/*
* Recieve packets from a proxy socket.
*/
-static int proxy_socket_tcp_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int proxy_socket_tcp_recv(rad_listen_t *listener)
{
- REQUEST *request;
RADIUS_PACKET *packet;
- RAD_REQUEST_FUNP fun = NULL;
listen_socket_t *sock = listener->data;
char buffer[128];
case PW_AUTHENTICATION_ACK:
case PW_ACCESS_CHALLENGE:
case PW_AUTHENTICATION_REJECT:
- fun = rad_authenticate;
break;
#ifdef WITH_ACCOUNTING
case PW_ACCOUNTING_RESPONSE:
- fun = rad_accounting;
break;
#endif
*
* Close the socket on bad packets...
*/
- request = received_proxy_response(packet);
- if (!request) {
+ if (!request_proxy_reply(packet)) {
+ rad_free(&packet);
return 0;
}
- rad_assert(fun != NULL);
- sock->opened = sock->last_packet = request->timestamp;
-
- *pfun = fun;
- *prequest = request;
+ sock->opened = sock->last_packet = time(NULL);
return 1;
}
}
/*
+ * Don't open sockets if we're checking the config.
+ */
+ if (check_config) {
+ this->fd = -1;
+ return 0;
+ }
+
+ /*
* Copy fr_socket() here, as we may need to bind to a device.
*/
this->fd = socket(sock->my_ipaddr.af, sock_type, 0);
if (sock->interface) {
#ifdef SO_BINDTODEVICE
struct ifreq ifreq;
- strcpy(ifreq.ifr_name, sock->interface);
+
+ memset(&ifreq, 0, sizeof(ifreq));
+ strlcpy(ifreq.ifr_name, sock->interface, sizeof(ifreq.ifr_name));
fr_suid_up();
rcode = setsockopt(this->fd, SOL_SOCKET, SO_BINDTODEVICE,
{
rad_listen_t *this;
listen_socket_t *sock;
+#ifndef NDEBUG
+ char buffer[256];
+#endif
if (!home) return 0;
sock->my_port = src_port;
sock->proto = home->proto;
+ if (debug_flag >= 2) {
+ this->print(this, buffer, sizeof(buffer));
+ DEBUG("Opening new %s", buffer);
+ }
+
#ifdef WITH_TCP
- sock->last_packet = time(NULL);
+ sock->opened = sock->last_packet = time(NULL);
if (home->proto == IPPROTO_TCP) {
this->recv = proxy_socket_tcp_recv;
*/
this->fd = fr_tcp_client_socket(&home->src_ipaddr,
&home->ipaddr, home->port);
+#ifdef WITH_TLS
+ if (home->tls) {
+ DEBUG("Trying SSL to port %d\n", home->port);
+ sock->ssn = tls_new_client_session(home->tls, this->fd);
+ if (!sock->ssn) {
+ listen_free(&this);
+ return 0;
+ }
+
+ this->recv = proxy_tls_recv;
+ this->send = proxy_tls_send;
+ }
+#endif
} else
#endif
this->fd = fr_socket(&home->src_ipaddr, src_port);
if (this->fd < 0) {
- DEBUG("Failed opening client socket: %s", fr_strerror());
+ this->print(this, buffer,sizeof(buffer));
+ DEBUG("Failed opening client socket ::%s:: : %s",
+ buffer, fr_strerror());
listen_free(&this);
return 0;
}
* Generate a list of listeners. Takes an input list of
* listeners, too, so we don't close sockets with waiting packets.
*/
-int listen_init(CONF_SECTION *config, rad_listen_t **head)
+int listen_init(CONF_SECTION *config, rad_listen_t **head, int spawn_flag)
{
int override = FALSE;
int rcode;
#ifdef WITH_PROXY
int defined_proxy = 0;
#endif
+#ifndef WITH_TLS
+ spawn_flag = spawn_flag; /* -Wunused */
+#endif
/*
* We shouldn't be called with a pre-existing list.
}
#endif
- event_new_fd(this);
+
+#ifdef WITH_TLS
+ if (!spawn_flag && this->tls) {
+ cf_log_err(cf_sectiontoitem(this->cs), "Threading must be enabled for TLS sockets to function properly.");
+ cf_log_err(cf_sectiontoitem(this->cs), "You probably need to do 'radiusd -fxx -l stdout' for debugging");
+ return -1;
+ }
+#endif
+ if (!check_config) event_new_fd(this);
}
/*
*/
#ifdef WITH_PROXY
if ((mainconfig.proxy_requests == TRUE) &&
+ !check_config &&
(*head != NULL) && !defined_proxy) {
listen_socket_t *sock = NULL;
int port = 0;
master_listen[this->type].free(this);
}
+#ifdef WITH_TLS
+ if (this->tls) tls_server_conf_free(this->tls);
+#endif
+
#ifdef WITH_TCP
if ((this->type == RAD_LISTEN_AUTH)
#ifdef WITH_ACCT
#endif
) {
listen_socket_t *sock = this->data;
- rad_free(&sock->packet);
- }
+
+#ifdef WITH_TLS
+ if (sock->request) {
+ pthread_mutex_destroy(&(sock->mutex));
+ request_free(&sock->request);
+ sock->packet = NULL;
+
+ if (sock->ssn) session_free(sock->ssn);
+ request_free(&sock->request);
+ } else
#endif
+ rad_free(&sock->packet);
+
+ }
+#endif /* WITH_TCP */
free(this->data);
free(this);
}
#endif
-rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port)
+rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port, int proto)
{
rad_listen_t *this;
for (this = mainconfig.listen; this != NULL; this = this->next) {
listen_socket_t *sock;
- /*
- * FIXME: For TCP, ignore the *secondary*
- * listeners associated with the main socket.
- */
- if ((this->type != RAD_LISTEN_AUTH)
-#ifdef WITH_ACCOUNTING
- && (this->type != RAD_LISTEN_ACCT)
-#endif
- ) continue;
-
sock = this->data;
- if ((sock->my_port == port) &&
- (fr_ipaddr_cmp(ipaddr, &sock->my_ipaddr) == 0)) {
- return this;
- }
+ if (sock->my_port != port) continue;
+ if (sock->proto != proto) continue;
+ if (fr_ipaddr_cmp(ipaddr, &sock->my_ipaddr) != 0) continue;
- if ((sock->my_port == port) &&
- fr_inaddr_any(&sock->my_ipaddr)) {
- return this;
- }
+ return this;
+ }
+
+ /*
+ * Failed to find a specific one. Find INADDR_ANY
+ */
+ for (this = mainconfig.listen; this != NULL; this = this->next) {
+ listen_socket_t *sock;
+
+ sock = this->data;
+
+ if (sock->my_port != port) continue;
+ if (sock->proto != proto) continue;
+ if (!fr_inaddr_any(&sock->my_ipaddr)) continue;
+
+ return this;
}
return NULL;