Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Mar 2017 23:41:54 -0700
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        svn-src-all@freebsd.org, svn-src-head@freebsd.org, freebsd-ports@FreeBSD.org
Subject:   Re: svn commit: r315662 - in head: contrib/bsnmp/snmp_mibII contrib/ipfilter/ipsend lib/libprocstat sys/netinet sys/sys usr.bin/netstat usr.bin/sockstat usr.bin/systat usr.sbin/tcpdrop usr.sbin/trpt
Message-ID:  <20170321064154.GL23308@FreeBSD.org>
In-Reply-To: <201703210639.v2L6dnRf055522@repo.freebsd.org>
References:  <201703210639.v2L6dnRf055522@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
  Hi!

  This change is known to break a ton of ports. More than 100 if
counting depends. I'm sorry for that and I already started to fix
them.

Please send all new breakages to me.

On Tue, Mar 21, 2017 at 06:39:49AM +0000, Gleb Smirnoff wrote:
T> Author: glebius
T> Date: Tue Mar 21 06:39:49 2017
T> New Revision: 315662
T> URL: https://svnweb.freebsd.org/changeset/base/315662
T> 
T> Log:
T>   Hide struct inpcb, struct tcpcb from the userland.
T>   
T>   This is a painful change, but it is needed.  On the one hand, we avoid
T>   modifying them, and this slows down some ideas, on the other hand we still
T>   eventually modify them and tools like netstat(1) never work on next version of
T>   FreeBSD.  We maintain a ton of spares in them, and we already got some ifdef
T>   hell at the end of tcpcb.
T>   
T>   Details:
T>   - Hide struct inpcb, struct tcpcb under _KERNEL || _WANT_FOO.
T>   - Make struct xinpcb, struct xtcpcb pure API structures, not including
T>     kernel structures inpcb and tcpcb inside.  Export into these structures
T>     the fields from inpcb and tcpcb that are known to be used, and put there
T>     a ton of spare space.
T>   - Make kernel and userland utilities compilable after these changes.
T>   - Bump __FreeBSD_version.
T>   
T>   Reviewed by:	rrs, gnn
T>   Differential Revision:	D10018
T> 
T> Modified:
T>   head/contrib/bsnmp/snmp_mibII/mibII_tcp.c
T>   head/contrib/bsnmp/snmp_mibII/mibII_udp.c
T>   head/contrib/ipfilter/ipsend/sock.c
T>   head/lib/libprocstat/libprocstat.c
T>   head/sys/netinet/in_pcb.c
T>   head/sys/netinet/in_pcb.h
T>   head/sys/netinet/ip_divert.c
T>   head/sys/netinet/raw_ip.c
T>   head/sys/netinet/tcp_subr.c
T>   head/sys/netinet/tcp_syncache.c
T>   head/sys/netinet/tcp_timer.c
T>   head/sys/netinet/tcp_timer.h
T>   head/sys/netinet/tcp_var.h
T>   head/sys/netinet/udp_usrreq.c
T>   head/sys/sys/param.h
T>   head/usr.bin/netstat/inet.c
T>   head/usr.bin/sockstat/sockstat.c
T>   head/usr.bin/systat/extern.h
T>   head/usr.bin/systat/netcmds.c
T>   head/usr.bin/systat/netstat.c
T>   head/usr.sbin/tcpdrop/tcpdrop.c
T>   head/usr.sbin/trpt/trpt.c
T> 
T> Modified: head/contrib/bsnmp/snmp_mibII/mibII_tcp.c
T> ==============================================================================
T> --- head/contrib/bsnmp/snmp_mibII/mibII_tcp.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/contrib/bsnmp/snmp_mibII/mibII_tcp.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -310,7 +310,7 @@ op_tcpconn(struct snmp_context *ctx __un
T>  	switch (value->var.subs[sub - 1]) {
T>  
T>  	  case LEAF_tcpConnState:
T> -		switch (tcpoids[i].tp->xt_tp.t_state) {
T> +		switch (tcpoids[i].tp->t_state) {
T>  
T>  		  case TCPS_CLOSED:
T>  			value->v.integer = 1;
T> 
T> Modified: head/contrib/bsnmp/snmp_mibII/mibII_udp.c
T> ==============================================================================
T> --- head/contrib/bsnmp/snmp_mibII/mibII_udp.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/contrib/bsnmp/snmp_mibII/mibII_udp.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -105,8 +105,8 @@ fetch_udp(void)
T>  	     ptr->xig_len > sizeof(struct xinpgen);
T>               ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
T>  		inp = (struct xinpcb *)ptr;
T> -		if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen ||
T> -		    (inp->xi_inp.inp_vflag & INP_IPV4) == 0)
T> +		if (inp->inp_gencnt > xinpgen->xig_gen ||
T> +		    (inp->inp_vflag & INP_IPV4) == 0)
T>  			continue;
T>  
T>  		udp_total++;
T> @@ -128,17 +128,17 @@ fetch_udp(void)
T>  	     ptr->xig_len > sizeof(struct xinpgen);
T>               ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) {
T>  		inp = (struct xinpcb *)ptr;
T> -		if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen ||
T> -		    (inp->xi_inp.inp_vflag & INP_IPV4) == 0)
T> +		if (inp->inp_gencnt > xinpgen->xig_gen ||
T> +		    (inp->inp_vflag & INP_IPV4) == 0)
T>  			continue;
T>  		oid->inp = inp;
T>  		oid->index.len = 5;
T> -		inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr);
T> +		inaddr = ntohl(inp->inp_laddr.s_addr);
T>  		oid->index.subs[0] = (inaddr >> 24) & 0xff;
T>  		oid->index.subs[1] = (inaddr >> 16) & 0xff;
T>  		oid->index.subs[2] = (inaddr >>  8) & 0xff;
T>  		oid->index.subs[3] = (inaddr >>  0) & 0xff;
T> -		oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport);
T> +		oid->index.subs[4] = ntohs(inp->inp_lport);
T>  		oid++;
T>  	}
T>  
T> 
T> Modified: head/contrib/ipfilter/ipsend/sock.c
T> ==============================================================================
T> --- head/contrib/ipfilter/ipsend/sock.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/contrib/ipfilter/ipsend/sock.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -78,8 +78,10 @@ typedef int     boolean_t;
T>  # include <net/route.h>
T>  #endif
T>  #include <netinet/ip_var.h>
T> +#define	_WANT_INPCB
T>  #include <netinet/in_pcb.h>
T>  #include <netinet/tcp_timer.h>
T> +#define	_WANT_TCPCB
T>  #include <netinet/tcp_var.h>
T>  #include <stdio.h>
T>  #include <unistd.h>
T> 
T> Modified: head/lib/libprocstat/libprocstat.c
T> ==============================================================================
T> --- head/lib/libprocstat/libprocstat.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/lib/libprocstat/libprocstat.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
T>  #include <netinet/in.h>
T>  #include <netinet/in_systm.h>
T>  #include <netinet/ip.h>
T> +#define	_WANT_INPCB
T>  #include <netinet/in_pcb.h>
T>  
T>  #include <assert.h>
T> 
T> Modified: head/sys/netinet/in_pcb.c
T> ==============================================================================
T> --- head/sys/netinet/in_pcb.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/in_pcb.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -2434,6 +2434,41 @@ so_sototcpcb(struct socket *so)
T>  	return (sototcpcb(so));
T>  }
T>  
T> +/*
T> + * Create an external-format (``xinpcb'') structure using the information in
T> + * the kernel-format in_pcb structure pointed to by inp.  This is done to
T> + * reduce the spew of irrelevant information over this interface, to isolate
T> + * user code from changes in the kernel structure, and potentially to provide
T> + * information-hiding if we decide that some of this information should be
T> + * hidden from users.
T> + */
T> +void
T> +in_pcbtoxinpcb(const struct inpcb *inp, struct xinpcb *xi)
T> +{
T> +
T> +	xi->xi_len = sizeof(struct xinpcb);
T> +	if (inp->inp_socket)
T> +		sotoxsocket(inp->inp_socket, &xi->xi_socket);
T> +	else
T> +		bzero(&xi->xi_socket, sizeof(struct xsocket));
T> +	bcopy(&inp->inp_inc, &xi->inp_inc, sizeof(struct in_conninfo));
T> +	xi->inp_gencnt = inp->inp_gencnt;
T> +	xi->inp_ppcb = inp->inp_ppcb;
T> +	xi->inp_flow = inp->inp_flow;
T> +	xi->inp_flowid = inp->inp_flowid;
T> +	xi->inp_flowtype = inp->inp_flowtype;
T> +	xi->inp_flags = inp->inp_flags;
T> +	xi->inp_flags2 = inp->inp_flags2;
T> +	xi->inp_rss_listen_bucket = inp->inp_rss_listen_bucket;
T> +	xi->in6p_cksum = inp->in6p_cksum;
T> +	xi->in6p_hops = inp->in6p_hops;
T> +	xi->inp_ip_tos = inp->inp_ip_tos;
T> +	xi->inp_vflag = inp->inp_vflag;
T> +	xi->inp_ip_ttl = inp->inp_ip_ttl;
T> +	xi->inp_ip_p = inp->inp_ip_p;
T> +	xi->inp_ip_minttl = inp->inp_ip_minttl;
T> +}
T> +
T>  #ifdef DDB
T>  static void
T>  db_print_indent(int indent)
T> 
T> Modified: head/sys/netinet/in_pcb.h
T> ==============================================================================
T> --- head/sys/netinet/in_pcb.h	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/in_pcb.h	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -53,7 +53,6 @@
T>  
T>  #define	in6pcb		inpcb	/* for KAME src sync over BSD*'s */
T>  #define	in6p_sp		inp_sp	/* for KAME src sync over BSD*'s */
T> -struct inpcbpolicy;
T>  
T>  /*
T>   * struct inpcb is the common protocol control block structure used in most
T> @@ -65,7 +64,7 @@ struct inpcbpolicy;
T>   */
T>  LIST_HEAD(inpcbhead, inpcb);
T>  LIST_HEAD(inpcbporthead, inpcbport);
T> -typedef	u_quad_t	inp_gen_t;
T> +typedef	uint64_t	inp_gen_t;
T>  
T>  /*
T>   * PCB with AF_INET6 null bind'ed laddr can receive AF_INET input packet.
T> @@ -130,9 +129,8 @@ struct in_conninfo {
T>  #define	inc6_laddr	inc_ie.ie6_laddr
T>  #define	inc6_zoneid	inc_ie.ie6_zoneid
T>  
T> -struct	icmp6_filter;
T> -
T> -/*-
T> +#if defined(_KERNEL) || defined(_WANT_INPCB)
T> +/*
T>   * struct inpcb captures the network layer state for TCP, UDP, and raw IPv4 and
T>   * IPv6 sockets.  In the case of TCP and UDP, further per-connection state is
T>   * hung off of inp_ppcb most of the time.  Almost all fields of struct inpcb
T> @@ -181,6 +179,8 @@ struct	icmp6_filter;
T>   * read-lock usage during modification, this model can be applied to other
T>   * protocols (especially SCTP).
T>   */
T> +struct icmp6_filter;
T> +struct inpcbpolicy;
T>  struct m_snd_tag;
T>  struct inpcb {
T>  	LIST_ENTRY(inpcb) inp_hash;	/* (h/i) hash list */
T> @@ -204,10 +204,8 @@ struct inpcb {
T>  	uint32_t inp_flowid;		/* (x) flow id / queue id */
T>  	u_int	inp_refcount;		/* (i) refcount */
T>  	struct m_snd_tag *inp_snd_tag;	/* (i) send tag for outgoing mbufs */
T> -	void	*inp_pspare[4];		/* (x) general use */
T>  	uint32_t inp_flowtype;		/* (x) M_HASHTYPE value */
T>  	uint32_t inp_rss_listen_bucket;	/* (x) overridden RSS listen bucket */
T> -	u_int	inp_ispare[4];		/* (x) user cookie / general use */
T>  
T>  	/* Local and foreign ports, local and foreign addr. */
T>  	struct	in_conninfo inp_inc;	/* (i) list for PCB's local port */
T> @@ -218,23 +216,23 @@ struct inpcb {
T>  
T>  	/* Protocol-dependent part; options. */
T>  	struct {
T> -		u_char	inp4_ip_tos;		/* (i) type of service proto */
T> -		struct	mbuf *inp4_options;	/* (i) IP options */
T> -		struct	ip_moptions *inp4_moptions; /* (i) IP mcast options */
T> -	} inp_depend4;
T> +		u_char	inp_ip_tos;		/* (i) type of service proto */
T> +		struct mbuf		*inp_options;	/* (i) IP options */
T> +		struct ip_moptions	*inp_moptions;	/* (i) mcast options */
T> +	};
T>  	struct {
T>  		/* (i) IP options */
T> -		struct	mbuf *inp6_options;
T> +		struct mbuf		*in6p_options;
T>  		/* (i) IP6 options for outgoing packets */
T> -		struct	ip6_pktopts *inp6_outputopts;
T> +		struct ip6_pktopts	*in6p_outputopts;
T>  		/* (i) IP multicast options */
T> -		struct	ip6_moptions *inp6_moptions;
T> +		struct ip6_moptions	*in6p_moptions;
T>  		/* (i) ICMPv6 code type filter */
T> -		struct	icmp6_filter *inp6_icmp6filt;
T> +		struct icmp6_filter	*in6p_icmp6filt;
T>  		/* (i) IPV6_CHECKSUM setsockopt */
T> -		int	inp6_cksum;
T> -		short	inp6_hops;
T> -	} inp_depend6;
T> +		int	in6p_cksum;
T> +		short	in6p_hops;
T> +	};
T>  	LIST_ENTRY(inpcb) inp_portlist;	/* (i/h) */
T>  	struct	inpcbport *inp_phd;	/* (i/h) head of this list */
T>  #define inp_zero_size offsetof(struct inpcb, inp_gencnt)
T> @@ -249,24 +247,17 @@ struct inpcb {
T>  #define inp_route inp_rtu.inpu_route
T>  #define inp_route6 inp_rtu.inpu_route6
T>  };
T> +#endif	/* _KERNEL */
T> +
T>  #define	inp_fport	inp_inc.inc_fport
T>  #define	inp_lport	inp_inc.inc_lport
T>  #define	inp_faddr	inp_inc.inc_faddr
T>  #define	inp_laddr	inp_inc.inc_laddr
T> -#define	inp_ip_tos	inp_depend4.inp4_ip_tos
T> -#define	inp_options	inp_depend4.inp4_options
T> -#define	inp_moptions	inp_depend4.inp4_moptions
T>  
T>  #define	in6p_faddr	inp_inc.inc6_faddr
T>  #define	in6p_laddr	inp_inc.inc6_laddr
T>  #define	in6p_zoneid	inp_inc.inc6_zoneid
T> -#define	in6p_hops	inp_depend6.inp6_hops	/* default hop limit */
T>  #define	in6p_flowinfo	inp_flow
T> -#define	in6p_options	inp_depend6.inp6_options
T> -#define	in6p_outputopts	inp_depend6.inp6_outputopts
T> -#define	in6p_moptions	inp_depend6.inp6_moptions
T> -#define	in6p_icmp6filt	inp_depend6.inp6_icmp6filt
T> -#define	in6p_cksum	inp_depend6.inp6_cksum
T>  
T>  #define	inp_vnet	inp_pcbinfo->ipi_vnet
T>  
T> @@ -280,21 +271,53 @@ struct inpcb {
T>  /*
T>   * Interface exported to userland by various protocols which use inpcbs.  Hack
T>   * alert -- only define if struct xsocket is in scope.
T> + * Fields prefixed with "xi_" are unique to this structure, and the rest
T> + * match fields in the struct inpcb, to ease coding and porting.
T> + *
T> + * Legend:
T> + * (s) - used by userland utilities in src
T> + * (p) - used by utilities in ports
T> + * (3) - is known to be used by third party software not in ports
T> + * (n) - no known usage
T>   */
T>  #ifdef _SYS_SOCKETVAR_H_
T> -struct	xinpcb {
T> -	size_t	xi_len;		/* length of this structure */
T> -	struct	inpcb xi_inp;
T> -	struct	xsocket xi_socket;
T> -	u_quad_t	xi_alignment_hack;
T> -};
T> -
T> -struct	xinpgen {
T> -	size_t	xig_len;	/* length of this structure */
T> -	u_int	xig_count;	/* number of PCBs at this time */
T> -	inp_gen_t xig_gen;	/* generation count at this time */
T> -	so_gen_t xig_sogen;	/* socket generation count at this time */
T> +struct xinpcb {
T> +	size_t		xi_len;		/* length of this structure */
T> +	struct xsocket	xi_socket;		/* (s,p) */
T> +	struct in_conninfo inp_inc;		/* (s,p) */
T> +	uint64_t	inp_gencnt;		/* (s,p) */
T> +	union {
T> +		void	*inp_ppcb;		/* (s) netstat(1) */
T> +		int64_t	ph_ppcb;
T> +	};
T> +	int64_t		inp_spare64[4];
T> +	uint32_t	inp_flow;		/* (s) */
T> +	uint32_t	inp_flowid;		/* (s) */
T> +	uint32_t	inp_flowtype;		/* (s) */
T> +	int32_t		inp_flags;		/* (s,p) */
T> +	int32_t		inp_flags2;		/* (s) */
T> +	int32_t		inp_rss_listen_bucket;	/* (n) */
T> +	int32_t		in6p_cksum;		/* (n) */
T> +	int32_t		inp_spare32[4];
T> +	uint16_t	in6p_hops;		/* (n) */
T> +	uint8_t		inp_ip_tos;		/* (n) */
T> +	int8_t		pad8;
T> +	uint8_t		inp_vflag;		/* (s,p) */
T> +	uint8_t		inp_ip_ttl;		/* (n) */
T> +	uint8_t		inp_ip_p;		/* (n) */
T> +	uint8_t		inp_ip_minttl;		/* (n) */
T> +	int8_t		inp_spare8[4];
T> +} __aligned(8);
T> +
T> +struct xinpgen {
T> +	size_t		xig_len;	/* length of this structure */
T> +	u_int		xig_count;	/* number of PCBs at this time */
T> +	inp_gen_t	xig_gen;	/* generation count at this time */
T> +	so_gen_t	xig_sogen;	/* socket generation count this time */
T>  };
T> +#ifdef	_KERNEL
T> +void	in_pcbtoxinpcb(const struct inpcb *, struct xinpcb *);
T> +#endif
T>  #endif /* _SYS_SOCKETVAR_H_ */
T>  
T>  struct inpcbport {
T> 
T> Modified: head/sys/netinet/ip_divert.c
T> ==============================================================================
T> --- head/sys/netinet/ip_divert.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/ip_divert.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -691,12 +691,8 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
T>  		INP_RLOCK(inp);
T>  		if (inp->inp_gencnt <= gencnt) {
T>  			struct xinpcb xi;
T> -			bzero(&xi, sizeof(xi));
T> -			xi.xi_len = sizeof xi;
T> -			/* XXX should avoid extra copy */
T> -			bcopy(inp, &xi.xi_inp, sizeof *inp);
T> -			if (inp->inp_socket)
T> -				sotoxsocket(inp->inp_socket, &xi.xi_socket);
T> +
T> +			in_pcbtoxinpcb(inp, &xi);
T>  			INP_RUNLOCK(inp);
T>  			error = SYSCTL_OUT(req, &xi, sizeof xi);
T>  		} else
T> 
T> Modified: head/sys/netinet/raw_ip.c
T> ==============================================================================
T> --- head/sys/netinet/raw_ip.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/raw_ip.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -1077,12 +1077,7 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
T>  		if (inp->inp_gencnt <= gencnt) {
T>  			struct xinpcb xi;
T>  
T> -			bzero(&xi, sizeof(xi));
T> -			xi.xi_len = sizeof xi;
T> -			/* XXX should avoid extra copy */
T> -			bcopy(inp, &xi.xi_inp, sizeof *inp);
T> -			if (inp->inp_socket)
T> -				sotoxsocket(inp->inp_socket, &xi.xi_socket);
T> +			in_pcbtoxinpcb(inp, &xi);
T>  			INP_RUNLOCK(inp);
T>  			error = SYSCTL_OUT(req, &xi, sizeof xi);
T>  		} else
T> 
T> Modified: head/sys/netinet/tcp_subr.c
T> ==============================================================================
T> --- head/sys/netinet/tcp_subr.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/tcp_subr.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -1773,30 +1773,8 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
T>  		INP_RLOCK(inp);
T>  		if (inp->inp_gencnt <= gencnt) {
T>  			struct xtcpcb xt;
T> -			void *inp_ppcb;
T>  
T> -			bzero(&xt, sizeof(xt));
T> -			xt.xt_len = sizeof xt;
T> -			/* XXX should avoid extra copy */
T> -			bcopy(inp, &xt.xt_inp, sizeof *inp);
T> -			inp_ppcb = inp->inp_ppcb;
T> -			if (inp_ppcb == NULL)
T> -				bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
T> -			else if (inp->inp_flags & INP_TIMEWAIT) {
T> -				bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
T> -				xt.xt_tp.t_state = TCPS_TIME_WAIT;
T> -			} else {
T> -				bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);
T> -				if (xt.xt_tp.t_timers)
T> -					tcp_timer_to_xtimer(&xt.xt_tp, xt.xt_tp.t_timers, &xt.xt_timer);
T> -			}
T> -			if (inp->inp_socket != NULL)
T> -				sotoxsocket(inp->inp_socket, &xt.xt_socket);
T> -			else {
T> -				bzero(&xt.xt_socket, sizeof xt.xt_socket);
T> -				xt.xt_socket.xso_protocol = IPPROTO_TCP;
T> -			}
T> -			xt.xt_inp.inp_gencnt = inp->inp_gencnt;
T> +			tcp_inptoxtp(inp, &xt);
T>  			INP_RUNLOCK(inp);
T>  			error = SYSCTL_OUT(req, &xt, sizeof xt);
T>  		} else
T> @@ -2765,3 +2743,53 @@ tcp_state_change(struct tcpcb *tp, int n
T>  	tp->t_state = newstate;
T>  	TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate);
T>  }
T> +
T> +/*
T> + * Create an external-format (``xtcpcb'') structure using the information in
T> + * the kernel-format tcpcb structure pointed to by tp.  This is done to
T> + * reduce the spew of irrelevant information over this interface, to isolate
T> + * user code from changes in the kernel structure, and potentially to provide
T> + * information-hiding if we decide that some of this information should be
T> + * hidden from users.
T> + */
T> +void
T> +tcp_inptoxtp(const struct inpcb *inp, struct xtcpcb *xt)
T> +{
T> +	struct tcpcb *tp = intotcpcb(inp);
T> +	sbintime_t now;
T> +
T> +	if (inp->inp_flags & INP_TIMEWAIT) {
T> +		bzero(xt, sizeof(struct xtcpcb));
T> +		xt->t_state = TCPS_TIME_WAIT;
T> +	} else {
T> +		xt->t_state = tp->t_state;
T> +		xt->t_flags = tp->t_flags;
T> +		xt->t_sndzerowin = tp->t_sndzerowin;
T> +		xt->t_sndrexmitpack = tp->t_sndrexmitpack;
T> +		xt->t_rcvoopack = tp->t_rcvoopack;
T> +
T> +		now = getsbinuptime();
T> +#define	COPYTIMER(ttt)	do {						\
T> +		if (callout_active(&tp->t_timers->ttt))			\
T> +			xt->ttt = (tp->t_timers->ttt.c_time - now) /	\
T> +			    SBT_1MS;					\
T> +		else							\
T> +			xt->ttt = 0;					\
T> +} while (0)
T> +		COPYTIMER(tt_delack);
T> +		COPYTIMER(tt_rexmt);
T> +		COPYTIMER(tt_persist);
T> +		COPYTIMER(tt_keep);
T> +		COPYTIMER(tt_2msl);
T> +#undef COPYTIMER
T> +		xt->t_rcvtime = 1000 * (ticks - tp->t_rcvtime) / hz;
T> +
T> +		bcopy(tp->t_fb->tfb_tcp_block_name, xt->xt_stack,
T> +		    TCP_FUNCTION_NAME_LEN_MAX);
T> +	}
T> +
T> +	xt->xt_len = sizeof(struct xtcpcb);
T> +	in_pcbtoxinpcb(inp, &xt->xt_inp);
T> +	if (inp->inp_socket == NULL)
T> +		xt->xt_inp.xi_socket.xso_protocol = IPPROTO_TCP;
T> +}
T> 
T> Modified: head/sys/netinet/tcp_syncache.c
T> ==============================================================================
T> --- head/sys/netinet/tcp_syncache.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/tcp_syncache.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -2217,13 +2217,13 @@ syncache_pcblist(struct sysctl_req *req,
T>  				xt.xt_inp.inp_vflag = INP_IPV6;
T>  			else
T>  				xt.xt_inp.inp_vflag = INP_IPV4;
T> -			bcopy(&sc->sc_inc, &xt.xt_inp.inp_inc, sizeof (struct in_conninfo));
T> -			xt.xt_tp.t_inpcb = &xt.xt_inp;
T> -			xt.xt_tp.t_state = TCPS_SYN_RECEIVED;
T> -			xt.xt_socket.xso_protocol = IPPROTO_TCP;
T> -			xt.xt_socket.xso_len = sizeof (struct xsocket);
T> -			xt.xt_socket.so_type = SOCK_STREAM;
T> -			xt.xt_socket.so_state = SS_ISCONNECTING;
T> +			bcopy(&sc->sc_inc, &xt.xt_inp.inp_inc,
T> +			    sizeof (struct in_conninfo));
T> +			xt.t_state = TCPS_SYN_RECEIVED;
T> +			xt.xt_inp.xi_socket.xso_protocol = IPPROTO_TCP;
T> +			xt.xt_inp.xi_socket.xso_len = sizeof (struct xsocket);
T> +			xt.xt_inp.xi_socket.so_type = SOCK_STREAM;
T> +			xt.xt_inp.xi_socket.so_state = SS_ISCONNECTING;
T>  			error = SYSCTL_OUT(req, &xt, sizeof xt);
T>  			if (error) {
T>  				SCH_UNLOCK(sch);
T> 
T> Modified: head/sys/netinet/tcp_timer.c
T> ==============================================================================
T> --- head/sys/netinet/tcp_timer.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/tcp_timer.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -1006,28 +1006,3 @@ tcp_timer_stop(struct tcpcb *tp, uint32_
T>  		tp->t_timers->tt_draincnt++;
T>  	}
T>  }
T> -
T> -#define	ticks_to_msecs(t)	(1000*(t) / hz)
T> -
T> -void
T> -tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer,
T> -    struct xtcp_timer *xtimer)
T> -{
T> -	sbintime_t now;
T> -
T> -	bzero(xtimer, sizeof(*xtimer));
T> -	if (timer == NULL)
T> -		return;
T> -	now = getsbinuptime();
T> -	if (callout_active(&timer->tt_delack))
T> -		xtimer->tt_delack = (timer->tt_delack.c_time - now) / SBT_1MS;
T> -	if (callout_active(&timer->tt_rexmt))
T> -		xtimer->tt_rexmt = (timer->tt_rexmt.c_time - now) / SBT_1MS;
T> -	if (callout_active(&timer->tt_persist))
T> -		xtimer->tt_persist = (timer->tt_persist.c_time - now) / SBT_1MS;
T> -	if (callout_active(&timer->tt_keep))
T> -		xtimer->tt_keep = (timer->tt_keep.c_time - now) / SBT_1MS;
T> -	if (callout_active(&timer->tt_2msl))
T> -		xtimer->tt_2msl = (timer->tt_2msl.c_time - now) / SBT_1MS;
T> -	xtimer->t_rcvtime = ticks_to_msecs(ticks - tp->t_rcvtime);
T> -}
T> 
T> Modified: head/sys/netinet/tcp_timer.h
T> ==============================================================================
T> --- head/sys/netinet/tcp_timer.h	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/tcp_timer.h	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -210,8 +210,6 @@ void	tcp_timer_keep(void *xtp);
T>  void	tcp_timer_persist(void *xtp);
T>  void	tcp_timer_rexmt(void *xtp);
T>  void	tcp_timer_delack(void *xtp);
T> -void	tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer,
T> -	struct xtcp_timer *xtimer);
T>  
T>  #endif /* _KERNEL */
T>  
T> 
T> Modified: head/sys/netinet/tcp_var.h
T> ==============================================================================
T> --- head/sys/netinet/tcp_var.h	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/tcp_var.h	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -39,15 +39,9 @@
T>  #ifdef _KERNEL
T>  #include <net/vnet.h>
T>  #include <sys/mbuf.h>
T> +#endif
T>  
T> -/*
T> - * Kernel variables for tcp.
T> - */
T> -VNET_DECLARE(int, tcp_do_rfc1323);
T> -#define	V_tcp_do_rfc1323	VNET(tcp_do_rfc1323)
T> -
T> -#endif /* _KERNEL */
T> -
T> +#if defined(_KERNEL) || defined(_WANT_TCPCB)
T>  /* TCP segment queue entry */
T>  struct tseg_qent {
T>  	LIST_ENTRY(tseg_qent) tqe_q;
T> @@ -83,90 +77,12 @@ struct sackhint {
T>  	uint64_t	_pad[1];	/* TBD */
T>  };
T>  
T> -struct tcptemp {
T> -	u_char	tt_ipgen[40]; /* the size must be of max ip header, now IPv6 */
T> -	struct	tcphdr tt_t;
T> -};
T> -
T> -#define tcp6cb		tcpcb  /* for KAME src sync over BSD*'s */
T> -
T> -/* 
T> - * TODO: We yet need to brave plowing in
T> - * to tcp_input() and the pru_usrreq() block.
T> - * Right now these go to the old standards which
T> - * are somewhat ok, but in the long term may
T> - * need to be changed. If we do tackle tcp_input()
T> - * then we need to get rid of the tcp_do_segment()
T> - * function below.
T> - */
T> -/* Flags for tcp functions */
T> -#define TCP_FUNC_BEING_REMOVED 0x01   	/* Can no longer be referenced */
T> -struct tcpcb;
T> -struct inpcb;
T> -struct sockopt;
T> -struct socket;
T> -
T> -/*
T> - * If defining the optional tcp_timers, in the
T> - * tfb_tcp_timer_stop call you must use the
T> - * callout_async_drain() function with the
T> - * tcp_timer_discard callback. You should check
T> - * the return of callout_async_drain() and if 0
T> - * increment tt_draincnt. Since the timer sub-system
T> - * does not know your callbacks you must provide a
T> - * stop_all function that loops through and calls
T> - * tcp_timer_stop() with each of your defined timers.
T> - * Adding a tfb_tcp_handoff_ok function allows the socket
T> - * option to change stacks to query you even if the
T> - * connection is in a later stage. You return 0 to
T> - * say you can take over and run your stack, you return
T> - * non-zero (an error number) to say no you can't.
T> - * If the function is undefined you can only change
T> - * in the early states (before connect or listen).
T> - * tfb_tcp_fb_fini is changed to add a flag to tell
T> - * the old stack if the tcb is being destroyed or
T> - * not. A one in the flag means the TCB is being
T> - * destroyed, a zero indicates its transitioning to
T> - * another stack (via socket option).
T> - */
T> -struct tcp_function_block {
T> -	char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX];
T> -	int	(*tfb_tcp_output)(struct tcpcb *);
T> -	void	(*tfb_tcp_do_segment)(struct mbuf *, struct tcphdr *,
T> -			    struct socket *, struct tcpcb *,
T> -			    int, int, uint8_t,
T> -			    int);
T> -	int     (*tfb_tcp_ctloutput)(struct socket *so, struct sockopt *sopt,
T> -			    struct inpcb *inp, struct tcpcb *tp);
T> -	/* Optional memory allocation/free routine */
T> -	void	(*tfb_tcp_fb_init)(struct tcpcb *);
T> -	void	(*tfb_tcp_fb_fini)(struct tcpcb *, int);
T> -	/* Optional timers, must define all if you define one */
T> -	int	(*tfb_tcp_timer_stop_all)(struct tcpcb *);
T> -	void	(*tfb_tcp_timer_activate)(struct tcpcb *,
T> -			    uint32_t, u_int);
T> -	int	(*tfb_tcp_timer_active)(struct tcpcb *, uint32_t);
T> -	void	(*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t);
T> -	void	(*tfb_tcp_rexmit_tmr)(struct tcpcb *);
T> -	int	(*tfb_tcp_handoff_ok)(struct tcpcb *);
T> -	volatile uint32_t tfb_refcnt;
T> -	uint32_t  tfb_flags;
T> -};
T> -
T> -struct tcp_function {
T> -	TAILQ_ENTRY(tcp_function) tf_next;
T> -	struct tcp_function_block *tf_fb;
T> -};
T> -
T> -TAILQ_HEAD(tcp_funchead, tcp_function);
T> -
T>  /*
T>   * Tcp control block, one per tcp; fields:
T>   * Organized for 16 byte cacheline efficiency.
T>   */
T>  struct tcpcb {
T>  	struct	tsegqe_head t_segq;	/* segment reassembly queue */
T> -	void	*t_pspare[2];		/* new reassembly queue */
T>  	int	t_segqlen;		/* segment reassembly queue length */
T>  	int	t_dupacks;		/* consecutive dup acks recd */
T>  
T> @@ -197,12 +113,10 @@ struct tcpcb {
T>  
T>  	uint32_t  snd_wnd;		/* send window */
T>  	uint32_t  snd_cwnd;		/* congestion-controlled window */
T> -	u_long	snd_spare1;		/* unused */
T>  	uint32_t  snd_ssthresh;		/* snd_cwnd size threshold for
T>  					 * for slow start exponential to
T>  					 * linear switch
T>  					 */
T> -	u_long	snd_spare2;		/* unused */
T>  	tcp_seq	snd_recover;		/* for use in NewReno Fast Recovery */
T>  
T>  	u_int	t_rcvtime;		/* inactivity time */
T> @@ -210,9 +124,6 @@ struct tcpcb {
T>  	u_int	t_rtttime;		/* RTT measurement start time */
T>  	tcp_seq	t_rtseq;		/* sequence number being timed */
T>  
T> -	u_int	t_bw_spare1;		/* unused */
T> -	tcp_seq	t_bw_spare2;		/* unused */
T> -
T>  	int	t_rxtcur;		/* current retransmit value (ticks) */
T>  	u_int	t_maxseg;		/* maximum segment size */
T>  	u_int	t_pmtud_saved_maxseg;	/* pre-blackhole MSS */
T> @@ -276,32 +187,97 @@ struct tcpcb {
T>  	u_int	t_tsomaxsegcount;	/* TSO maximum segment count */
T>  	u_int	t_tsomaxsegsize;	/* TSO maximum segment size in bytes */
T>  	u_int	t_flags2;		/* More tcpcb flags storage */
T> -#if defined(_KERNEL) && defined(TCP_RFC7413)
T> -	uint32_t t_ispare[6];		/* 5 UTO, 1 TBD */
T> -	uint64_t t_tfo_cookie;		/* TCP Fast Open cookie */
T> -#else
T> -	uint32_t t_ispare[8];		/* 5 UTO, 3 TBD */
T> -#endif
T>  	struct tcp_function_block *t_fb;/* TCP function call block */
T>  	void	*t_fb_ptr;		/* Pointer to t_fb specific data */
T> -#if defined(_KERNEL) && defined(TCP_RFC7413)
T> +#ifdef TCP_RFC7413
T> +	uint64_t t_tfo_cookie;		/* TCP Fast Open cookie */
T>  	unsigned int *t_tfo_pending;	/* TCP Fast Open pending counter */
T> -	void	*t_pspare2[1];		/* 1 TCP_SIGNATURE */
T> -#else
T> -	void	*t_pspare2[2];		/* 1 TCP_SIGNATURE, 1 TBD */
T>  #endif
T> -#if defined(_KERNEL) && defined(TCPPCAP)
T> +#ifdef TCPPCAP
T>  	struct mbufq t_inpkts;		/* List of saved input packets. */
T>  	struct mbufq t_outpkts;		/* List of saved output packets. */
T> -#ifdef _LP64
T> -	uint64_t _pad[0];		/* all used! */
T> -#else
T> -	uint64_t _pad[2];		/* 2 are available */
T> -#endif /* _LP64 */
T> -#else
T> -	uint64_t _pad[6];
T> -#endif /* defined(_KERNEL) && defined(TCPPCAP) */
T> +#endif
T>  };
T> +#endif	/* _KERNEL || _WANT_TCPCB */
T> +
T> +#ifdef _KERNEL
T> +/*
T> + * Kernel variables for tcp.
T> + */
T> +VNET_DECLARE(int, tcp_do_rfc1323);
T> +#define	V_tcp_do_rfc1323	VNET(tcp_do_rfc1323)
T> +
T> +struct tcptemp {
T> +	u_char	tt_ipgen[40]; /* the size must be of max ip header, now IPv6 */
T> +	struct	tcphdr tt_t;
T> +};
T> +
T> +/* 
T> + * TODO: We yet need to brave plowing in
T> + * to tcp_input() and the pru_usrreq() block.
T> + * Right now these go to the old standards which
T> + * are somewhat ok, but in the long term may
T> + * need to be changed. If we do tackle tcp_input()
T> + * then we need to get rid of the tcp_do_segment()
T> + * function below.
T> + */
T> +/* Flags for tcp functions */
T> +#define TCP_FUNC_BEING_REMOVED 0x01   	/* Can no longer be referenced */
T> +
T> +/*
T> + * If defining the optional tcp_timers, in the
T> + * tfb_tcp_timer_stop call you must use the
T> + * callout_async_drain() function with the
T> + * tcp_timer_discard callback. You should check
T> + * the return of callout_async_drain() and if 0
T> + * increment tt_draincnt. Since the timer sub-system
T> + * does not know your callbacks you must provide a
T> + * stop_all function that loops through and calls
T> + * tcp_timer_stop() with each of your defined timers.
T> + * Adding a tfb_tcp_handoff_ok function allows the socket
T> + * option to change stacks to query you even if the
T> + * connection is in a later stage. You return 0 to
T> + * say you can take over and run your stack, you return
T> + * non-zero (an error number) to say no you can't.
T> + * If the function is undefined you can only change
T> + * in the early states (before connect or listen).
T> + * tfb_tcp_fb_fini is changed to add a flag to tell
T> + * the old stack if the tcb is being destroyed or
T> + * not. A one in the flag means the TCB is being
T> + * destroyed, a zero indicates its transitioning to
T> + * another stack (via socket option).
T> + */
T> +struct tcp_function_block {
T> +	char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX];
T> +	int	(*tfb_tcp_output)(struct tcpcb *);
T> +	void	(*tfb_tcp_do_segment)(struct mbuf *, struct tcphdr *,
T> +			    struct socket *, struct tcpcb *,
T> +			    int, int, uint8_t,
T> +			    int);
T> +	int     (*tfb_tcp_ctloutput)(struct socket *so, struct sockopt *sopt,
T> +			    struct inpcb *inp, struct tcpcb *tp);
T> +	/* Optional memory allocation/free routine */
T> +	void	(*tfb_tcp_fb_init)(struct tcpcb *);
T> +	void	(*tfb_tcp_fb_fini)(struct tcpcb *, int);
T> +	/* Optional timers, must define all if you define one */
T> +	int	(*tfb_tcp_timer_stop_all)(struct tcpcb *);
T> +	void	(*tfb_tcp_timer_activate)(struct tcpcb *,
T> +			    uint32_t, u_int);
T> +	int	(*tfb_tcp_timer_active)(struct tcpcb *, uint32_t);
T> +	void	(*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t);
T> +	void	(*tfb_tcp_rexmit_tmr)(struct tcpcb *);
T> +	int	(*tfb_tcp_handoff_ok)(struct tcpcb *);
T> +	volatile uint32_t tfb_refcnt;
T> +	uint32_t  tfb_flags;
T> +};
T> +
T> +struct tcp_function {
T> +	TAILQ_ENTRY(tcp_function) tf_next;
T> +	struct tcp_function_block *tf_fb;
T> +};
T> +
T> +TAILQ_HEAD(tcp_funchead, tcp_function);
T> +#endif	/* _KERNEL */
T>  
T>  /*
T>   * Flags and utility macros for the t_flags field.
T> @@ -656,26 +632,41 @@ struct tcp_hhook_data {
T>  
T>  /*
T>   * TCB structure exported to user-land via sysctl(3).
T> + *
T> + * Fields prefixed with "xt_" are unique to the export structure, and fields
T> + * with "t_" or other prefixes match corresponding fields of 'struct tcpcb'.
T> + *
T> + * Legend:
T> + * (s) - used by userland utilities in src
T> + * (p) - used by utilities in ports
T> + * (3) - is known to be used by third party software not in ports
T> + * (n) - no known usage
T> + *
T>   * Evil hack: declare only if in_pcb.h and sys/socketvar.h have been
T>   * included.  Not all of our clients do.
T>   */
T>  #if defined(_NETINET_IN_PCB_H_) && defined(_SYS_SOCKETVAR_H_)
T> -struct xtcp_timer {
T> -	int tt_rexmt;	/* retransmit timer */
T> -	int tt_persist;	/* retransmit persistence */
T> -	int tt_keep;	/* keepalive */
T> -	int tt_2msl;	/* 2*msl TIME_WAIT timer */
T> -	int tt_delack;	/* delayed ACK timer */
T> -	int t_rcvtime;	/* Time since last packet received */
T> -};
T> -struct	xtcpcb {
T> -	size_t	xt_len;
T> -	struct	inpcb	xt_inp;
T> -	struct	tcpcb	xt_tp;
T> -	struct	xsocket	xt_socket;
T> -	struct	xtcp_timer xt_timer;
T> -	u_quad_t	xt_alignment_hack;
T> -};
T> +struct xtcpcb {
T> +	size_t		xt_len;		/* length of this structure */
T> +	struct xinpcb	xt_inp;
T> +	char		xt_stack[TCP_FUNCTION_NAME_LEN_MAX];	/* (n) */
T> +	int64_t		spare64[8];
T> +	int32_t		t_state;		/* (s,p) */
T> +	uint32_t	t_flags;		/* (s,p) */
T> +	int32_t		t_sndzerowin;		/* (s) */
T> +	int32_t		t_sndrexmitpack;	/* (s) */
T> +	int32_t		t_rcvoopack;		/* (s) */
T> +	int32_t		t_rcvtime;		/* (s) */
T> +	int32_t		tt_rexmt;		/* (s) */
T> +	int32_t		tt_persist;		/* (s) */
T> +	int32_t		tt_keep;		/* (s) */
T> +	int32_t		tt_2msl;		/* (s) */
T> +	int32_t		tt_delack;		/* (s) */
T> +	int32_t		spare32[32];
T> +} __aligned(8);
T> +#ifdef _KERNEL
T> +void	tcp_inptoxtp(const struct inpcb *, struct xtcpcb *);
T> +#endif
T>  #endif
T>  
T>  /*
T> 
T> Modified: head/sys/netinet/udp_usrreq.c
T> ==============================================================================
T> --- head/sys/netinet/udp_usrreq.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/netinet/udp_usrreq.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -905,13 +905,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
T>  		if (inp->inp_gencnt <= gencnt) {
T>  			struct xinpcb xi;
T>  
T> -			bzero(&xi, sizeof(xi));
T> -			xi.xi_len = sizeof xi;
T> -			/* XXX should avoid extra copy */
T> -			bcopy(inp, &xi.xi_inp, sizeof *inp);
T> -			if (inp->inp_socket)
T> -				sotoxsocket(inp->inp_socket, &xi.xi_socket);
T> -			xi.xi_inp.inp_gencnt = inp->inp_gencnt;
T> +			in_pcbtoxinpcb(inp, &xi);
T>  			INP_RUNLOCK(inp);
T>  			error = SYSCTL_OUT(req, &xi, sizeof xi);
T>  		} else
T> 
T> Modified: head/sys/sys/param.h
T> ==============================================================================
T> --- head/sys/sys/param.h	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/sys/sys/param.h	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -58,7 +58,7 @@
T>   *		in the range 5 to 9.
T>   */
T>  #undef __FreeBSD_version
T> -#define __FreeBSD_version 1200025	/* Master, propagated to newvers */
T> +#define __FreeBSD_version 1200026	/* Master, propagated to newvers */
T>  
T>  /*
T>   * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
T> 
T> Modified: head/usr.bin/netstat/inet.c
T> ==============================================================================
T> --- head/usr.bin/netstat/inet.c	Tue Mar 21 05:15:10 2017	(r315661)
T> +++ head/usr.bin/netstat/inet.c	Tue Mar 21 06:39:49 2017	(r315662)
T> @@ -91,7 +91,7 @@ static int udp_done, tcp_done, sdp_done;
T>  #endif /* INET6 */
T>  
T>  static int
T> -pcblist_sysctl(int proto, const char *name, char **bufp, int istcp __unused)
T> +pcblist_sysctl(int proto, const char *name, char **bufp)
T>  {
T>  	const char *mibvar;
T>  	char *buf;
T> @@ -181,120 +181,6 @@ sotoxsocket(struct socket *so, struct xs
T>  	return (0);
T>  }
T>  
T> -static int
T> -pcblist_kvm(u_long off, char **bufp, int istcp)
T> -{
T> -	struct inpcbinfo pcbinfo;
T> -	struct inpcbhead listhead;
T> -	struct inpcb *inp;
T> -	struct xinpcb xi;
T> -	struct xinpgen xig;
T> -	struct xtcpcb xt;
T> -	struct socket so;
T> -	struct xsocket *xso;
T> -	char *buf, *p;
T> -	size_t len;
T> -
T> -	if (off == 0)
T> -		return (0);
T> -	kread(off, &pcbinfo, sizeof(pcbinfo));
T> -	if (istcp)
T> -		len = 2 * sizeof(xig) +
T> -		    (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
T> -		    sizeof(struct xtcpcb);
T> -	else
T> -		len = 2 * sizeof(xig) +
T> -		    (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
T> -		    sizeof(struct xinpcb);
T> -	if ((buf = malloc(len)) == NULL) {
T> -		xo_warnx("malloc %lu bytes", (u_long)len);
T> -		return (0);
T> -	}
T> -	p = buf;
T> -
T> -#define	COPYOUT(obj, size) do {						\
T> -	if (len < (size)) {						\
T> -		xo_warnx("buffer size exceeded");			\
T> -		goto fail;						\
T> -	}								\
T> -	bcopy((obj), p, (size));					\
T> -	len -= (size);							\
T> -	p += (size);							\
T> -} while (0)
T> -
T> -#define	KREAD(off, buf, len) do {					\
T> -	if (kread((uintptr_t)(off), (buf), (len)) != 0)			\
T> -		goto fail;						\
T> -} while (0)
T> -
T> -	/* Write out header. */
T> -	xig.xig_len = sizeof xig;
T> -	xig.xig_count = pcbinfo.ipi_count;
T> -	xig.xig_gen = pcbinfo.ipi_gencnt;
T> -	xig.xig_sogen = 0;
T> -	COPYOUT(&xig, sizeof xig);
T> -
T> -	/* Walk the PCB list. */
T> -	xt.xt_len = sizeof xt;
T> -	xi.xi_len = sizeof xi;
T> -	if (istcp)
T> -		xso = &xt.xt_socket;
T> -	else
T> -		xso = &xi.xi_socket;
T> -	KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead));
T> -	LIST_FOREACH(inp, &listhead, inp_list) {
T> -		if (istcp) {
T> -			KREAD(inp, &xt.xt_inp, sizeof(*inp));
T> -			inp = &xt.xt_inp;
T> -		} else {
T> -			KREAD(inp, &xi.xi_inp, sizeof(*inp));
T> -			inp = &xi.xi_inp;
T> -		}
T> -
T> -		if (inp->inp_gencnt > pcbinfo.ipi_gencnt)
T> -			continue;
T> -
T> -		if (istcp) {
T> -			if (inp->inp_ppcb == NULL)
T> -				bzero(&xt.xt_tp, sizeof xt.xt_tp);
T> -			else if (inp->inp_flags & INP_TIMEWAIT) {
T> -				bzero(&xt.xt_tp, sizeof xt.xt_tp);
T> -				xt.xt_tp.t_state = TCPS_TIME_WAIT;
T> -			} else
T> -				KREAD(inp->inp_ppcb, &xt.xt_tp,
T> -				    sizeof xt.xt_tp);
T> -		}
T> -		if (inp->inp_socket) {
T> -			KREAD(inp->inp_socket, &so, sizeof(so));
T> -			if (sotoxsocket(&so, xso) != 0)
T> -				goto fail;
T> -		} else {
T> -			bzero(xso, sizeof(*xso));
T> -			if (istcp)
T> -				xso->xso_protocol = IPPROTO_TCP;
T> -		}
T> -		if (istcp)
T> -			COPYOUT(&xt, sizeof xt);
T> -		else
T> -			COPYOUT(&xi, sizeof xi);
T> -	}
T> -
T> -	/* Reread the pcbinfo and write out the footer. */
T> -	kread(off, &pcbinfo, sizeof(pcbinfo));
T> -	xig.xig_count = pcbinfo.ipi_count;
T> -	xig.xig_gen = pcbinfo.ipi_gencnt;
T> -	COPYOUT(&xig, sizeof xig);
T> -
T> -	*bufp = buf;
T> -	return (1);
T> -
T> -fail:
T> -	free(buf);
T> -	return (0);
T> -#undef COPYOUT
T> -#undef KREAD
T> -}
T> -
T>  /*
T>   * Print a summary of connections related to an Internet
T>   * protocol.  For TCP, also give state of connection.
T> @@ -304,15 +190,14 @@ fail:
T>  void
T>  protopr(u_long off, const char *name, int af1, int proto)
T>  {
T> -	int istcp;
T>  	static int first = 1;
T> +	int istcp;
T>  	char *buf;
T>  	const char *vchar;
T> -	struct tcpcb *tp = NULL;
T> -	struct inpcb *inp;
T> +	struct xtcpcb *tp;
T> +	struct xinpcb *inp;
T>  	struct xinpgen *xig, *oxig;
T>  	struct xsocket *so;
T> -	struct xtcp_timer *timer;
T>  
T>  	istcp = 0;
T>  	switch (proto) {
T> @@ -341,28 +226,21 @@ protopr(u_long off, const char *name, in
T>  #endif
T>  		break;
T>  	}
T> -	if (live) {
T> -		if (!pcblist_sysctl(proto, name, &buf, istcp))
T> -			return;
T> -	} else {
T> -		if (!pcblist_kvm(off, &buf, istcp))
T> -			return;
T> -	}
T> +
T> +	if (!pcblist_sysctl(proto, name, &buf))
T> +		return;
T>  
T>  	oxig = xig = (struct xinpgen *)buf;
T>  	for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
T>  	    xig->xig_len > sizeof(struct xinpgen);
T>  	    xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
T>  		if (istcp) {
T> -			timer = &((struct xtcpcb *)xig)->xt_timer;
T> -			tp = &((struct xtcpcb *)xig)->xt_tp;
T> -			inp = &((struct xtcpcb *)xig)->xt_inp;
T> -			so = &((struct xtcpcb *)xig)->xt_socket;
T> +			tp = (struct xtcpcb *)xig;
T> +			inp = &tp->xt_inp;
T>  		} else {
T> -			inp = &((struct xinpcb *)xig)->xi_inp;
T> -			so = &((struct xinpcb *)xig)->xi_socket;
T> -			timer = NULL;
T> +			inp = (struct xinpcb *)xig;
T>  		}
T> +		so = &inp->xi_socket;
T>  
T> 
T> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
T> _______________________________________________
T> svn-src-all@freebsd.org mailing list
T> https://lists.freebsd.org/mailman/listinfo/svn-src-all
T> To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"

-- 
Totus tuus, Glebius.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170321064154.GL23308>