]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/in_pcblist.c
xnu-3248.40.184.tar.gz
[apple/xnu.git] / bsd / netinet / in_pcblist.c
index 4df416c6aac9558ab00a40df5eb4ca62c5366fbf..e54d8b996cc276a23c52c261d6434a2afc08d0b5 100644 (file)
@@ -245,8 +245,8 @@ tcpcb_to_xtcpcb_n(struct tcpcb *tp, struct xtcpcb_n *xt)
        xt->ts_recent = tp->ts_recent;
        xt->ts_recent_age = tp->ts_recent_age;
        xt->last_ack_sent = tp->last_ack_sent;
-       xt->cc_send = tp->cc_send;
-       xt->cc_recv = tp->cc_recv;
+       xt->cc_send = 0;
+       xt->cc_recv = 0;
        xt->snd_recover = tp->snd_recover;
        xt->snd_cwnd_prev = tp->snd_cwnd_prev;
        xt->snd_ssthresh_prev = tp->snd_ssthresh_prev;
@@ -401,21 +401,30 @@ inpcb_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags,
        struct socket *so;
        inp_gen_t gencnt;
        bool iswildcard, wildcardok, nowakeok;
+       bool recvanyifonly, extbgidleok;
+       bool activeonly;
 
        wildcardok = ((flags & INPCB_GET_PORTS_USED_WILDCARDOK) != 0);
        nowakeok = ((flags & INPCB_GET_PORTS_USED_NOWAKEUPOK) != 0);
+       recvanyifonly = ((flags & INPCB_GET_PORTS_USED_RECVANYIFONLY) != 0);
+       extbgidleok = ((flags & INPCB_GET_PORTS_USED_EXTBGIDLEONLY) != 0);
+       activeonly = ((flags & INPCB_GET_PORTS_USED_ACTIVEONLY) != 0);
+
        lck_rw_lock_shared(pcbinfo->ipi_lock);
        gencnt = pcbinfo->ipi_gencnt;
+
        for (inp = LIST_FIRST(pcbinfo->ipi_listhead); inp;
            inp = LIST_NEXT(inp, inp_list)) {
                uint16_t port;
 
                if (inp->inp_gencnt > gencnt ||
-                   inp->inp_state == INPCB_STATE_DEAD)
+                   inp->inp_state == INPCB_STATE_DEAD ||
+                   inp->inp_wantcnt == WNT_STOPUSING)
                        continue;
 
                if ((so = inp->inp_socket) == NULL ||
-                   (so->so_state & SS_DEFUNCT))
+                   (so->so_state & SS_DEFUNCT) ||
+                   (so->so_state & SS_ISDISCONNECTED))
                        continue;
 
                if (!(protocol == PF_UNSPEC ||
@@ -435,12 +444,71 @@ inpcb_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags,
                        !nowakeok)
                        continue;
 
+               if (!(inp->inp_flags & INP_RECV_ANYIF) &&
+                       recvanyifonly)
+                       continue;
+
+               if (!(so->so_flags1 & SOF1_EXTEND_BK_IDLE_WANTED) &&
+                       extbgidleok)
+                       continue;
+
                if (!iswildcard &&
                    !(ifindex == 0 || inp->inp_last_outifp == NULL ||
                    ifindex == inp->inp_last_outifp->if_index))
                        continue;
 
+               if (SOCK_PROTO(inp->inp_socket) == IPPROTO_UDP &&
+                   so->so_state & SS_CANTRCVMORE)
+                       continue;
+
+               if (SOCK_PROTO(inp->inp_socket) == IPPROTO_TCP) {
+                       struct  tcpcb *tp = sototcpcb(inp->inp_socket);
+
+                       /*
+                        * Workaround race where inp_ppcb is NULL during
+                        * socket initialization
+                        */
+                       if (tp == NULL)
+                               continue;
+
+                       switch (tp->t_state) {
+                               case TCPS_CLOSED:
+                                       continue;
+                                       /* NOT REACHED */
+                               case TCPS_LISTEN:
+                               case TCPS_SYN_SENT:
+                               case TCPS_SYN_RECEIVED:
+                               case TCPS_ESTABLISHED:
+                               case TCPS_FIN_WAIT_1:
+                                       /*
+                                        * Note: FIN_WAIT_1 is an active state
+                                        * because we need our FIN to be
+                                        * acknowledged
+                                        */
+                                       break;
+                               case TCPS_CLOSE_WAIT:
+                               case TCPS_CLOSING:
+                               case TCPS_LAST_ACK:
+                               case TCPS_FIN_WAIT_2:
+                                       /*
+                                        * In the closing states, the connection
+                                        * is not idle when there is outgoing
+                                        * data having to be acknowledged
+                                        */
+                                       if (activeonly && so->so_snd.sb_cc == 0)
+                                               continue;
+                                       break;
+                               case TCPS_TIME_WAIT:
+                                       continue;
+                                       /* NOT REACHED */
+                       }
+               }
+               /*
+                * Final safeguard to exclude unspecified local port
+                */
                port = ntohs(inp->inp_lport);
+               if (port == 0)
+                       continue;
                bit_set(bitfield, port);
        }
        lck_rw_done(pcbinfo->ipi_lock);