]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/ip_divert.c
xnu-2050.7.9.tar.gz
[apple/xnu.git] / bsd / netinet / ip_divert.c
index f5db5922a0434739d60fce23fd33b3e3032a673e..1af24caecc1e79be52ba72a02df81e4161e8b694 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -236,12 +236,14 @@ divert_packet(struct mbuf *m, int incoming, int port, int rule)
                /* Find IP address for receive interface */
                ifnet_lock_shared(m->m_pkthdr.rcvif);
                TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) {
-                       if (ifa->ifa_addr == NULL)
-                               continue;
-                       if (ifa->ifa_addr->sa_family != AF_INET)
+                       IFA_LOCK(ifa);
+                       if (ifa->ifa_addr->sa_family != AF_INET) {
+                               IFA_UNLOCK(ifa);
                                continue;
+                       }
                        divsrc.sin_addr =
-                           ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
+                           ((struct sockaddr_in *)(void *) ifa->ifa_addr)->sin_addr;
+                       IFA_UNLOCK(ifa);
                        break;
                }
                ifnet_lock_done(m->m_pkthdr.rcvif);
@@ -312,12 +314,15 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr,
 {
        struct inpcb *const inp = sotoinpcb(so);
        struct ip *const ip = mtod(m, struct ip *);
-       struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+       struct sockaddr_in *sin = (struct sockaddr_in *)(void *)addr;
        int error = 0;
+       mbuf_svc_class_t msc = MBUF_SC_UNSPEC;
 
-       if (control)
-               m_freem(control);               /* XXX */
+       if (control != NULL) {
+               msc = mbuf_service_class_from_control(control);
 
+               m_freem(control);               /* XXX */
+       }
        /* Loopback avoidance and state recovery */
        if (sin) {
                struct m_tag *mtag;
@@ -325,8 +330,8 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr,
                int     len = 0;
                char    *c = sin->sin_zero;
 
-               mtag = m_tag_alloc(KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_DIVERT,
-                               sizeof(struct divert_tag), M_NOWAIT);
+               mtag = m_tag_create(KERNEL_MODULE_TAG_ID, KERNEL_TAG_TYPE_DIVERT,
+                               sizeof(struct divert_tag), M_NOWAIT, m);
                if (mtag == NULL) {
                        error = ENOBUFS;
                        goto cantsend;
@@ -352,8 +357,10 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr,
 
        /* Reinject packet into the system as incoming or outgoing */
        if (!sin || sin->sin_addr.s_addr == 0) {
-               struct ip_out_args ipoa = { IFSCOPE_NONE };
+               struct ip_out_args ipoa =
+                   { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF };
                struct route ro;
+               struct ip_moptions *imo;
 
                /*
                 * Don't allow both user specified and setsockopt options,
@@ -375,11 +382,11 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr,
                /* Copy the cached route and take an extra reference */
                inp_route_copyout(inp, &ro);
 
-#if PKT_PRIORITY
-               if (soisbackground(so))
-                       m_prio_background(m);
-#endif /* PKT_PRIORITY */
+               set_packet_service_class(m, so, msc, 0);
 
+               imo = inp->inp_moptions;
+               if (imo != NULL)
+                       IMO_ADDREF(imo);
                socket_unlock(so, 0);
 #if CONFIG_MACF_NET
                mac_mbuf_label_associate_inpcb(inp, m);
@@ -388,9 +395,11 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr,
                error = ip_output(m, inp->inp_options, &ro,
                        (so->so_options & SO_DONTROUTE) |
                        IP_ALLOWBROADCAST | IP_RAWOUTPUT | IP_OUTARGS,
-                       inp->inp_moptions, &ipoa);
+                       imo, &ipoa);
 
                socket_lock(so, 0);
+               if (imo != NULL)
+                       IMO_REMREF(imo);
                /* Synchronize cached PCB route */
                inp_route_copyin(inp, &ro);
        } else {
@@ -411,7 +420,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr *addr,
                                goto cantsend;
                        }
                        m->m_pkthdr.rcvif = ifa->ifa_ifp;
-                       ifafree(ifa);
+                       IFA_REMREF(ifa);
                }
 #if CONFIG_MACF_NET
                mac_mbuf_label_associate_socket(so, m);
@@ -456,7 +465,7 @@ div_attach(struct socket *so, int proto, struct proc *p)
 
 #ifdef MORE_DICVLOCK_DEBUG
        printf("div_attach: so=%p sopcb=%p lock=%x ref=%x\n",
-                       so, so->so_pcb, ((struct inpcb *)so->so_pcb)->inpcb_mtx, so->so_usecount);
+                       so, so->so_pcb, &(((struct inpcb *)so->so_pcb)->inpcb_mtx), so->so_usecount);
 #endif
        return 0;
 }
@@ -468,7 +477,7 @@ div_detach(struct socket *so)
 
 #ifdef MORE_DICVLOCK_DEBUG
        printf("div_detach: so=%p sopcb=%p lock=%x ref=%x\n",
-                       so, so->so_pcb, ((struct inpcb *)so->so_pcb)->inpcb_mtx, so->so_usecount);
+                       so, so->so_pcb, &(((struct inpcb *)so->so_pcb)->inpcb_mtx), so->so_usecount);
 #endif
        inp = sotoinpcb(so);
        if (inp == 0)
@@ -510,7 +519,7 @@ div_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
        if (nam->sa_family != AF_INET) {
                error = EAFNOSUPPORT;
        } else {
-               ((struct sockaddr_in *)nam)->sin_addr.s_addr = INADDR_ANY;
+               ((struct sockaddr_in *)(void *)nam)->sin_addr.s_addr = INADDR_ANY;
                error = in_pcbbind(inp, nam, p);
        }
        return error;
@@ -650,11 +659,11 @@ div_lock(struct socket *so, int refcount, void *lr)
 #ifdef MORE_DICVLOCK_DEBUG
        printf("div_lock: so=%p sopcb=%p lock=%p ref=%x lr=%p\n",
            so, so->so_pcb, so->so_pcb ?
-           ((struct inpcb *)so->so_pcb)->inpcb_mtx : NULL,
+           &(((struct inpcb *)so->so_pcb)->inpcb_mtx) : NULL,
            so->so_usecount, lr_saved);
 #endif
        if (so->so_pcb) {
-               lck_mtx_lock(((struct inpcb *)so->so_pcb)->inpcb_mtx);
+               lck_mtx_lock(&((struct inpcb *)so->so_pcb)->inpcb_mtx);
        } else  {
                panic("div_lock: so=%p NO PCB! lr=%p lrh= lrh= %s\n", 
                    so, lr_saved, solockhistory_nr(so));
@@ -691,7 +700,7 @@ div_unlock(struct socket *so, int refcount, void *lr)
 #ifdef MORE_DICVLOCK_DEBUG
        printf("div_unlock: so=%p sopcb=%p lock=%p ref=%x lr=%p\n",
            so, so->so_pcb, so->so_pcb ?
-           ((struct inpcb *)so->so_pcb)->inpcb_mtx : NULL,
+           &(((struct inpcb *)so->so_pcb)->inpcb_mtx) : NULL,
            so->so_usecount, lr_saved);
 #endif
        if (refcount)
@@ -707,7 +716,7 @@ div_unlock(struct socket *so, int refcount, void *lr)
                    so, so->so_usecount, lr_saved, solockhistory_nr(so));
                /* NOTREACHED */
        }
-       mutex_held = ((struct inpcb *)so->so_pcb)->inpcb_mtx;
+       mutex_held = &((struct inpcb *)so->so_pcb)->inpcb_mtx;
 
        if (so->so_usecount == 0 && (inp->inp_wantcnt == WNT_STOPUSING)) {
                lck_rw_lock_exclusive(divcbinfo.mtx);
@@ -733,7 +742,7 @@ div_getlock(struct socket *so, __unused int locktype)
                if (so->so_usecount < 0)
                        panic("div_getlock: so=%p usecount=%x lrh= %s\n", 
                            so, so->so_usecount, solockhistory_nr(so));
-               return(inpcb->inpcb_mtx);
+               return(&inpcb->inpcb_mtx);
        } else {
                panic("div_getlock: so=%p NULL NO PCB lrh= %s\n", 
                    so, solockhistory_nr(so));