/*
* Find a per-socket client.
*/
-RADCLIENT *client_listener_find(const rad_listen_t *listener,
+RADCLIENT *client_listener_find(rad_listen_t *listener,
const fr_ipaddr_t *ipaddr, int src_port)
{
#ifdef WITH_DYNAMIC_CLIENTS
* can be defined.
*/
rad_assert(client->dynamic == 0);
- } else {
+
+ } else if (!client->dynamic && client->rate_limit) {
/*
* The IP is unknown, so we've found an enclosing
* network. Enable DoS protection. We only
case RAD_LISTEN_NONE:
#endif
case RAD_LISTEN_AUTH:
- dval = dict_valbyname(PW_AUTZ_TYPE, "Status-Server");
+ dval = dict_valbyname(PW_AUTZ_TYPE, 0, "Status-Server");
if (dval) {
rcode = module_authorize(dval->value, request);
} else {
#ifdef WITH_ACCOUNTING
case RAD_LISTEN_ACCT:
- dval = dict_valbyname(PW_ACCT_TYPE, "Status-Server");
+ dval = dict_valbyname(PW_ACCT_TYPE, 0, "Status-Server");
if (dval) {
rcode = module_accounting(dval->value, request);
} else {
* the WG. We like it, so it goes in here.
*/
case RAD_LISTEN_COA:
- dval = dict_valbyname(PW_RECV_COA_TYPE, "Status-Server");
+ dval = dict_valbyname(PW_RECV_COA_TYPE, 0, "Status-Server");
if (dval) {
rcode = module_recv_coa(dval->value, request);
} else {
/*
* This function is stupid and complicated.
*/
-static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
+static int socket_print(const rad_listen_t *this, char *buffer, size_t bufsize)
{
size_t len;
listen_socket_t *sock = this->data;
return 1;
}
+#ifdef WITH_PROXY
/*
* Maybe it's a socket that we opened to a home server.
*/
return 1;
}
-#endif
+#endif /* WITH_PROXY */
+#endif /* WITH_TCP */
ADDSTRING(" address ");
return 1;
}
+extern int check_config; /* radiusd.c */
+
/*
* Parse an authentication or accounting socket.
* TCP requires a destination IP for sockets.
* UDP doesn't, so it's allowed.
*/
+#ifdef WITH_PROXY
if ((this->type == RAD_LISTEN_PROXY) &&
(sock->proto != IPPROTO_UDP)) {
cf_log_err(cf_sectiontoitem(cs),
"Proxy listeners can only listen on proto = udp");
return -1;
}
-#endif
+#endif /* WITH_PROXY */
+#endif /* WITH_TCP */
}
sock->my_ipaddr = ipaddr;
sock->my_port = listen_port;
+#ifdef WITH_PROXY
+ if (check_config) {
+ if (home_server_find(&sock->my_ipaddr, sock->my_port, sock->proto)) {
+ char buffer[128];
+
+ DEBUG("ERROR: We have been asked to listen on %s port %d, which is also listed as a home server. This can create a proxy loop.",
+ ip_ntoh(&sock->my_ipaddr, buffer, sizeof(buffer)),
+ sock->my_port);
+ return -1;
+ }
+
+ return 0; /* don't do anything */
+ }
+#endif
+
/*
* If we can bind to interfaces, do so,
* else don't.
/*
* Inform the user about RFC requirements.
*/
- s1 = pairfind(request->proxy->vps, PW_STATE);
+ s1 = pairfind(request->proxy->vps, PW_STATE, 0);
if (s1) {
- s2 = pairfind(request->proxy_reply->vps, PW_STATE);
+ 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.");
* with Service-Type = Authorize-Only, it MUST
* have a State attribute in it.
*/
- vp = pairfind(request->packet->vps, PW_SERVICE_TYPE);
+ vp = pairfind(request->packet->vps, PW_SERVICE_TYPE, 0);
if (request->packet->code == PW_COA_REQUEST) {
if (vp && (vp->vp_integer == 17)) {
- vp = pairfind(request->packet->vps, PW_STATE);
+ vp = pairfind(request->packet->vps, PW_STATE, 0);
if (!vp || (vp->length == 0)) {
RDEBUG("ERROR: CoA-Request with Service-Type = Authorize-Only MUST contain a State attribute");
request->reply->code = PW_COA_NAK;
* Copy State from the request to the reply.
* See RFC 5176 Section 3.3.
*/
- vp = paircopy2(request->packet->vps, PW_STATE);
+ vp = paircopy2(request->packet->vps, PW_STATE, 0);
if (vp) pairadd(&request->reply->vps, vp);
/*
#ifdef WITH_COMMAND_SOCKET
/* TCP command socket */
- { command_socket_parse, NULL,
+ { command_socket_parse, command_socket_free,
command_domain_accept, command_domain_send,
command_socket_print, command_socket_encode, command_socket_decode },
#endif
case RAD_LISTEN_COA:
svp = getservbyname ("radius-dynauth", "udp");
if (svp != NULL) {
- sock->port = ntohs(svp->s_port);
+ sock->my_port = ntohs(svp->s_port);
} else {
- sock->port = PW_COA_UDP_PORT;
+ sock->my_port = PW_COA_UDP_PORT;
}
break;
#endif
default:
- radlog(L_ERR, "ERROR: Non-fatal internal sanity check failed in bind.");
+ DEBUG("WARNING: Internal sanity check failed in binding to socket. Ignoring problem.");
return -1;
}
}
* been defined, set the scope to the scope of
* the interface.
*/
- if (sock->ipaddr.af == AF_INET6) {
- if (sock->ipaddr.scope == 0) {
- sock->ipaddr.scope = if_nametoindex(sock->interface);
- if (sock->ipaddr.scope == 0) {
+ if (sock->my_ipaddr.af == AF_INET6) {
+ if (sock->my_ipaddr.scope == 0) {
+ sock->my_ipaddr.scope = if_nametoindex(sock->interface);
+ if (sock->my_ipaddr.scope == 0) {
close(this->fd);
radlog(L_ERR, "Failed finding interface %s: %s",
sock->interface, strerror(errno));
return this;
}
+#ifdef WITH_PROXY
+static int is_loopback(const fr_ipaddr_t *ipaddr)
+{
+ /*
+ * We shouldn't proxy on loopback.
+ */
+ if ((ipaddr->af == AF_INET) &&
+ (ipaddr->ipaddr.ip4addr.s_addr == htonl(INADDR_LOOPBACK))) {
+ return 1;
+ }
+
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+ if ((ipaddr->af == AF_INET6) &&
+ (IN6_IS_ADDR_LINKLOCAL(&ipaddr->ipaddr.ip6addr))) {
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+#endif
+
/*
* Generate a list of listeners. Takes an input list of
* listeners, too, so we don't close sockets with waiting packets.
add_sockets:
/*
+ * No sockets to receive packets, this is an error.
+ * proxying is pointless.
+ */
+ if (!*head) {
+ radlog(L_ERR, "The server is not configured to listen on any ports. Cannot start.");
+ return -1;
+ }
+
+ /*
* Print out which sockets we're listening on, and
* add them to the event list.
*/
for (this = *head; this != NULL; this = this->next) {
if (this->type == RAD_LISTEN_AUTH) {
sock = this->data;
+
+ if (is_loopback(&sock->my_ipaddr)) continue;
+
if (home.src_ipaddr.af == AF_UNSPEC) {
home.src_ipaddr = sock->my_ipaddr;
}
#ifdef WITH_ACCT
if (this->type == RAD_LISTEN_ACCT) {
sock = this->data;
+
+ if (is_loopback(&sock->my_ipaddr)) continue;
+
if (home.src_ipaddr.af == AF_UNSPEC) {
home.src_ipaddr = sock->my_ipaddr;
}
}
#ifdef WITH_TCP
- if ((this->type == RAD_LISTEN_AUTH) ||
+ if ((this->type == RAD_LISTEN_AUTH)
#ifdef WITH_ACCT
- (this->type == RAD_LISTEN_ACCT) ||
+ || (this->type == RAD_LISTEN_ACCT)
#endif
#ifdef WITH_PROXY
- (this->type == RAD_LISTEN_PROXY)
+ || (this->type == RAD_LISTEN_PROXY)
#endif
) {
listen_socket_t *sock = this->data;
for (this = mainconfig.listen; this != NULL; this = this->next) {
listen_socket_t *sock;
- if ((this->type != RAD_LISTEN_AUTH) &&
- (this->type != RAD_LISTEN_ACCT)) continue;
+ if ((this->type != RAD_LISTEN_AUTH)
+#ifdef WITH_ACCOUNTING
+ && (this->type != RAD_LISTEN_ACCT)
+#endif
+ ) continue;
sock = this->data;
* FIXME: For TCP, ignore the *secondary*
* listeners associated with the main socket.
*/
- if ((this->type != RAD_LISTEN_AUTH) &&
- (this->type != RAD_LISTEN_ACCT)) continue;
+ if ((this->type != RAD_LISTEN_AUTH)
+#ifdef WITH_ACCOUNTING
+ && (this->type != RAD_LISTEN_ACCT)
+#endif
+ ) continue;
sock = this->data;
}
if ((sock->my_port == port) &&
- ((sock->my_ipaddr.af == AF_INET) &&
- (sock->my_ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY))) {
+ fr_inaddr_any(&sock->my_ipaddr)) {
return this;
}
-
-#ifdef HAVE_STRUCT_SOCKADDR_IN6
- if ((sock->my_port == port) &&
- (sock->my_ipaddr.af == AF_INET6) &&
- (IN6_IS_ADDR_UNSPECIFIED(&sock->my_ipaddr.ipaddr.ip6addr))) {
- return this;
- }
-#endif
}
return NULL;