Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Make ifconfig(8) set and display preference numbers for IPv6



details:   https://anonhg.NetBSD.org/src/rev/b53de366f352
branches:  trunk
changeset: 747344:b53de366f352
user:      dyoung <dyoung%NetBSD.org@localhost>
date:      Fri Sep 11 22:06:29 2009 +0000

description:
Make ifconfig(8) set and display preference numbers for IPv6
addresses.  Make the kernel support SIOC[SG]IFADDRPREF for IPv6
interface addresses.

In in6ifa_ifpforlinklocal(), consult preference numbers before
making an otherwise arbitrary choice of in6_ifaddr.  Otherwise,
preference numbers are *not* consulted by the kernel, but that will
be rather easy for somebody with a little bit of free time to fix.

Please note that setting the preference number for a link-local
IPv6 address does not work right, yet, but that ought to be fixed
soon.

In support of the changes above,

1 Add a method to struct domain for "externalizing" a sockaddr, and
  provide an implementation for IPv6.  Expect more work in this area: it
  may be more proper to say that the IPv6 implementation "internalizes"
  a sockaddr.  Add sockaddr_externalize().

2 Add a subroutine, sofamily(), that returns a struct socket's address
  family or AF_UNSPEC.

3 Make a lot of IPv4-specific code generic, and move it from
  sys/netinet/ to sys/net/ for re-use by IPv6 parts of the kernel and
  ifconfig(8).

diffstat:

 sbin/ifconfig/af_inet.c  |  58 +++-------------------------------
 sbin/ifconfig/af_inet6.c |  11 ++++--
 sbin/ifconfig/util.c     |  58 ++++++++++++++++++++++++++++++++++-
 sbin/ifconfig/util.h     |   6 +++
 sys/kern/uipc_domain.c   |  18 +++++++++-
 sys/kern/uipc_socket.c   |  17 +++++++++-
 sys/net/if.c             |  66 ++++++++++++++++++++++++++++++++++++++-
 sys/net/if.h             |   4 +-
 sys/netinet/in.c         |  79 ++++-------------------------------------------
 sys/netinet6/in6.c       |  30 +++++++++++------
 sys/netinet6/in6.h       |   4 +-
 sys/netinet6/in6_proto.c |   5 +-
 sys/netinet6/scope6.c    |  18 +++++++++-
 sys/sys/domain.h         |   5 ++-
 sys/sys/socket.h         |   4 +-
 sys/sys/socketvar.h      |   3 +-
 16 files changed, 231 insertions(+), 155 deletions(-)

diffs (truncated from 780 to 300 lines):

diff -r fd6e01b94fb6 -r b53de366f352 sbin/ifconfig/af_inet.c
--- a/sbin/ifconfig/af_inet.c   Fri Sep 11 21:25:07 2009 +0000
+++ b/sbin/ifconfig/af_inet.c   Fri Sep 11 22:06:29 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: af_inet.c,v 1.13 2009/08/07 19:35:55 dyoung Exp $      */
+/*     $NetBSD: af_inet.c,v 1.14 2009/09/11 22:06:29 dyoung Exp $      */
 
 /*
  * Copyright (c) 1983, 1993
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: af_inet.c,v 1.13 2009/08/07 19:35:55 dyoung Exp $");
+__RCSID("$NetBSD: af_inet.c,v 1.14 2009/09/11 22:06:29 dyoung Exp $");
 #endif /* not lint */
 
 #include <sys/param.h> 
@@ -63,7 +63,6 @@
 static void in_commit_address(prop_dictionary_t, prop_dictionary_t);
 static void in_alias(const char *, prop_dictionary_t, prop_dictionary_t,
     struct in_aliasreq *);
-static void in_preference(const char *, const struct sockaddr *);
 
 static struct afswtch af = {
        .af_name = "inet", .af_af = AF_INET, .af_status = in_status,
@@ -139,46 +138,12 @@
        }
 }
 
-static int16_t
-in_get_preference(const char *ifname, const struct sockaddr *sa)
-{
-       struct if_addrprefreq ifap;
-       int s;
-
-       if ((s = getsock(AF_INET)) == -1) {
-               if (errno == EPROTONOSUPPORT)
-                       return 0;
-               err(EXIT_FAILURE, "socket");
-       }
-       memset(&ifap, 0, sizeof(ifap));
-       estrlcpy(ifap.ifap_name, ifname, sizeof(ifap.ifap_name));
-       memcpy(&ifap.ifap_addr, sa, MIN(sizeof(ifap.ifap_addr), sa->sa_len));
-       if (ioctl(s, SIOCGIFADDRPREF, &ifap) == -1) {
-               if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)
-                       return 0;
-               warn("SIOCGIFADDRPREF");
-       }
-       return ifap.ifap_preference;
-}
-
-static void
-in_preference(const char *ifname, const struct sockaddr *sa)
-{
-       int16_t preference;
-
-       if (lflag)
-               return;
-
-       preference = in_get_preference(ifname, sa);
-       printf(" preference %" PRId16, preference);
-}
-
 static void
 in_status(prop_dictionary_t env, prop_dictionary_t oenv, bool force)
 {
        struct ifaddrs *ifap, *ifa;
        struct in_aliasreq ifra;
-       int printprefs = 0;
+       bool printprefs = false;
        const char *ifname;
 
        if ((ifname = getifname(env)) == NULL)
@@ -187,19 +152,8 @@
        if (getifaddrs(&ifap) != 0)
                err(EXIT_FAILURE, "getifaddrs");
 
-       /* Print address preference numbers if any address has a non-zero
-        * preference assigned.
-        */
-       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
-               if (strcmp(ifname, ifa->ifa_name) != 0)
-                       continue;
-               if (ifa->ifa_addr->sa_family != AF_INET)
-                       continue;
-               if (in_get_preference(ifa->ifa_name, ifa->ifa_addr) != 0) {
-                       printprefs = 1;
-                       break;
-               }
-       }
+       printprefs = ifa_any_preferences(ifname, ifap, AF_INET);
+
        for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
                if (strcmp(ifname, ifa->ifa_name) != 0)
                        continue;
@@ -213,7 +167,7 @@
                memcpy(&ifra.ifra_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
                in_alias(ifa->ifa_name, env, oenv, &ifra);
                if (printprefs)
-                       in_preference(ifa->ifa_name, ifa->ifa_addr);
+                       ifa_print_preference(ifa->ifa_name, ifa->ifa_addr);
                printf("\n");
        }
        freeifaddrs(ifap);
diff -r fd6e01b94fb6 -r b53de366f352 sbin/ifconfig/af_inet6.c
--- a/sbin/ifconfig/af_inet6.c  Fri Sep 11 21:25:07 2009 +0000
+++ b/sbin/ifconfig/af_inet6.c  Fri Sep 11 22:06:29 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: af_inet6.c,v 1.24 2009/08/07 18:53:37 dyoung Exp $     */
+/*     $NetBSD: af_inet6.c,v 1.25 2009/09/11 22:06:29 dyoung Exp $     */
 
 /*
  * Copyright (c) 1983, 1993
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: af_inet6.c,v 1.24 2009/08/07 18:53:37 dyoung Exp $");
+__RCSID("$NetBSD: af_inet6.c,v 1.25 2009/09/11 22:06:29 dyoung Exp $");
 #endif /* not lint */
 
 #include <sys/param.h> 
@@ -374,8 +374,6 @@
                                printf("infty");
                }
        }
-
-       printf("\n");
 }
 
 static void
@@ -384,12 +382,14 @@
        struct ifaddrs *ifap, *ifa;
        struct in6_ifreq ifr;
        const char *ifname;
+       bool printprefs = false;
 
        if ((ifname = getifname(env)) == NULL)
                err(EXIT_FAILURE, "%s: getifname", __func__);
 
        if (getifaddrs(&ifap) != 0)
                err(EXIT_FAILURE, "getifaddrs");
+       printprefs = ifa_any_preferences(ifname, ifap, AF_INET6);
        for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
                if (strcmp(ifname, ifa->ifa_name) != 0)
                        continue;
@@ -402,6 +402,9 @@
                estrlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
                memcpy(&ifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
                in6_alias(ifname, env, oenv, &ifr);
+               if (printprefs)
+                       ifa_print_preference(ifa->ifa_name, ifa->ifa_addr);
+               printf("\n");
        }
        freeifaddrs(ifap);
 }
diff -r fd6e01b94fb6 -r b53de366f352 sbin/ifconfig/util.c
--- a/sbin/ifconfig/util.c      Fri Sep 11 21:25:07 2009 +0000
+++ b/sbin/ifconfig/util.c      Fri Sep 11 22:06:29 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: util.c,v 1.12 2009/08/07 18:53:37 dyoung Exp $ */
+/*     $NetBSD: util.c,v 1.13 2009/09/11 22:06:29 dyoung Exp $ */
 
 /*-
  * Copyright (c) 2008 David Young.  All rights reserved.
@@ -27,7 +27,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: util.c,v 1.12 2009/08/07 18:53:37 dyoung Exp $");
+__RCSID("$NetBSD: util.c,v 1.13 2009/09/11 22:06:29 dyoung Exp $");
 #endif /* not lint */
 
 #include <ctype.h>
@@ -290,6 +290,60 @@
        freeifaddrs(ifap);
 }
 
+int16_t
+ifa_get_preference(const char *ifname, const struct sockaddr *sa)
+{
+       struct if_addrprefreq ifap;
+       int s;
+
+       if ((s = getsock(sa->sa_family)) == -1) {
+               if (errno == EPROTONOSUPPORT)
+                       return 0;
+               err(EXIT_FAILURE, "socket");
+       }
+       memset(&ifap, 0, sizeof(ifap));
+       estrlcpy(ifap.ifap_name, ifname, sizeof(ifap.ifap_name));
+       memcpy(&ifap.ifap_addr, sa, MIN(sizeof(ifap.ifap_addr), sa->sa_len));
+       if (ioctl(s, SIOCGIFADDRPREF, &ifap) == -1) {
+               if (errno == EADDRNOTAVAIL || errno == EAFNOSUPPORT)
+                       return 0;
+               warn("SIOCGIFADDRPREF");
+       }
+       return ifap.ifap_preference;
+}
+
+void
+ifa_print_preference(const char *ifname, const struct sockaddr *sa)
+{
+       int16_t preference;
+
+       if (lflag)
+               return;
+
+       preference = ifa_get_preference(ifname, sa);
+       printf(" preference %" PRId16, preference);
+}
+
+bool
+ifa_any_preferences(const char *ifname, struct ifaddrs *ifap, int family)
+{
+       struct ifaddrs *ifa;
+
+       /* Print address preference numbers if any address has a non-zero
+        * preference assigned.
+        */
+       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+               if (strcmp(ifname, ifa->ifa_name) != 0)
+                       continue;
+               if (ifa->ifa_addr->sa_family != family)
+                       continue;
+               if (ifa_get_preference(ifa->ifa_name, ifa->ifa_addr) != 0)
+                       return true;
+       }
+       return false;
+}
+
+
 #ifdef INET6
 /* KAME idiosyncrasy */
 void
diff -r fd6e01b94fb6 -r b53de366f352 sbin/ifconfig/util.h
--- a/sbin/ifconfig/util.h      Fri Sep 11 21:25:07 2009 +0000
+++ b/sbin/ifconfig/util.h      Fri Sep 11 22:06:29 2009 +0000
@@ -2,6 +2,9 @@
 #define _IFCONFIG_UTIL_H
 
 #include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
 
 #include "parse.h"
 
@@ -25,5 +28,8 @@
 #ifdef INET6
 void in6_fillscopeid(struct sockaddr_in6 *sin6);
 #endif /* INET6        */
+bool ifa_any_preferences(const char *, struct ifaddrs *, int);
+void ifa_print_preference(const char *, const struct sockaddr *);
+int16_t ifa_get_preference(const char *, const struct sockaddr *);
 
 #endif /* _IFCONFIG_UTIL_H */
diff -r fd6e01b94fb6 -r b53de366f352 sys/kern/uipc_domain.c
--- a/sys/kern/uipc_domain.c    Fri Sep 11 21:25:07 2009 +0000
+++ b/sys/kern/uipc_domain.c    Fri Sep 11 22:06:29 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_domain.c,v 1.83 2009/09/08 18:01:34 dyoung Exp $  */
+/*     $NetBSD: uipc_domain.c,v 1.84 2009/09/11 22:06:29 dyoung Exp $  */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.83 2009/09/08 18:01:34 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.84 2009/09/11 22:06:29 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -268,6 +268,20 @@
        return memcpy(dst, src, src->sa_len);
 }
 
+struct sockaddr *
+sockaddr_externalize(struct sockaddr *dst, socklen_t socklen,
+    const struct sockaddr *src)
+{
+       struct domain *dom;
+
+       dom = pffinddomain(src->sa_family);
+
+       if (dom != NULL && dom->dom_sockaddr_externalize != NULL)
+               return (*dom->dom_sockaddr_externalize)(dst, socklen, src);
+
+       return sockaddr_copy(dst, socklen, src);
+}
+
 int
 sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2)
 {
diff -r fd6e01b94fb6 -r b53de366f352 sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c    Fri Sep 11 21:25:07 2009 +0000
+++ b/sys/kern/uipc_socket.c    Fri Sep 11 22:06:29 2009 +0000



Home | Main Index | Thread Index | Old Index