]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Allow IPv6 to bind to interface with scope.
authorAlan T. DeKok <aland@freeradius.org>
Sat, 6 Mar 2010 14:45:08 +0000 (15:45 +0100)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 6 Mar 2010 14:45:08 +0000 (15:45 +0100)
A follow-on to the previous patch.

src/main/listen.c

index 9527c2e4bdeadd3ca1b789c799bebe13c11414f7..59ff3141c3ce5b9412eb73a9873a1101818a22ed 100644 (file)
@@ -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
        /*