From: Alan T. DeKok Date: Sat, 6 Mar 2010 14:45:08 +0000 (+0100) Subject: Allow IPv6 to bind to interface with scope. X-Git-Tag: release_2_1_9~71 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f84b61fb47b8cb905bfeea297dbf6524347de87f;p=thirdparty%2Ffreeradius-server.git Allow IPv6 to bind to interface with scope. A follow-on to the previous patch. --- diff --git a/src/main/listen.c b/src/main/listen.c index 9527c2e4bde..59ff3141c3c 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -72,9 +72,7 @@ typedef struct listen_socket_t { */ fr_ipaddr_t ipaddr; int port; -#ifdef SO_BINDTODEVICE const char *interface; -#endif RADCLIENT_LIST *clients; } listen_socket_t; @@ -432,12 +430,10 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize) ADDSTRING(name); -#ifdef SO_BINDTODEVICE if (sock->interface) { ADDSTRING(" interface "); ADDSTRING(sock->interface); } -#endif ADDSTRING(" address "); @@ -519,11 +515,6 @@ static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) * 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"); @@ -535,7 +526,6 @@ static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) return -1; } sock->interface = value; -#endif } /* @@ -1428,7 +1418,12 @@ static int listen_bind(rad_listen_t *this) #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 @@ -1447,11 +1442,11 @@ static int listen_bind(rad_listen_t *this) 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); @@ -1465,8 +1460,43 @@ static int listen_bind(rad_listen_t *this) 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 /*