Merge branches 'master' and 'suser_to_priv'
[dragonfly.git] / sys / netinet6 / in6.c
index c29085b..ef148f6 100644 (file)
@@ -1,5 +1,5 @@
 /*     $FreeBSD: src/sys/netinet6/in6.c,v 1.7.2.9 2002/04/28 05:40:26 suz Exp $        */
-/*     $DragonFly: src/sys/netinet6/in6.c,v 1.29 2008/04/20 13:44:26 swildner Exp $    */
+/*     $DragonFly: src/sys/netinet6/in6.c,v 1.30 2008/10/03 07:59:20 hasso Exp $       */
 /*     $KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $  */
 
 /*
@@ -77,6 +77,7 @@
 #include <sys/sockio.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
+#include <sys/priv.h>
 #include <sys/time.h>
 #include <sys/kernel.h>
 #include <sys/syslog.h>
@@ -385,7 +386,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
        int error;
 
        privileged = 0;
-       if (suser(td) == 0)
+       if (priv_check(td, PRIV_ROOT) == 0)
                privileged++;
 
        switch (cmd) {
@@ -394,6 +395,14 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
                return (mrt6_ioctl(cmd, data));
        }
 
+       switch(cmd) {
+       case SIOCAADDRCTL_POLICY:
+       case SIOCDADDRCTL_POLICY:
+               if (!privileged)
+                       return (EPERM);
+               return (in6_src_ioctl(cmd, data));
+       }
+
        if (ifp == NULL)
                return (EOPNOTSUPP);
 
@@ -611,9 +620,14 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
 
        case SIOCAIFADDR_IN6:
        {
-               int i, error = 0;
+               int i, error = 0, iaIsNew;
                struct nd_prefix pr0, *pr;
 
+               if (ia != NULL)
+                       iaIsNew = 0;
+               else
+                       iaIsNew = 1;
+
                /*
                 * first, make or update the interface address structure,
                 * and link it to the list.
@@ -708,8 +722,11 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
                         */
                        pfxlist_onlink_check();
                }
-               if (error == 0 && ia)
-                       EVENTHANDLER_INVOKE(ifaddr_event, ifp);
+               if (error == 0 && ia) {
+                       EVENTHANDLER_INVOKE(ifaddr_event, ifp,
+                       iaIsNew ? IFADDR_EVENT_ADD : IFADDR_EVENT_CHANGE,
+                       &ia->ia_ifa);
+               }
                break;
        }
 
@@ -755,9 +772,10 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
                        pr->ndpr_expire = 1; /* XXX: just for expiration */
                }
 
-         purgeaddr:
+purgeaddr:
+               EVENTHANDLER_INVOKE(ifaddr_event, ifp, IFADDR_EVENT_DELETE,
+                                   &ia->ia_ifa);
                in6_purgeaddr(&ia->ia_ifa);
-               EVENTHANDLER_INVOKE(ifaddr_event, ifp);
                break;
        }
 
@@ -1783,6 +1801,34 @@ in6ifa_ifpwithaddr(struct ifnet *ifp, struct in6_addr *addr)
                return (NULL);
 }
 
+/*
+ * find the internet address on a given interface corresponding to a neighbor's
+ * address.
+ */
+struct in6_ifaddr *
+in6ifa_ifplocaladdr(const struct ifnet *ifp, const struct in6_addr *addr)
+{
+       struct ifaddr *ifa;
+       struct in6_ifaddr *ia;
+       struct ifaddr_container *ifac;
+
+       TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
+               ifa = ifac->ifa;
+
+               if (ifa->ifa_addr == NULL)
+                       continue;       /* just for safety */
+               if (ifa->ifa_addr->sa_family != AF_INET6)
+                       continue;
+               ia = (struct in6_ifaddr *)ifa;
+               if (IN6_ARE_MASKED_ADDR_EQUAL(addr,
+                               &ia->ia_addr.sin6_addr,
+                               &ia->ia_prefixmask.sin6_addr))
+                       return ia;
+       }
+
+       return NULL;
+}
+
 /*
  * Convert IP6 address to printable (loggable) representation.
  */