/ duct-tape / xnu / bsd / netinet / in_pcb.h
in_pcb.h
  1  /*
  2   * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
  3   *
  4   * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  5   *
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. The rights granted to you under the License
 10   * may not be used to create, or enable the creation or redistribution of,
 11   * unlawful or unlicensed copies of an Apple operating system, or to
 12   * circumvent, violate, or enable the circumvention or violation of, any
 13   * terms of an Apple operating system software license agreement.
 14   *
 15   * Please obtain a copy of the License at
 16   * http://www.opensource.apple.com/apsl/ and read it before using this file.
 17   *
 18   * The Original Code and all software distributed under the License are
 19   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 20   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 21   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 22   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 23   * Please see the License for the specific language governing rights and
 24   * limitations under the License.
 25   *
 26   * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 27   */
 28  /*
 29   * Copyright (c) 1982, 1986, 1990, 1993
 30   *	The Regents of the University of California.  All rights reserved.
 31   *
 32   * Redistribution and use in source and binary forms, with or without
 33   * modification, are permitted provided that the following conditions
 34   * are met:
 35   * 1. Redistributions of source code must retain the above copyright
 36   *    notice, this list of conditions and the following disclaimer.
 37   * 2. Redistributions in binary form must reproduce the above copyright
 38   *    notice, this list of conditions and the following disclaimer in the
 39   *    documentation and/or other materials provided with the distribution.
 40   * 3. All advertising materials mentioning features or use of this software
 41   *    must display the following acknowledgement:
 42   *	This product includes software developed by the University of
 43   *	California, Berkeley and its contributors.
 44   * 4. Neither the name of the University nor the names of its contributors
 45   *    may be used to endorse or promote products derived from this software
 46   *    without specific prior written permission.
 47   *
 48   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 49   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 50   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 51   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 52   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 53   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 54   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 55   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 56   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 57   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 58   * SUCH DAMAGE.
 59   *
 60   *	@(#)in_pcb.h	8.1 (Berkeley) 6/10/93
 61   * $FreeBSD: src/sys/netinet/in_pcb.h,v 1.32.2.4 2001/08/13 16:26:17 ume Exp $
 62   */
 63  /*
 64   * NOTICE: This file was modified by SPARTA, Inc. in 2007 to introduce
 65   * support for mandatory and extensible security protections.  This notice
 66   * is included in support of clause 2.2 (b) of the Apple Public License,
 67   * Version 2.0.
 68   */
 69  
 70  #ifndef _NETINET_IN_PCB_H_
 71  #define _NETINET_IN_PCB_H_
 72  #include <sys/appleapiopts.h>
 73  
 74  #include <sys/types.h>
 75  #include <sys/queue.h>
 76  #ifdef BSD_KERNEL_PRIVATE
 77  #include <sys/bitstring.h>
 78  #include <sys/tree.h>
 79  #include <kern/locks.h>
 80  #include <kern/zalloc.h>
 81  #include <netinet/in_stat.h>
 82  #endif /* BSD_KERNEL_PRIVATE */
 83  #if !KERNEL
 84  #include <TargetConditionals.h>
 85  #endif
 86  
 87  #if IPSEC
 88  #include <netinet6/ipsec.h> /* for IPSEC */
 89  #endif /* IPSEC */
 90  
 91  #if NECP
 92  #include <net/necp.h>
 93  #endif
 94  
 95  
 96  #ifdef BSD_KERNEL_PRIVATE
 97  /*
 98   * struct inpcb is the common protocol control block structure used in most
 99   * IP transport protocols.
100   *
101   * Pointers to local and foreign host table entries, local and foreign socket
102   * numbers, and pointers up (to a socket structure) and down (to a
103   * protocol-specific control block) are stored here.
104   */
105  LIST_HEAD(inpcbhead, inpcb);
106  LIST_HEAD(inpcbporthead, inpcbport);
107  #endif /* BSD_KERNEL_PRIVATE */
108  typedef u_quad_t        inp_gen_t;
109  
110  /*
111   * PCB with AF_INET6 null bind'ed laddr can receive AF_INET input packet.
112   * So, AF_INET6 null laddr is also used as AF_INET null laddr, by utilizing
113   * the following structure.
114   */
115  struct in_addr_4in6 {
116  	u_int32_t       ia46_pad32[3];
117  	struct  in_addr ia46_addr4;
118  };
119  
120  #ifdef BSD_KERNEL_PRIVATE
121  /*
122   * NB: the zone allocator is type-stable EXCEPT FOR THE FIRST TWO LONGS
123   * of the structure.  Therefore, it is important that the members in
124   * that position not contain any information which is required to be
125   * stable.
126   */
127  struct  icmp6_filter;
128  struct ifnet;
129  
130  struct inp_stat {
131  	u_int64_t       rxpackets;
132  	u_int64_t       rxbytes;
133  	u_int64_t       txpackets;
134  	u_int64_t       txbytes;
135  };
136  
137  /*
138   * struct inpcb captures the network layer state for TCP, UDP and raw IPv6
139   * and IPv6 sockets.  In the case of TCP, further per-connection state is
140   * hung off of inp_ppcb most of the time.
141   */
142  struct inpcb {
143  	decl_lck_mtx_data(, inpcb_mtx); /* inpcb per-socket mutex */
144  	LIST_ENTRY(inpcb) inp_hash;     /* hash list */
145  	LIST_ENTRY(inpcb) inp_list;     /* list for all PCBs of this proto */
146  	void    *inp_ppcb;              /* pointer to per-protocol pcb */
147  	struct inpcbinfo *inp_pcbinfo;  /* PCB list info */
148  	struct socket *inp_socket;      /* back pointer to socket */
149  	LIST_ENTRY(inpcb) inp_portlist; /* list for this PCB's local port */
150  	RB_ENTRY(inpcb) infc_link;      /* link for flowhash RB tree */
151  	struct inpcbport *inp_phd;      /* head of this list */
152  	inp_gen_t inp_gencnt;           /* generation count of this instance */
153  	int     inp_hash_element;       /* array index of pcb's hash list */
154  	int     inp_wantcnt;            /* wanted count; atomically updated */
155  	int     inp_state;              /* state (INUSE/CACHED/DEAD) */
156  	u_short inp_fport;              /* foreign port */
157  	u_short inp_lport;              /* local port */
158  	u_int32_t inp_flags;            /* generic IP/datagram flags */
159  	u_int32_t inp_flags2;           /* generic IP/datagram flags #2 */
160  	u_int32_t inp_flow;             /* IPv6 flow information */
161  
162  	u_char  inp_sndinprog_cnt;      /* outstanding send operations */
163  	uint32_t inp_sndingprog_waiters;/* waiters for outstanding send */
164  	u_char  inp_vflag;              /* INP_IPV4 or INP_IPV6 */
165  
166  	u_char inp_ip_ttl;              /* time to live proto */
167  	u_char inp_ip_p;                /* protocol proto */
168  
169  	struct ifnet *inp_boundifp;     /* interface for INP_BOUND_IF */
170  	struct ifnet *inp_last_outifp;  /* last known outgoing interface */
171  	u_int32_t inp_flowhash;         /* flow hash */
172  
173  	/* Protocol-dependent part */
174  	union {
175  		/* foreign host table entry */
176  		struct in_addr_4in6 inp46_foreign;
177  		struct in6_addr inp6_foreign;
178  	} inp_dependfaddr;
179  	union {
180  		/* local host table entry */
181  		struct in_addr_4in6 inp46_local;
182  		struct in6_addr inp6_local;
183  	} inp_dependladdr;
184  	union {
185  		/* placeholder for routing entry */
186  		struct route inp4_route;
187  		struct route_in6 inp6_route;
188  	} inp_dependroute;
189  	struct {
190  		/* type of service proto */
191  		u_char inp4_ip_tos;
192  		/* IP options */
193  		struct mbuf *inp4_options;
194  		/* IP multicast options */
195  		struct ip_moptions *inp4_moptions;
196  	} inp_depend4;
197  	struct {
198  		/* IP options */
199  		struct mbuf *inp6_options;
200  		/* IP6 options for outgoing packets */
201  		struct  ip6_pktopts *inp6_outputopts;
202  		/* IP multicast options */
203  		struct  ip6_moptions *inp6_moptions;
204  		/* ICMPv6 code type filter */
205  		struct  icmp6_filter *inp6_icmp6filt;
206  		/* IPV6_CHECKSUM setsockopt */
207  		int     inp6_cksum;
208  		short   inp6_hops;
209  	} inp_depend6;
210  
211  	caddr_t inp_saved_ppcb;         /* place to save pointer while cached */
212  #if IPSEC
213  	struct inpcbpolicy *inp_sp;     /* for IPsec */
214  #endif /* IPSEC */
215  #if NECP
216  	struct {
217  		char *inp_domain;
218  		char *inp_account;
219  	} inp_necp_attributes;
220  	struct necp_inpcb_result inp_policyresult;
221  	uuid_t necp_client_uuid;
222  	necp_client_flow_cb necp_cb;
223  #endif
224  	u_char *inp_keepalive_data;     /* for keepalive offload */
225  	u_int8_t inp_keepalive_datalen; /* keepalive data length */
226  	u_int8_t inp_keepalive_type;    /* type of application */
227  	u_int16_t inp_keepalive_interval; /* keepalive interval */
228  	uint32_t inp_nstat_refcnt __attribute__((aligned(4)));
229  	struct inp_stat *inp_stat;
230  	struct inp_stat *inp_cstat;     /* cellular data */
231  	struct inp_stat *inp_wstat;     /* Wi-Fi data */
232  	struct inp_stat *inp_Wstat;     /* Wired data */
233  	u_int8_t inp_stat_store[sizeof(struct inp_stat) + sizeof(u_int64_t)];
234  	u_int8_t inp_cstat_store[sizeof(struct inp_stat) + sizeof(u_int64_t)];
235  	u_int8_t inp_wstat_store[sizeof(struct inp_stat) + sizeof(u_int64_t)];
236  	u_int8_t inp_Wstat_store[sizeof(struct inp_stat) + sizeof(u_int64_t)];
237  	activity_bitmap_t inp_nw_activity;
238  	u_int64_t inp_start_timestamp;
239  
240  	char inp_last_proc_name[MAXCOMLEN + 1];
241  	char inp_e_proc_name[MAXCOMLEN + 1];
242  };
243  
244  #define INP_ADD_STAT(_inp, _cnt_cellular, _cnt_wifi, _cnt_wired, _a, _n) \
245  do {                                                                    \
246  	locked_add_64(&((_inp)->inp_stat->_a), (_n));                   \
247  	if (_cnt_cellular)                                              \
248  	        locked_add_64(&((_inp)->inp_cstat->_a), (_n));          \
249  	if (_cnt_wifi)                                                  \
250  	        locked_add_64(&((_inp)->inp_wstat->_a), (_n));          \
251  	if (_cnt_wired)                                                 \
252  	        locked_add_64(&((_inp)->inp_Wstat->_a), (_n));          \
253  } while (0);
254  #endif /* BSD_KERNEL_PRIVATE */
255  
256  /*
257   * Interface exported to userland by various protocols which use
258   * inpcbs.  Hack alert -- only define if struct xsocket is in scope.
259   */
260  #pragma pack(4)
261  
262  #if defined(__LP64__)
263  struct _inpcb_list_entry {
264  	u_int32_t   le_next;
265  	u_int32_t   le_prev;
266  };
267  #define _INPCB_PTR(x)           u_int32_t
268  #define _INPCB_LIST_ENTRY(x)    struct _inpcb_list_entry
269  #else /* !__LP64__ */
270  #define _INPCB_PTR(x)           x
271  #define _INPCB_LIST_ENTRY(x)    LIST_ENTRY(x)
272  #endif /* !__LP64__ */
273  
274  #ifdef XNU_KERNEL_PRIVATE
275  /*
276   * This is a copy of the inpcb as it shipped in Panther. This structure
277   * is filled out in a copy function. This allows the inpcb to change
278   * without breaking userland tools.
279   *
280   * CAUTION: Many fields may not be filled out. Fewer may be filled out
281   * in the future. Code defensively.
282   */
283  struct inpcb_compat {
284  #else
285  struct inpcbinfo;
286  struct inpcbport;
287  struct mbuf;
288  struct ip6_pktopts;
289  struct ip6_moptions;
290  struct icmp6_filter;
291  struct inpcbpolicy;
292  
293  struct inpcb {
294  #endif /* KERNEL_PRIVATE */
295  	_INPCB_LIST_ENTRY(inpcb) inp_hash;      /* hash list */
296  	struct in_addr reserved1;               /* reserved */
297  	struct in_addr reserved2;               /* reserved */
298  	u_short inp_fport;                      /* foreign port */
299  	u_short inp_lport;                      /* local port */
300  	_INPCB_LIST_ENTRY(inpcb) inp_list;      /* list for all peer PCBs */
301  	_INPCB_PTR(caddr_t) inp_ppcb;           /* per-protocol pcb */
302  	_INPCB_PTR(struct inpcbinfo *) inp_pcbinfo;     /* PCB list info */
303  	_INPCB_PTR(void *) inp_socket;  /* back pointer to socket */
304  	u_char nat_owner;               /* Used to NAT TCP/UDP traffic */
305  	u_int32_t nat_cookie;           /* Cookie stored and returned to NAT */
306  	_INPCB_LIST_ENTRY(inpcb) inp_portlist;  /* this PCB's local port list */
307  	_INPCB_PTR(struct inpcbport *) inp_phd; /* head of this list */
308  	inp_gen_t inp_gencnt;           /* generation count of this instance */
309  	int inp_flags;                  /* generic IP/datagram flags */
310  	u_int32_t inp_flow;
311  
312  	u_char inp_vflag;
313  
314  	u_char inp_ip_ttl;              /* time to live proto */
315  	u_char inp_ip_p;                /* protocol proto */
316  	/* protocol dependent part */
317  	union {
318  		/* foreign host table entry */
319  		struct in_addr_4in6 inp46_foreign;
320  		struct in6_addr inp6_foreign;
321  	} inp_dependfaddr;
322  	union {
323  		/* local host table entry */
324  		struct in_addr_4in6 inp46_local;
325  		struct in6_addr inp6_local;
326  	} inp_dependladdr;
327  	union {
328  		/* placeholder for routing entry */
329  		u_char inp4_route[20];
330  		u_char inp6_route[32];
331  	} inp_dependroute;
332  	struct {
333  		/* type of service proto */
334  		u_char inp4_ip_tos;
335  		/* IP options */
336  		_INPCB_PTR(struct mbuf *) inp4_options;
337  		/* IP multicast options */
338  		_INPCB_PTR(struct ip_moptions *) inp4_moptions;
339  	} inp_depend4;
340  
341  	struct {
342  		/* IP options */
343  		_INPCB_PTR(struct mbuf *) inp6_options;
344  		u_int8_t inp6_hlim;
345  		u_int8_t unused_uint8_1;
346  		ushort unused_uint16_1;
347  		/* IP6 options for outgoing packets */
348  		_INPCB_PTR(struct ip6_pktopts *) inp6_outputopts;
349  		/* IP multicast options */
350  		_INPCB_PTR(struct ip6_moptions *) inp6_moptions;
351  		/* ICMPv6 code type filter */
352  		_INPCB_PTR(struct icmp6_filter *) inp6_icmp6filt;
353  		/* IPV6_CHECKSUM setsockopt */
354  		int     inp6_cksum;
355  		u_short inp6_ifindex;
356  		short   inp6_hops;
357  	} inp_depend6;
358  
359  	int hash_element;               /* Array index of pcb's hash list */
360  	_INPCB_PTR(caddr_t) inp_saved_ppcb; /* pointer while cached */
361  	_INPCB_PTR(struct inpcbpolicy *) inp_sp;
362  	u_int32_t       reserved[3];    /* reserved */
363  };
364  
365  struct  xinpcb {
366  	u_int32_t       xi_len;         /* length of this structure */
367  #ifdef XNU_KERNEL_PRIVATE
368  	struct  inpcb_compat xi_inp;
369  #else
370  	struct  inpcb xi_inp;
371  #endif
372  	struct  xsocket xi_socket;
373  	u_quad_t        xi_alignment_hack;
374  };
375  
376  #if XNU_TARGET_OS_OSX || KERNEL || !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
377  struct inpcb64_list_entry {
378  	u_int64_t   le_next;
379  	u_int64_t   le_prev;
380  };
381  
382  struct  xinpcb64 {
383  	u_int64_t       xi_len;         /* length of this structure */
384  	u_int64_t       xi_inpp;
385  	u_short         inp_fport;      /* foreign port */
386  	u_short         inp_lport;      /* local port */
387  	struct inpcb64_list_entry inp_list; /* list for all PCBs */
388  	u_int64_t       inp_ppcb;       /* ptr to per-protocol PCB */
389  	u_int64_t       inp_pcbinfo;    /* PCB list info */
390  	struct inpcb64_list_entry inp_portlist; /* this PCB's local port list */
391  	u_int64_t       inp_phd;        /* head of this list */
392  	inp_gen_t       inp_gencnt;     /* current generation count */
393  	int             inp_flags;      /* generic IP/datagram flags */
394  	u_int32_t       inp_flow;
395  	u_char          inp_vflag;
396  	u_char          inp_ip_ttl;     /* time to live */
397  	u_char          inp_ip_p;       /* protocol */
398  	union {                         /* foreign host table entry */
399  		struct  in_addr_4in6    inp46_foreign;
400  		struct  in6_addr        inp6_foreign;
401  	} inp_dependfaddr;
402  	union {                         /* local host table entry */
403  		struct  in_addr_4in6    inp46_local;
404  		struct  in6_addr        inp6_local;
405  	} inp_dependladdr;
406  	struct {
407  		u_char  inp4_ip_tos;    /* type of service */
408  	} inp_depend4;
409  	struct {
410  		u_int8_t inp6_hlim;
411  		int     inp6_cksum;
412  		u_short inp6_ifindex;
413  		short   inp6_hops;
414  	} inp_depend6;
415  	struct  xsocket64 xi_socket;
416  	u_quad_t        xi_alignment_hack;
417  };
418  #endif /* XNU_TARGET_OS_OSX || KERNEL || !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
419  
420  #ifdef PRIVATE
421  struct xinpcb_list_entry {
422  	u_int64_t   le_next;
423  	u_int64_t   le_prev;
424  };
425  
426  struct  xinpcb_n {
427  	u_int32_t       xi_len;         /* length of this structure */
428  	u_int32_t       xi_kind;        /* XSO_INPCB */
429  	u_int64_t       xi_inpp;
430  	u_short         inp_fport;      /* foreign port */
431  	u_short         inp_lport;      /* local port */
432  	u_int64_t       inp_ppcb;       /* pointer to per-protocol pcb */
433  	inp_gen_t       inp_gencnt;     /* generation count of this instance */
434  	int             inp_flags;      /* generic IP/datagram flags */
435  	u_int32_t       inp_flow;
436  	u_char          inp_vflag;
437  	u_char          inp_ip_ttl;     /* time to live */
438  	u_char          inp_ip_p;       /* protocol */
439  	union {                         /* foreign host table entry */
440  		struct in_addr_4in6     inp46_foreign;
441  		struct in6_addr         inp6_foreign;
442  	} inp_dependfaddr;
443  	union {                         /* local host table entry */
444  		struct in_addr_4in6     inp46_local;
445  		struct in6_addr         inp6_local;
446  	} inp_dependladdr;
447  	struct {
448  		u_char  inp4_ip_tos;    /* type of service */
449  	} inp_depend4;
450  	struct {
451  		u_int8_t inp6_hlim;
452  		int     inp6_cksum;
453  		u_short inp6_ifindex;
454  		short   inp6_hops;
455  	} inp_depend6;
456  	u_int32_t               inp_flowhash;
457  	u_int32_t       inp_flags2;
458  };
459  #endif /* PRIVATE */
460  
461  struct  xinpgen {
462  	u_int32_t       xig_len;        /* length of this structure */
463  	u_int           xig_count;      /* number of PCBs at this time */
464  	inp_gen_t       xig_gen;        /* generation count at this time */
465  	so_gen_t        xig_sogen;      /* current socket generation count */
466  };
467  
468  #pragma pack()
469  
470  /*
471   * These defines are for use with the inpcb.
472   */
473  #define INP_IPV4        0x1
474  #define INP_IPV6        0x2
475  #define inp_faddr       inp_dependfaddr.inp46_foreign.ia46_addr4
476  #define inp_laddr       inp_dependladdr.inp46_local.ia46_addr4
477  #define in6p_faddr      inp_dependfaddr.inp6_foreign
478  #define in6p_laddr      inp_dependladdr.inp6_local
479  
480  #ifdef BSD_KERNEL_PRIVATE
481  #define inp_route       inp_dependroute.inp4_route
482  #define inp_ip_tos      inp_depend4.inp4_ip_tos
483  #define inp_options     inp_depend4.inp4_options
484  #define inp_moptions    inp_depend4.inp4_moptions
485  #define in6p_route      inp_dependroute.inp6_route
486  #define in6p_ip6_hlim   inp_depend6.inp6_hlim
487  #define in6p_hops       inp_depend6.inp6_hops   /* default hop limit */
488  #define in6p_ip6_nxt    inp_ip_p
489  #define in6p_vflag      inp_vflag
490  #define in6p_options    inp_depend6.inp6_options
491  #define in6p_outputopts inp_depend6.inp6_outputopts
492  #define in6p_moptions   inp_depend6.inp6_moptions
493  #define in6p_icmp6filt  inp_depend6.inp6_icmp6filt
494  #define in6p_cksum      inp_depend6.inp6_cksum
495  #define in6p_ifindex    inp_depend6.inp6_ifindex
496  #define in6p_flags      inp_flags
497  #define in6p_flags2     inp_flags2
498  #define in6p_socket     inp_socket
499  #define in6p_lport      inp_lport
500  #define in6p_fport      inp_fport
501  #define in6p_ppcb       inp_ppcb
502  #define in6p_state      inp_state
503  #define in6p_wantcnt    inp_wantcnt
504  #define in6p_last_outifp inp_last_outifp
505  #define in6pcb          inpcb
506  #if IPSEC
507  #define in6p_sp         inp_sp
508  #endif /* IPSEC */
509  #define INP_INC_IFNET_STAT(_inp_, _stat_) { \
510  	if ((_inp_)->inp_last_outifp != NULL) { \
511  	        if ((_inp_)->inp_vflag & INP_IPV6) { \
512  	                (_inp_)->inp_last_outifp->if_ipv6_stat->_stat_++;\
513  	        } else { \
514  	                (_inp_)->inp_last_outifp->if_ipv4_stat->_stat_++;\
515  	        }\
516  	}\
517  }
518  
519  struct inpcbport {
520  	LIST_ENTRY(inpcbport) phd_hash;
521  	struct inpcbhead phd_pcblist;
522  	u_short phd_port;
523  };
524  
525  struct intimercount {
526  	u_int32_t intimer_lazy; /* lazy requests for timer scheduling */
527  	u_int32_t intimer_fast; /* fast requests, can be coalesced */
528  	u_int32_t intimer_nodelay; /* fast requests, never coalesced */
529  };
530  
531  typedef void (*inpcb_timer_func_t)(struct inpcbinfo *);
532  
533  /*
534   * Global data structure for each high-level protocol (UDP, TCP, ...) in both
535   * IPv4 and IPv6.  Holds inpcb lists and information for managing them.  Each
536   * pcbinfo is protected by a RW lock: ipi_lock.
537   *
538   * All INPCB pcbinfo entries are linked together via ipi_entry.
539   */
540  struct inpcbinfo {
541  	/*
542  	 * Glue to all PCB infos, as well as garbage collector and
543  	 * timer callbacks, protected by inpcb_lock.  Callout request
544  	 * counts are atomically updated.
545  	 */
546  	TAILQ_ENTRY(inpcbinfo)  ipi_entry;
547  	inpcb_timer_func_t      ipi_gc;
548  	inpcb_timer_func_t      ipi_timer;
549  	struct intimercount     ipi_gc_req;
550  	struct intimercount     ipi_timer_req;
551  
552  	/*
553  	 * Per-protocol lock protecting pcb list, pcb count, etc.
554  	 */
555  	lck_rw_t                *ipi_lock;
556  
557  	/*
558  	 * List and count of pcbs on the protocol.
559  	 */
560  	struct inpcbhead        *ipi_listhead;
561  	uint32_t                ipi_count;
562  
563  	/*
564  	 * Count of pcbs marked with INP2_TIMEWAIT flag.
565  	 */
566  	uint32_t                ipi_twcount;
567  
568  	/*
569  	 * Generation count -- incremented each time a connection is
570  	 * allocated or freed.
571  	 */
572  	uint64_t                ipi_gencnt;
573  
574  	/*
575  	 * Fields associated with port lookup and allocation.
576  	 */
577  	uint16_t                ipi_lastport;
578  	uint16_t                ipi_lastlow;
579  	uint16_t                ipi_lasthi;
580  
581  	/*
582  	 * Zone from which inpcbs are allocated for this protocol.
583  	 */
584  	struct zone             *ipi_zone;
585  
586  	/*
587  	 * Per-protocol hash of pcbs, hashed by local and foreign
588  	 * addresses and port numbers.
589  	 */
590  	struct inpcbhead        *ipi_hashbase;
591  	u_long                  ipi_hashmask;
592  
593  	/*
594  	 * Per-protocol hash of pcbs, hashed by only local port number.
595  	 */
596  	struct inpcbporthead    *ipi_porthashbase;
597  	u_long                  ipi_porthashmask;
598  
599  	/*
600  	 * Misc.
601  	 */
602  	lck_attr_t              *ipi_lock_attr;
603  	lck_grp_t               *ipi_lock_grp;
604  	lck_grp_attr_t          *ipi_lock_grp_attr;
605  
606  #define INPCBINFO_UPDATE_MSS    0x1
607  #define INPCBINFO_HANDLE_LQM_ABORT      0x2
608  	u_int32_t               ipi_flags;
609  };
610  
611  #define INP_PCBHASH(faddr, lport, fport, mask) \
612  	(((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport))) & (mask))
613  #define INP_PCBPORTHASH(lport, mask) \
614  	(ntohs((lport)) & (mask))
615  
616  #define INP_IS_FLOW_CONTROLLED(_inp_) \
617  	((_inp_)->inp_flags & INP_FLOW_CONTROLLED)
618  #define INP_IS_FLOW_SUSPENDED(_inp_) \
619  	(((_inp_)->inp_flags & INP_FLOW_SUSPENDED) ||   \
620  	((_inp_)->inp_socket->so_flags & SOF_SUSPENDED))
621  #define INP_WAIT_FOR_IF_FEEDBACK(_inp_) \
622  	(((_inp_)->inp_flags & (INP_FLOW_CONTROLLED | INP_FLOW_SUSPENDED)) != 0)
623  
624  #define INP_NO_CELLULAR(_inp) \
625  	((_inp)->inp_flags & INP_NO_IFT_CELLULAR)
626  #define INP_NO_EXPENSIVE(_inp) \
627  	((_inp)->inp_flags2 & INP2_NO_IFF_EXPENSIVE)
628  #define INP_NO_CONSTRAINED(_inp) \
629  	((_inp)->inp_flags2 & INP2_NO_IFF_CONSTRAINED)
630  #define INP_AWDL_UNRESTRICTED(_inp) \
631  	((_inp)->inp_flags2 & INP2_AWDL_UNRESTRICTED)
632  #define INP_INTCOPROC_ALLOWED(_inp) \
633  	((_inp)->inp_flags2 & INP2_INTCOPROC_ALLOWED)
634  
635  #endif /* BSD_KERNEL_PRIVATE */
636  
637  /*
638   * Flags for inp_flags.
639   *
640   * Some of these are publicly defined for legacy reasons, as they are
641   * (unfortunately) used by certain applications to determine, at compile
642   * time, whether or not the OS supports certain features.
643   */
644  #ifdef BSD_KERNEL_PRIVATE
645  #define INP_RECVOPTS            0x00000001 /* receive incoming IP options */
646  #define INP_RECVRETOPTS         0x00000002 /* receive IP options for reply */
647  #define INP_RECVDSTADDR         0x00000004 /* receive IP dst address */
648  #define INP_HDRINCL             0x00000008 /* user supplies entire IP header */
649  #define INP_HIGHPORT            0x00000010 /* user wants "high" port binding */
650  #define INP_LOWPORT             0x00000020 /* user wants "low" port binding */
651  #endif /* BSD_KERNEL_PRIVATE */
652  
653  #define INP_ANONPORT            0x00000040 /* port chosen for user */
654  
655  #ifdef BSD_KERNEL_PRIVATE
656  #define INP_RECVIF              0x00000080 /* receive incoming interface */
657  #define INP_MTUDISC             0x00000100 /* unused */
658  #define INP_STRIPHDR            0x00000200 /* strip hdrs in raw_ip (for OT) */
659  #define INP_RECV_ANYIF          0x00000400 /* don't restrict inbound iface */
660  #define INP_INADDR_ANY          0x00000800 /* local address wasn't specified */
661  #define INP_IN6ADDR_ANY         INP_INADDR_ANY
662  #define INP_RECVTTL             0x00001000 /* receive incoming IP TTL */
663  #define INP_UDP_NOCKSUM         0x00002000 /* turn off outbound UDP checksum */
664  #define INP_BOUND_IF            0x00004000 /* bind socket to an interface */
665  #endif /* BSD_KERNEL_PRIVATE */
666  
667  #define IN6P_IPV6_V6ONLY        0x00008000 /* restrict AF_INET6 socket for v6 */
668  
669  #ifdef BSD_KERNEL_PRIVATE
670  #define IN6P_PKTINFO            0x00010000 /* receive IP6 dst and I/F */
671  #define IN6P_HOPLIMIT           0x00020000 /* receive hoplimit */
672  #define IN6P_HOPOPTS            0x00040000 /* receive hop-by-hop options */
673  #define IN6P_DSTOPTS            0x00080000 /* receive dst options after rthdr */
674  #define IN6P_RTHDR              0x00100000 /* receive routing header */
675  #define IN6P_RTHDRDSTOPTS       0x00200000 /* receive dstoptions before rthdr */
676  #define IN6P_TCLASS             0x00400000 /* receive traffic class value */
677  #define INP_RECVTOS             IN6P_TCLASS     /* receive incoming IP TOS */
678  #define IN6P_AUTOFLOWLABEL      0x00800000 /* attach flowlabel automatically */
679  #endif /* BSD_KERNEL_PRIVATE */
680  
681  #define IN6P_BINDV6ONLY         0x01000000 /* do not grab IPv4 traffic */
682  
683  #ifdef BSD_KERNEL_PRIVATE
684  #define IN6P_RFC2292            0x02000000 /* used RFC2292 API on the socket */
685  #define IN6P_MTU                0x04000000 /* receive path MTU for IPv6 */
686  #define INP_PKTINFO             0x08000000 /* rcv and snd PKTINFO for IPv4 */
687  #define INP_FLOW_SUSPENDED      0x10000000 /* flow suspended */
688  #define INP_NO_IFT_CELLULAR     0x20000000 /* do not use cellular interface */
689  #define INP_FLOW_CONTROLLED     0x40000000 /* flow controlled */
690  #define INP_FC_FEEDBACK         0x80000000 /* got interface flow adv feedback */
691  
692  #define INP_CONTROLOPTS \
693  	(INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|INP_RECVIF|INP_RECVTTL| \
694  	INP_PKTINFO|IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|IN6P_DSTOPTS| \
695  	IN6P_RTHDR|IN6P_RTHDRDSTOPTS|IN6P_TCLASS|IN6P_RFC2292|IN6P_MTU)
696  
697  #define INP_UNMAPPABLEOPTS \
698  	(IN6P_HOPOPTS|IN6P_DSTOPTS|IN6P_RTHDR|IN6P_AUTOFLOWLABEL)
699  
700  /*
701   * Flags for inp_flags2.
702   *
703   * Overflowed INP flags; use INP2 prefix to avoid misuse.
704   */
705  #define INP2_TIMEWAIT           0x00000001 /* in TIMEWAIT */
706  #define INP2_IN_FCTREE          0x00000002 /* in inp_fc_tree */
707  #define INP2_WANT_APP_POLICY    0x00000004 /* necp app policy check is desired */
708  #define INP2_NO_IFF_EXPENSIVE   0x00000008 /* do not use expensive interface */
709  #define INP2_INHASHLIST         0x00000010 /* pcb is in inp_hash list */
710  #define INP2_AWDL_UNRESTRICTED  0x00000020 /* AWDL restricted mode allowed */
711  #define INP2_KEEPALIVE_OFFLOAD  0x00000040 /* Enable UDP or TCP keepalive offload */
712  #define INP2_INTCOPROC_ALLOWED  0x00000080 /* Allow communication via internal co-processor interfaces */
713  #define INP2_CONNECT_IN_PROGRESS        0x00000100 /* A connect call is in progress, so binds are intermediate steps */
714  #define INP2_CLAT46_FLOW        0x00000200 /* The flow is going to use CLAT46 path */
715  #define INP2_EXTERNAL_PORT      0x00000400 /* The port is registered externally, for NECP listeners */
716  #define INP2_NO_IFF_CONSTRAINED 0x00000800 /* do not use constrained interface */
717  #define INP2_DONTFRAG           0x00001000 /* mark the DF bit in the IP header to avoid fragmentation */
718  
719  /*
720   * Flags passed to in_pcblookup*() functions.
721   */
722  #define INPLOOKUP_WILDCARD      1
723  
724  #define sotoinpcb(so)   ((struct inpcb *)(so)->so_pcb)
725  #define sotoin6pcb(so)  sotoinpcb(so)
726  
727  struct sysctl_req;
728  
729  extern int ipport_lowfirstauto;
730  extern int ipport_lowlastauto;
731  extern int ipport_firstauto;
732  extern int ipport_lastauto;
733  extern int ipport_hifirstauto;
734  extern int ipport_hilastauto;
735  extern int allow_udp_port_exhaustion;
736  #define UDP_RANDOM_PORT_RESERVE   4096
737  
738  /* freshly allocated PCB, it's in use */
739  #define INPCB_STATE_INUSE       0x1
740  /* this pcb is sitting in a a cache */
741  #define INPCB_STATE_CACHED      0x2
742  /* should treat as gone, will be garbage collected and freed */
743  #define INPCB_STATE_DEAD        0x3
744  
745  /* marked as ready to be garbaged collected, should be treated as not found */
746  #define WNT_STOPUSING           0xffff
747  /* that pcb is being acquired, do not recycle this time */
748  #define WNT_ACQUIRE             0x1
749  /* release acquired mode, can be garbage collected when wantcnt is null */
750  #define WNT_RELEASE             0x2
751  
752  extern void in_pcbinit(void);
753  extern void in_pcbinfo_attach(struct inpcbinfo *);
754  extern int in_pcbinfo_detach(struct inpcbinfo *);
755  
756  /* type of timer to be scheduled by inpcb_gc_sched and inpcb_timer_sched */
757  enum {
758  	INPCB_TIMER_LAZY = 0x1,
759  	INPCB_TIMER_FAST,
760  	INPCB_TIMER_NODELAY
761  };
762  extern void inpcb_gc_sched(struct inpcbinfo *, u_int32_t type);
763  extern void inpcb_timer_sched(struct inpcbinfo *, u_int32_t type);
764  
765  extern void in_losing(struct inpcb *);
766  extern void in_rtchange(struct inpcb *, int);
767  extern int in_pcballoc(struct socket *, struct inpcbinfo *, struct proc *);
768  extern int in_pcbbind(struct inpcb *, struct sockaddr *, struct proc *);
769  extern int in_pcbconnect(struct inpcb *, struct sockaddr *, struct proc *,
770      unsigned int, struct ifnet **);
771  extern void in_pcbdetach(struct inpcb *);
772  extern void in_pcbdispose(struct inpcb *);
773  extern void in_pcbdisconnect(struct inpcb *);
774  extern int in_pcbinshash(struct inpcb *, int);
775  extern int in_pcbladdr(struct inpcb *, struct sockaddr *, struct in_addr *,
776      unsigned int, struct ifnet **, int);
777  extern struct inpcb *in_pcblookup_local(struct inpcbinfo *, struct in_addr,
778      u_int, int);
779  extern struct inpcb *in_pcblookup_local_and_cleanup(struct inpcbinfo *,
780      struct in_addr, u_int, int);
781  extern struct inpcb *in_pcblookup_hash(struct inpcbinfo *, struct in_addr,
782      u_int, struct in_addr, u_int, int, struct ifnet *);
783  extern int in_pcblookup_hash_exists(struct inpcbinfo *, struct in_addr,
784      u_int, struct in_addr, u_int, int, uid_t *, gid_t *, struct ifnet *);
785  extern void in_pcbnotifyall(struct inpcbinfo *, struct in_addr, int,
786      void (*)(struct inpcb *, int));
787  extern void in_pcbrehash(struct inpcb *);
788  extern int in_getpeeraddr(struct socket *, struct sockaddr **);
789  extern int in_getsockaddr(struct socket *, struct sockaddr **);
790  extern int in_getsockaddr_s(struct socket *, struct sockaddr_in *);
791  extern int in_pcb_checkstate(struct inpcb *, int, int);
792  extern void in_pcbremlists(struct inpcb *);
793  extern void inpcb_to_compat(struct inpcb *, struct inpcb_compat *);
794  #if XNU_TARGET_OS_OSX
795  extern void inpcb_to_xinpcb64(struct inpcb *, struct xinpcb64 *);
796  #endif /* XNU_TARGET_OS_OSX */
797  
798  extern int get_pcblist_n(short, struct sysctl_req *, struct inpcbinfo *);
799  
800  extern void inpcb_get_ports_used(u_int32_t, int, u_int32_t, bitstr_t *,
801      struct inpcbinfo *);
802  #define INPCB_OPPORTUNISTIC_THROTTLEON  0x0001
803  #define INPCB_OPPORTUNISTIC_SETCMD      0x0002
804  extern uint32_t inpcb_count_opportunistic(unsigned int, struct inpcbinfo *,
805      u_int32_t);
806  extern uint32_t inpcb_find_anypcb_byaddr(struct ifaddr *, struct inpcbinfo *);
807  extern void inp_route_copyout(struct inpcb *, struct route *);
808  extern void inp_route_copyin(struct inpcb *, struct route *);
809  extern int inp_bindif(struct inpcb *, unsigned int, struct ifnet **);
810  extern void inp_set_nocellular(struct inpcb *);
811  extern void inp_clear_nocellular(struct inpcb *);
812  extern void inp_set_noexpensive(struct inpcb *);
813  extern void inp_set_noconstrained(struct inpcb *);
814  extern void inp_set_awdl_unrestricted(struct inpcb *);
815  extern boolean_t inp_get_awdl_unrestricted(struct inpcb *);
816  extern void inp_clear_awdl_unrestricted(struct inpcb *);
817  extern void inp_set_intcoproc_allowed(struct inpcb *);
818  extern boolean_t inp_get_intcoproc_allowed(struct inpcb *);
819  extern void inp_clear_intcoproc_allowed(struct inpcb *);
820  #if NECP
821  extern void inp_update_necp_policy(struct inpcb *, struct sockaddr *, struct sockaddr *, u_int);
822  extern void inp_set_want_app_policy(struct inpcb *);
823  extern void inp_clear_want_app_policy(struct inpcb *);
824  #endif /* NECP */
825  extern u_int32_t inp_calc_flowhash(struct inpcb *);
826  extern void inp_reset_fc_state(struct inpcb *);
827  extern int inp_set_fc_state(struct inpcb *, int advcode);
828  extern void inp_fc_unthrottle_tcp(struct inpcb *);
829  extern void inp_fc_throttle_tcp(struct inpcb *inp);
830  extern void inp_flowadv(uint32_t);
831  extern int inp_flush(struct inpcb *, int);
832  extern int inp_findinpcb_procinfo(struct inpcbinfo *, uint32_t, struct so_procinfo *);
833  extern void inp_get_soprocinfo(struct inpcb *, struct so_procinfo *);
834  extern int inp_update_policy(struct inpcb *);
835  extern boolean_t inp_restricted_recv(struct inpcb *, struct ifnet *);
836  extern boolean_t inp_restricted_send(struct inpcb *, struct ifnet *);
837  extern void inp_incr_sndbytes_total(struct socket *, int);
838  extern void inp_decr_sndbytes_total(struct socket *, int);
839  extern void inp_count_sndbytes(struct inpcb *, u_int32_t);
840  extern void inp_incr_sndbytes_unsent(struct socket *, int32_t);
841  extern void inp_decr_sndbytes_unsent(struct socket *, int32_t);
842  extern int32_t inp_get_sndbytes_allunsent(struct socket *, u_int32_t);
843  extern void inp_decr_sndbytes_allunsent(struct socket *, u_int32_t);
844  extern void inp_set_activity_bitmap(struct inpcb *inp);
845  extern void inp_get_activity_bitmap(struct inpcb *inp, activity_bitmap_t *b);
846  extern void inp_update_last_owner(struct socket *so, struct proc *p, struct proc *ep);
847  extern void inp_copy_last_owner(struct socket *so, struct socket *head);
848  #endif /* BSD_KERNEL_PRIVATE */
849  #ifdef KERNEL_PRIVATE
850  /* exported for PPP */
851  extern void inp_clear_INP_INADDR_ANY(struct socket *);
852  extern int inp_limit_companion_link(struct inpcbinfo *pcbinfo, u_int32_t limit);
853  extern int inp_recover_companion_link(struct inpcbinfo *pcbinfo);
854  #endif /* KERNEL_PRIVATE */
855  #endif /* !_NETINET_IN_PCB_H_ */