*/
fr_ipaddr_t ipaddr;
int port;
-#ifdef SO_BINDTODEVICE
const char *interface;
-#endif
RADCLIENT_LIST *clients;
} listen_socket_t;
* 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
ADDSTRING(name);
-#ifdef SO_BINDTODEVICE
if (sock->interface) {
ADDSTRING(" interface ");
ADDSTRING(sock->interface);
}
-#endif
ADDSTRING(" address ");
return 1;
}
+extern int check_config; /* radiusd.c */
+
/*
* Parse an authentication or accounting socket.
sock->ipaddr = ipaddr;
sock->port = listen_port;
+ if (check_config) {
+ if (home_server_find(&sock->ipaddr, sock->port)) {
+ 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->ipaddr, buffer, sizeof(buffer)),
+ sock->port);
+ return -1;
+ }
+
+ return 0; /* don't do anything */
+ }
+
/*
* If we can bind to interfaces, do so,
* else don't.
*/
if (cf_pair_find(cs, "interface")) {
-#ifndef SO_BINDTODEVICE
- cf_log_err(cf_sectiontoitem(cs),
- "System does not support binding to interfaces. Delete this line from the configuration file.");
- return -1;
-#else
const char *value;
CONF_PAIR *cp = cf_pair_find(cs, "interface");
return -1;
}
sock->interface = value;
-#endif
}
/*
#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
#ifdef WITH_COA
case RAD_LISTEN_COA:
- sock->port = PW_COA_UDP_PORT;
+ svp = getservbyname ("radius-dynauth", "udp");
+ if (svp != NULL) {
+ sock->port = ntohs(svp->s_port);
+ } else {
+ sock->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;
}
}
return -1;
}
-#ifdef SO_BINDTODEVICE
/*
* Bind to a device BEFORE touching IP addresses.
*/
if (sock->interface) {
+#ifdef SO_BINDTODEVICE
struct ifreq ifreq;
strcpy(ifreq.ifr_name, sock->interface);
sock->interface, strerror(errno));
return -1;
} /* else it worked. */
- }
+#else
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+#ifdef HAVE_NET_IF_H
+ /*
+ * Odds are that any system supporting "bind to
+ * device" also supports IPv6, so this next bit
+ * isn't necessary. But it's here for
+ * completeness.
+ *
+ * If we're doing IPv6, and the scope hasn't yet
+ * 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) {
+ close(this->fd);
+ radlog(L_ERR, "Failed finding interface %s: %s",
+ sock->interface, strerror(errno));
+ return -1;
+ }
+ } /* else scope was defined: we're OK. */
+ } else
+#endif
+#endif
+ /*
+ * IPv4: no link local addresses,
+ * and no bind to device.
+ */
+ {
+ close(this->fd);
+ radlog(L_ERR, "Failed binding to interface %s: \"bind to device\" is unsupported", sock->interface);
+ return -1;
+ }
#endif
+ }
#ifdef WITH_UDPFROMTO
/*
*/
rad_listen_t *proxy_new_listener(fr_ipaddr_t *ipaddr, int exists)
{
- int last_proxy_port, port;
rad_listen_t *this, *tmp, **last;
listen_socket_t *sock, *old;
/*
* Find an existing proxy socket to copy.
*/
- last_proxy_port = 0;
old = NULL;
last = &mainconfig.listen;
for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {
continue;
}
- if (sock->port > last_proxy_port) {
- last_proxy_port = sock->port + 1;
- }
if (!old) old = sock;
last = &(tmp->next);
}
+ this = listen_alloc(RAD_LISTEN_PROXY);
+ sock = this->data;
+
if (!old) {
/*
* The socket MUST already exist if we're binding
* If we're initializing the server, it's OK for the
* socket to NOT exist.
*/
- if (!exists) return NULL;
-
- this = listen_alloc(RAD_LISTEN_PROXY);
-
- sock = this->data;
- sock->ipaddr = *ipaddr;
+ if (!exists) {
+ DEBUG("WARNING: No previous template for proxy socket. Source IP address may be chosen by the OS");
+ }
+ if (ipaddr->af != AF_UNSPEC) {
+ sock->ipaddr = *ipaddr;
+ } else {
+ memset(&sock->ipaddr, 0, sizeof(sock->ipaddr));
+ sock->ipaddr.af = AF_INET; /* Oh well */
+ }
} else {
- this = listen_alloc(RAD_LISTEN_PROXY);
-
- sock = this->data;
sock->ipaddr = old->ipaddr;
}
- /*
- * Keep going until we find an unused port.
- */
- for (port = last_proxy_port; port < 64000; port++) {
- int rcode;
+ sock->port = 0;
- sock->port = port;
-
- rcode = listen_bind(this);
- if (rcode < 0) {
- continue;
- }
-
+ if (listen_bind(this) >= 0) {
/*
* Add the new listener to the list of
* listeners.
return this;
}
+ DEBUG("Failed binding to new proxy socket");
listen_free(&this);
return NULL;
}
listen_socket_t *sock;
server_ipaddr.af = AF_INET;
- 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'.");
+ radlog(L_INFO, "WARNING: The directive 'bind_address' is deprecated, and will be removed in future versions of FreeRADIUS. Please edit the configuration files to use the directive 'listen'.");
bind_it:
#ifdef WITH_VMPS