Index: head/contrib/bsnmp/snmp_mibII/mibII_tcp.c =================================================================== --- head/contrib/bsnmp/snmp_mibII/mibII_tcp.c +++ head/contrib/bsnmp/snmp_mibII/mibII_tcp.c @@ -310,7 +310,7 @@ switch (value->var.subs[sub - 1]) { case LEAF_tcpConnState: - switch (tcpoids[i].tp->xt_tp.t_state) { + switch (tcpoids[i].tp->t_state) { case TCPS_CLOSED: value->v.integer = 1; Index: head/contrib/bsnmp/snmp_mibII/mibII_udp.c =================================================================== --- head/contrib/bsnmp/snmp_mibII/mibII_udp.c +++ head/contrib/bsnmp/snmp_mibII/mibII_udp.c @@ -105,8 +105,8 @@ ptr->xig_len > sizeof(struct xinpgen); ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { inp = (struct xinpcb *)ptr; - if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || - (inp->xi_inp.inp_vflag & INP_IPV4) == 0) + if (inp->inp_gencnt > xinpgen->xig_gen || + (inp->inp_vflag & INP_IPV4) == 0) continue; udp_total++; @@ -128,17 +128,17 @@ ptr->xig_len > sizeof(struct xinpgen); ptr = (struct xinpgen *)(void *)((char *)ptr + ptr->xig_len)) { inp = (struct xinpcb *)ptr; - if (inp->xi_inp.inp_gencnt > xinpgen->xig_gen || - (inp->xi_inp.inp_vflag & INP_IPV4) == 0) + if (inp->inp_gencnt > xinpgen->xig_gen || + (inp->inp_vflag & INP_IPV4) == 0) continue; oid->inp = inp; oid->index.len = 5; - inaddr = ntohl(inp->xi_inp.inp_laddr.s_addr); + inaddr = ntohl(inp->inp_laddr.s_addr); oid->index.subs[0] = (inaddr >> 24) & 0xff; oid->index.subs[1] = (inaddr >> 16) & 0xff; oid->index.subs[2] = (inaddr >> 8) & 0xff; oid->index.subs[3] = (inaddr >> 0) & 0xff; - oid->index.subs[4] = ntohs(inp->xi_inp.inp_lport); + oid->index.subs[4] = ntohs(inp->inp_lport); oid++; } Index: head/contrib/ipfilter/ipsend/sock.c =================================================================== --- head/contrib/ipfilter/ipsend/sock.c +++ head/contrib/ipfilter/ipsend/sock.c @@ -78,8 +78,10 @@ # include #endif #include +#define _WANT_INPCB #include #include +#define _WANT_TCPCB #include #include #include Index: head/lib/libprocstat/libprocstat.c =================================================================== --- head/lib/libprocstat/libprocstat.c +++ head/lib/libprocstat/libprocstat.c @@ -82,6 +82,7 @@ #include #include #include +#define _WANT_INPCB #include #include Index: head/sys/netinet/in_pcb.h =================================================================== --- head/sys/netinet/in_pcb.h +++ head/sys/netinet/in_pcb.h @@ -53,7 +53,6 @@ #define in6pcb inpcb /* for KAME src sync over BSD*'s */ #define in6p_sp inp_sp /* for KAME src sync over BSD*'s */ -struct inpcbpolicy; /* * struct inpcb is the common protocol control block structure used in most @@ -65,7 +64,7 @@ */ LIST_HEAD(inpcbhead, inpcb); LIST_HEAD(inpcbporthead, inpcbport); -typedef u_quad_t inp_gen_t; +typedef uint64_t inp_gen_t; /* * PCB with AF_INET6 null bind'ed laddr can receive AF_INET input packet. @@ -130,9 +129,8 @@ #define inc6_laddr inc_ie.ie6_laddr #define inc6_zoneid inc_ie.ie6_zoneid -struct icmp6_filter; - -/*- +#if defined(_KERNEL) || defined(_WANT_INPCB) +/* * struct inpcb captures the network layer state for TCP, UDP, and raw IPv4 and * IPv6 sockets. In the case of TCP and UDP, further per-connection state is * hung off of inp_ppcb most of the time. Almost all fields of struct inpcb @@ -181,6 +179,8 @@ * read-lock usage during modification, this model can be applied to other * protocols (especially SCTP). */ +struct icmp6_filter; +struct inpcbpolicy; struct m_snd_tag; struct inpcb { LIST_ENTRY(inpcb) inp_hash; /* (h/i) hash list */ @@ -204,10 +204,8 @@ uint32_t inp_flowid; /* (x) flow id / queue id */ u_int inp_refcount; /* (i) refcount */ struct m_snd_tag *inp_snd_tag; /* (i) send tag for outgoing mbufs */ - void *inp_pspare[4]; /* (x) general use */ uint32_t inp_flowtype; /* (x) M_HASHTYPE value */ uint32_t inp_rss_listen_bucket; /* (x) overridden RSS listen bucket */ - u_int inp_ispare[4]; /* (x) user cookie / general use */ /* Local and foreign ports, local and foreign addr. */ struct in_conninfo inp_inc; /* (i) list for PCB's local port */ @@ -218,23 +216,23 @@ /* Protocol-dependent part; options. */ struct { - u_char inp4_ip_tos; /* (i) type of service proto */ - struct mbuf *inp4_options; /* (i) IP options */ - struct ip_moptions *inp4_moptions; /* (i) IP mcast options */ - } inp_depend4; + u_char inp_ip_tos; /* (i) type of service proto */ + struct mbuf *inp_options; /* (i) IP options */ + struct ip_moptions *inp_moptions; /* (i) mcast options */ + }; struct { /* (i) IP options */ - struct mbuf *inp6_options; + struct mbuf *in6p_options; /* (i) IP6 options for outgoing packets */ - struct ip6_pktopts *inp6_outputopts; + struct ip6_pktopts *in6p_outputopts; /* (i) IP multicast options */ - struct ip6_moptions *inp6_moptions; + struct ip6_moptions *in6p_moptions; /* (i) ICMPv6 code type filter */ - struct icmp6_filter *inp6_icmp6filt; + struct icmp6_filter *in6p_icmp6filt; /* (i) IPV6_CHECKSUM setsockopt */ - int inp6_cksum; - short inp6_hops; - } inp_depend6; + int in6p_cksum; + short in6p_hops; + }; LIST_ENTRY(inpcb) inp_portlist; /* (i/h) */ struct inpcbport *inp_phd; /* (i/h) head of this list */ #define inp_zero_size offsetof(struct inpcb, inp_gencnt) @@ -249,24 +247,17 @@ #define inp_route inp_rtu.inpu_route #define inp_route6 inp_rtu.inpu_route6 }; +#endif /* _KERNEL */ + #define inp_fport inp_inc.inc_fport #define inp_lport inp_inc.inc_lport #define inp_faddr inp_inc.inc_faddr #define inp_laddr inp_inc.inc_laddr -#define inp_ip_tos inp_depend4.inp4_ip_tos -#define inp_options inp_depend4.inp4_options -#define inp_moptions inp_depend4.inp4_moptions #define in6p_faddr inp_inc.inc6_faddr #define in6p_laddr inp_inc.inc6_laddr #define in6p_zoneid inp_inc.inc6_zoneid -#define in6p_hops inp_depend6.inp6_hops /* default hop limit */ #define in6p_flowinfo inp_flow -#define in6p_options inp_depend6.inp6_options -#define in6p_outputopts inp_depend6.inp6_outputopts -#define in6p_moptions inp_depend6.inp6_moptions -#define in6p_icmp6filt inp_depend6.inp6_icmp6filt -#define in6p_cksum inp_depend6.inp6_cksum #define inp_vnet inp_pcbinfo->ipi_vnet @@ -280,21 +271,53 @@ /* * Interface exported to userland by various protocols which use inpcbs. Hack * alert -- only define if struct xsocket is in scope. + * Fields prefixed with "xi_" are unique to this structure, and the rest + * match fields in the struct inpcb, to ease coding and porting. + * + * Legend: + * (s) - used by userland utilities in src + * (p) - used by utilities in ports + * (3) - is known to be used by third party software not in ports + * (n) - no known usage */ #ifdef _SYS_SOCKETVAR_H_ -struct xinpcb { - size_t xi_len; /* length of this structure */ - struct inpcb xi_inp; - struct xsocket xi_socket; - u_quad_t xi_alignment_hack; -}; - -struct xinpgen { - size_t xig_len; /* length of this structure */ - u_int xig_count; /* number of PCBs at this time */ - inp_gen_t xig_gen; /* generation count at this time */ - so_gen_t xig_sogen; /* socket generation count at this time */ +struct xinpcb { + size_t xi_len; /* length of this structure */ + struct xsocket xi_socket; /* (s,p) */ + struct in_conninfo inp_inc; /* (s,p) */ + uint64_t inp_gencnt; /* (s,p) */ + union { + void *inp_ppcb; /* (s) netstat(1) */ + int64_t ph_ppcb; + }; + int64_t inp_spare64[4]; + uint32_t inp_flow; /* (s) */ + uint32_t inp_flowid; /* (s) */ + uint32_t inp_flowtype; /* (s) */ + int32_t inp_flags; /* (s,p) */ + int32_t inp_flags2; /* (s) */ + int32_t inp_rss_listen_bucket; /* (n) */ + int32_t in6p_cksum; /* (n) */ + int32_t inp_spare32[4]; + uint16_t in6p_hops; /* (n) */ + uint8_t inp_ip_tos; /* (n) */ + int8_t pad8; + uint8_t inp_vflag; /* (s,p) */ + uint8_t inp_ip_ttl; /* (n) */ + uint8_t inp_ip_p; /* (n) */ + uint8_t inp_ip_minttl; /* (n) */ + int8_t inp_spare8[4]; +} __aligned(8); + +struct xinpgen { + size_t xig_len; /* length of this structure */ + u_int xig_count; /* number of PCBs at this time */ + inp_gen_t xig_gen; /* generation count at this time */ + so_gen_t xig_sogen; /* socket generation count this time */ }; +#ifdef _KERNEL +void in_pcbtoxinpcb(const struct inpcb *, struct xinpcb *); +#endif #endif /* _SYS_SOCKETVAR_H_ */ struct inpcbport { Index: head/sys/netinet/in_pcb.c =================================================================== --- head/sys/netinet/in_pcb.c +++ head/sys/netinet/in_pcb.c @@ -2434,6 +2434,41 @@ return (sototcpcb(so)); } +/* + * Create an external-format (``xinpcb'') structure using the information in + * the kernel-format in_pcb structure pointed to by inp. This is done to + * reduce the spew of irrelevant information over this interface, to isolate + * user code from changes in the kernel structure, and potentially to provide + * information-hiding if we decide that some of this information should be + * hidden from users. + */ +void +in_pcbtoxinpcb(const struct inpcb *inp, struct xinpcb *xi) +{ + + xi->xi_len = sizeof(struct xinpcb); + if (inp->inp_socket) + sotoxsocket(inp->inp_socket, &xi->xi_socket); + else + bzero(&xi->xi_socket, sizeof(struct xsocket)); + bcopy(&inp->inp_inc, &xi->inp_inc, sizeof(struct in_conninfo)); + xi->inp_gencnt = inp->inp_gencnt; + xi->inp_ppcb = inp->inp_ppcb; + xi->inp_flow = inp->inp_flow; + xi->inp_flowid = inp->inp_flowid; + xi->inp_flowtype = inp->inp_flowtype; + xi->inp_flags = inp->inp_flags; + xi->inp_flags2 = inp->inp_flags2; + xi->inp_rss_listen_bucket = inp->inp_rss_listen_bucket; + xi->in6p_cksum = inp->in6p_cksum; + xi->in6p_hops = inp->in6p_hops; + xi->inp_ip_tos = inp->inp_ip_tos; + xi->inp_vflag = inp->inp_vflag; + xi->inp_ip_ttl = inp->inp_ip_ttl; + xi->inp_ip_p = inp->inp_ip_p; + xi->inp_ip_minttl = inp->inp_ip_minttl; +} + #ifdef DDB static void db_print_indent(int indent) Index: head/sys/netinet/ip_divert.c =================================================================== --- head/sys/netinet/ip_divert.c +++ head/sys/netinet/ip_divert.c @@ -691,12 +691,8 @@ INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt) { struct xinpcb xi; - bzero(&xi, sizeof(xi)); - xi.xi_len = sizeof xi; - /* XXX should avoid extra copy */ - bcopy(inp, &xi.xi_inp, sizeof *inp); - if (inp->inp_socket) - sotoxsocket(inp->inp_socket, &xi.xi_socket); + + in_pcbtoxinpcb(inp, &xi); INP_RUNLOCK(inp); error = SYSCTL_OUT(req, &xi, sizeof xi); } else Index: head/sys/netinet/raw_ip.c =================================================================== --- head/sys/netinet/raw_ip.c +++ head/sys/netinet/raw_ip.c @@ -1077,12 +1077,7 @@ if (inp->inp_gencnt <= gencnt) { struct xinpcb xi; - bzero(&xi, sizeof(xi)); - xi.xi_len = sizeof xi; - /* XXX should avoid extra copy */ - bcopy(inp, &xi.xi_inp, sizeof *inp); - if (inp->inp_socket) - sotoxsocket(inp->inp_socket, &xi.xi_socket); + in_pcbtoxinpcb(inp, &xi); INP_RUNLOCK(inp); error = SYSCTL_OUT(req, &xi, sizeof xi); } else Index: head/sys/netinet/tcp_subr.c =================================================================== --- head/sys/netinet/tcp_subr.c +++ head/sys/netinet/tcp_subr.c @@ -1773,30 +1773,8 @@ INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt) { struct xtcpcb xt; - void *inp_ppcb; - bzero(&xt, sizeof(xt)); - xt.xt_len = sizeof xt; - /* XXX should avoid extra copy */ - bcopy(inp, &xt.xt_inp, sizeof *inp); - inp_ppcb = inp->inp_ppcb; - if (inp_ppcb == NULL) - bzero((char *) &xt.xt_tp, sizeof xt.xt_tp); - else if (inp->inp_flags & INP_TIMEWAIT) { - bzero((char *) &xt.xt_tp, sizeof xt.xt_tp); - xt.xt_tp.t_state = TCPS_TIME_WAIT; - } else { - bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp); - if (xt.xt_tp.t_timers) - tcp_timer_to_xtimer(&xt.xt_tp, xt.xt_tp.t_timers, &xt.xt_timer); - } - if (inp->inp_socket != NULL) - sotoxsocket(inp->inp_socket, &xt.xt_socket); - else { - bzero(&xt.xt_socket, sizeof xt.xt_socket); - xt.xt_socket.xso_protocol = IPPROTO_TCP; - } - xt.xt_inp.inp_gencnt = inp->inp_gencnt; + tcp_inptoxtp(inp, &xt); INP_RUNLOCK(inp); error = SYSCTL_OUT(req, &xt, sizeof xt); } else @@ -2765,3 +2743,53 @@ tp->t_state = newstate; TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate); } + +/* + * Create an external-format (``xtcpcb'') structure using the information in + * the kernel-format tcpcb structure pointed to by tp. This is done to + * reduce the spew of irrelevant information over this interface, to isolate + * user code from changes in the kernel structure, and potentially to provide + * information-hiding if we decide that some of this information should be + * hidden from users. + */ +void +tcp_inptoxtp(const struct inpcb *inp, struct xtcpcb *xt) +{ + struct tcpcb *tp = intotcpcb(inp); + sbintime_t now; + + if (inp->inp_flags & INP_TIMEWAIT) { + bzero(xt, sizeof(struct xtcpcb)); + xt->t_state = TCPS_TIME_WAIT; + } else { + xt->t_state = tp->t_state; + xt->t_flags = tp->t_flags; + xt->t_sndzerowin = tp->t_sndzerowin; + xt->t_sndrexmitpack = tp->t_sndrexmitpack; + xt->t_rcvoopack = tp->t_rcvoopack; + + now = getsbinuptime(); +#define COPYTIMER(ttt) do { \ + if (callout_active(&tp->t_timers->ttt)) \ + xt->ttt = (tp->t_timers->ttt.c_time - now) / \ + SBT_1MS; \ + else \ + xt->ttt = 0; \ +} while (0) + COPYTIMER(tt_delack); + COPYTIMER(tt_rexmt); + COPYTIMER(tt_persist); + COPYTIMER(tt_keep); + COPYTIMER(tt_2msl); +#undef COPYTIMER + xt->t_rcvtime = 1000 * (ticks - tp->t_rcvtime) / hz; + + bcopy(tp->t_fb->tfb_tcp_block_name, xt->xt_stack, + TCP_FUNCTION_NAME_LEN_MAX); + } + + xt->xt_len = sizeof(struct xtcpcb); + in_pcbtoxinpcb(inp, &xt->xt_inp); + if (inp->inp_socket == NULL) + xt->xt_inp.xi_socket.xso_protocol = IPPROTO_TCP; +} Index: head/sys/netinet/tcp_syncache.c =================================================================== --- head/sys/netinet/tcp_syncache.c +++ head/sys/netinet/tcp_syncache.c @@ -2217,13 +2217,13 @@ xt.xt_inp.inp_vflag = INP_IPV6; else xt.xt_inp.inp_vflag = INP_IPV4; - bcopy(&sc->sc_inc, &xt.xt_inp.inp_inc, sizeof (struct in_conninfo)); - xt.xt_tp.t_inpcb = &xt.xt_inp; - xt.xt_tp.t_state = TCPS_SYN_RECEIVED; - xt.xt_socket.xso_protocol = IPPROTO_TCP; - xt.xt_socket.xso_len = sizeof (struct xsocket); - xt.xt_socket.so_type = SOCK_STREAM; - xt.xt_socket.so_state = SS_ISCONNECTING; + bcopy(&sc->sc_inc, &xt.xt_inp.inp_inc, + sizeof (struct in_conninfo)); + xt.t_state = TCPS_SYN_RECEIVED; + xt.xt_inp.xi_socket.xso_protocol = IPPROTO_TCP; + xt.xt_inp.xi_socket.xso_len = sizeof (struct xsocket); + xt.xt_inp.xi_socket.so_type = SOCK_STREAM; + xt.xt_inp.xi_socket.so_state = SS_ISCONNECTING; error = SYSCTL_OUT(req, &xt, sizeof xt); if (error) { SCH_UNLOCK(sch); Index: head/sys/netinet/tcp_timer.h =================================================================== --- head/sys/netinet/tcp_timer.h +++ head/sys/netinet/tcp_timer.h @@ -210,8 +210,6 @@ void tcp_timer_persist(void *xtp); void tcp_timer_rexmt(void *xtp); void tcp_timer_delack(void *xtp); -void tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer, - struct xtcp_timer *xtimer); #endif /* _KERNEL */ Index: head/sys/netinet/tcp_timer.c =================================================================== --- head/sys/netinet/tcp_timer.c +++ head/sys/netinet/tcp_timer.c @@ -1006,28 +1006,3 @@ tp->t_timers->tt_draincnt++; } } - -#define ticks_to_msecs(t) (1000*(t) / hz) - -void -tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer, - struct xtcp_timer *xtimer) -{ - sbintime_t now; - - bzero(xtimer, sizeof(*xtimer)); - if (timer == NULL) - return; - now = getsbinuptime(); - if (callout_active(&timer->tt_delack)) - xtimer->tt_delack = (timer->tt_delack.c_time - now) / SBT_1MS; - if (callout_active(&timer->tt_rexmt)) - xtimer->tt_rexmt = (timer->tt_rexmt.c_time - now) / SBT_1MS; - if (callout_active(&timer->tt_persist)) - xtimer->tt_persist = (timer->tt_persist.c_time - now) / SBT_1MS; - if (callout_active(&timer->tt_keep)) - xtimer->tt_keep = (timer->tt_keep.c_time - now) / SBT_1MS; - if (callout_active(&timer->tt_2msl)) - xtimer->tt_2msl = (timer->tt_2msl.c_time - now) / SBT_1MS; - xtimer->t_rcvtime = ticks_to_msecs(ticks - tp->t_rcvtime); -} Index: head/sys/netinet/tcp_var.h =================================================================== --- head/sys/netinet/tcp_var.h +++ head/sys/netinet/tcp_var.h @@ -39,15 +39,9 @@ #ifdef _KERNEL #include #include +#endif -/* - * Kernel variables for tcp. - */ -VNET_DECLARE(int, tcp_do_rfc1323); -#define V_tcp_do_rfc1323 VNET(tcp_do_rfc1323) - -#endif /* _KERNEL */ - +#if defined(_KERNEL) || defined(_WANT_TCPCB) /* TCP segment queue entry */ struct tseg_qent { LIST_ENTRY(tseg_qent) tqe_q; @@ -83,90 +77,12 @@ uint64_t _pad[1]; /* TBD */ }; -struct tcptemp { - u_char tt_ipgen[40]; /* the size must be of max ip header, now IPv6 */ - struct tcphdr tt_t; -}; - -#define tcp6cb tcpcb /* for KAME src sync over BSD*'s */ - -/* - * TODO: We yet need to brave plowing in - * to tcp_input() and the pru_usrreq() block. - * Right now these go to the old standards which - * are somewhat ok, but in the long term may - * need to be changed. If we do tackle tcp_input() - * then we need to get rid of the tcp_do_segment() - * function below. - */ -/* Flags for tcp functions */ -#define TCP_FUNC_BEING_REMOVED 0x01 /* Can no longer be referenced */ -struct tcpcb; -struct inpcb; -struct sockopt; -struct socket; - -/* - * If defining the optional tcp_timers, in the - * tfb_tcp_timer_stop call you must use the - * callout_async_drain() function with the - * tcp_timer_discard callback. You should check - * the return of callout_async_drain() and if 0 - * increment tt_draincnt. Since the timer sub-system - * does not know your callbacks you must provide a - * stop_all function that loops through and calls - * tcp_timer_stop() with each of your defined timers. - * Adding a tfb_tcp_handoff_ok function allows the socket - * option to change stacks to query you even if the - * connection is in a later stage. You return 0 to - * say you can take over and run your stack, you return - * non-zero (an error number) to say no you can't. - * If the function is undefined you can only change - * in the early states (before connect or listen). - * tfb_tcp_fb_fini is changed to add a flag to tell - * the old stack if the tcb is being destroyed or - * not. A one in the flag means the TCB is being - * destroyed, a zero indicates its transitioning to - * another stack (via socket option). - */ -struct tcp_function_block { - char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX]; - int (*tfb_tcp_output)(struct tcpcb *); - void (*tfb_tcp_do_segment)(struct mbuf *, struct tcphdr *, - struct socket *, struct tcpcb *, - int, int, uint8_t, - int); - int (*tfb_tcp_ctloutput)(struct socket *so, struct sockopt *sopt, - struct inpcb *inp, struct tcpcb *tp); - /* Optional memory allocation/free routine */ - void (*tfb_tcp_fb_init)(struct tcpcb *); - void (*tfb_tcp_fb_fini)(struct tcpcb *, int); - /* Optional timers, must define all if you define one */ - int (*tfb_tcp_timer_stop_all)(struct tcpcb *); - void (*tfb_tcp_timer_activate)(struct tcpcb *, - uint32_t, u_int); - int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t); - void (*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t); - void (*tfb_tcp_rexmit_tmr)(struct tcpcb *); - int (*tfb_tcp_handoff_ok)(struct tcpcb *); - volatile uint32_t tfb_refcnt; - uint32_t tfb_flags; -}; - -struct tcp_function { - TAILQ_ENTRY(tcp_function) tf_next; - struct tcp_function_block *tf_fb; -}; - -TAILQ_HEAD(tcp_funchead, tcp_function); - /* * Tcp control block, one per tcp; fields: * Organized for 16 byte cacheline efficiency. */ struct tcpcb { struct tsegqe_head t_segq; /* segment reassembly queue */ - void *t_pspare[2]; /* new reassembly queue */ int t_segqlen; /* segment reassembly queue length */ int t_dupacks; /* consecutive dup acks recd */ @@ -197,12 +113,10 @@ uint32_t snd_wnd; /* send window */ uint32_t snd_cwnd; /* congestion-controlled window */ - u_long snd_spare1; /* unused */ uint32_t snd_ssthresh; /* snd_cwnd size threshold for * for slow start exponential to * linear switch */ - u_long snd_spare2; /* unused */ tcp_seq snd_recover; /* for use in NewReno Fast Recovery */ u_int t_rcvtime; /* inactivity time */ @@ -210,9 +124,6 @@ u_int t_rtttime; /* RTT measurement start time */ tcp_seq t_rtseq; /* sequence number being timed */ - u_int t_bw_spare1; /* unused */ - tcp_seq t_bw_spare2; /* unused */ - int t_rxtcur; /* current retransmit value (ticks) */ u_int t_maxseg; /* maximum segment size */ u_int t_pmtud_saved_maxseg; /* pre-blackhole MSS */ @@ -276,33 +187,98 @@ u_int t_tsomaxsegcount; /* TSO maximum segment count */ u_int t_tsomaxsegsize; /* TSO maximum segment size in bytes */ u_int t_flags2; /* More tcpcb flags storage */ -#if defined(_KERNEL) && defined(TCP_RFC7413) - uint32_t t_ispare[6]; /* 5 UTO, 1 TBD */ - uint64_t t_tfo_cookie; /* TCP Fast Open cookie */ -#else - uint32_t t_ispare[8]; /* 5 UTO, 3 TBD */ -#endif struct tcp_function_block *t_fb;/* TCP function call block */ void *t_fb_ptr; /* Pointer to t_fb specific data */ -#if defined(_KERNEL) && defined(TCP_RFC7413) +#ifdef TCP_RFC7413 + uint64_t t_tfo_cookie; /* TCP Fast Open cookie */ unsigned int *t_tfo_pending; /* TCP Fast Open pending counter */ - void *t_pspare2[1]; /* 1 TCP_SIGNATURE */ -#else - void *t_pspare2[2]; /* 1 TCP_SIGNATURE, 1 TBD */ #endif -#if defined(_KERNEL) && defined(TCPPCAP) +#ifdef TCPPCAP struct mbufq t_inpkts; /* List of saved input packets. */ struct mbufq t_outpkts; /* List of saved output packets. */ -#ifdef _LP64 - uint64_t _pad[0]; /* all used! */ -#else - uint64_t _pad[2]; /* 2 are available */ -#endif /* _LP64 */ -#else - uint64_t _pad[6]; -#endif /* defined(_KERNEL) && defined(TCPPCAP) */ +#endif +}; +#endif /* _KERNEL || _WANT_TCPCB */ + +#ifdef _KERNEL +/* + * Kernel variables for tcp. + */ +VNET_DECLARE(int, tcp_do_rfc1323); +#define V_tcp_do_rfc1323 VNET(tcp_do_rfc1323) + +struct tcptemp { + u_char tt_ipgen[40]; /* the size must be of max ip header, now IPv6 */ + struct tcphdr tt_t; }; +/* + * TODO: We yet need to brave plowing in + * to tcp_input() and the pru_usrreq() block. + * Right now these go to the old standards which + * are somewhat ok, but in the long term may + * need to be changed. If we do tackle tcp_input() + * then we need to get rid of the tcp_do_segment() + * function below. + */ +/* Flags for tcp functions */ +#define TCP_FUNC_BEING_REMOVED 0x01 /* Can no longer be referenced */ + +/* + * If defining the optional tcp_timers, in the + * tfb_tcp_timer_stop call you must use the + * callout_async_drain() function with the + * tcp_timer_discard callback. You should check + * the return of callout_async_drain() and if 0 + * increment tt_draincnt. Since the timer sub-system + * does not know your callbacks you must provide a + * stop_all function that loops through and calls + * tcp_timer_stop() with each of your defined timers. + * Adding a tfb_tcp_handoff_ok function allows the socket + * option to change stacks to query you even if the + * connection is in a later stage. You return 0 to + * say you can take over and run your stack, you return + * non-zero (an error number) to say no you can't. + * If the function is undefined you can only change + * in the early states (before connect or listen). + * tfb_tcp_fb_fini is changed to add a flag to tell + * the old stack if the tcb is being destroyed or + * not. A one in the flag means the TCB is being + * destroyed, a zero indicates its transitioning to + * another stack (via socket option). + */ +struct tcp_function_block { + char tfb_tcp_block_name[TCP_FUNCTION_NAME_LEN_MAX]; + int (*tfb_tcp_output)(struct tcpcb *); + void (*tfb_tcp_do_segment)(struct mbuf *, struct tcphdr *, + struct socket *, struct tcpcb *, + int, int, uint8_t, + int); + int (*tfb_tcp_ctloutput)(struct socket *so, struct sockopt *sopt, + struct inpcb *inp, struct tcpcb *tp); + /* Optional memory allocation/free routine */ + void (*tfb_tcp_fb_init)(struct tcpcb *); + void (*tfb_tcp_fb_fini)(struct tcpcb *, int); + /* Optional timers, must define all if you define one */ + int (*tfb_tcp_timer_stop_all)(struct tcpcb *); + void (*tfb_tcp_timer_activate)(struct tcpcb *, + uint32_t, u_int); + int (*tfb_tcp_timer_active)(struct tcpcb *, uint32_t); + void (*tfb_tcp_timer_stop)(struct tcpcb *, uint32_t); + void (*tfb_tcp_rexmit_tmr)(struct tcpcb *); + int (*tfb_tcp_handoff_ok)(struct tcpcb *); + volatile uint32_t tfb_refcnt; + uint32_t tfb_flags; +}; + +struct tcp_function { + TAILQ_ENTRY(tcp_function) tf_next; + struct tcp_function_block *tf_fb; +}; + +TAILQ_HEAD(tcp_funchead, tcp_function); +#endif /* _KERNEL */ + /* * Flags and utility macros for the t_flags field. */ @@ -656,26 +632,41 @@ /* * TCB structure exported to user-land via sysctl(3). + * + * Fields prefixed with "xt_" are unique to the export structure, and fields + * with "t_" or other prefixes match corresponding fields of 'struct tcpcb'. + * + * Legend: + * (s) - used by userland utilities in src + * (p) - used by utilities in ports + * (3) - is known to be used by third party software not in ports + * (n) - no known usage + * * Evil hack: declare only if in_pcb.h and sys/socketvar.h have been * included. Not all of our clients do. */ #if defined(_NETINET_IN_PCB_H_) && defined(_SYS_SOCKETVAR_H_) -struct xtcp_timer { - int tt_rexmt; /* retransmit timer */ - int tt_persist; /* retransmit persistence */ - int tt_keep; /* keepalive */ - int tt_2msl; /* 2*msl TIME_WAIT timer */ - int tt_delack; /* delayed ACK timer */ - int t_rcvtime; /* Time since last packet received */ -}; -struct xtcpcb { - size_t xt_len; - struct inpcb xt_inp; - struct tcpcb xt_tp; - struct xsocket xt_socket; - struct xtcp_timer xt_timer; - u_quad_t xt_alignment_hack; -}; +struct xtcpcb { + size_t xt_len; /* length of this structure */ + struct xinpcb xt_inp; + char xt_stack[TCP_FUNCTION_NAME_LEN_MAX]; /* (n) */ + int64_t spare64[8]; + int32_t t_state; /* (s,p) */ + uint32_t t_flags; /* (s,p) */ + int32_t t_sndzerowin; /* (s) */ + int32_t t_sndrexmitpack; /* (s) */ + int32_t t_rcvoopack; /* (s) */ + int32_t t_rcvtime; /* (s) */ + int32_t tt_rexmt; /* (s) */ + int32_t tt_persist; /* (s) */ + int32_t tt_keep; /* (s) */ + int32_t tt_2msl; /* (s) */ + int32_t tt_delack; /* (s) */ + int32_t spare32[32]; +} __aligned(8); +#ifdef _KERNEL +void tcp_inptoxtp(const struct inpcb *, struct xtcpcb *); +#endif #endif /* Index: head/sys/netinet/udp_usrreq.c =================================================================== --- head/sys/netinet/udp_usrreq.c +++ head/sys/netinet/udp_usrreq.c @@ -905,13 +905,7 @@ if (inp->inp_gencnt <= gencnt) { struct xinpcb xi; - bzero(&xi, sizeof(xi)); - xi.xi_len = sizeof xi; - /* XXX should avoid extra copy */ - bcopy(inp, &xi.xi_inp, sizeof *inp); - if (inp->inp_socket) - sotoxsocket(inp->inp_socket, &xi.xi_socket); - xi.xi_inp.inp_gencnt = inp->inp_gencnt; + in_pcbtoxinpcb(inp, &xi); INP_RUNLOCK(inp); error = SYSCTL_OUT(req, &xi, sizeof xi); } else Index: head/sys/sys/param.h =================================================================== --- head/sys/sys/param.h +++ head/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1200025 /* Master, propagated to newvers */ +#define __FreeBSD_version 1200026 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, Index: head/usr.bin/netstat/inet.c =================================================================== --- head/usr.bin/netstat/inet.c +++ head/usr.bin/netstat/inet.c @@ -91,7 +91,7 @@ #endif /* INET6 */ static int -pcblist_sysctl(int proto, const char *name, char **bufp, int istcp __unused) +pcblist_sysctl(int proto, const char *name, char **bufp) { const char *mibvar; char *buf; @@ -181,120 +181,6 @@ return (0); } -static int -pcblist_kvm(u_long off, char **bufp, int istcp) -{ - struct inpcbinfo pcbinfo; - struct inpcbhead listhead; - struct inpcb *inp; - struct xinpcb xi; - struct xinpgen xig; - struct xtcpcb xt; - struct socket so; - struct xsocket *xso; - char *buf, *p; - size_t len; - - if (off == 0) - return (0); - kread(off, &pcbinfo, sizeof(pcbinfo)); - if (istcp) - len = 2 * sizeof(xig) + - (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) * - sizeof(struct xtcpcb); - else - len = 2 * sizeof(xig) + - (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) * - sizeof(struct xinpcb); - if ((buf = malloc(len)) == NULL) { - xo_warnx("malloc %lu bytes", (u_long)len); - return (0); - } - p = buf; - -#define COPYOUT(obj, size) do { \ - if (len < (size)) { \ - xo_warnx("buffer size exceeded"); \ - goto fail; \ - } \ - bcopy((obj), p, (size)); \ - len -= (size); \ - p += (size); \ -} while (0) - -#define KREAD(off, buf, len) do { \ - if (kread((uintptr_t)(off), (buf), (len)) != 0) \ - goto fail; \ -} while (0) - - /* Write out header. */ - xig.xig_len = sizeof xig; - xig.xig_count = pcbinfo.ipi_count; - xig.xig_gen = pcbinfo.ipi_gencnt; - xig.xig_sogen = 0; - COPYOUT(&xig, sizeof xig); - - /* Walk the PCB list. */ - xt.xt_len = sizeof xt; - xi.xi_len = sizeof xi; - if (istcp) - xso = &xt.xt_socket; - else - xso = &xi.xi_socket; - KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead)); - LIST_FOREACH(inp, &listhead, inp_list) { - if (istcp) { - KREAD(inp, &xt.xt_inp, sizeof(*inp)); - inp = &xt.xt_inp; - } else { - KREAD(inp, &xi.xi_inp, sizeof(*inp)); - inp = &xi.xi_inp; - } - - if (inp->inp_gencnt > pcbinfo.ipi_gencnt) - continue; - - if (istcp) { - if (inp->inp_ppcb == NULL) - bzero(&xt.xt_tp, sizeof xt.xt_tp); - else if (inp->inp_flags & INP_TIMEWAIT) { - bzero(&xt.xt_tp, sizeof xt.xt_tp); - xt.xt_tp.t_state = TCPS_TIME_WAIT; - } else - KREAD(inp->inp_ppcb, &xt.xt_tp, - sizeof xt.xt_tp); - } - if (inp->inp_socket) { - KREAD(inp->inp_socket, &so, sizeof(so)); - if (sotoxsocket(&so, xso) != 0) - goto fail; - } else { - bzero(xso, sizeof(*xso)); - if (istcp) - xso->xso_protocol = IPPROTO_TCP; - } - if (istcp) - COPYOUT(&xt, sizeof xt); - else - COPYOUT(&xi, sizeof xi); - } - - /* Reread the pcbinfo and write out the footer. */ - kread(off, &pcbinfo, sizeof(pcbinfo)); - xig.xig_count = pcbinfo.ipi_count; - xig.xig_gen = pcbinfo.ipi_gencnt; - COPYOUT(&xig, sizeof xig); - - *bufp = buf; - return (1); - -fail: - free(buf); - return (0); -#undef COPYOUT -#undef KREAD -} - /* * Print a summary of connections related to an Internet * protocol. For TCP, also give state of connection. @@ -304,15 +190,14 @@ void protopr(u_long off, const char *name, int af1, int proto) { - int istcp; static int first = 1; + int istcp; char *buf; const char *vchar; - struct tcpcb *tp = NULL; - struct inpcb *inp; + struct xtcpcb *tp; + struct xinpcb *inp; struct xinpgen *xig, *oxig; struct xsocket *so; - struct xtcp_timer *timer; istcp = 0; switch (proto) { @@ -341,28 +226,21 @@ #endif break; } - if (live) { - if (!pcblist_sysctl(proto, name, &buf, istcp)) - return; - } else { - if (!pcblist_kvm(off, &buf, istcp)) - return; - } + + if (!pcblist_sysctl(proto, name, &buf)) + return; oxig = xig = (struct xinpgen *)buf; for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); xig->xig_len > sizeof(struct xinpgen); xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { if (istcp) { - timer = &((struct xtcpcb *)xig)->xt_timer; - tp = &((struct xtcpcb *)xig)->xt_tp; - inp = &((struct xtcpcb *)xig)->xt_inp; - so = &((struct xtcpcb *)xig)->xt_socket; + tp = (struct xtcpcb *)xig; + inp = &tp->xt_inp; } else { - inp = &((struct xinpcb *)xig)->xi_inp; - so = &((struct xinpcb *)xig)->xi_socket; - timer = NULL; + inp = (struct xinpcb *)xig; } + so = &inp->xi_socket; /* Ignore sockets for protocols other than the desired one. */ if (so->xso_protocol != proto) @@ -574,25 +452,25 @@ so->so_rcv.sb_lowat, so->so_snd.sb_lowat, so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt, so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax); - if (timer != NULL) + if (istcp) xo_emit(" {:retransmit-timer/%4d.%02d} " "{:persist-timer/%4d.%02d} " "{:keepalive-timer/%4d.%02d} " "{:msl2-timer/%4d.%02d} " "{:delay-ack-timer/%4d.%02d} " "{:inactivity-timer/%4d.%02d}", - timer->tt_rexmt / 1000, - (timer->tt_rexmt % 1000) / 10, - timer->tt_persist / 1000, - (timer->tt_persist % 1000) / 10, - timer->tt_keep / 1000, - (timer->tt_keep % 1000) / 10, - timer->tt_2msl / 1000, - (timer->tt_2msl % 1000) / 10, - timer->tt_delack / 1000, - (timer->tt_delack % 1000) / 10, - timer->t_rcvtime / 1000, - (timer->t_rcvtime % 1000) / 10); + tp->tt_rexmt / 1000, + (tp->tt_rexmt % 1000) / 10, + tp->tt_persist / 1000, + (tp->tt_persist % 1000) / 10, + tp->tt_keep / 1000, + (tp->tt_keep % 1000) / 10, + tp->tt_2msl / 1000, + (tp->tt_2msl % 1000) / 10, + tp->tt_delack / 1000, + (tp->tt_delack % 1000) / 10, + tp->t_rcvtime / 1000, + (tp->t_rcvtime % 1000) / 10); } if (istcp && !Lflag && !xflag && !Tflag && !Rflag) { if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) Index: head/usr.bin/sockstat/sockstat.c =================================================================== --- head/usr.bin/sockstat/sockstat.c +++ head/usr.bin/sockstat/sockstat.c @@ -562,7 +562,6 @@ struct xinpgen *xig, *exig; struct xinpcb *xip; struct xtcpcb *xtp; - struct inpcb *inp; struct xsocket *so; struct sock *sock; struct addr *laddr, *faddr; @@ -625,54 +624,52 @@ xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); if (xig >= exig) break; - xip = (struct xinpcb *)xig; - xtp = (struct xtcpcb *)xig; switch (proto) { case IPPROTO_TCP: + xtp = (struct xtcpcb *)xig; + xip = &xtp->xt_inp; if (xtp->xt_len != sizeof(*xtp)) { warnx("struct xtcpcb size mismatch"); goto out; } - inp = &xtp->xt_inp; - so = &xtp->xt_socket; - protoname = xtp->xt_tp.t_flags & TF_TOE ? "toe" : "tcp"; + protoname = xtp->t_flags & TF_TOE ? "toe" : "tcp"; break; case IPPROTO_UDP: case IPPROTO_DIVERT: + xip = (struct xinpcb *)xig; if (xip->xi_len != sizeof(*xip)) { warnx("struct xinpcb size mismatch"); goto out; } - inp = &xip->xi_inp; - so = &xip->xi_socket; break; default: errx(1, "protocol %d not supported", proto); } - if ((inp->inp_vflag & vflag) == 0) + so = &xip->xi_socket; + if ((xip->inp_vflag & vflag) == 0) continue; - if (inp->inp_vflag & INP_IPV4) { - if ((inp->inp_fport == 0 && !opt_l) || - (inp->inp_fport != 0 && !opt_c)) + if (xip->inp_vflag & INP_IPV4) { + if ((xip->inp_fport == 0 && !opt_l) || + (xip->inp_fport != 0 && !opt_c)) continue; #define __IN_IS_ADDR_LOOPBACK(pina) \ ((ntohl((pina)->s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) if (opt_L && - (__IN_IS_ADDR_LOOPBACK(&inp->inp_faddr) || - __IN_IS_ADDR_LOOPBACK(&inp->inp_laddr))) + (__IN_IS_ADDR_LOOPBACK(&xip->inp_faddr) || + __IN_IS_ADDR_LOOPBACK(&xip->inp_laddr))) continue; #undef __IN_IS_ADDR_LOOPBACK - } else if (inp->inp_vflag & INP_IPV6) { - if ((inp->inp_fport == 0 && !opt_l) || - (inp->inp_fport != 0 && !opt_c)) + } else if (xip->inp_vflag & INP_IPV6) { + if ((xip->inp_fport == 0 && !opt_l) || + (xip->inp_fport != 0 && !opt_c)) continue; if (opt_L && - (IN6_IS_ADDR_LOOPBACK(&inp->in6p_faddr) || - IN6_IS_ADDR_LOOPBACK(&inp->in6p_laddr))) + (IN6_IS_ADDR_LOOPBACK(&xip->in6p_faddr) || + IN6_IS_ADDR_LOOPBACK(&xip->in6p_laddr))) continue; } else { if (opt_v) - warnx("invalid vflag 0x%x", inp->inp_vflag); + warnx("invalid vflag 0x%x", xip->inp_vflag); continue; } if ((sock = calloc(1, sizeof(*sock))) == NULL) @@ -683,26 +680,26 @@ err(1, "malloc()"); sock->socket = so->xso_so; sock->proto = proto; - if (inp->inp_vflag & INP_IPV4) { + if (xip->inp_vflag & INP_IPV4) { sock->family = AF_INET; sockaddr(&laddr->address, sock->family, - &inp->inp_laddr, inp->inp_lport); + &xip->inp_laddr, xip->inp_lport); sockaddr(&faddr->address, sock->family, - &inp->inp_faddr, inp->inp_fport); - } else if (inp->inp_vflag & INP_IPV6) { + &xip->inp_faddr, xip->inp_fport); + } else if (xip->inp_vflag & INP_IPV6) { sock->family = AF_INET6; sockaddr(&laddr->address, sock->family, - &inp->in6p_laddr, inp->inp_lport); + &xip->in6p_laddr, xip->inp_lport); sockaddr(&faddr->address, sock->family, - &inp->in6p_faddr, inp->inp_fport); + &xip->in6p_faddr, xip->inp_fport); } laddr->next = NULL; faddr->next = NULL; sock->laddr = laddr; sock->faddr = faddr; - sock->vflag = inp->inp_vflag; + sock->vflag = xip->inp_vflag; if (proto == IPPROTO_TCP) - sock->state = xtp->xt_tp.t_state; + sock->state = xtp->t_state; sock->protoname = protoname; hash = (int)((uintptr_t)sock->socket % HASHSIZE); sock->next = sockhash[hash]; Index: head/usr.bin/systat/extern.h =================================================================== --- head/usr.bin/systat/extern.h +++ head/usr.bin/systat/extern.h @@ -56,7 +56,7 @@ extern int verbose; extern unsigned int delay; -struct inpcb; +struct in_conninfo; extern struct device_selection *dev_select; extern long generation; @@ -67,8 +67,8 @@ extern struct nlist namelist[]; -int checkhost(struct inpcb *); -int checkport(struct inpcb *); +int checkhost(struct in_conninfo *); +int checkport(struct in_conninfo *); void closeicmp(WINDOW *); void closeicmp6(WINDOW *); void closeifstat(WINDOW *); Index: head/usr.bin/systat/netcmds.c =================================================================== --- head/usr.bin/systat/netcmds.c +++ head/usr.bin/systat/netcmds.c @@ -224,13 +224,13 @@ } int -checkport(struct inpcb *inp) +checkport(struct in_conninfo *inc) { struct pitem *p; if (ports) for (p = ports; p < ports+nports; p++) - if (p->port == inp->inp_lport || p->port == inp->inp_fport) + if (p->port == inc->inc_lport || p->port == inc->inc_fport) return (p->onoff); return (1); } @@ -281,14 +281,14 @@ } int -checkhost(struct inpcb *inp) +checkhost(struct in_conninfo *inc) { struct hitem *p; if (hosts) for (p = hosts; p < hosts+nhosts; p++) - if (p->addr.s_addr == inp->inp_laddr.s_addr || - p->addr.s_addr == inp->inp_faddr.s_addr) + if (p->addr.s_addr == inc->inc_laddr.s_addr || + p->addr.s_addr == inc->inc_faddr.s_addr) return (p->onoff); return (1); } Index: head/usr.bin/systat/netstat.c =================================================================== --- head/usr.bin/systat/netstat.c +++ head/usr.bin/systat/netstat.c @@ -52,6 +52,7 @@ #ifdef INET6 #include #endif +#define _WANT_INPCB #include #include #include @@ -62,6 +63,7 @@ #define TCPSTATES #include #include +#define _WANT_TCPCB #include #include #include @@ -76,9 +78,9 @@ #include "systat.h" #include "extern.h" -static struct netinfo *enter(struct inpcb *, int, const char *); +static struct netinfo *enter(struct in_conninfo *, uint8_t, int, const char *); static void enter_kvm(struct inpcb *, struct socket *, int, const char *); -static void enter_sysctl(struct inpcb *, struct xsocket *, int, const char *); +static void enter_sysctl(struct xinpcb *, struct xsocket *, int, const char *); static void fetchnetstat_kvm(void); static void fetchnetstat_sysctl(void); static char *inetname(struct sockaddr *); @@ -212,9 +214,9 @@ } #endif } - if (nhosts && !checkhost(&inpcb)) + if (nhosts && !checkhost(&inpcb.inp_inc)) continue; - if (nports && !checkport(&inpcb)) + if (nports && !checkport(&inpcb.inp_inc)) continue; if (istcp) { if (inpcb.inp_flags & INP_TIMEWAIT) { @@ -245,7 +247,6 @@ int idx; struct xinpgen *inpg; char *cur, *end; - struct inpcb *inpcb; struct xinpcb *xip = NULL; struct xtcpcb *xtp = NULL; int plen; @@ -291,37 +292,36 @@ while (cur + plen <= end) { if (idx == 0) { /* TCP */ xtp = (struct xtcpcb *)cur; - inpcb = &xtp->xt_inp; + xip = &xtp->xt_inp; } else { xip = (struct xinpcb *)cur; - inpcb = &xip->xi_inp; } cur += plen; if (!aflag) { - if (inpcb->inp_vflag & INP_IPV4) { - if (inet_lnaof(inpcb->inp_laddr) == + if (xip->inp_vflag & INP_IPV4) { + if (inet_lnaof(xip->inp_laddr) == INADDR_ANY) continue; } #ifdef INET6 - else if (inpcb->inp_vflag & INP_IPV6) { - if (memcmp(&inpcb->in6p_laddr, + else if (xip->inp_vflag & INP_IPV6) { + if (memcmp(&xip->in6p_laddr, &in6addr_any, sizeof(in6addr_any)) == 0) continue; } #endif } - if (nhosts && !checkhost(inpcb)) + if (nhosts && !checkhost(&xip->inp_inc)) continue; - if (nports && !checkport(inpcb)) + if (nports && !checkport(&xip->inp_inc)) continue; - if (idx == 0) /* TCP */ - enter_sysctl(inpcb, &xtp->xt_socket, - xtp->xt_tp.t_state, "tcp"); - else /* UDP */ - enter_sysctl(inpcb, &xip->xi_socket, 0, "udp"); + if (idx == 0) + enter_sysctl(xip, &xip->xi_socket, + xtp->t_state, "tcp"); + else + enter_sysctl(xip, &xip->xi_socket, 0, "udp"); } free(inpg); } @@ -332,25 +332,26 @@ { struct netinfo *p; - if ((p = enter(inp, state, proto)) != NULL) { + if ((p = enter(&inp->inp_inc, inp->inp_vflag, state, proto)) != NULL) { p->ni_rcvcc = so->so_rcv.sb_ccc; p->ni_sndcc = so->so_snd.sb_ccc; } } static void -enter_sysctl(struct inpcb *inp, struct xsocket *so, int state, const char *proto) +enter_sysctl(struct xinpcb *xip, struct xsocket *so, int state, + const char *proto) { struct netinfo *p; - if ((p = enter(inp, state, proto)) != NULL) { + if ((p = enter(&xip->inp_inc, xip->inp_vflag, state, proto)) != NULL) { p->ni_rcvcc = so->so_rcv.sb_cc; p->ni_sndcc = so->so_snd.sb_cc; } } static struct netinfo * -enter(struct inpcb *inp, int state, const char *proto) +enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto) { struct netinfo *p; struct sockaddr_storage lsa, fsa; @@ -361,32 +362,32 @@ memset(&lsa, 0, sizeof(lsa)); memset(&fsa, 0, sizeof(fsa)); - if (inp->inp_vflag & INP_IPV4) { + if (vflag & INP_IPV4) { sa4 = (struct sockaddr_in *)&lsa; - sa4->sin_addr = inp->inp_laddr; - sa4->sin_port = inp->inp_lport; + sa4->sin_addr = inc->inc_laddr; + sa4->sin_port = inc->inc_lport; sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); sa4 = (struct sockaddr_in *)&fsa; - sa4->sin_addr = inp->inp_faddr; - sa4->sin_port = inp->inp_fport; + sa4->sin_addr = inc->inc_faddr; + sa4->sin_port = inc->inc_fport; sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); } #ifdef INET6 - else if (inp->inp_vflag & INP_IPV6) { + else if (vflag & INP_IPV6) { sa6 = (struct sockaddr_in6 *)&lsa; - memcpy(&sa6->sin6_addr, &inp->in6p_laddr, + memcpy(&sa6->sin6_addr, &inc->inc6_laddr, sizeof(struct in6_addr)); - sa6->sin6_port = inp->inp_lport; + sa6->sin6_port = inc->inc_lport; sa6->sin6_family = AF_INET6; sa6->sin6_len = sizeof(struct sockaddr_in6); sa6 = (struct sockaddr_in6 *)&fsa; - memcpy(&sa6->sin6_addr, &inp->in6p_faddr, + memcpy(&sa6->sin6_addr, &inc->inc6_faddr, sizeof(struct in6_addr)); - sa6->sin6_port = inp->inp_fport; + sa6->sin6_port = inc->inc_fport; sa6->sin6_family = AF_INET6; sa6->sin6_len = sizeof(struct sockaddr_in6); } Index: head/usr.sbin/tcpdrop/tcpdrop.c =================================================================== --- head/usr.sbin/tcpdrop/tcpdrop.c +++ head/usr.sbin/tcpdrop/tcpdrop.c @@ -205,9 +205,8 @@ tcpdropall(void) { struct xinpgen *head, *xinp; - struct xtcpcb *xpcb; - struct tcpcb *tp; - struct inpcb *inp; + struct xtcpcb *xtp; + struct xinpcb *xip; bool ok; ok = true; @@ -219,9 +218,8 @@ for (xinp = XINP_NEXT(head); xinp->xig_len > sizeof *xinp; xinp = XINP_NEXT(xinp)) { - xpcb = (struct xtcpcb *)xinp; - tp = &xpcb->xt_tp; - inp = &xpcb->xt_inp; + xtp = (struct xtcpcb *)xinp; + xip = &xtp->xt_inp; /* * XXX @@ -229,14 +227,14 @@ */ /* Ignore PCBs which were freed during copyout. */ - if (inp->inp_gencnt > head->xig_gen) + if (xip->inp_gencnt > head->xig_gen) continue; /* Skip listening sockets. */ - if (tp->t_state == TCPS_LISTEN) + if (xtp->t_state == TCPS_LISTEN) continue; - if (!tcpdropconn(&inp->inp_inc)) + if (!tcpdropconn(&xip->inp_inc)) ok = false; } free(head); Index: head/usr.sbin/trpt/trpt.c =================================================================== --- head/usr.sbin/trpt/trpt.c +++ head/usr.sbin/trpt/trpt.c @@ -66,6 +66,7 @@ #include #define TCPTIMERS #include +#define _WANT_TCPCB #include #include #define TANAMES