diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile index 4fd7faefc3d8..46f7046d874f 100644 --- a/cddl/lib/libdtrace/Makefile +++ b/cddl/lib/libdtrace/Makefile @@ -48,8 +48,11 @@ SRCS= dt_aggregate.c \ DSRCS= errno.d \ io.d \ + ip.d \ psinfo.d \ signal.d \ + tcp.d \ + udp.d \ unistd.d WARNS?= 1 diff --git a/cddl/lib/libdtrace/ip.d b/cddl/lib/libdtrace/ip.d new file mode 100644 index 000000000000..b886a0ad2543 --- /dev/null +++ b/cddl/lib/libdtrace/ip.d @@ -0,0 +1,285 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013 Mark Johnston + */ + +#pragma D depends_on provider ip + +/* + * pktinfo is where packet ID info can be made available for deeper + * analysis if packet IDs become supported by the kernel in the future. + * The pkt_addr member is currently always NULL. + */ +typedef struct pktinfo { + uintptr_t pkt_addr; +} pktinfo_t; + +/* + * csinfo is where connection state info is made available. + */ +typedef uint32_t zoneid_t; +typedef struct csinfo { + uintptr_t cs_addr; + uint64_t cs_cid; + pid_t cs_pid; + zoneid_t cs_zoneid; +} csinfo_t; + +/* + * ipinfo contains common IP info for both IPv4 and IPv6. + */ +typedef struct ipinfo { + uint8_t ip_ver; /* IP version (4, 6) */ + uint32_t ip_plength; /* payload length */ + string ip_saddr; /* source address */ + string ip_daddr; /* destination address */ +} ipinfo_t; + +/* + * ifinfo contains network interface info. + */ +typedef struct ifinfo { + string if_name; /* interface name */ + int8_t if_local; /* is delivered locally */ + /*netstackid_t if_ipstack;*/ /* ipstack ID */ + uintptr_t if_addr; /* pointer to raw ill_t */ +} ifinfo_t; + +typedef uint32_t ipaddr_t; +typedef struct { + uint8_t ipha_version_and_hdr_length; + uint8_t ipha_type_of_service; + uint16_t ipha_length; + uint16_t ipha_ident; + uint16_t ipha_fragment_offset_and_flags; + uint8_t ipha_ttl; + uint8_t ipha_protocol; + uint16_t ipha_hdr_checksum; + ipaddr_t ipha_src; + ipaddr_t ipha_dst; +} ipha_t; + +/* + * ipv4info is a translated version of the IPv4 header (with raw pointer). + * These values are NULL if the packet is not IPv4. + */ +typedef struct ipv4info { + uint8_t ipv4_ver; /* IP version (4) */ + uint8_t ipv4_ihl; /* header length, bytes */ + uint8_t ipv4_tos; /* type of service field */ + uint16_t ipv4_length; /* length (header + payload) */ + uint16_t ipv4_ident; /* identification */ + uint8_t ipv4_flags; /* IP flags */ + uint16_t ipv4_offset; /* fragment offset */ + uint8_t ipv4_ttl; /* time to live */ + uint8_t ipv4_protocol; /* next level protocol */ + string ipv4_protostr; /* next level protocol, as a string */ + uint16_t ipv4_checksum; /* header checksum */ + ipaddr_t ipv4_src; /* source address */ + ipaddr_t ipv4_dst; /* destination address */ + string ipv4_saddr; /* source address, string */ + string ipv4_daddr; /* destination address, string */ + ipha_t *ipv4_hdr; /* pointer to raw header */ +} ipv4info_t; + +/* + * ipv6info is a translated version of the IPv6 header (with raw pointer). + * These values are NULL if the packet is not IPv6. + */ +typedef struct in6_addr in6_addr_t; +typedef struct ip6_hdr ip6_t; +typedef struct ipv6info { + uint8_t ipv6_ver; /* IP version (6) */ + uint8_t ipv6_tclass; /* traffic class */ + uint32_t ipv6_flow; /* flow label */ + uint16_t ipv6_plen; /* payload length */ + uint8_t ipv6_nexthdr; /* next header protocol */ + string ipv6_nextstr; /* next header protocol, as a string */ + uint8_t ipv6_hlim; /* hop limit */ + in6_addr_t *ipv6_src; /* source address */ + in6_addr_t *ipv6_dst; /* destination address */ + string ipv6_saddr; /* source address, string */ + string ipv6_daddr; /* destination address, string */ + ip6_t *ipv6_hdr; /* pointer to raw header */ +} ipv6info_t; + +#pragma D binding "1.0" IPPROTO_IP +inline short IPPROTO_IP = 0; +#pragma D binding "1.0" IPPROTO_ICMP +inline short IPPROTO_ICMP = 1; +#pragma D binding "1.0" IPPROTO_IGMP +inline short IPPROTO_IGMP = 2; +#pragma D binding "1.0" IPPROTO_IPV4 +inline short IPPROTO_IPV4 = 4; +#pragma D binding "1.0" IPPROTO_TCP +inline short IPPROTO_TCP = 6; +#pragma D binding "1.0" IPPROTO_UDP +inline short IPPROTO_UDP = 17; +#pragma D binding "1.0" IPPROTO_IPV6 +inline short IPPROTO_IPV6 = 41; +#pragma D binding "1.0" IPPROTO_ROUTING +inline short IPPROTO_ROUTING = 43; +#pragma D binding "1.0" IPPROTO_FRAGMENT +inline short IPPROTO_FRAGMENT = 44; +#pragma D binding "1.0" IPPROTO_RSVP +inline short IPPROTO_RSVP = 46; +#pragma D binding "1.0" IPPROTO_GRE +inline short IPPROTO_GRE = 47; +#pragma D binding "1.0" IPPROTO_ESP +inline short IPPROTO_ESP = 50; +#pragma D binding "1.0" IPPROTO_AH +inline short IPPROTO_AH = 51; +#pragma D binding "1.0" IPPROTO_MOBILE +inline short IPPROTO_MOBILE = 55; +#pragma D binding "1.0" IPPROTO_ICMPV6 +inline short IPPROTO_ICMPV6 = 58; +#pragma D binding "1.0" IPPROTO_DSTOPTS +inline short IPPROTO_DSTOPTS = 60; +#pragma D binding "1.0" IPPROTO_ETHERIP +inline short IPPROTO_ETHERIP = 97; +#pragma D binding "1.0" IPPROTO_PIM +inline short IPPROTO_PIM = 103; +#pragma D binding "1.0" IPPROTO_IPCOMP +inline short IPPROTO_IPCOMP = 108; +#pragma D binding "1.0" IPPROTO_SCTP +inline short IPPROTO_SCTP = 132; +#pragma D binding "1.0" IPPROTO_RAW +inline short IPPROTO_RAW = 255; + +inline uint8_t INP_IPV4 = 0x01; +inline uint8_t INP_IPV6 = 0x02; + +#pragma D binding "1.0" protocols +inline string protocols[int proto] = + proto == IPPROTO_IP ? "IP" : + proto == IPPROTO_ICMP ? "ICMP" : + proto == IPPROTO_IGMP ? "IGMP" : + proto == IPPROTO_IPV4 ? "IPV4" : + proto == IPPROTO_TCP ? "TCP" : + proto == IPPROTO_UDP ? "UDP" : + proto == IPPROTO_IPV6 ? "IPV6" : + proto == IPPROTO_ROUTING ? "ROUTING" : + proto == IPPROTO_FRAGMENT ? "FRAGMENT" : + proto == IPPROTO_RSVP ? "RSVP" : + proto == IPPROTO_GRE ? "GRE" : + proto == IPPROTO_ESP ? "ESP" : + proto == IPPROTO_AH ? "AH" : + proto == IPPROTO_MOBILE ? "MOBILE" : + proto == IPPROTO_ICMPV6 ? "ICMPV6" : + proto == IPPROTO_DSTOPTS ? "DSTOPTS" : + proto == IPPROTO_ETHERIP ? "ETHERIP" : + proto == IPPROTO_PIM ? "PIM" : + proto == IPPROTO_IPCOMP ? "IPCOMP" : + proto == IPPROTO_SCTP ? "SCTP" : + proto == IPPROTO_RAW ? "RAW" : + ""; + +/* + * This field is always NULL according to the current definition of the ip + * probes. + */ +#pragma D binding "1.0" translator +translator pktinfo_t < void *p > { + pkt_addr = NULL; +}; + +#pragma D binding "1.0" translator +translator csinfo_t < void *p > { + cs_addr = NULL; + cs_cid = (uint64_t)p; + cs_pid = 0; + cs_zoneid = 0; +}; + +#pragma D binding "1.0" translator +translator csinfo_t < struct inpcb *p > { + cs_addr = NULL; + cs_cid = (uint64_t)p; + cs_pid = 0; /* XXX */ + cs_zoneid = 0; +}; + +#pragma D binding "1.0" translator +translator ipinfo_t < uint8_t *p > { + ip_ver = p == NULL ? 0 : ((struct ip *)p)->ip_v; + ip_plength = p == NULL ? 0 : + ((struct ip *)p)->ip_v == 4 ? + ntohs(((struct ip *)p)->ip_len) - (((struct ip *)p)->ip_hl << 2): + ntohs(((struct ip6_hdr *)p)->ip6_ctlun.ip6_un1.ip6_un1_plen); + ip_saddr = p == NULL ? 0 : + ((struct ip *)p)->ip_v == 4 ? + inet_ntoa(&((struct ip *)p)->ip_src.s_addr) : + inet_ntoa6(&((struct ip6_hdr *)p)->ip6_src); + ip_daddr = p == NULL ? 0 : + ((struct ip *)p)->ip_v == 4 ? + inet_ntoa(&((struct ip *)p)->ip_dst.s_addr) : + inet_ntoa6(&((struct ip6_hdr *)p)->ip6_dst); +}; + +#pragma D binding "1.0" IFF_LOOPBACK +inline int IFF_LOOPBACK = 0x8; + +#pragma D binding "1.0" translator +translator ifinfo_t < struct ifnet *p > { + if_name = p->if_xname; + if_local = (p->if_flags & IFF_LOOPBACK) == 0 ? 0 : 1; + if_addr = (uintptr_t)p; +}; + +#pragma D binding "1.0" translator +translator ipv4info_t < struct ip *p > { + ipv4_ver = p == NULL ? 0 : p->ip_v; + ipv4_ihl = p == NULL ? 0 : p->ip_hl; + ipv4_tos = p == NULL ? 0 : p->ip_tos; + ipv4_length = p == NULL ? 0 : ntohs(p->ip_len); + ipv4_ident = p == NULL ? 0 : ntohs(p->ip_id); + ipv4_flags = p == NULL ? 0 : (p->ip_off & 0xe000); + ipv4_offset = p == NULL ? 0 : p->ip_off; + ipv4_ttl = p == NULL ? 0 : p->ip_ttl; + ipv4_protocol = p == NULL ? 0 : p->ip_p; + ipv4_protostr = p == NULL ? "" : protocols[p->ip_p]; + ipv4_checksum = p == NULL ? 0 : ntohs(p->ip_sum); + ipv4_src = p == NULL ? 0 : (ipaddr_t)ntohl(p->ip_src.s_addr); + ipv4_dst = p == NULL ? 0 : (ipaddr_t)ntohl(p->ip_dst.s_addr); + ipv4_saddr = p == NULL ? 0 : inet_ntoa(&p->ip_src.s_addr); + ipv4_daddr = p == NULL ? 0 : inet_ntoa(&p->ip_dst.s_addr); + ipv4_hdr = (ipha_t *)p; +}; + +#pragma D binding "1.0" translator +translator ipv6info_t < struct ip6_hdr *p > { + ipv6_ver = p == NULL ? 0 : (ntohl(p->ip6_ctlun.ip6_un1.ip6_un1_flow) & 0xf0000000) >> 28; + ipv6_tclass = p == NULL ? 0 : (ntohl(p->ip6_ctlun.ip6_un1.ip6_un1_flow) & 0x0ff00000) >> 20; + ipv6_flow = p == NULL ? 0 : ntohl(p->ip6_ctlun.ip6_un1.ip6_un1_flow) & 0x000fffff; + ipv6_plen = p == NULL ? 0 : ntohs(p->ip6_ctlun.ip6_un1.ip6_un1_plen); + ipv6_nexthdr = p == NULL ? 0 : p->ip6_ctlun.ip6_un1.ip6_un1_nxt; + ipv6_nextstr = p == NULL ? "" : protocols[p->ip6_ctlun.ip6_un1.ip6_un1_nxt]; + ipv6_hlim = p == NULL ? 0 : p->ip6_ctlun.ip6_un1.ip6_un1_hlim; + ipv6_src = p == NULL ? 0 : (in6_addr_t *)&p->ip6_src; + ipv6_dst = p == NULL ? 0 : (in6_addr_t *)&p->ip6_dst; + ipv6_saddr = p == NULL ? 0 : inet_ntoa6(&p->ip6_src); + ipv6_daddr = p == NULL ? 0 : inet_ntoa6(&p->ip6_dst); + ipv6_hdr = (ip6_t *)p; +}; diff --git a/cddl/lib/libdtrace/tcp.d b/cddl/lib/libdtrace/tcp.d new file mode 100644 index 000000000000..271266584d48 --- /dev/null +++ b/cddl/lib/libdtrace/tcp.d @@ -0,0 +1,203 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013 Mark Johnston + */ + +#pragma D depends_on library ip.d +#pragma D depends_on provider tcp + +/* + * Convert a TCP state value to a string. + */ +#pragma D binding "1.0" TCPS_CLOSED +inline int TCPS_CLOSED = 0; +#pragma D binding "1.0" TCPS_LISTEN +inline int TCPS_LISTEN = 1; +#pragma D binding "1.0" TCPS_SYN_SENT +inline int TCPS_SYN_SENT = 2; +#pragma D binding "1.0" TCPS_SYN_RECEIVED +inline int TCPS_SYN_RECEIVED = 3; +#pragma D binding "1.0" TCPS_ESTABLISHED +inline int TCPS_ESTABLISHED = 4; +#pragma D binding "1.0" TCPS_CLOSE_WAIT +inline int TCPS_CLOSE_WAIT = 5; +#pragma D binding "1.0" TCPS_FIN_WAIT_1 +inline int TCPS_FIN_WAIT_1 = 6; +#pragma D binding "1.0" TCPS_CLOSING +inline int TCPS_CLOSING = 7; +#pragma D binding "1.0" TCPS_LAST_ACK +inline int TCPS_LAST_ACK = 8; +#pragma D binding "1.0" TCPS_FIN_WAIT_2 +inline int TCPS_FIN_WAIT_2 = 9; +#pragma D binding "1.0" TCPS_TIME_WAIT +inline int TCPS_TIME_WAIT = 10; + +/* TCP segment flags. */ +#pragma D binding "1.0" TH_FIN +inline uint8_t TH_FIN = 0x01; +#pragma D binding "1.0" TH_SYN +inline uint8_t TH_SYN = 0x02; +#pragma D binding "1.0" TH_RST +inline uint8_t TH_RST = 0x04; +#pragma D binding "1.0" TH_PUSH +inline uint8_t TH_PUSH = 0x08; +#pragma D binding "1.0" TH_ACK +inline uint8_t TH_ACK = 0x10; +#pragma D binding "1.0" TH_URG +inline uint8_t TH_URG = 0x20; +#pragma D binding "1.0" TH_ECE +inline uint8_t TH_ECE = 0x40; +#pragma D binding "1.0" TH_CWR +inline uint8_t TH_CWR = 0x80; + +/* TCP connection state strings. */ +#pragma D binding "1.0" tcp_state_string +inline string tcp_state_string[int32_t state] = + state == TCPS_CLOSED ? "state-closed" : + state == TCPS_LISTEN ? "state-listen" : + state == TCPS_SYN_SENT ? "state-syn-sent" : + state == TCPS_SYN_RECEIVED ? "state-syn-received" : + state == TCPS_ESTABLISHED ? "state-established" : + state == TCPS_CLOSE_WAIT ? "state-close-wait" : + state == TCPS_FIN_WAIT_1 ? "state-fin-wait-1" : + state == TCPS_CLOSING ? "state-closing" : + state == TCPS_LAST_ACK ? "state-last-ack" : + state == TCPS_FIN_WAIT_2 ? "state-fin-wait-2" : + state == TCPS_TIME_WAIT ? "state-time-wait" : + ""; + +/* + * tcpsinfo contains stable TCP details from tcp_t. + */ +typedef struct tcpsinfo { + uintptr_t tcps_addr; + int tcps_local; /* is delivered locally, boolean */ + int tcps_active; /* active open (from here), boolean */ + uint16_t tcps_lport; /* local port */ + uint16_t tcps_rport; /* remote port */ + string tcps_laddr; /* local address, as a string */ + string tcps_raddr; /* remote address, as a string */ + int32_t tcps_state; /* TCP state */ + uint32_t tcps_iss; /* Initial sequence # sent */ + uint32_t tcps_suna; /* sequence # sent but unacked */ + uint32_t tcps_snxt; /* next sequence # to send */ + uint32_t tcps_rack; /* sequence # we have acked */ + uint32_t tcps_rnxt; /* next sequence # expected */ + uint32_t tcps_swnd; /* send window size */ + int32_t tcps_snd_ws; /* send window scaling */ + uint32_t tcps_rwnd; /* receive window size */ + int32_t tcps_rcv_ws; /* receive window scaling */ + uint32_t tcps_cwnd; /* congestion window */ + uint32_t tcps_cwnd_ssthresh; /* threshold for congestion avoidance */ + uint32_t tcps_sack_fack; /* SACK sequence # we have acked */ + uint32_t tcps_sack_snxt; /* next SACK seq # for retransmission */ + uint32_t tcps_rto; /* round-trip timeout, msec */ + uint32_t tcps_mss; /* max segment size */ + int tcps_retransmit; /* retransmit send event, boolean */ +} tcpsinfo_t; + +/* + * tcplsinfo provides the old tcp state for state changes. + */ +typedef struct tcplsinfo { + int32_t tcps_state; /* previous TCP state */ +} tcplsinfo_t; + +/* + * tcpinfo is the TCP header fields. + */ +typedef struct tcpinfo { + uint16_t tcp_sport; /* source port */ + uint16_t tcp_dport; /* destination port */ + uint32_t tcp_seq; /* sequence number */ + uint32_t tcp_ack; /* acknowledgment number */ + uint8_t tcp_offset; /* data offset, in bytes */ + uint8_t tcp_flags; /* flags */ + uint16_t tcp_window; /* window size */ + uint16_t tcp_checksum; /* checksum */ + uint16_t tcp_urgent; /* urgent data pointer */ + struct tcphdr *tcp_hdr; /* raw TCP header */ +} tcpinfo_t; + +#pragma D binding "1.0" translator +translator csinfo_t < struct tcpcb *p > { + cs_addr = NULL; + cs_cid = (uint64_t)p; + cs_pid = 0; + cs_zoneid = 0; +}; + +#pragma D binding "1.0" translator +translator tcpsinfo_t < struct tcpcb *p > { + tcps_addr = (uintptr_t)p; + tcps_local = -1; /* XXX */ + tcps_active = -1; /* XXX */ + tcps_lport = p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_lport); + tcps_rport = p == NULL ? 0 : ntohs(p->t_inpcb->inp_inc.inc_ie.ie_fport); + tcps_laddr = p == NULL ? 0 : + p->t_inpcb->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_addr4.s_addr) : + inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependladdr.ie6_local); + tcps_raddr = p == NULL ? 0 : + p->t_inpcb->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie46_foreign.ia46_addr4.s_addr) : + inet_ntoa6(&p->t_inpcb->inp_inc.inc_ie.ie_dependfaddr.ie6_foreign); + tcps_state = p == NULL ? -1 : p->t_state; + tcps_iss = p == NULL ? 0 : p->iss; + tcps_suna = p == NULL ? 0 : p->snd_una; + tcps_snxt = p == NULL ? 0 : p->snd_nxt; + tcps_rack = p == NULL ? 0 : p->last_ack_sent; + tcps_rnxt = p == NULL ? 0 : p->rcv_nxt; + tcps_swnd = p == NULL ? -1 : p->snd_wnd; + tcps_snd_ws = p == NULL ? -1 : p->snd_scale; + tcps_rwnd = p == NULL ? -1 : p->rcv_wnd; + tcps_rcv_ws = p == NULL ? -1 : p->rcv_scale; + tcps_cwnd = p == NULL ? -1 : p->snd_cwnd; + tcps_cwnd_ssthresh = p == NULL ? -1 : p->snd_ssthresh; + tcps_sack_fack = p == NULL ? 0 : p->snd_fack; + tcps_sack_snxt = p == NULL ? 0 : p->sack_newdata; + tcps_rto = p == NULL ? -1 : p->t_rxtcur / 1000; /* XXX */ + tcps_mss = p == NULL ? -1 : p->t_maxseg; + tcps_retransmit = -1; /* XXX */ +}; + +#pragma D binding "1.0" translator +translator tcpinfo_t < struct tcphdr *p > { + tcp_sport = p == NULL ? 0 : ntohs(p->th_sport); + tcp_dport = p == NULL ? 0 : ntohs(p->th_dport); + tcp_seq = p == NULL ? -1 : ntohl(p->th_seq); + tcp_ack = p == NULL ? -1 : ntohl(p->th_ack); + tcp_offset = p == NULL ? -1 : (p->th_off >> 2); + tcp_flags = p == NULL ? 0 : p->th_flags; + tcp_window = p == NULL ? 0 : ntohs(p->th_win); + tcp_checksum = p == NULL ? 0 : ntohs(p->th_sum); + tcp_urgent = p == NULL ? 0 : ntohs(p->th_urp); + tcp_hdr = (struct tcphdr *)p; +}; + +#pragma D binding "1.0" translator +translator tcplsinfo_t < int s > { + tcps_state = s; +}; diff --git a/cddl/lib/libdtrace/udp.d b/cddl/lib/libdtrace/udp.d new file mode 100644 index 000000000000..5ad625de1bc6 --- /dev/null +++ b/cddl/lib/libdtrace/udp.d @@ -0,0 +1,75 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013 Mark Johnston + */ + +#pragma D depends_on library ip.d +#pragma D depends_on provider udp + +/* + * udpsinfo contains stable UDP details. + */ +typedef struct udpsinfo { + uintptr_t udps_addr; + uint16_t udps_lport; /* local port */ + uint16_t udps_rport; /* remote port */ + string udps_laddr; /* local address, as a string */ + string udps_raddr; /* remote address, as a string */ +} udpsinfo_t; + +/* + * udpinfo is the UDP header fields. + */ +typedef struct udpinfo { + uint16_t udp_sport; /* source port */ + uint16_t udp_dport; /* destination port */ + uint16_t udp_length; /* total length */ + uint16_t udp_checksum; /* headers + data checksum */ + struct udphdr *udp_hdr; /* raw UDP header */ +} udpinfo_t; + +#pragma D binding "1.0" translator +translator udpsinfo_t < struct inpcb *p > { + udps_addr = (uintptr_t)p; + udps_lport = p == NULL ? 0 : ntohs(p->inp_inc.inc_ie.ie_lport); + udps_rport = p == NULL ? 0 : ntohs(p->inp_inc.inc_ie.ie_fport); + udps_laddr = p == NULL ? "" : + p->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->inp_inc.inc_ie.ie_dependladdr.ie46_local.ia46_addr4.s_addr) : + inet_ntoa6(&p->inp_inc.inc_ie.ie_dependladdr.ie6_local); + udps_raddr = p == NULL ? "" : + p->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->inp_inc.inc_ie.ie_dependfaddr.ie46_foreign.ia46_addr4.s_addr) : + inet_ntoa6(&p->inp_inc.inc_ie.ie_dependfaddr.ie6_foreign); +}; + +#pragma D binding "1.0" translator +translator udpinfo_t < struct udphdr *p > { + udp_sport = p == NULL ? 0 : ntohs(p->uh_sport); + udp_dport = p == NULL ? 0 : ntohs(p->uh_dport); + udp_length = p == NULL ? 0 : ntohs(p->uh_ulen); + udp_checksum = p == NULL ? 0 : ntohs(p->uh_sum); + udp_hdr = p; +}; diff --git a/sys/conf/files b/sys/conf/files index 6b811f3bbbc8..ec59771573ae 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3228,6 +3228,7 @@ netinet/if_ether.c optional inet ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/in_debug.c optional inet ddb +netinet/in_kdtrace.c optional inet | inet6 netinet/ip_carp.c optional inet carp | inet6 carp netinet/in_gif.c optional gif inet | netgraph_gif inet netinet/ip_gre.c optional gre inet diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c new file mode 100644 index 000000000000..85a5a4ead495 --- /dev/null +++ b/sys/netinet/in_kdtrace.c @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 2013 Mark Johnston + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_kdtrace.h" + +#include +#include +#include + +SDT_PROVIDER_DEFINE(ip); +SDT_PROVIDER_DEFINE(tcp); +SDT_PROVIDER_DEFINE(udp); + +SDT_PROBE_DEFINE6_XLATE(ip, , , receive, receive, + "void *", "pktinfo_t *", + "void *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct ifnet *", "ifinfo_t *", + "struct ip *", "ipv4info_t *", + "struct ip6_hdr *", "ipv6info_t *"); + +SDT_PROBE_DEFINE6_XLATE(ip, , , send, send, + "void *", "pktinfo_t *", + "void *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct ifnet *", "ifinfo_t *", + "struct ip *", "ipv4info_t *", + "struct ip6_hdr *", "ipv6info_t *"); + +SDT_PROBE_DEFINE5_XLATE(tcp, , , accept_established, accept-established, + "void *", "pktinfo_t *", + "struct tcpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct tcpcb *", "tcpsinfo_t *" , + "struct tcphdr *", "tcpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(tcp, , , accept_refused, accept-refused, + "void *", "pktinfo_t *", + "struct tcpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct tcpcb *", "tcpsinfo_t *" , + "struct tcphdr *", "tcpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(tcp, , , connect_established, connect-established, + "void *", "pktinfo_t *", + "struct tcpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct tcpcb *", "tcpsinfo_t *" , + "struct tcphdr *", "tcpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(tcp, , , connect_refused, connect-refused, + "void *", "pktinfo_t *", + "struct tcpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct tcpcb *", "tcpsinfo_t *" , + "struct tcphdr *", "tcpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(tcp, , , connect_request, connect-request, + "void *", "pktinfo_t *", + "struct tcpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct tcpcb *", "tcpsinfo_t *" , + "struct tcphdr *", "tcpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(tcp, , , receive, receive, + "void *", "pktinfo_t *", + "struct tcpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct tcpcb *", "tcpsinfo_t *" , + "struct tcphdr *", "tcpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(tcp, , , send, send, + "void *", "pktinfo_t *", + "struct tcpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct tcpcb *", "tcpsinfo_t *" , + "struct tcphdr *", "tcpinfo_t *"); + +SDT_PROBE_DEFINE6_XLATE(tcp, , , state_change, state-change, + "void *", "void *", + "struct tcpcb *", "csinfo_t *", + "void *", "void *", + "struct tcpcb *", "tcpsinfo_t *", + "void *", "void *", + "int", "tcplsinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(udp, , , receive, receive, + "void *", "pktinfo_t *", + "struct inpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct inpcb *", "udpsinfo_t *", + "struct udphdr *", "udpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(udp, , , send, send, + "void *", "pktinfo_t *", + "struct inpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct inpcb *", "udpsinfo_t *", + "struct udphdr *", "udpinfo_t *"); diff --git a/sys/netinet/in_kdtrace.h b/sys/netinet/in_kdtrace.h new file mode 100644 index 000000000000..1759fac5128c --- /dev/null +++ b/sys/netinet/in_kdtrace.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2013 Mark Johnston + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_IN_KDTRACE_H_ +#define _SYS_IN_KDTRACE_H_ + +#define IP_PROBE(probe, arg0, arg1, arg2, arg3, arg4, arg5) \ + SDT_PROBE6(ip, , , probe, arg0, arg1, arg2, arg3, arg4, arg5) +#define UDP_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \ + SDT_PROBE5(udp, , , probe, arg0, arg1, arg2, arg3, arg4) +#define TCP_PROBE5(probe, arg0, arg1, arg2, arg3, arg4) \ + SDT_PROBE5(tcp, , , probe, arg0, arg1, arg2, arg3, arg4) +#define TCP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5) \ + SDT_PROBE6(tcp, , , probe, arg0, arg1, arg2, arg3, arg4, arg5) + +SDT_PROVIDER_DECLARE(ip); +SDT_PROVIDER_DECLARE(tcp); +SDT_PROVIDER_DECLARE(udp); + +SDT_PROBE_DECLARE(ip, , , receive); +SDT_PROBE_DECLARE(ip, , , send); + +SDT_PROBE_DECLARE(tcp, , , accept_established); +SDT_PROBE_DECLARE(tcp, , , accept_refused); +SDT_PROBE_DECLARE(tcp, , , connect_established); +SDT_PROBE_DECLARE(tcp, , , connect_refused); +SDT_PROBE_DECLARE(tcp, , , connect_request); +SDT_PROBE_DECLARE(tcp, , , receive); +SDT_PROBE_DECLARE(tcp, , , send); +SDT_PROBE_DECLARE(tcp, , , state_change); + +SDT_PROBE_DECLARE(udp, , , receive); +SDT_PROBE_DECLARE(udp, , , send); + +#endif diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index 989318ed35f2..7d8147566cd9 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ipfw.h" #include "opt_ipstealth.h" +#include "opt_kdtrace.h" #include #include @@ -85,6 +86,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -97,6 +99,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -531,6 +534,7 @@ ip_fastforward(struct mbuf *m) /* * Send off the packet via outgoing interface */ + IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, &ro); } else { @@ -562,6 +566,7 @@ ip_fastforward(struct mbuf *m) */ m_clrprotoflags(m); + IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, &ro); if (error) diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index ca55c5e183de..707d2be2b2a2 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include "opt_ipfw.h" #include "opt_ipstealth.h" #include "opt_ipsec.h" +#include "opt_kdtrace.h" #include "opt_route.h" #include @@ -49,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -63,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -429,6 +432,8 @@ ip_input(struct mbuf *m) ip = mtod(m, struct ip *); } + IP_PROBE(receive, NULL, NULL, ip, m->m_pkthdr.rcvif, ip, NULL); + /* 127/8 must not appear on wire - RFC1122 */ ifp = m->m_pkthdr.rcvif; if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 0a87e7a3311b..464c85289e41 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -34,9 +34,10 @@ __FBSDID("$FreeBSD$"); #include "opt_ipfw.h" #include "opt_ipsec.h" -#include "opt_route.h" +#include "opt_kdtrace.h" #include "opt_mbuf_stress_test.h" #include "opt_mpath.h" +#include "opt_route.h" #include "opt_sctp.h" #include @@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -64,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -622,6 +625,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, * to avoid confusing lower layers. */ m_clrprotoflags(m); + IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); error = (*ifp->if_output)(ifp, m, (const struct sockaddr *)gw, ro); goto done; @@ -656,6 +660,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, */ m_clrprotoflags(m); + IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); error = (*ifp->if_output)(ifp, m, (const struct sockaddr *)gw, ro); } else diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 99bbbd3c41b6..0d7eb1933498 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_kdtrace.h" #include "opt_tcpdebug.h" #include @@ -63,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include #include /* for proc0 declaration */ #include +#include #include #include #include @@ -82,6 +84,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -688,7 +691,10 @@ tcp_input(struct mbuf *m, int off0) bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); ipov->ih_len = htons(tlen); th->th_sum = in_cksum(m, len); + /* Reset length for SDT probes. */ + ip->ip_len = htons(tlen + off0); } + if (th->th_sum) { TCPSTAT_INC(tcps_rcvbadsum); goto drop; @@ -1384,6 +1390,8 @@ tcp_input(struct mbuf *m, int off0) } #endif + TCP_PROBE5(receive, NULL, tp, m->m_data, tp, th); + /* * Segment belongs to a connection in SYN_SENT, ESTABLISHED or later * state. tcp_do_segment() always consumes the mbuf chain, unlocks @@ -1394,6 +1402,8 @@ tcp_input(struct mbuf *m, int off0) return; dropwithreset: + TCP_PROBE5(receive, NULL, tp, m->m_data, tp, th); + if (ti_locked == TI_WLOCKED) { INP_INFO_WUNLOCK(&V_tcbinfo); ti_locked = TI_UNLOCKED; @@ -1415,6 +1425,9 @@ tcp_input(struct mbuf *m, int off0) goto drop; dropunlock: + if (m != NULL) + TCP_PROBE5(receive, NULL, tp, m->m_data, tp, th); + if (ti_locked == TI_WLOCKED) { INP_INFO_WUNLOCK(&V_tcbinfo); ti_locked = TI_UNLOCKED; @@ -1910,8 +1923,11 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, rstreason = BANDLIM_UNLIMITED; goto dropwithreset; } - if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) + if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) { + TCP_PROBE5(connect_refused, NULL, tp, m->m_data, tp, + th); tp = tcp_drop(tp, ECONNREFUSED); + } if (thflags & TH_RST) goto drop; if (!(thflags & TH_SYN)) @@ -1956,11 +1972,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ tp->t_starttime = ticks; if (tp->t_flags & TF_NEEDFIN) { - tp->t_state = TCPS_FIN_WAIT_1; + tcp_state_change(tp, TCPS_FIN_WAIT_1); tp->t_flags &= ~TF_NEEDFIN; thflags &= ~TH_SYN; } else { - tp->t_state = TCPS_ESTABLISHED; + tcp_state_change(tp, TCPS_ESTABLISHED); + TCP_PROBE5(connect_established, NULL, tp, + m->m_data, tp, th); cc_conn_init(tp); tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); @@ -1978,7 +1996,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN); tcp_timer_activate(tp, TT_REXMT, 0); - tp->t_state = TCPS_SYN_RECEIVED; + tcp_state_change(tp, TCPS_SYN_RECEIVED); } KASSERT(ti_locked == TI_WLOCKED, ("%s: trimthenstep6: " @@ -2116,7 +2134,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, ti_locked)); INP_INFO_WLOCK_ASSERT(&V_tcbinfo); - tp->t_state = TCPS_CLOSED; + tcp_state_change(tp, TCPS_CLOSED); TCPSTAT_INC(tcps_drops); tp = tcp_close(tp); break; @@ -2361,10 +2379,12 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ tp->t_starttime = ticks; if (tp->t_flags & TF_NEEDFIN) { - tp->t_state = TCPS_FIN_WAIT_1; + tcp_state_change(tp, TCPS_FIN_WAIT_1); tp->t_flags &= ~TF_NEEDFIN; } else { - tp->t_state = TCPS_ESTABLISHED; + tcp_state_change(tp, TCPS_ESTABLISHED); + TCP_PROBE5(accept_established, NULL, tp, m->m_data, tp, + th); cc_conn_init(tp); tcp_timer_activate(tp, TT_KEEP, TP_KEEPIDLE(tp)); } @@ -2752,7 +2772,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, tcp_finwait2_timeout : TP_MAXIDLE(tp))); } - tp->t_state = TCPS_FIN_WAIT_2; + tcp_state_change(tp, TCPS_FIN_WAIT_2); } break; @@ -2978,7 +2998,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, tp->t_starttime = ticks; /* FALLTHROUGH */ case TCPS_ESTABLISHED: - tp->t_state = TCPS_CLOSE_WAIT; + tcp_state_change(tp, TCPS_CLOSE_WAIT); break; /* @@ -2986,7 +3006,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * enter the CLOSING state. */ case TCPS_FIN_WAIT_1: - tp->t_state = TCPS_CLOSING; + tcp_state_change(tp, TCPS_CLOSING); break; /* diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index b4342f3b7b3f..00d541596b02 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_kdtrace.h" #include "opt_tcpdebug.h" #include @@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -56,6 +58,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -1174,6 +1177,18 @@ tcp_output(struct tcpcb *tp) */ ip6->ip6_hlim = in6_selecthlim(tp->t_inpcb, NULL); + /* + * Set the packet size here for the benefit of DTrace probes. + * ip6_output() will set it properly; it's supposed to include + * the option header lengths as well. + */ + ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); + + if (tp->t_state == TCPS_SYN_SENT) + TCP_PROBE5(connect_request, NULL, tp, ip6, tp, th); + + TCP_PROBE5(send, NULL, tp, ip6, tp, th); + /* TODO: IPv6 IP6TOS_ECT bit on */ error = ip6_output(m, tp->t_inpcb->in6p_outputopts, &ro, ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), @@ -1208,6 +1223,11 @@ tcp_output(struct tcpcb *tp) if (V_path_mtu_discovery && tp->t_maxopd > V_tcp_minmss) ip->ip_off |= htons(IP_DF); + if (tp->t_state == TCPS_SYN_SENT) + TCP_PROBE5(connect_request, NULL, tp, ip, tp, th); + + TCP_PROBE5(send, NULL, tp, ip, tp, th); + error = ip_output(m, tp->t_inpcb->inp_options, &ro, ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0, tp->t_inpcb); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index c466bf470c73..5d37b504707f 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_kdtrace.h" #include "opt_tcpdebug.h" #include @@ -53,6 +54,7 @@ __FBSDID("$FreeBSD$"); #endif #include #include +#include #include #include #include @@ -66,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -632,8 +635,8 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, ip6->ip6_flow = 0; ip6->ip6_vfc = IPV6_VERSION; ip6->ip6_nxt = IPPROTO_TCP; - ip6->ip6_plen = 0; /* Set in ip6_output(). */ tlen += sizeof (struct ip6_hdr) + sizeof (struct tcphdr); + ip6->ip6_plen = htons(tlen - sizeof(*ip6)); } #endif #if defined(INET) && defined(INET6) @@ -702,6 +705,10 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, if (tp == NULL || (inp->inp_socket->so_options & SO_DEBUG)) tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0); #endif + if (flags & TH_RST) + TCP_PROBE5(accept_refused, NULL, NULL, m->m_data, tp, nth); + + TCP_PROBE5(send, NULL, tp, m->m_data, tp, nth); #ifdef INET6 if (isipv6) (void) ip6_output(m, NULL, NULL, ipflags, NULL, NULL, inp); @@ -882,7 +889,7 @@ tcp_drop(struct tcpcb *tp, int errno) INP_WLOCK_ASSERT(tp->t_inpcb); if (TCPS_HAVERCVDSYN(tp->t_state)) { - tp->t_state = TCPS_CLOSED; + tcp_state_change(tp, TCPS_CLOSED); (void) tcp_output(tp); TCPSTAT_INC(tcps_drops); } else @@ -2376,3 +2383,19 @@ tcp_log_addr(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr, panic("%s: string too long", __func__); return (s); } + +/* + * A subroutine which makes it easy to track TCP state changes with DTrace. + * This function shouldn't be called for t_state initializations that don't + * correspond to actual TCP state transitions. + */ +void +tcp_state_change(struct tcpcb *tp, int newstate) +{ +#if defined(KDTRACE_HOOKS) + int pstate = tp->t_state; +#endif + + tp->t_state = newstate; + TCP_PROBE6(state_change, NULL, tp, NULL, tp, NULL, pstate); +} diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index cd7b424e0b13..1c27d7a02187 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -835,7 +835,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) #endif /* INET */ INP_HASH_WUNLOCK(&V_tcbinfo); tp = intotcpcb(inp); - tp->t_state = TCPS_SYN_RECEIVED; + tcp_state_change(tp, TCPS_SYN_RECEIVED); tp->iss = sc->sc_iss; tp->irs = sc->sc_irs; tcp_rcvseqinit(tp); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index ef0aad1639e6..88755e739dd3 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -367,7 +367,7 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td) error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred); INP_HASH_WUNLOCK(&V_tcbinfo); if (error == 0) { - tp->t_state = TCPS_LISTEN; + tcp_state_change(tp, TCPS_LISTEN); solisten_proto(so, backlog); #ifdef TCP_OFFLOAD if ((so->so_options & SO_NO_OFFLOAD) == 0) @@ -412,7 +412,7 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td) } INP_HASH_WUNLOCK(&V_tcbinfo); if (error == 0) { - tp->t_state = TCPS_LISTEN; + tcp_state_change(tp, TCPS_LISTEN); solisten_proto(so, backlog); #ifdef TCP_OFFLOAD if ((so->so_options & SO_NO_OFFLOAD) == 0) @@ -1152,7 +1152,7 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) soisconnecting(so); TCPSTAT_INC(tcps_connattempt); - tp->t_state = TCPS_SYN_SENT; + tcp_state_change(tp, TCPS_SYN_SENT); tp->iss = tcp_new_isn(tp); tcp_sendseqinit(tp); @@ -1224,7 +1224,7 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) soisconnecting(so); TCPSTAT_INC(tcps_connattempt); - tp->t_state = TCPS_SYN_SENT; + tcp_state_change(tp, TCPS_SYN_SENT); tp->iss = tcp_new_isn(tp); tcp_sendseqinit(tp); @@ -1704,7 +1704,7 @@ tcp_usrclosed(struct tcpcb *tp) #endif /* FALLTHROUGH */ case TCPS_CLOSED: - tp->t_state = TCPS_CLOSED; + tcp_state_change(tp, TCPS_CLOSED); tp = tcp_close(tp); /* * tcp_close() should never return NULL here as the socket is @@ -1720,11 +1720,11 @@ tcp_usrclosed(struct tcpcb *tp) break; case TCPS_ESTABLISHED: - tp->t_state = TCPS_FIN_WAIT_1; + tcp_state_change(tp, TCPS_FIN_WAIT_1); break; case TCPS_CLOSE_WAIT: - tp->t_state = TCPS_LAST_ACK; + tcp_state_change(tp, TCPS_LAST_ACK); break; } if (tp->t_state >= TCPS_FIN_WAIT_2) { diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index cfba5d9ccdaf..b22713fc8da7 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -701,6 +701,7 @@ struct inpcb * struct tcpcb * tcp_newtcpcb(struct inpcb *); int tcp_output(struct tcpcb *); +void tcp_state_change(struct tcpcb *, int); void tcp_respond(struct tcpcb *, void *, struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int); void tcp_tw_init(void); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index afd11e68c019..66aa6d418b94 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" +#include "opt_kdtrace.h" #include #include @@ -54,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -68,6 +70,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -616,6 +619,8 @@ udp_input(struct mbuf *m, int off) m_freem(m); return; } + + UDP_PROBE(receive, NULL, inp, ip, ip, uh); udp_append(inp, ip, m, iphlen, &udp_in); INP_RUNLOCK(inp); return; @@ -1193,6 +1198,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, */ ui = mtod(m, struct udpiphdr *); bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */ + ui->ui_v = IPVERSION << 4; ui->ui_pr = IPPROTO_UDP; ui->ui_src = laddr; ui->ui_dst = faddr; @@ -1243,6 +1249,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, INP_HASH_WUNLOCK(&V_udbinfo); else if (unlock_udbinfo == UH_RLOCKED) INP_HASH_RUNLOCK(&V_udbinfo); + UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u); error = ip_output(m, inp->inp_options, NULL, ipflags, inp->inp_moptions, inp); if (unlock_udbinfo == UH_WLOCKED) diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index 0c26b88cd436..461c9861b697 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -42,6 +42,7 @@ struct udpiphdr { struct udphdr ui_u; /* udp header */ }; #define ui_x1 ui_i.ih_x1 +#define ui_v ui_i.ih_x1[0] #define ui_pr ui_i.ih_pr #define ui_len ui_i.ih_len #define ui_src ui_i.ih_src diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 02bbf75b1b81..31f048f1886e 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet6.h" #include "opt_ipfw.h" #include "opt_ipsec.h" +#include "opt_kdtrace.h" #include "opt_route.h" #include @@ -76,6 +77,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -92,6 +94,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -538,6 +541,8 @@ ip6_input(struct mbuf *m) IP6STAT_INC(ip6s_nxthist[ip6->ip6_nxt]); + IP_PROBE(receive, NULL, NULL, ip6, m->m_pkthdr.rcvif, NULL, ip6); + /* * Check against address spoofing/corruption. */ diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c index 40c8c44c4db5..96346367aa8b 100644 --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet6.h" +#include "opt_kdtrace.h" #include #include @@ -93,6 +94,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -114,6 +116,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -1644,6 +1647,8 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m) dst6.sin6_len = sizeof(struct sockaddr_in6); dst6.sin6_family = AF_INET6; dst6.sin6_addr = ip6->ip6_dst; + + IP_PROBE(send, NULL, NULL, ip6, ifp, NULL, ip6); /* * We just call if_output instead of nd6_output here, since * we need no ND for a multicast forwarded packet...right? diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 7755da1fbb43..e76121d3d4b1 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_kdtrace.h" #include #include @@ -50,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -62,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #define L3_ADDR_SIN6(le) ((struct sockaddr_in6 *) L3_ADDR(le)) #include @@ -2083,6 +2086,8 @@ nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0, return (error); } m_clrprotoflags(m); /* Avoid confusing lower layers. */ + IP_PROBE(send, NULL, NULL, mtod(m, struct ip6_hdr *), ifp, NULL, + mtod(m, struct ip6_hdr *)); if ((ifp->if_flags & IFF_LOOPBACK) != 0) { return ((*ifp->if_output)(origifp, m, (struct sockaddr *)dst, NULL)); diff --git a/sys/netinet6/send.c b/sys/netinet6/send.c index 233abdb1fef6..aa6ec673fcd5 100644 --- a/sys/netinet6/send.c +++ b/sys/netinet6/send.c @@ -27,12 +27,15 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_kdtrace.h" + #include #include #include #include #include #include +#include #include #include #include @@ -46,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -182,6 +186,8 @@ send_output(struct mbuf *m, struct ifnet *ifp, int direction) m_clrprotoflags(m); /* Avoid confusing lower layers. */ + IP_PROBE(send, NULL, NULL, ip6, ifp, NULL, ip6); + /* * Output the packet as nd6.c:nd6_output_lle() would do. * The mbuf is always consumed, so we do not have to care diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 6aadae10d47d..7df0db753778 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$"); #include "opt_inet6.h" #include "opt_ipfw.h" #include "opt_ipsec.h" +#include "opt_kdtrace.h" #include #include @@ -82,6 +83,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -95,6 +97,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -377,6 +380,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto) INP_RLOCK(last); INP_INFO_RUNLOCK(&V_udbinfo); up = intoudpcb(last); + UDP_PROBE(receive, NULL, last, ip6, last, uh); if (up->u_tun_func == NULL) { udp6_append(last, m, off, &fromsa); } else { @@ -455,6 +459,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto) } INP_RLOCK_ASSERT(inp); up = intoudpcb(inp); + UDP_PROBE(receive, NULL, inp, ip6, inp, uh); if (up->u_tun_func == NULL) { udp6_append(inp, m, off, &fromsa); } else { @@ -771,9 +776,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6, ip6->ip6_flow = inp->inp_flow & IPV6_FLOWINFO_MASK; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; -#if 0 /* ip6_plen will be filled in ip6_output. */ ip6->ip6_plen = htons((u_short)plen); -#endif ip6->ip6_nxt = IPPROTO_UDP; ip6->ip6_hlim = in6_selecthlim(inp, NULL); ip6->ip6_src = *laddr; @@ -785,6 +788,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6, flags = 0; + UDP_PROBE(send, NULL, inp, ip6, inp, udp6); UDPSTAT_INC(udps_opackets); error = ip6_output(m, optp, NULL, flags, inp->in6p_moptions, NULL, inp);