]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/net/pf_if.c
xnu-3789.1.32.tar.gz
[apple/xnu.git] / bsd / net / pf_if.c
index 7e187cb9416417fb9a6be1ba66e7b26168452dc7..05f265677392dfb7e4cf085e73f95bb7d45b3649 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2007-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -148,7 +148,8 @@ pfi_kif_get(const char *kif_name)
 
        bzero(&s, sizeof (s));
        strlcpy(s.pfik_name, kif_name, sizeof (s.pfik_name));
-       if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL)
+       if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs,
+           (struct pfi_kif *)(void *)&s)) != NULL)
                return (kif);
 
        /* create new one */
@@ -156,7 +157,7 @@ pfi_kif_get(const char *kif_name)
                return (NULL);
 
        strlcpy(kif->pfik_name, kif_name, sizeof (kif->pfik_name));
-       kif->pfik_tzero = pf_time_second();
+       kif->pfik_tzero = pf_calendar_time_second();
        TAILQ_INIT(&kif->pfik_dynaddrs);
 
        RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
@@ -229,14 +230,11 @@ void
 pfi_attach_ifnet(struct ifnet *ifp)
 {
        struct pfi_kif *kif;
-       char if_name[IFNAMSIZ];
 
        lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
 
        pfi_update++;
-       (void) snprintf(if_name, sizeof (if_name), "%s%d",
-           ifp->if_name, ifp->if_unit);
-       if ((kif = pfi_kif_get(if_name)) == NULL)
+       if ((kif = pfi_kif_get(if_name(ifp))) == NULL)
                panic("pfi_kif_get failed");
 
        ifnet_lock_exclusive(ifp);
@@ -286,7 +284,6 @@ pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
                default:
                        return (pfr_match_addr(dyn->pfid_kt, a, AF_INET));
                }
-               break;
 #endif /* INET */
 #if INET6
        case AF_INET6:
@@ -299,7 +296,6 @@ pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
                default:
                        return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6));
                }
-               break;
 #endif /* INET6 */
        default:
                return (0);
@@ -419,8 +415,8 @@ pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
        if (kif->pfik_ifp != NULL)
                pfi_instance_add(kif->pfik_ifp, net, flags);
 
-       if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2,
-           NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
+       if ((e = pfr_set_addrs(&kt->pfrkt_t, CAST_USER_ADDR_T(pfi_buffer),
+           pfi_buffer_cnt, &size2, NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
                printf("pfi_table_update: cannot set %d new addresses "
                    "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
 }
@@ -436,28 +432,45 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags)
                return;
        ifnet_lock_shared(ifp);
        TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
-               if (ia->ifa_addr == NULL)
+               IFA_LOCK(ia);
+               if (ia->ifa_addr == NULL) {
+                       IFA_UNLOCK(ia);
                        continue;
+               }
                af = ia->ifa_addr->sa_family;
-               if (af != AF_INET && af != AF_INET6)
+               if (af != AF_INET && af != AF_INET6) {
+                       IFA_UNLOCK(ia);
                        continue;
-               if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6)
+               }
+               if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6) {
+                       IFA_UNLOCK(ia);
                        continue;
+               }
                if ((flags & PFI_AFLAG_BROADCAST) &&
-                   !(ifp->if_flags & IFF_BROADCAST))
+                   !(ifp->if_flags & IFF_BROADCAST)) {
+                       IFA_UNLOCK(ia);
                        continue;
+               }
                if ((flags & PFI_AFLAG_PEER) &&
-                   !(ifp->if_flags & IFF_POINTOPOINT))
+                   !(ifp->if_flags & IFF_POINTOPOINT)) {
+                       IFA_UNLOCK(ia);
                        continue;
+               }
                if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 &&
-                   IN6_IS_ADDR_LINKLOCAL(
-                   &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr))
+                   IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
+                   (void *)ia->ifa_addr)->sin6_addr)) {
+                       IFA_UNLOCK(ia);
                        continue;
+               }
                if (flags & PFI_AFLAG_NOALIAS) {
-                       if (af == AF_INET && got4)
+                       if (af == AF_INET && got4) {
+                               IFA_UNLOCK(ia);
                                continue;
-                       if (af == AF_INET6 && got6)
+                       }
+                       if (af == AF_INET6 && got6) {
+                               IFA_UNLOCK(ia);
                                continue;
+                       }
                }
                if (af == AF_INET)
                        got4 = 1;
@@ -467,10 +480,10 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags)
                if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) {
                        if (af == AF_INET)
                                net2 = pfi_unmask(&((struct sockaddr_in *)
-                                   ia->ifa_netmask)->sin_addr);
+                                   (void *)ia->ifa_netmask)->sin_addr);
                        else if (af == AF_INET6)
                                net2 = pfi_unmask(&((struct sockaddr_in6 *)
-                                   ia->ifa_netmask)->sin6_addr);
+                                   (void *)ia->ifa_netmask)->sin6_addr);
                }
                if (af == AF_INET && net2 > 32)
                        net2 = 32;
@@ -480,6 +493,7 @@ pfi_instance_add(struct ifnet *ifp, int net, int flags)
                        pfi_address_add(ia->ifa_dstaddr, af, net2);
                else
                        pfi_address_add(ia->ifa_addr, af, net2);
+               IFA_UNLOCK(ia);
        }
        ifnet_lock_done(ifp);
 }
@@ -518,9 +532,10 @@ pfi_address_add(struct sockaddr *sa, int af, int net)
        p->pfra_af = af;
        p->pfra_net = net;
        if (af == AF_INET)
-               p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr;
+               p->pfra_ip4addr = ((struct sockaddr_in *)(void *)sa)->sin_addr;
        else if (af == AF_INET6) {
-               p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
+               p->pfra_ip6addr =
+                   ((struct sockaddr_in6 *)(void *)sa)->sin6_addr;
                if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr))
                        p->pfra_ip6addr.s6_addr16[1] = 0;
        }
@@ -583,34 +598,33 @@ pfi_update_status(const char *name, struct pf_status *pfs)
        lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
 
        strlcpy(key.pfik_name, name, sizeof (key.pfik_name));
-       p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key);
+       p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)(void *)&key);
        if (p == NULL)
                return;
 
-       if (pfs) {
+       if (pfs != NULL) {
                bzero(pfs->pcounters, sizeof (pfs->pcounters));
                bzero(pfs->bcounters, sizeof (pfs->bcounters));
-       }
-       /* just clear statistics */
-       if (pfs == NULL) {
+               for (i = 0; i < 2; i++)
+                       for (j = 0; j < 2; j++)
+                               for (k = 0; k < 2; k++) {
+                                       pfs->pcounters[i][j][k] +=
+                                               p->pfik_packets[i][j][k];
+                                       pfs->bcounters[i][j] +=
+                                               p->pfik_bytes[i][j][k];
+                               }
+       } else {
+               /* just clear statistics */
                bzero(p->pfik_packets, sizeof (p->pfik_packets));
                bzero(p->pfik_bytes, sizeof (p->pfik_bytes));
-               p->pfik_tzero = pf_time_second();
+               p->pfik_tzero = pf_calendar_time_second();
        }
-       for (i = 0; i < 2; i++)
-               for (j = 0; j < 2; j++)
-                       for (k = 0; k < 2; k++) {
-                               pfs->pcounters[i][j][k] +=
-                                   p->pfik_packets[i][j][k];
-                               pfs->bcounters[i][j] +=
-                                   p->pfik_bytes[i][j][k];
-                       }
 }
 
 int
-pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
+pfi_get_ifaces(const char *name, user_addr_t buf, int *size)
 {
-       struct pfi_kif  *p, *nextp;
+       struct pfi_kif   *p, *nextp;
        int              n = 0;
 
        lck_mtx_assert(pf_lock, LCK_MTX_ASSERT_OWNED);
@@ -620,14 +634,29 @@ pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
                if (pfi_skip_if(name, p))
                        continue;
                if (*size > n++) {
+                       struct pfi_uif u;
+
                        if (!p->pfik_tzero)
-                               p->pfik_tzero = pf_time_second();
+                               p->pfik_tzero = pf_calendar_time_second();
                        pfi_kif_ref(p, PFI_KIF_REF_RULE);
-                       buf++;
-                       if (copyout(p, CAST_USER_ADDR_T(buf), sizeof (*buf))) {
+
+                       /* return the user space version of pfi_kif */
+                       bzero(&u, sizeof (u));
+                       bcopy(p->pfik_name, &u.pfik_name, sizeof (u.pfik_name));
+                       bcopy(p->pfik_packets, &u.pfik_packets,
+                           sizeof (u.pfik_packets));
+                       bcopy(p->pfik_bytes, &u.pfik_bytes,
+                           sizeof (u.pfik_bytes));
+                       u.pfik_tzero = p->pfik_tzero;
+                       u.pfik_flags = p->pfik_flags;
+                       u.pfik_states = p->pfik_states;
+                       u.pfik_rules = p->pfik_rules;
+
+                       if (copyout(&u, buf, sizeof (u))) {
                                pfi_kif_unref(p, PFI_KIF_REF_RULE);
                                return (EFAULT);
                        }
+                       buf += sizeof (u);
                        nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
                        pfi_kif_unref(p, PFI_KIF_REF_RULE);
                }