Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh (nonexistent) +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh (revision 337018) @@ -0,0 +1,125 @@ +#!/usr/bin/env ksh +# +# 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 +# + +# +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +# + +# +# Test {ip,udplite}:::{send,receive} of IPv4 UDP-Lite to a local address. +# +# This may fail due to: +# +# 1. A change to the ip stack breaking expected probe behavior, +# which is the reason we are testing. +# 2. No physical network interface is plumbed and up. +# 3. No other hosts on this subnet are reachable and listening on rpcbind. +# 4. An unlikely race causes the unlocked global send/receive +# variables to be corrupted. +# +# This test sends a UDP-Lite message using perl and checks that at least the +# following counts were traced: +# +# 1 x ip:::send (UDPLite sent to UDP-Lite port 33434) +# 1 x udplite:::send (UDPLite sent to UDP-Lite port 33434) +# 1 x ip:::receive (UDP-Lite received) +# 1 x udplite:::receive (UDP-Lite received) +# +# A udplite:::receive event is expected even if the received UDP-Lite packet +# elicits an ICMP PORT_UNREACHABLE message since there is no UDP-Lite +# socket for receiving the packet. +# + +if (( $# != 1 )); then + print -u2 "expected one argument: " + exit 2 +fi + +dtrace=$1 +local=127.0.0.1 +port=33434 +DIR=/var/tmp/dtest.$$ + +mkdir $DIR +cd $DIR + +cat > test.pl <<-EOPERL + use IO::Socket; + my \$s = IO::Socket::INET->new( + Type => SOCK_DGRAM, + Proto => "udplite", + PeerAddr => "$local", + PeerPort => $port); + die "Could not create UDP-Lite socket $local port $port" unless \$s; + send \$s, "Hello", 0; + close \$s; + sleep(2); +EOPERL + +$dtrace -c 'perl test.pl' -qs /dev/stdin <ip_saddr == "$local" && args[2]->ip_daddr == "$local" && + args[4]->ipv4_protocol == IPPROTO_UDPLITE/ +{ + ipsend++; +} + +udplite:::send +/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/ +{ + udplitesend++; +} + +ip:::receive +/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local" && + args[4]->ipv4_protocol == IPPROTO_UDPLITE/ +{ + ipreceive++; +} + +udplite:::receive +/args[2]->ip_saddr == "$local" && args[2]->ip_daddr == "$local"/ +{ + udplitereceive++; +} + +END +{ + printf("Minimum UDP-Lite events seen\n\n"); + printf("ip:::send - %s\n", ipsend >= 1 ? "yes" : "no"); + printf("ip:::receive - %s\n", ipreceive >= 1 ? "yes" : "no"); + printf("udplite:::send - %s\n", udplitesend >= 1 ? "yes" : "no"); + printf("udplite:::receive - %s\n", udplitereceive >= 1 ? "yes" : "no"); +} +EODTRACE + +status=$? + +cd / +/bin/rm -rf $DIR + +exit $status Property changes on: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh.out =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh.out (nonexistent) +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localudplite.ksh.out (revision 337018) @@ -0,0 +1,7 @@ +Minimum UDP-Lite events seen + +ip:::send - yes +ip:::receive - yes +udplite:::send - yes +udplite:::receive - yes + Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh (nonexistent) +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh (revision 337018) @@ -0,0 +1,113 @@ +#!/usr/bin/env ksh93 +# +# 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 +# + +# +# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +# + +# +# Test {udplite,ip}:::{send,receive} of IPv4 UDP-Lite to a remote host. +# +# This may fail due to: +# +# 1. A change to the ip stack breaking expected probe behavior, +# which is the reason we are testing. +# 2. No physical network interface is plumbed and up. +# 3. No other hosts on this subnet are reachable and listening on rpcbind. +# 4. An unlikely race causes the unlocked global send/receive +# variables to be corrupted. +# +# This test sends a UDP-Lite message using perl and checks that at least the +# following counts were traced: +# +# 1 x ip:::send (UDP-Lite sent to UDP-Lite port 33434) +# 1 x udplite:::send (UDP-Lite sent to UDP-Lite port 33434) +# + +if (( $# != 1 )); then + print -u2 "expected one argument: " + exit 2 +fi + +dtrace=$1 +getaddr=./get.ipv4remote.pl +port=33434 +DIR=/var/tmp/dtest.$$ + +if [[ ! -x $getaddr ]]; then + print -u2 "could not find or execute sub program: $getaddr" + exit 3 +fi +$getaddr | read source dest +if (( $? != 0 )); then + exit 4 +fi + +mkdir $DIR +cd $DIR + +cat > test.pl <<-EOPERL + use IO::Socket; + my \$s = IO::Socket::INET->new( + Type => SOCK_DGRAM, + Proto => "udplite", + PeerAddr => "$dest", + PeerPort => $port); + die "Could not create UDP-Lite socket $dest port $port" unless \$s; + send \$s, "Hello", 0; + close \$s; + sleep(2); +EOPERL + +$dtrace -c 'perl test.pl' -qs /dev/stdin <ip_saddr == "$source" && args[2]->ip_daddr == "$dest" && + args[4]->ipv4_protocol == IPPROTO_UDPLITE/ +{ + ipsend++; +} + +udplite:::send +/args[2]->ip_saddr == "$source" && args[2]->ip_daddr == "$dest"/ +{ + udplitesend++; +} + +END +{ + printf("Minimum UDPLite events seen\n\n"); + printf("ip:::send - %s\n", ipsend >= 1 ? "yes" : "no"); + printf("udplite:::send - %s\n", udplitesend >= 1 ? "yes" : "no"); +} +EODTRACE + +status=$? + +cd / +/bin/rm -rf $DIR + +exit $status Property changes on: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh.out =================================================================== --- head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh.out (nonexistent) +++ head/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteudplite.ksh.out (revision 337018) @@ -0,0 +1,5 @@ +Minimum UDP-Lite events seen + +ip:::send - yes +udplite:::send - yes + Index: head/cddl/lib/libdtrace/Makefile =================================================================== --- head/cddl/lib/libdtrace/Makefile (revision 337017) +++ head/cddl/lib/libdtrace/Makefile (revision 337018) @@ -1,131 +1,132 @@ # $FreeBSD$ .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/common .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libgen/common LIB= dtrace SRCS= dt_aggregate.c \ dt_as.c \ dt_buf.c \ dt_cc.c \ dt_cg.c \ dt_consume.c \ dt_decl.c \ dt_dis.c \ dt_dof.c \ dt_error.c \ dt_errtags.c \ dt_grammar.y \ dt_handle.c \ dt_ident.c \ dt_isadep.c \ dt_inttab.c \ dt_lex.l \ dt_link.c \ dt_list.c \ dt_map.c \ dt_module.c \ dt_names.c \ dt_open.c \ dt_options.c \ dt_parser.c \ dt_pcb.c \ dt_pid.c \ dt_pq.c \ dt_pragma.c \ dt_print.c \ dt_printf.c \ dt_proc.c \ dt_program.c \ dt_provider.c \ dt_regset.c \ dt_string.c \ dt_strtab.c \ dt_subr.c \ dt_sugar.c \ dt_work.c \ dt_xlator.c \ gmatch.c DSRCS= errno.d \ io.d \ ip.d \ psinfo.d \ siftr.d \ signal.d \ tcp.d \ socket.d \ udp.d \ + udplite.d \ unistd.d FILES= ${DSRCS} FILESDIR= /usr/lib/dtrace FILESMODE= ${NOBINMODE} WARNS?= 1 CFLAGS+= -I${.OBJDIR} -I${.CURDIR} \ -I${SRCTOP}/sys/cddl/dev/dtrace/${MACHINE_ARCH} \ -I${SRCTOP}/sys/cddl/compat/opensolaris \ -I${SRCTOP}/cddl/compat/opensolaris/include \ -I${OPENSOLARIS_USR_DISTDIR}/head \ -I${OPENSOLARIS_USR_DISTDIR}/lib/libctf/common \ -I${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common \ -I${OPENSOLARIS_SYS_DISTDIR}/uts/common #CFLAGS+= -DYYDEBUG .if ${MACHINE_CPUARCH} == "aarch64" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/aarch64 .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/aarch64 .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/aarch64 .elif ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" CFLAGS+= -I${SRCTOP}/sys/cddl/dev/dtrace/x86 CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel -DDIS_MEM .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/i386 .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/${MACHINE_ARCH} .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/x86 .elif ${MACHINE_CPUARCH} == "arm" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/arm .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/arm .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/arm .elif ${MACHINE_CPUARCH} == "mips" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/mips .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/mips .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/mips .elif ${MACHINE_CPUARCH} == "powerpc" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/powerpc .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/powerpc .elif ${MACHINE_CPUARCH} == "riscv" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/riscv .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/riscv .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/riscv .elif ${MACHINE_CPUARCH} == "sparc64" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/sparc .else # temporary hack CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel .endif .if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64" SRCS+= dis_tables.c DSRCS+= regs_x86.d .endif LFLAGS+=-l YFLAGS+=-d LIBADD= ctf elf proc pthread rtld_db CLEANFILES= dt_errtags.c dt_names.c .include dt_errtags.c: ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/dt_errtags.h sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mkerrtags.sh < ${.ALLSRC} > ${.TARGET} dt_names.c: ${OPENSOLARIS_SYS_DISTDIR}/uts/common/sys/dtrace.h sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mknames.sh < ${.ALLSRC} > ${.TARGET} Index: head/cddl/lib/libdtrace/ip.d =================================================================== --- head/cddl/lib/libdtrace/ip.d (revision 337017) +++ head/cddl/lib/libdtrace/ip.d (revision 337018) @@ -1,303 +1,306 @@ /* * 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 module kernel #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 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 */ struct ip6_hdr *ipv6_hdr; /* pointer to raw header */ } ipv6info_t; #pragma D binding "1.5" IPPROTO_IP inline short IPPROTO_IP = 0; #pragma D binding "1.5" IPPROTO_ICMP inline short IPPROTO_ICMP = 1; #pragma D binding "1.5" IPPROTO_IGMP inline short IPPROTO_IGMP = 2; #pragma D binding "1.5" IPPROTO_IPV4 inline short IPPROTO_IPV4 = 4; #pragma D binding "1.5" IPPROTO_TCP inline short IPPROTO_TCP = 6; #pragma D binding "1.5" IPPROTO_UDP inline short IPPROTO_UDP = 17; #pragma D binding "1.5" IPPROTO_IPV6 inline short IPPROTO_IPV6 = 41; #pragma D binding "1.5" IPPROTO_ROUTING inline short IPPROTO_ROUTING = 43; #pragma D binding "1.5" IPPROTO_FRAGMENT inline short IPPROTO_FRAGMENT = 44; #pragma D binding "1.5" IPPROTO_RSVP inline short IPPROTO_RSVP = 46; #pragma D binding "1.5" IPPROTO_GRE inline short IPPROTO_GRE = 47; #pragma D binding "1.5" IPPROTO_ESP inline short IPPROTO_ESP = 50; #pragma D binding "1.5" IPPROTO_AH inline short IPPROTO_AH = 51; #pragma D binding "1.5" IPPROTO_MOBILE inline short IPPROTO_MOBILE = 55; #pragma D binding "1.5" IPPROTO_ICMPV6 inline short IPPROTO_ICMPV6 = 58; #pragma D binding "1.5" IPPROTO_DSTOPTS inline short IPPROTO_DSTOPTS = 60; #pragma D binding "1.5" IPPROTO_ETHERIP inline short IPPROTO_ETHERIP = 97; #pragma D binding "1.5" IPPROTO_PIM inline short IPPROTO_PIM = 103; #pragma D binding "1.5" IPPROTO_IPCOMP inline short IPPROTO_IPCOMP = 108; #pragma D binding "1.5" IPPROTO_SCTP inline short IPPROTO_SCTP = 132; #pragma D binding "1.5" IPPROTO_RAW inline short IPPROTO_RAW = 255; +#pragma D binding "1.13" IPPROTO_UDPLITE +inline short IPPROTO_UDPLITE = 136; inline uint8_t INP_IPV4 = 0x01; inline uint8_t INP_IPV6 = 0x02; #pragma D binding "1.5" 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_UDPLITE ? "UDPLITE" : proto == IPPROTO_RAW ? "RAW" : ""; /* * This field is always NULL according to the current definition of the ip * probes. */ #pragma D binding "1.5" translator translator pktinfo_t < void *p > { pkt_addr = NULL; }; #pragma D binding "1.5" translator translator csinfo_t < void *p > { cs_addr = NULL; cs_cid = (uint64_t)p; cs_pid = 0; cs_zoneid = 0; }; #pragma D binding "1.6.3" 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.5" 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 ? "" : ((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 ? "" : ((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.13" translator translator ipinfo_t < struct mbuf *m > { ip_ver = m == NULL ? 0 : ((struct ip *)m->m_data)->ip_v; ip_plength = m == NULL ? 0 : ((struct ip *)m->m_data)->ip_v == 4 ? ntohs(((struct ip *)m->m_data)->ip_len) - (((struct ip *)m->m_data)->ip_hl << 2): ntohs(((struct ip6_hdr *)m->m_data)->ip6_ctlun.ip6_un1.ip6_un1_plen); ip_saddr = m == NULL ? "" : ((struct ip *)m->m_data)->ip_v == 4 ? inet_ntoa(&((struct ip *)m->m_data)->ip_src.s_addr) : inet_ntoa6(&((struct ip6_hdr *)m->m_data)->ip6_src); ip_daddr = m == NULL ? "" : ((struct ip *)m->m_data)->ip_v == 4 ? inet_ntoa(&((struct ip *)m->m_data)->ip_dst.s_addr) : inet_ntoa6(&((struct ip6_hdr *)m->m_data)->ip6_dst); }; #pragma D binding "1.5" IFF_LOOPBACK inline int IFF_LOOPBACK = 0x8; #pragma D binding "1.5" 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.5" 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 : (ntohs(p->ip_off) & 0xe000) >> 8; ipv4_offset = p == NULL ? 0 : ntohs(p->ip_off) & 0x1fff; 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.5" 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 = p; }; Index: head/cddl/lib/libdtrace/udplite.d =================================================================== --- head/cddl/lib/libdtrace/udplite.d (nonexistent) +++ head/cddl/lib/libdtrace/udplite.d (revision 337018) @@ -0,0 +1,77 @@ +/* + * 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 + * Copyright (c) 2018 Michael Tuexen + */ + +#pragma D depends_on library ip.d +#pragma D depends_on module kernel +#pragma D depends_on provider udplite + +/* + * udplitesinfo contains stable UDPLite details. + */ +typedef struct udplitesinfo { + uintptr_t udplites_addr; + uint16_t udplites_lport; /* local port */ + uint16_t udplites_rport; /* remote port */ + string udplites_laddr; /* local address, as a string */ + string udplites_raddr; /* remote address, as a string */ +} udplitesinfo_t; + +/* + * udpliteinfo is the UDPLite header fields. + */ +typedef struct udpliteinfo { + uint16_t udplite_sport; /* source port */ + uint16_t udplite_dport; /* destination port */ + uint16_t udplite_coverage; /* checksum coverage */ + uint16_t udplite_checksum; /* headers + data checksum */ + struct udplitehdr *udplite_hdr; /* raw UDPLite header */ +} udpliteinfo_t; + +#pragma D binding "1.13" translator +translator udplitesinfo_t < struct inpcb *p > { + udplites_addr = (uintptr_t)p; + udplites_lport = p == NULL ? 0 : ntohs(p->inp_inc.inc_ie.ie_lport); + udplites_rport = p == NULL ? 0 : ntohs(p->inp_inc.inc_ie.ie_fport); + udplites_laddr = p == NULL ? "" : + p->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->inp_inc.inc_ie.ie_dependladdr.id46_addr.ia46_addr4.s_addr) : + inet_ntoa6(&p->inp_inc.inc_ie.ie_dependladdr.id6_addr); + udplites_raddr = p == NULL ? "" : + p->inp_vflag == INP_IPV4 ? + inet_ntoa(&p->inp_inc.inc_ie.ie_dependfaddr.id46_addr.ia46_addr4.s_addr) : + inet_ntoa6(&p->inp_inc.inc_ie.ie_dependfaddr.id6_addr); +}; + +#pragma D binding "1.13" translator +translator udpliteinfo_t < struct udphdr *p > { + udplite_sport = p == NULL ? 0 : ntohs(p->uh_sport); + udplite_dport = p == NULL ? 0 : ntohs(p->uh_dport); + udplite_coverage = p == NULL ? 0 : ntohs(p->uh_ulen); + udplite_checksum = p == NULL ? 0 : ntohs(p->uh_sum); + udplite_hdr = (struct udplitehdr *)p; +}; Property changes on: head/cddl/lib/libdtrace/udplite.d ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile =================================================================== --- head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile (revision 337017) +++ head/cddl/usr.sbin/dtrace/tests/common/ip/Makefile (revision 337018) @@ -1,38 +1,42 @@ # $FreeBSD$ # # This Makefile was generated by $srcdir/cddl/usr.sbin/dtrace/tests/tools/genmakefiles.sh. # PACKAGE= tests ${PACKAGE}FILES= \ tst.ipv4localicmp.ksh \ tst.ipv4localicmp.ksh.out \ tst.ipv4localtcp.ksh \ tst.ipv4localtcp.ksh.out \ tst.ipv4localudp.ksh \ tst.ipv4localudp.ksh.out \ + tst.ipv4localudplite.ksh \ + tst.ipv4localudplite.ksh.out \ tst.ipv4remoteicmp.ksh \ tst.ipv4remoteicmp.ksh.out \ tst.ipv4remotetcp.ksh \ tst.ipv4remotetcp.ksh.out \ tst.ipv4remoteudp.ksh \ tst.ipv4remoteudp.ksh.out \ + tst.ipv4remoteudplite.ksh \ + tst.ipv4remoteudplite.ksh.out \ tst.ipv6localicmp.ksh \ tst.ipv6localicmp.ksh.out \ tst.ipv6remoteicmp.ksh \ tst.ipv6remoteicmp.ksh.out \ tst.localtcpstate.ksh \ tst.localtcpstate.ksh.out \ tst.remotetcpstate.ksh \ tst.remotetcpstate.ksh.out \ TESTEXES= \ CFILES= \ .include "../../dtrace.test.mk" Index: head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh =================================================================== --- head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh (revision 337017) +++ head/cddl/usr.sbin/dtrace/tests/tools/exclude.sh (revision 337018) @@ -1,194 +1,195 @@ # $FreeBSD$ # This file lists DTrace tests which are known to fail or hang/crash the # system. They were pulled from the legacy DTrace test infrastructure in # tools/tests/dtrace and may be out of date. # # Tests are listed here generally because one or more of the following is true: # # 1) The test is broken (usually because it assumes it's running on Solaris and # the test encodes some sort of Solarisism). # 2) The functionality being tested is buggy (often but not always the result # of a FreeBSD-specific bug). # 3) The test relies on DTrace functionality that's not yet available in FreeBSD # (e.g. tests for a specific SDT provider that we don't have). # # An end goal is to remove this file, concentrating first on instances of # 1) and 2). # # The SKIP variable contains tests that should not be executed at all. The # EXFAIL variable contains tests that are expected to fail when run. Please # avoid adding tests to SKIP unless it really is necessary; with EXFAIL, tests # that begin passing as the result of a change are visible in the test summary. exclude() { eval $1=\"\$$1\\n$2\" } exclude EXFAIL common/aggs/tst.subr.d exclude EXFAIL common/dtraceUtil/tst.ELFGenerationOut.d.ksh exclude EXFAIL common/dtraceUtil/tst.ELFGenerationWithO.d.ksh exclude EXFAIL common/funcs/tst.copyin.d exclude EXFAIL common/funcs/tst.copyinto.d exclude EXFAIL common/funcs/tst.ddi_pathname.d exclude EXFAIL common/io/tst.fds.d exclude EXFAIL common/mdb/tst.dtracedcmd.ksh exclude EXFAIL common/misc/tst.dofmax.ksh exclude EXFAIL common/misc/tst.include.ksh exclude EXFAIL common/safety/tst.copyin2.d exclude EXFAIL common/safety/tst.msgdsize.d exclude EXFAIL common/safety/tst.msgsize.d exclude EXFAIL common/scalars/tst.misc.d exclude EXFAIL common/scalars/tst.selfarray2.d exclude EXFAIL common/sched/tst.enqueue.d exclude EXFAIL common/speculation/tst.SpecSizeVariations3.d exclude EXFAIL common/tracemem/err.D_TRACEMEM_ADDR.badaddr.d exclude EXFAIL common/translators/tst.TestTransStability2.ksh exclude EXFAIL common/types/tst.struct.d exclude EXFAIL common/types/tst.typedef.d # We don't have a cpc provider. exclude SKIP common/cpc/err.D_PDESC_ZERO.lowfrequency.d exclude SKIP common/cpc/err.D_PDESC_ZERO.malformedoverflow.d exclude SKIP common/cpc/err.D_PDESC_ZERO.nonexistentevent.d exclude SKIP common/cpc/err.cpcvscpustatpart1.ksh exclude SKIP common/cpc/err.cpcvscpustatpart2.ksh exclude SKIP common/cpc/err.cputrackfailtostart.ksh exclude SKIP common/cpc/err.cputrackterminates.ksh exclude SKIP common/cpc/err.toomanyenablings.d exclude SKIP common/cpc/tst.allcpus.ksh exclude SKIP common/cpc/tst.genericevent.d exclude SKIP common/cpc/tst.platformevent.ksh # We don't have a mib provider. exclude EXFAIL common/mib/tst.icmp.ksh exclude EXFAIL common/mib/tst.tcp.ksh exclude EXFAIL common/mib/tst.udp.ksh # At the moment dtrace(1) always needs to run as root. exclude SKIP common/privs/tst.fds.ksh exclude SKIP common/privs/tst.func_access.ksh exclude SKIP common/privs/tst.getf.ksh exclude SKIP common/privs/tst.kpriv.ksh exclude SKIP common/privs/tst.op_access.ksh exclude SKIP common/privs/tst.procpriv.ksh exclude SKIP common/privs/tst.providers.ksh exclude SKIP common/privs/tst.unpriv_funcs.ksh # These tests hang for reasons unknown. exclude SKIP common/buffering/tst.ring3.d exclude SKIP common/funcs/tst.chill.ksh exclude SKIP common/funcs/tst.index.d # No Java support at the moment. exclude EXFAIL common/java_api/tst.Abort.ksh exclude EXFAIL common/java_api/tst.Bean.ksh exclude EXFAIL common/java_api/tst.Close.ksh exclude EXFAIL common/java_api/tst.Drop.ksh exclude EXFAIL common/java_api/tst.Enable.ksh exclude EXFAIL common/java_api/tst.FunctionLookup.ksh exclude EXFAIL common/java_api/tst.GetAggregate.ksh exclude EXFAIL common/java_api/tst.MaxConsumers.ksh exclude EXFAIL common/java_api/tst.MultiAggPrinta.ksh exclude EXFAIL common/java_api/tst.ProbeData.ksh exclude EXFAIL common/java_api/tst.ProbeDescription.ksh exclude EXFAIL common/java_api/tst.StateMachine.ksh exclude EXFAIL common/java_api/tst.StopLock.ksh # Expects specific formatting from banner(6). exclude EXFAIL common/aggs/tst.aggpackbanner.ksh # Test assumes we're running on a Solaris kernel. exclude EXFAIL common/misc/tst.roch.d exclude EXFAIL common/predicates/tst.argsnotcached.d exclude EXFAIL common/safety/tst.vahole.d # Tests that depend on the plockstat provider. exclude EXFAIL common/plockstat/tst.available.d exclude EXFAIL common/plockstat/tst.libmap.d exclude EXFAIL common/usdt/tst.andpid.ksh # Depends on java. exclude SKIP common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d # Interrupt priority isn't relevant on FreeBSD. exclude SKIP common/builtinvar/tst.ipl.d exclude SKIP common/builtinvar/tst.ipl1.d # These tests rely on being able to find a host via broadcast pings. exclude EXFAIL common/ip/tst.ipv4remotetcp.ksh exclude EXFAIL common/ip/tst.ipv4remoteudp.ksh +exclude EXFAIL common/ip/tst.ipv4remoteudplite.ksh exclude EXFAIL common/ip/tst.ipv6remoteicmp.ksh exclude EXFAIL common/ip/tst.ipv4remoteicmp.ksh exclude EXFAIL common/ip/tst.remotetcpstate.ksh # Tries to enable pid$target:libc::entry, though there's no "libc" module. # Currently unsure as to whether this might be a libproc bug. exclude EXFAIL common/pid/tst.probemod.ksh # Assumes date(1) has a pid$target::main:return probe. exclude EXFAIL common/pid/tst.newprobes.ksh # libproc+librtld_db don't handle dlopen(2) yet. exclude EXFAIL common/pid/tst.provregex2.ksh exclude EXFAIL common/pid/tst.provregex4.ksh # This test appears to be invalid. dtrace is supposed to press on if a # depends_on pragma cannot be satisfied, per the comment above # dt_load_libs_dir() in libdtrace. exclude EXFAIL common/pragma/err.invalidlibdep.ksh # This test checks for a leading tab on a line before #define. That is illegal # on Solaris, but the clang pre-processor on FreeBSD is happy with code like # that. exclude EXFAIL common/preprocessor/err.D_PRAGCTL_INVAL.tabdefine.d # This test uses proc:::signal-handle, which we don't appear to have. exclude EXFAIL common/proc/tst.signal.ksh # This test uses proc:::lwp-start, which we don't appear to have. exclude EXFAIL common/proc/tst.startexit.ksh # This test causes a panic at the moment because fbt instruments the lock class' # lc_owned method. exclude SKIP common/safety/tst.rw.d # Depends on some implementation details of the runtime linker. exclude EXFAIL common/vars/tst.ucaller.ksh # These rely on process attributes that FreeBSD doesn't carry. exclude EXFAIL common/scripting/tst.projid.ksh exclude EXFAIL common/scripting/tst.taskid.ksh # Depends on tst.chasestrings.exe being ELF32. See r326181 and r326285. exclude EXFAIL common/uctf/err.user64mode.ksh # This test expects its test program to be installed without CTF data, but # the rest of the programs for this feature need CTF data. Not yet sure how # to build that. exclude EXFAIL common/uctf/tst.libtype.ksh # libproc doesn't have linkmap support yet. exclude EXFAIL common/uctf/tst.linkmap.ksh # Uses Sun-specific compiler options. exclude EXFAIL common/usdt/tst.badguess.ksh exclude EXFAIL common/usdt/tst.guess32.ksh exclude EXFAIL common/usdt/tst.guess64.ksh # Depends on non-standard static linker behaviour. exclude EXFAIL common/usdt/tst.eliminate.ksh # Generated headers include , so _DTRACE_VERSION is always defined. exclude EXFAIL common/usdt/tst.nodtrace.ksh # The second dtrace -G invocation returns an error with "no probes found," which # makes sense to me. Not yet sure what the expected behaviour is here. exclude EXFAIL common/usdt/tst.static2.ksh # Uses the Solaris-specific ppriv(1). exclude EXFAIL common/usdt/tst.user.ksh # Triggers a lock assertion by using the raise() action from a profile probe. exclude SKIP common/ustack/tst.spin.ksh Index: head/cddl/usr.sbin/dwatch/libexec/Makefile =================================================================== --- head/cddl/usr.sbin/dwatch/libexec/Makefile (revision 337017) +++ head/cddl/usr.sbin/dwatch/libexec/Makefile (revision 337018) @@ -1,87 +1,90 @@ # $FreeBSD$ FILESDIR= ${LIBEXECDIR}/dwatch FILES= chmod \ errno \ io \ ip \ kill \ nanosleep \ open \ proc \ rw \ sched \ sendrecv \ tcp \ udp \ + udplite \ vop_create \ vop_readdir \ vop_rename \ vop_symlink LINKS= ${LIBEXECDIR}/dwatch/chmod ${LIBEXECDIR}/dwatch/fchmodat LINKS+= ${LIBEXECDIR}/dwatch/chmod ${LIBEXECDIR}/dwatch/lchmod LINKS+= ${LIBEXECDIR}/dwatch/io ${LIBEXECDIR}/dwatch/io-done LINKS+= ${LIBEXECDIR}/dwatch/io ${LIBEXECDIR}/dwatch/io-start LINKS+= ${LIBEXECDIR}/dwatch/ip ${LIBEXECDIR}/dwatch/ip-receive LINKS+= ${LIBEXECDIR}/dwatch/ip ${LIBEXECDIR}/dwatch/ip-send LINKS+= ${LIBEXECDIR}/dwatch/open ${LIBEXECDIR}/dwatch/openat LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-create LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-exec LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-exec-failure LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-exec-success LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-exit LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-signal LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-signal-clear LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-signal-discard LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-signal-send LINKS+= ${LIBEXECDIR}/dwatch/proc ${LIBEXECDIR}/dwatch/proc-status LINKS+= ${LIBEXECDIR}/dwatch/rw ${LIBEXECDIR}/dwatch/read LINKS+= ${LIBEXECDIR}/dwatch/rw ${LIBEXECDIR}/dwatch/write LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-change-pri LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-cpu LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-dequeue LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-enqueue LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-exec LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-lend-pri LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-load-change LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-off-cpu LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-on-cpu LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-preempt LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-pri LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-queue LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-remain-cpu LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-sleep LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-surrender LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-tick LINKS+= ${LIBEXECDIR}/dwatch/sched ${LIBEXECDIR}/dwatch/sched-wakeup LINKS+= ${LIBEXECDIR}/dwatch/sendrecv ${LIBEXECDIR}/dwatch/recv LINKS+= ${LIBEXECDIR}/dwatch/sendrecv ${LIBEXECDIR}/dwatch/recvfrom LINKS+= ${LIBEXECDIR}/dwatch/sendrecv ${LIBEXECDIR}/dwatch/recvmsg LINKS+= ${LIBEXECDIR}/dwatch/sendrecv ${LIBEXECDIR}/dwatch/send LINKS+= ${LIBEXECDIR}/dwatch/sendrecv ${LIBEXECDIR}/dwatch/sendmsg LINKS+= ${LIBEXECDIR}/dwatch/sendrecv ${LIBEXECDIR}/dwatch/sendto LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-accept LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-accept-established LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-accept-refused LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-connect LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-connect-established LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-connect-refused LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-connect-request LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-established LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-init LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-io LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-receive LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-refused LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-send LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-state-change LINKS+= ${LIBEXECDIR}/dwatch/tcp ${LIBEXECDIR}/dwatch/tcp-status LINKS+= ${LIBEXECDIR}/dwatch/udp ${LIBEXECDIR}/dwatch/udp-receive LINKS+= ${LIBEXECDIR}/dwatch/udp ${LIBEXECDIR}/dwatch/udp-send +LINKS+= ${LIBEXECDIR}/dwatch/udplite ${LIBEXECDIR}/dwatch/udplite-receive +LINKS+= ${LIBEXECDIR}/dwatch/udplite ${LIBEXECDIR}/dwatch/udplite-send LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_lookup LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_mkdir LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_mknod LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_remove LINKS+= ${LIBEXECDIR}/dwatch/vop_create ${LIBEXECDIR}/dwatch/vop_rmdir .include Index: head/cddl/usr.sbin/dwatch/libexec/udplite =================================================================== --- head/cddl/usr.sbin/dwatch/libexec/udplite (nonexistent) +++ head/cddl/usr.sbin/dwatch/libexec/udplite (revision 337018) @@ -0,0 +1,89 @@ +# -*- tab-width: 4 -*- ;; Emacs +# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM +############################################################ IDENT(1) +# +# $Title: dwatch(8) module for dtrace_udplite(4) $ +# $Copyright: 2014-2018 Devin Teske. All rights reserved. $ +# $FreeBSD$ +# +############################################################ DESCRIPTION +# +# Display local/remote UDP addresses/ports and bytes sent/received for UDP I/O +# +############################################################ PROBE + +case "$PROFILE" in +udplite) : ${PROBE:=udplite:::send, udplite:::receive} ;; + *) : ${PROBE:=udplite:::${PROFILE#udplite-}} +esac + +############################################################ ACTIONS + +exec 9<"); +} + /* + * dtrace_udplite(4) + */ + this->recv = probename == "receive" ? 1 : 0; + this->flow = this->recv ? "<-" : "->"; + + /* + * ipinfo_t * + */ + this->local = this->recv ? args[2]->ip_daddr : args[2]->ip_saddr; + this->remote = this->recv ? args[2]->ip_saddr : args[2]->ip_daddr; + + /* + * udpliteinfo_t * + */ + this->coverage = (uint16_t)args[4]->udplite_coverage; + this->lport = this->recv ? args[4]->udplite_dport : args[4]->udplite_sport; + this->rport = this->recv ? args[4]->udplite_sport : args[4]->udplite_dport; + + /* + * IPv6 support + */ + this->local6 = strstr(this->local, ":") != NULL ? 1 : 0; + this->remote6 = strstr(this->remote, ":") != NULL ? 1 : 0; + this->local = strjoin(strjoin(this->local6 ? "[" : "", + this->local), this->local6 ? "]" : ""); + this->remote = strjoin(strjoin(this->remote6 ? "[" : "", + this->remote), this->remote6 ? "]" : ""); +} +EOF +ACTIONS=$( cat <&9 ) +ID=$(( $ID + 1 )) + +############################################################ EVENT DETAILS + +if [ ! "$CUSTOM_DETAILS" ]; then +exec 9<local, this->lport, + this->flow, + this->remote, this->rport, + this->coverage, + this->coverage == 1 ? "" : "s"); +EOF +EVENT_DETAILS=$( cat <&9 ) +fi + +################################################################################ +# END +################################################################################ Property changes on: head/cddl/usr.sbin/dwatch/libexec/udplite ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/share/man/man4/Makefile =================================================================== --- head/share/man/man4/Makefile (revision 337017) +++ head/share/man/man4/Makefile (revision 337018) @@ -1,1005 +1,1006 @@ # @(#)Makefile 8.1 (Berkeley) 6/18/93 # $FreeBSD$ .include PACKAGE=runtime-manuals MAN= aac.4 \ aacraid.4 \ acpi.4 \ ${_acpi_asus.4} \ ${_acpi_asus_wmi.4} \ ${_acpi_dock.4} \ ${_acpi_fujitsu.4} \ ${_acpi_hp.4} \ ${_acpi_ibm.4} \ ${_acpi_panasonic.4} \ ${_acpi_rapidstart.4} \ ${_acpi_sony.4} \ acpi_thermal.4 \ ${_acpi_toshiba.4} \ acpi_video.4 \ ${_acpi_wmi.4} \ ada.4 \ adm6996fc.4 \ adv.4 \ adw.4 \ ae.4 \ ${_aesni.4} \ age.4 \ agp.4 \ aha.4 \ ahc.4 \ ahci.4 \ ahd.4 \ ${_aibs.4} \ aio.4 \ alc.4 \ ale.4 \ alpm.4 \ altera_atse.4 \ altera_avgen.4 \ altera_jtag_uart.4 \ altera_sdcard.4 \ altq.4 \ amdpm.4 \ ${_amdsbwd.4} \ ${_amdsmb.4} \ ${_amdsmn.4} \ ${_amdtemp.4} \ ${_bxe.4} \ amr.4 \ an.4 \ ${_aout.4} \ ${_apic.4} \ arcmsr.4 \ ${_asmc.4} \ ata.4 \ ath.4 \ ath_ahb.4 \ ath_hal.4 \ ath_pci.4 \ atkbd.4 \ atkbdc.4 \ atp.4 \ ${_atf_test_case.4} \ ${_atrtc.4} \ ${_attimer.4} \ audit.4 \ auditpipe.4 \ aue.4 \ axe.4 \ axge.4 \ bce.4 \ bcma.4 \ bfe.4 \ bge.4 \ ${_bhyve.4} \ bhnd.4 \ bhnd_chipc.4 \ bhnd_pmu.4 \ bhndb.4 \ bhndb_pci.4 \ bktr.4 \ blackhole.4 \ bnxt.4 \ bpf.4 \ bridge.4 \ bt.4 \ bwi.4 \ bwn.4 \ ${_bytgpio.4} \ ${_chvgpio.4} \ capsicum.4 \ cardbus.4 \ carp.4 \ cas.4 \ cc_cdg.4 \ cc_chd.4 \ cc_cubic.4 \ cc_dctcp.4 \ cc_hd.4 \ cc_htcp.4 \ cc_newreno.4 \ cc_vegas.4 \ ${_ccd.4} \ ccr.4 \ cd.4 \ cdce.4 \ cfi.4 \ cfumass.4 \ ch.4 \ chromebook_platform.4 \ ciss.4 \ cloudabi.4 \ cmx.4 \ ${_coretemp.4} \ ${_cpuctl.4} \ cpufreq.4 \ crypto.4 \ ctl.4 \ cue.4 \ cxgb.4 \ cxgbe.4 \ cxgbev.4 \ cy.4 \ cyapa.4 \ da.4 \ dc.4 \ dcons.4 \ dcons_crom.4 \ ddb.4 \ de.4 \ devctl.4 \ disc.4 \ divert.4 \ ${_dpms.4} \ dpt.4 \ ds1307.4 \ ds3231.4 \ ${_dtrace_provs} \ dummynet.4 \ ed.4 \ edsc.4 \ ehci.4 \ em.4 \ ena.4 \ enc.4 \ epair.4 \ esp.4 \ est.4 \ et.4 \ etherswitch.4 \ eventtimers.4 \ exca.4 \ e6060sw.4 \ fd.4 \ fdc.4 \ fdt.4 \ fdt_pinctrl.4 \ fdtbus.4 \ ffclock.4 \ filemon.4 \ firewire.4 \ full.4 \ fwe.4 \ fwip.4 \ fwohci.4 \ fxp.4 \ gbde.4 \ gdb.4 \ gem.4 \ geom.4 \ geom_fox.4 \ geom_linux_lvm.4 \ geom_map.4 \ geom_uzip.4 \ gif.4 \ gpio.4 \ gpioiic.4 \ gpioled.4 \ gre.4 \ h_ertt.4 \ hifn.4 \ hme.4 \ hpet.4 \ ${_hpt27xx.4} \ ${_hptiop.4} \ ${_hptmv.4} \ ${_hptnr.4} \ ${_hptrr.4} \ ${_hv_kvp.4} \ ${_hv_netvsc.4} \ ${_hv_storvsc.4} \ ${_hv_utils.4} \ ${_hv_vmbus.4} \ ${_hv_vss.4} \ hwpmc.4 \ ichsmb.4 \ ${_ichwd.4} \ icmp.4 \ icmp6.4 \ ida.4 \ if_ipsec.4 \ ifmib.4 \ ig4.4 \ igmp.4 \ iic.4 \ iicbb.4 \ iicbus.4 \ iicsmb.4 \ iir.4 \ ${_imcsmb.4} \ inet.4 \ inet6.4 \ intpm.4 \ intro.4 \ ${_io.4} \ ${_ioat.4} \ ip.4 \ ip6.4 \ ipfirewall.4 \ ipheth.4 \ ${_ipmi.4} \ ips.4 \ ipsec.4 \ ipw.4 \ ipwfw.4 \ isci.4 \ isl.4 \ ismt.4 \ isp.4 \ ispfw.4 \ iwi.4 \ iwifw.4 \ iwm.4 \ iwmfw.4 \ iwn.4 \ iwnfw.4 \ ixgbe.4 \ ixl.4 \ ixlv.4 \ jedec_dimm.4 \ jedec_ts.4 \ jme.4 \ joy.4 \ kbdmux.4 \ keyboard.4 \ kld.4 \ ksyms.4 \ ksz8995ma.4 \ ktr.4 \ kue.4 \ lagg.4 \ le.4 \ led.4 \ lge.4 \ ${_linux.4} \ liquidio.4 \ lm75.4 \ lo.4 \ lp.4 \ lpbb.4 \ lpt.4 \ mac.4 \ mac_biba.4 \ mac_bsdextended.4 \ mac_ifoff.4 \ mac_lomac.4 \ mac_mls.4 \ mac_none.4 \ mac_partition.4 \ mac_portacl.4 \ mac_seeotheruids.4 \ mac_stub.4 \ mac_test.4 \ malo.4 \ md.4 \ mdio.4 \ me.4 \ mem.4 \ meteor.4 \ mfi.4 \ miibus.4 \ mk48txx.4 \ mld.4 \ mlx.4 \ mlx4en.4 \ mlx5en.4 \ mly.4 \ mmc.4 \ mmcsd.4 \ mn.4 \ mod_cc.4 \ mos.4 \ mouse.4 \ mpr.4 \ mps.4 \ mpt.4 \ mrsas.4 \ msk.4 \ mtio.4 \ multicast.4 \ muge.4 \ mvs.4 \ mwl.4 \ mwlfw.4 \ mxge.4 \ my.4 \ nand.4 \ nandsim.4 \ ncr.4 \ ncv.4 \ ${_ndis.4} \ net80211.4 \ netdump.4 \ netfpga10g_nf10bmac.4 \ netgraph.4 \ netintro.4 \ netmap.4 \ ${_nfe.4} \ ${_nfsmb.4} \ ng_async.4 \ ngatmbase.4 \ ng_atmllc.4 \ ng_bpf.4 \ ng_bridge.4 \ ng_bt3c.4 \ ng_btsocket.4 \ ng_car.4 \ ng_ccatm.4 \ ng_cisco.4 \ ng_deflate.4 \ ng_device.4 \ nge.4 \ ng_echo.4 \ ng_eiface.4 \ ng_etf.4 \ ng_ether.4 \ ng_ether_echo.4 \ ng_frame_relay.4 \ ng_gif.4 \ ng_gif_demux.4 \ ng_h4.4 \ ng_hci.4 \ ng_hole.4 \ ng_hub.4 \ ng_iface.4 \ ng_ipfw.4 \ ng_ip_input.4 \ ng_ksocket.4 \ ng_l2cap.4 \ ng_l2tp.4 \ ng_lmi.4 \ ng_mppc.4 \ ng_nat.4 \ ng_netflow.4 \ ng_one2many.4 \ ng_patch.4 \ ng_ppp.4 \ ng_pppoe.4 \ ng_pptpgre.4 \ ng_pred1.4 \ ng_rfc1490.4 \ ng_socket.4 \ ng_source.4 \ ng_split.4 \ ng_sppp.4 \ ng_sscfu.4 \ ng_sscop.4 \ ng_tag.4 \ ng_tcpmss.4 \ ng_tee.4 \ ng_tty.4 \ ng_ubt.4 \ ng_UI.4 \ ng_uni.4 \ ng_vjc.4 \ ng_vlan.4 \ nmdm.4 \ nsp.4 \ ${_ntb.4} \ ${_ntb_hw_intel.4} \ ${_ntb_hw_plx.4} \ ${_ntb_transport.4} \ ${_nda.4} \ ${_if_ntb.4} \ null.4 \ numa.4 \ ${_nvd.4} \ ${_nvme.4} \ ${_nvram.4} \ ${_nvram2env.4} \ oce.4 \ ocs_fc.4\ ohci.4 \ orm.4 \ ow.4 \ ow_temp.4 \ owc.4 \ ${_padlock.4} \ pass.4 \ pccard.4 \ pccbb.4 \ pcf.4 \ pci.4 \ pcib.4 \ pcic.4 \ pcm.4 \ pcn.4 \ ${_pf.4} \ ${_pflog.4} \ ${_pfsync.4} \ pim.4 \ pms.4 \ polling.4 \ ppbus.4 \ ppc.4 \ ppi.4 \ procdesc.4 \ proto.4 \ psm.4 \ pst.4 \ pt.4 \ pts.4 \ pty.4 \ puc.4 \ ${_qlxge.4} \ ${_qlxgb.4} \ ${_qlxgbe.4} \ ${_qlnxe.4} \ ral.4 \ random.4 \ rc.4 \ rctl.4 \ re.4 \ rgephy.4 \ rights.4 \ rl.4 \ rndtest.4 \ route.4 \ rp.4 \ rtwn.4 \ rtwnfw.4 \ rtwn_pci.4 \ rue.4 \ sa.4 \ safe.4 \ sbp.4 \ sbp_targ.4 \ scc.4 \ sched_4bsd.4 \ sched_ule.4 \ screen.4 \ scsi.4 \ sctp.4 \ sdhci.4 \ sem.4 \ send.4 \ ses.4 \ sf.4 \ ${_sfxge.4} \ sge.4 \ siba.4 \ siftr.4 \ siis.4 \ simplebus.4 \ sio.4 \ sis.4 \ sk.4 \ ${_smartpqi.4} \ smb.4 \ smbus.4 \ smp.4 \ smsc.4 \ sn.4 \ snd_ad1816.4 \ snd_als4000.4 \ snd_atiixp.4 \ snd_cmi.4 \ snd_cs4281.4 \ snd_csa.4 \ snd_ds1.4 \ snd_emu10k1.4 \ snd_emu10kx.4 \ snd_envy24.4 \ snd_envy24ht.4 \ snd_es137x.4 \ snd_ess.4 \ snd_fm801.4 \ snd_gusc.4 \ snd_hda.4 \ snd_hdspe.4 \ snd_ich.4 \ snd_maestro3.4 \ snd_maestro.4 \ snd_mss.4 \ snd_neomagic.4 \ snd_sbc.4 \ snd_solo.4 \ snd_spicds.4 \ snd_t4dwave.4 \ snd_uaudio.4 \ snd_via8233.4 \ snd_via82c686.4 \ snd_vibes.4 \ snp.4 \ spigen.4 \ ${_spkr.4} \ splash.4 \ sppp.4 \ ste.4 \ stf.4 \ stg.4 \ stge.4 \ sym.4 \ syncache.4 \ syncer.4 \ syscons.4 \ sysmouse.4 \ tap.4 \ targ.4 \ tcp.4 \ tdfx.4 \ terasic_mtl.4 \ termios.4 \ textdump.4 \ ti.4 \ timecounters.4 \ tl.4 \ ${_tpm.4} \ trm.4 \ tty.4 \ tun.4 \ twa.4 \ twe.4 \ tws.4 \ tx.4 \ txp.4 \ udp.4 \ udplite.4 \ ure.4 \ vale.4 \ vga.4 \ vge.4 \ viapm.4 \ ${_viawd.4} \ ${_virtio.4} \ ${_virtio_balloon.4} \ ${_virtio_blk.4} \ ${_virtio_console.4} \ ${_virtio_random.4} \ ${_virtio_scsi.4} \ vkbd.4 \ vlan.4 \ vxlan.4 \ ${_vmm.4} \ ${_vmx.4} \ vpo.4 \ vr.4 \ vt.4 \ vte.4 \ ${_vtnet.4} \ watchdog.4 \ wb.4 \ ${_wbwd.4} \ wi.4 \ witness.4 \ wlan.4 \ wlan_acl.4 \ wlan_amrr.4 \ wlan_ccmp.4 \ wlan_tkip.4 \ wlan_wep.4 \ wlan_xauth.4 \ wmt.4 \ ${_wpi.4} \ wsp.4 \ xe.4 \ ${_xen.4} \ xhci.4 \ xl.4 \ ${_xnb.4} \ xpt.4 \ zero.4 MLINKS= ae.4 if_ae.4 MLINKS+=age.4 if_age.4 MLINKS+=agp.4 agpgart.4 MLINKS+=alc.4 if_alc.4 MLINKS+=ale.4 if_ale.4 MLINKS+=altera_atse.4 atse.4 MLINKS+=altera_sdcard.4 altera_sdcardc.4 MLINKS+=altq.4 ALTQ.4 MLINKS+=ath.4 if_ath.4 MLINKS+=ath_pci.4 if_ath_pci.4 MLINKS+=an.4 if_an.4 MLINKS+=aue.4 if_aue.4 MLINKS+=axe.4 if_axe.4 MLINKS+=bce.4 if_bce.4 MLINKS+=bfe.4 if_bfe.4 MLINKS+=bge.4 if_bge.4 MLINKS+=bktr.4 brooktree.4 MLINKS+=bnxt.4 if_bnxt.4 MLINKS+=bridge.4 if_bridge.4 MLINKS+=bwi.4 if_bwi.4 MLINKS+=bwn.4 if_bwn.4 MLINKS+=${_bxe.4} ${_if_bxe.4} MLINKS+=cas.4 if_cas.4 MLINKS+=cdce.4 if_cdce.4 MLINKS+=cfi.4 cfid.4 MLINKS+=cloudabi.4 cloudabi32.4 \ cloudabi.4 cloudabi64.4 MLINKS+=crypto.4 cryptodev.4 MLINKS+=cue.4 if_cue.4 MLINKS+=cxgb.4 if_cxgb.4 MLINKS+=cxgbe.4 if_cxgbe.4 \ cxgbe.4 vcxgbe.4 \ cxgbe.4 if_vcxgbe.4 \ cxgbe.4 cxl.4 \ cxgbe.4 if_cxl.4 \ cxgbe.4 vcxl.4 \ cxgbe.4 if_vcxl.4 \ cxgbe.4 cc.4 \ cxgbe.4 if_cc.4 \ cxgbe.4 vcc.4 \ cxgbe.4 if_vcc.4 MLINKS+=cxgbev.4 if_cxgbev.4 \ cxgbev.4 cxlv.4 \ cxgbev.4 if_cxlv.4 \ cxgbev.4 ccv.4 \ cxgbev.4 if_ccv.4 MLINKS+=dc.4 if_dc.4 MLINKS+=de.4 if_de.4 MLINKS+=disc.4 if_disc.4 MLINKS+=ed.4 if_ed.4 MLINKS+=edsc.4 if_edsc.4 MLINKS+=em.4 if_em.4 MLINKS+=enc.4 if_enc.4 MLINKS+=epair.4 if_epair.4 MLINKS+=et.4 if_et.4 MLINKS+=fd.4 stderr.4 \ fd.4 stdin.4 \ fd.4 stdout.4 MLINKS+=fdt.4 FDT.4 MLINKS+=firewire.4 ieee1394.4 MLINKS+=fwe.4 if_fwe.4 MLINKS+=fwip.4 if_fwip.4 MLINKS+=fxp.4 if_fxp.4 MLINKS+=gem.4 if_gem.4 MLINKS+=geom.4 GEOM.4 MLINKS+=gif.4 if_gif.4 MLINKS+=gpio.4 gpiobus.4 MLINKS+=gre.4 if_gre.4 MLINKS+=hme.4 if_hme.4 MLINKS+=hpet.4 acpi_hpet.4 MLINKS+=${_hptrr.4} ${_rr232x.4} MLINKS+=${_attimer.4} ${_i8254.4} MLINKS+=ip.4 rawip.4 MLINKS+=ipfirewall.4 ipaccounting.4 \ ipfirewall.4 ipacct.4 \ ipfirewall.4 ipfw.4 MLINKS+=ipheth.4 if_ipheth.4 MLINKS+=ipw.4 if_ipw.4 MLINKS+=iwi.4 if_iwi.4 MLINKS+=iwm.4 if_iwm.4 MLINKS+=iwn.4 if_iwn.4 MLINKS+=ixgbe.4 ix.4 MLINKS+=ixgbe.4 if_ix.4 MLINKS+=ixgbe.4 if_ixgbe.4 MLINKS+=ixl.4 if_ixl.4 MLINKS+=ixlv.4 if_ixlv.4 MLINKS+=jme.4 if_jme.4 MLINKS+=kue.4 if_kue.4 MLINKS+=lagg.4 trunk.4 MLINKS+=lagg.4 if_lagg.4 MLINKS+=le.4 if_le.4 MLINKS+=lge.4 if_lge.4 MLINKS+=lo.4 loop.4 MLINKS+=lp.4 plip.4 MLINKS+=malo.4 if_malo.4 MLINKS+=md.4 vn.4 MLINKS+=mem.4 kmem.4 MLINKS+=mfi.4 mfi_linux.4 \ mfi.4 mfip.4 MLINKS+=mlx5en.4 mce.4 MLINKS+=mn.4 if_mn.4 MLINKS+=mos.4 if_mos.4 MLINKS+=msk.4 if_msk.4 MLINKS+=mwl.4 if_mwl.4 MLINKS+=mxge.4 if_mxge.4 MLINKS+=my.4 if_my.4 MLINKS+=${_ndis.4} ${_if_ndis.4} MLINKS+=netfpga10g_nf10bmac.4 if_nf10bmac.4 MLINKS+=netintro.4 net.4 \ netintro.4 networking.4 MLINKS+=${_nfe.4} ${_if_nfe.4} MLINKS+=nge.4 if_nge.4 MLINKS+=ow.4 onewire.4 MLINKS+=pccbb.4 cbb.4 MLINKS+=pcm.4 snd.4 \ pcm.4 sound.4 MLINKS+=pcn.4 if_pcn.4 MLINKS+=pms.4 pmspcv.4 MLINKS+=ral.4 if_ral.4 MLINKS+=re.4 if_re.4 MLINKS+=rl.4 if_rl.4 MLINKS+=rtwn_pci.4 if_rtwn_pci.4 MLINKS+=rue.4 if_rue.4 MLINKS+=scsi.4 CAM.4 \ scsi.4 cam.4 \ scsi.4 scbus.4 \ scsi.4 SCSI.4 MLINKS+=sf.4 if_sf.4 MLINKS+=sge.4 if_sge.4 MLINKS+=sis.4 if_sis.4 MLINKS+=sk.4 if_sk.4 MLINKS+=smp.4 SMP.4 MLINKS+=smsc.4 if_smsc.4 MLINKS+=sn.4 if_sn.4 MLINKS+=snd_envy24.4 snd_ak452x.4 MLINKS+=snd_sbc.4 snd_sb16.4 \ snd_sbc.4 snd_sb8.4 MLINKS+=${_spkr.4} ${_speaker.4} MLINKS+=splash.4 screensaver.4 MLINKS+=ste.4 if_ste.4 MLINKS+=stf.4 if_stf.4 MLINKS+=stge.4 if_stge.4 MLINKS+=syncache.4 syncookies.4 MLINKS+=syscons.4 sc.4 MLINKS+=tap.4 if_tap.4 MLINKS+=tdfx.4 tdfx_linux.4 MLINKS+=ti.4 if_ti.4 MLINKS+=tl.4 if_tl.4 MLINKS+=tun.4 if_tun.4 MLINKS+=tx.4 if_tx.4 MLINKS+=txp.4 if_txp.4 MLINKS+=ure.4 if_ure.4 MLINKS+=vge.4 if_vge.4 MLINKS+=vlan.4 if_vlan.4 MLINKS+=vxlan.4 if_vxlan.4 MLINKS+=${_vmx.4} ${_if_vmx.4} MLINKS+=vpo.4 imm.4 MLINKS+=vr.4 if_vr.4 MLINKS+=vte.4 if_vte.4 MLINKS+=${_vtnet.4} ${_if_vtnet.4} MLINKS+=watchdog.4 SW_WATCHDOG.4 MLINKS+=wb.4 if_wb.4 MLINKS+=wi.4 if_wi.4 MLINKS+=${_wpi.4} ${_if_wpi.4} MLINKS+=xe.4 if_xe.4 MLINKS+=xl.4 if_xl.4 .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" _acpi_asus.4= acpi_asus.4 _acpi_asus_wmi.4= acpi_asus_wmi.4 _acpi_dock.4= acpi_dock.4 _acpi_fujitsu.4=acpi_fujitsu.4 _acpi_hp.4= acpi_hp.4 _acpi_ibm.4= acpi_ibm.4 _acpi_panasonic.4=acpi_panasonic.4 _acpi_rapidstart.4=acpi_rapidstart.4 _acpi_sony.4= acpi_sony.4 _acpi_toshiba.4=acpi_toshiba.4 _acpi_wmi.4= acpi_wmi.4 _aesni.4= aesni.4 _aout.4= aout.4 _apic.4= apic.4 _atrtc.4= atrtc.4 _attimer.4= attimer.4 _aibs.4= aibs.4 _amdsbwd.4= amdsbwd.4 _amdsmb.4= amdsmb.4 _amdsmn.4= amdsmn.4 _amdtemp.4= amdtemp.4 _asmc.4= asmc.4 _bxe.4= bxe.4 _bytgpio.4= bytgpio.4 _chvgpio.4= chvgpio.4 _coretemp.4= coretemp.4 _cpuctl.4= cpuctl.4 _dpms.4= dpms.4 _hpt27xx.4= hpt27xx.4 _hptiop.4= hptiop.4 _hptmv.4= hptmv.4 _hptnr.4= hptnr.4 _hptrr.4= hptrr.4 _hv_kvp.4= hv_kvp.4 _hv_netvsc.4= hv_netvsc.4 _hv_storvsc.4= hv_storvsc.4 _hv_utils.4= hv_utils.4 _hv_vmbus.4= hv_vmbus.4 _hv_vss.4= hv_vss.4 _i8254.4= i8254.4 _ichwd.4= ichwd.4 _if_bxe.4= if_bxe.4 _if_ndis.4= if_ndis.4 _if_nfe.4= if_nfe.4 _if_urtw.4= if_urtw.4 _if_vmx.4= if_vmx.4 _if_vtnet.4= if_vtnet.4 _if_wpi.4= if_wpi.4 _imcsmb.4= imcsmb.4 _ipmi.4= ipmi.4 _io.4= io.4 _linux.4= linux.4 _nda.4= nda.4 _ndis.4= ndis.4 _nfe.4= nfe.4 _nfsmb.4= nfsmb.4 _nvd.4= nvd.4 _nvme.4= nvme.4 _nvram.4= nvram.4 _virtio.4= virtio.4 _virtio_balloon.4=virtio_balloon.4 _virtio_blk.4= virtio_blk.4 _virtio_console.4=virtio_console.4 _virtio_random.4= virtio_random.4 _virtio_scsi.4= virtio_scsi.4 _vmx.4= vmx.4 _vtnet.4= vtnet.4 _padlock.4= padlock.4 _rr232x.4= rr232x.4 _speaker.4= speaker.4 _spkr.4= spkr.4 _tpm.4= tpm.4 _urtw.4= urtw.4 _viawd.4= viawd.4 _wbwd.4= wbwd.4 _wpi.4= wpi.4 _xen.4= xen.4 _xnb.4= xnb.4 .endif .if ${MACHINE_CPUARCH} == "amd64" _if_ntb.4= if_ntb.4 _ioat.4= ioat.4 _ntb.4= ntb.4 _ntb_hw_intel.4= ntb_hw_intel.4 _ntb_hw_plx.4= ntb_hw_plx.4 _ntb_transport.4=ntb_transport.4 _qlxge.4= qlxge.4 _qlxgb.4= qlxgb.4 _qlxgbe.4= qlxgbe.4 _qlnxe.4= qlnxe.4 _sfxge.4= sfxge.4 _smartpqi.4= smartpqi.4 MLINKS+=qlxge.4 if_qlxge.4 MLINKS+=qlxgb.4 if_qlxgb.4 MLINKS+=qlxgbe.4 if_qlxgbe.4 MLINKS+=qlnxe.4 if_qlnxe.4 MLINKS+=sfxge.4 if_sfxge.4 .if ${MK_BHYVE} != "no" _bhyve.4= bhyve.4 _vmm.4= vmm.4 .endif .endif .if ${MACHINE_CPUARCH} == "mips" _nvram2env.4= nvram2env.4 .endif .if ${MACHINE_CPUARCH} == "powerpc" _nvd.4= nvd.4 _nvme.4= nvme.4 .endif .if empty(MAN_ARCH) __arches= ${MACHINE} ${MACHINE_ARCH} ${MACHINE_CPUARCH} .elif ${MAN_ARCH} == "all" __arches= ${:!/bin/sh -c "/bin/ls -d ${.CURDIR}/man4.*"!:E} .else __arches= ${MAN_ARCH} .endif .for __arch in ${__arches:O:u} .if exists(${.CURDIR}/man4.${__arch}) SUBDIR+= man4.${__arch} .endif .endfor .if ${MK_BLUETOOTH} != "no" MAN+= ng_bluetooth.4 .endif .if ${MK_CCD} != "no" _ccd.4= ccd.4 .endif .if ${MK_CDDL} != "no" _dtrace_provs= dtrace_io.4 \ dtrace_ip.4 \ dtrace_lockstat.4 \ dtrace_proc.4 \ dtrace_sched.4 \ dtrace_sctp.4 \ dtrace_tcp.4 \ - dtrace_udp.4 + dtrace_udp.4 \ + dtrace_udplite.4 .endif .if ${MK_ISCSI} != "no" MAN+= cfiscsi.4 MAN+= iscsi.4 MAN+= iscsi_initiator.4 MAN+= iser.4 .endif .if ${MK_OFED} != "no" MAN+= mlx4ib.4 MAN+= mlx5ib.4 .endif .if ${MK_MLX5TOOL} != "no" MAN+= mlx5io.4 .endif .if ${MK_TESTS} != "no" ATF= ${SRCTOP}/contrib/atf .PATH: ${ATF}/doc _atf_test_case.4= atf-test-case.4 .endif .if ${MK_PF} != "no" _pf.4= pf.4 _pflog.4= pflog.4 _pfsync.4= pfsync.4 .endif .if ${MK_USB} != "no" MAN+= \ otus.4 \ otusfw.4 \ rsu.4 \ rsufw.4 \ rtwn_usb.4 \ rum.4 \ run.4 \ runfw.4 \ u3g.4 \ uark.4 \ uart.4 \ uath.4 \ ubsa.4 \ ubsec.4 \ ubser.4 \ ubtbcmfw.4 \ uchcom.4 \ ucom.4 \ ucycom.4 \ udav.4 \ udbp.4 \ udl.4 \ uep.4 \ ufm.4 \ ufoma.4 \ uftdi.4 \ ugen.4 \ ugold.4 \ uhci.4 \ uhid.4 \ uhso.4 \ uipaq.4 \ ukbd.4 \ uled.4 \ ulpt.4 \ umass.4 \ umcs.4 \ umct.4 \ umodem.4 \ umoscom.4 \ ums.4 \ unix.4 \ upgt.4 \ uplcom.4 \ ural.4 \ urio.4 \ urndis.4 \ ${_urtw.4} \ usb.4 \ usb_quirk.4 \ usb_template.4 \ usfs.4 \ uslcom.4 \ uvisor.4 \ uvscom.4 \ zyd.4 MLINKS+=otus.4 if_otus.4 MLINKS+=rsu.4 if_rsu.4 MLINKS+=rtwn_usb.4 if_rtwn_usb.4 MLINKS+=rum.4 if_rum.4 MLINKS+=run.4 if_run.4 MLINKS+=u3g.4 u3gstub.4 MLINKS+=uath.4 if_uath.4 MLINKS+=udav.4 if_udav.4 MLINKS+=upgt.4 if_upgt.4 MLINKS+=ural.4 if_ural.4 MLINKS+=urndis.4 if_urndis.4 MLINKS+=${_urtw.4} ${_if_urtw.4} MLINKS+=zyd.4 if_zyd.4 .endif .include Index: head/share/man/man4/dtrace_sctp.4 =================================================================== --- head/share/man/man4/dtrace_sctp.4 (revision 337017) +++ head/share/man/man4/dtrace_sctp.4 (revision 337018) @@ -1,130 +1,131 @@ .\" Copyright (c) 2018 Devin Teske .\" .\" 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$ .\" -.Dd April 22, 2018 +.Dd August 1, 2018 .Dt DTRACE_SCTP 4 .Os .Sh NAME .Nm dtrace_sctp .Nd a DTrace provider for tracing events related to the .Xr sctp 4 protocol .Sh SYNOPSIS .Fn sctp:cwnd::init uint32_t uint32_t uintptr_t int int .Fn sctp:cwnd::ack uint32_t uint32_t uintptr_t int int .Fn sctp:cwnd::rttvar uint64_t uint64_t uint64_t uint64_t uint64_t .Fn sctp:cwnd::rttstep uint64_t uint64_t uint64_t uint64_t uint64_t .Fn sctp:cwnd::fr uint32_t uint32_t uintptr_t int int .Fn sctp:cwnd::to uint32_t uint32_t uintptr_t int int .Fn sctp:cwnd::bl uint32_t uint32_t uintptr_t int int .Fn sctp:cwnd::ecn uint32_t uint32_t uintptr_t int int .Fn sctp:cwnd::pd uint32_t uint32_t uintptr_t int int .Fn sctp:rwnd:assoc:val uint32_t uint32_t int int .Fn sctp:flightsize:net:val uint32_t uint32_t uintptr_t int int .Fn sctp:flightsize:assoc:val uint32_t uint32_t int int .Sh DESCRIPTION The DTrace .Nm sctp provider allows users to trace events in the .Xr sctp 4 protocol implementation. This provider is similar to the .Xr dtrace_ip 4 and .Xr dtrace_udp 4 providers, but additionally contains probes corresponding to protocol events at a level higher than packet reception and transmission. .Pp The .Fn sctp:cwnd:: probes track changes in the congestion window on a netp. The .Fn sctp:rwnd:: probes track changes in the receiver window for an assoc. The .Fn sctp:flightsize:net:val probe tracks changes in the flight size on a net or assoc and the .Fn sctp:flightsize:assoc:val probe provides the total flight version. .Pp The arguments of all .Nm sctp probes except for .Fn sctp:cwnd::rtt* and .Fn sctp::assoc:val are the Vtag for this end, the port number of the local side, the pointer to .Dv struct sctp_nets *changing , the old value of the cwnd, and the new value of the cwnd. .Pp The arguments of .Fn sctp:::val are similar to the above except the fourth argument is the up/down amount. .Pp The .Fn sctp:cwnd::rtt* probe arguments are a bitmap of .Dv Vtag << 32 | localport << 16 | remoteport , a bitmap of .Dv obw | nbw , a bitmap of .Dv bwrtt | newrtt , .Dv flight , and a bitmap of .Dv (cwnd << 32) | point << 16 | retval(0/1) . .Pp The .Fn sctp:cwnd::init probe fires when a remotely-initiated active SCTP open succeeds. At this point the new connection is in the ESTABLISHED state, and the probe arguments expose the headers associated with the final ACK of the four-way handshake. .\" .Sh ARGUMENTS .\" .Sh FILES .\" .Sh EXAMPLES .\" .Sh COMPATIBILITY .\" This provider has not been tested for compatiblity with the .\" .Nm sctp .\" provider in Solaris .\" .Pq if one exists . .Sh SEE ALSO .Xr dtrace 1 , .Xr dtrace_ip 4 , .Xr dtrace_udp 4 , +.Xr dtrace_udplite 4 , .Xr sctp 4 , .Xr SDT 9 .\" .Sh HISTORY .\" The .\" .Nm sctp .\" provider first appeared in .\" .Fx .\" UNKNOWN. .Sh AUTHORS This manual page was written by .An Devin Teske Aq Mt dteske@FreeBSD.org . Index: head/share/man/man4/dtrace_tcp.4 =================================================================== --- head/share/man/man4/dtrace_tcp.4 (revision 337017) +++ head/share/man/man4/dtrace_tcp.4 (revision 337018) @@ -1,396 +1,398 @@ .\" Copyright (c) 2015 Mark Johnston .\" All rights reserved. .\" .\" 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$ .\" -.Dd February 10, 2018 +.Dd August 1, 2018 .Dt DTRACE_TCP 4 .Os .Sh NAME .Nm dtrace_tcp .Nd a DTrace provider for tracing events related to the .Xr tcp 4 protocol .Sh SYNOPSIS .Fn tcp:::accept-established "pktinfo_t *" "csinfo_t *" "ipinfo_t *" \ "tcpsinfo_t *" "tcpinfo_t *" .Fn tcp:::accept-refused "pktinfo_t *" "csinfo_t *" "ipinfo_t *" \ "tcpsinfo_t *" "tcpinfo_t *" .Fn tcp:::connect-established "pktinfo_t *" "csinfo_t *" "ipinfo_t *" \ "tcpsinfo_t *" "tcpinfo_t *" .Fn tcp:::connect-refused "pktinfo_t *" "csinfo_t *" "ipinfo_t *" \ "tcpsinfo_t *" "tcpinfo_t *" .Fn tcp:::connect-request "pktinfo_t *" "csinfo_t *" "ipinfo_t *" \ "tcpsinfo_t *" "tcpinfo_t *" .Fn tcp:::receive "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "tcpsinfo_t *" \ "tcpinfo_t *" .Fn tcp:::send "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "tcpsinfo_t *" \ "tcpinfo_t *" .Fn tcp:::state-change "void *" "csinfo_t *" "void *" "tcpsinfo_t *" "void *" \ "tcplsinfo_t *" .Sh DESCRIPTION The DTrace .Nm tcp provider allows users to trace events in the .Xr tcp 4 protocol implementation. This provider is similar to the .Xr dtrace_ip 4 and .Xr dtrace_udp 4 providers, but additionally contains probes corresponding to protocol events at a level higher than packet reception and transmission. All .Nm tcp probes except for .Fn tcp:::state-change have the same number and type of arguments. The last three arguments are used to describe a TCP segment: the .Vt ipinfo_t argument exposes the version-agnostic fields of the IP header, while the .Vt tcpinfo_t argument exposes the TCP header, and the .Vt tcpsinfo_t argument describes details of the corresponding TCP connection state, if any. Their fields are described in the ARGUMENTS section. .Pp The .Fn tcp:::accept-established probe fires when a remotely-initiated active TCP open succeeds. At this point the new connection is in the ESTABLISHED state, and the probe arguments expose the headers associated with the final ACK of the three-way handshake. The .Fn tcp:::accept-refused probe fires when a SYN arrives on a port without a listening socket. The probe arguments expose the headers associated with the RST to be transmitted to the remote host in response to the SYN segment. .Pp The .Fn tcp:::connect-established , .Fn tcp:::connect-refused , and .Fn tcp:::connect-request probes are similar to the .Ql accept probes, except that they correspond to locally-initiated TCP connections. The .Fn tcp:::connect-established probe fires when the SYN-ACK segment of a three-way handshake is received from the remote host and a final ACK is prepared for transmission. This occurs immediately after the local connection state transitions from SYN-SENT to ESTABLISHED. The probe arguments describe the headers associated with the received SYN-ACK segment. The .Fn tcp:::connect-refused probe fires when the local host receives a RST segment in response to a SYN segment, indicating that the remote host refused to open a connection. The probe arguments describe the IP and TCP headers associated with the received RST segment. The .Fn tcp:::connect-request probe fires as the kernel prepares to transmit the initial SYN segment of a three-way handshake. .Pp The .Fn tcp:::send and .Fn tcp:::receive probes fire when the host sends or receives a TCP packet, respectively. As with the .Xr dtrace_udp 4 provider, .Nm tcp probes fire only for packets sent by or to the local host; forwarded packets are handled in the IP layer and are only visible to the .Xr dtrace_ip 4 provider. .Pp The .Fn tcp:::state-change probe fires upon local TCP connection state transitions. Its first, third and fifth arguments are currently always .Dv NULL . Its last argument describes the from-state in the transition, and the to-state can be obtained from .Dv args[3]->tcps_state . .Sh ARGUMENTS The .Vt pktinfo_t argument is currently unimplemented and is included for compatibility with other implementations of this provider. Its fields are: .Bl -tag -width "uinptr_t pkt_addr" -offset indent .It Vt uinptr_t pkt_addr Always set to 0. .El .Pp The .Vt csinfo_t argument is currently unimplemented and is included for compatibility with other implementations of this provider. Its fields are: .Bl -tag -width "uintptr_t cs_addr" -offset indent .It Vt uintptr_t cs_addr Always set to 0. .It Vt uint64_t cs_cid A pointer to the .Vt struct inpcb for this packet, or .Dv NULL . .It Vt pid_t cs_pid Always set to 0. .El .Pp The .Vt ipinfo_t type is a version-agnostic representation of fields from an IP header. Its fields are described in the .Xr dtrace_ip 4 manual page. .Pp The .Vt tcpsinfo_t type is used to provide a stable representation of TCP connection state. Some .Nm tcp probes, such as .Fn tcp:::accept-refused , fire in a context where there is no TCP connection; this argument is .Dv NULL in that case. Its fields are: .Bl -tag -width "uint16_t tcps_lport" -offset indent .It Vt uintptr_t tcps_addr The address of the corresponding TCP control block. This is currently a pointer to a .Vt struct tcpcb . .It Vt int tcps_local A boolean indicating whether the connection is local to the host. Currently unimplemented and always set to -1. .It Vt int tcps_active A boolean indicating whether the connection was initiated by the local host. Currently unimplemented and always set to -1. .It Vt uint16_t tcps_lport Local TCP port. .It Vt uint16_t tcps_rport Remote TCP port. .It Vt string tcps_laddr Local address. .It Vt string tcps_raddr Remote address. .It Vt int32_t tcps_state Current TCP state. The valid TCP state values are given by the constants prefixed with .Ql TCPS_ in .Pa /usr/lib/dtrace/tcp.d . .It Vt uint32_t tcps_iss Initial send sequence number. .It Vt uint32_t tcps_suna Initial sequence number of sent but unacknowledged data. .It Vt uint32_t tcps_snxt Next sequence number for send. .It Vt uint32_t tcps_rack Sequence number of received and acknowledged data. .It Vt uint32_t tcps_rnxt Next expected sequence number for receive. .It Vt u_long tcps_swnd TCP send window size. .It Vt int32_t tcps_snd_ws Window scaling factor for the TCP send window. .It Vt u_long tcps_rwnd TCP receive window size. .It Vt int32_t tcps_rcv_ws Window scaling factor for the TCP receive window. .It Vt u_long tcps_cwnd TCP congestion window size. .It Vt u_long tcps_cwnd_ssthresh Congestion window threshold at which slow start ends and congestion avoidance begins. .It Vt uint32_t tcps_sack_fack Last sequence number selectively acknowledged by the receiver. .It Vt uint32_t tcps_sack_snxt Next selectively acknowledge sequence number at which to begin retransmitting. .It Vt uint32_t tcps_rto Round-trip timeout, in milliseconds. .It Vt uint32_t tcps_mss Maximum segment size. .It Vt int tcps_retransmit A boolean indicating that the local sender is retransmitting data. .It Vt int tcps_srtt Smoothed round-trip time. .El .Pp The .Vt tcpinfo_t type exposes the fields in a TCP segment header in host order. Its fields are: .Bl -tag -width "struct tcphdr *tcp_hdr" -offset indent .It Vt uint16_t tcp_sport Source TCP port. .It Vt uint16_t tcp_dport Destination TCP port. .It Vt uint32_t tcp_seq Sequence number. .It Vt uint32_t tcp_ack Acknowledgement number. .It Vt uint8_t tcp_offset Data offset, in bytes. .It Vt uint8_t tcp_flags TCP flags. .It Vt uint16_t tcp_window TCP window size. .It Vt uint16_t tcp_checksum Checksum. .It Vt uint16_t tcp_urgent Urgent data pointer. .It Vt struct tcphdr *tcp_hdr A pointer to the raw TCP header. .El .Pp The .Vt tcplsinfo_t type is used by the .Fn tcp:::state-change probe to provide the from-state of a transition. Its fields are: .Bl -tag -width "int32_t tcps_state" -offset indent .It Vt int32_t tcps_state A TCP state. The valid TCP state values are given by the constants prefixed with .Ql TCPS_ in .Pa /usr/lib/dtrace/tcp.d . .El .Sh FILES .Bl -tag -width "/usr/lib/dtrace/tcp.d" -compact .It Pa /usr/lib/dtrace/tcp.d DTrace type and translator definitions for the .Nm tcp provider. .El .Sh EXAMPLES The following script logs TCP segments in real time: .Bd -literal -offset indent #pragma D option quiet #pragma D option switchrate=10hz dtrace:::BEGIN { printf(" %3s %15s:%-5s %15s:%-5s %6s %s\\n", "CPU", "LADDR", "LPORT", "RADDR", "RPORT", "BYTES", "FLAGS"); } tcp:::send { this->length = args[2]->ip_plength - args[4]->tcp_offset; printf(" %3d %16s:%-5d -> %16s:%-5d %6d (", cpu, args[2]->ip_saddr, args[4]->tcp_sport, args[2]->ip_daddr, args[4]->tcp_dport, this->length); printf("%s", args[4]->tcp_flags & TH_FIN ? "FIN|" : ""); printf("%s", args[4]->tcp_flags & TH_SYN ? "SYN|" : ""); printf("%s", args[4]->tcp_flags & TH_RST ? "RST|" : ""); printf("%s", args[4]->tcp_flags & TH_PUSH ? "PUSH|" : ""); printf("%s", args[4]->tcp_flags & TH_ACK ? "ACK|" : ""); printf("%s", args[4]->tcp_flags & TH_URG ? "URG|" : ""); printf("%s", args[4]->tcp_flags == 0 ? "null " : ""); printf("\b)\\n"); } tcp:::receive { this->length = args[2]->ip_plength - args[4]->tcp_offset; printf(" %3d %16s:%-5d <- %16s:%-5d %6d (", cpu, args[2]->ip_daddr, args[4]->tcp_dport, args[2]->ip_saddr, args[4]->tcp_sport, this->length); printf("%s", args[4]->tcp_flags & TH_FIN ? "FIN|" : ""); printf("%s", args[4]->tcp_flags & TH_SYN ? "SYN|" : ""); printf("%s", args[4]->tcp_flags & TH_RST ? "RST|" : ""); printf("%s", args[4]->tcp_flags & TH_PUSH ? "PUSH|" : ""); printf("%s", args[4]->tcp_flags & TH_ACK ? "ACK|" : ""); printf("%s", args[4]->tcp_flags & TH_URG ? "URG|" : ""); printf("%s", args[4]->tcp_flags == 0 ? "null " : ""); printf("\b)\\n"); } .Ed The following script logs TCP connection state changes as they occur: .Bd -literal -offset indent #pragma D option quiet #pragma D option switchrate=25hz int last[int]; dtrace:::BEGIN { printf(" %12s %-20s %-20s %s\\n", "DELTA(us)", "OLD", "NEW", "TIMESTAMP"); } tcp:::state-change { this->elapsed = (timestamp - last[args[1]->cs_cid]) / 1000; printf(" %12d %-20s -> %-20s %d\\n", this->elapsed, tcp_state_string[args[5]->tcps_state], tcp_state_string[args[3]->tcps_state], timestamp); last[args[1]->cs_cid] = timestamp; } tcp:::state-change /last[args[1]->cs_cid] == 0/ { printf(" %12s %-20s -> %-20s %d\\n", "-", tcp_state_string[args[5]->tcps_state], tcp_state_string[args[3]->tcps_state], timestamp); last[args[1]->cs_cid] = timestamp; } .Ed .Sh COMPATIBILITY This provider is compatible with the .Nm tcp provider in Solaris. .Sh SEE ALSO .Xr dtrace 1 , .Xr dtrace_ip 4 , +.Xr dtrace_sctp 4 , .Xr dtrace_udp 4 , +.Xr dtrace_udplite 4 , .Xr tcp 4 , .Xr SDT 9 .Sh HISTORY The .Nm tcp provider first appeared in .Fx 10.0. .Sh AUTHORS This manual page was written by .An Mark Johnston Aq Mt markj@FreeBSD.org . .Sh BUGS The .Vt tcps_local and .Vt tcps_active fields of .Vt tcpsinfo_t are not filled in by the translator. Index: head/share/man/man4/dtrace_udp.4 =================================================================== --- head/share/man/man4/dtrace_udp.4 (revision 337017) +++ head/share/man/man4/dtrace_udp.4 (revision 337018) @@ -1,203 +1,205 @@ .\" Copyright (c) 2015 Mark Johnston .\" All rights reserved. .\" .\" 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$ .\" -.Dd July 20, 2018 +.Dd August 1, 2018 .Dt DTRACE_UDP 4 .Os .Sh NAME .Nm dtrace_udp .Nd a DTrace provider for tracing events related to the UDP protocol .Sh SYNOPSIS .Fn udp:::receive "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "udpsinfo_t *" \ "udpinfo_t *" .Fn udp:::send "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "udpsinfo_t *" \ "udpinfo_t *" .Sh DESCRIPTION The DTrace .Nm udp provider allows users to trace events in the .Xr udp 4 protocol implementation. The .Fn udp:::send probe fires whenever the kernel prepares to transmit a UDP packet, and the .Fn udp:::receive probe fires whenever the kernel receives a UDP packet, unless the UDP header is incomplete, the destination port is 0, the length field is invalid, or the checksum is wrong. The arguments to these probes can be used to obtain detailed information about the IP and UDP headers of the corresponding packet. .Sh ARGUMENTS The .Vt pktinfo_t argument is currently unimplemented and is included for compatibility with other implementations of this provider. Its fields are: .Bl -tag -width "uintptr_t pkt_addr" -offset indent .It Vt uintptr_t pkt_addr Always set to 0. .El .Pp The .Vt csinfo_t argument is currently unimplemented and is included for compatibility with other implementations of this provider. Its fields are: .Bl -tag -width "uintptr_t cs_addr" -offset indent .It Vt uintptr_t cs_addr Always set to 0. .It Vt uint64_t cs_cid A pointer to the .Vt struct inpcb for this packet, or .Dv NULL . .It Vt pid_t cs_pid Always set to 0. .El .Pp The .Vt ipinfo_t argument contains IP fields common to both IPv4 and IPv6 packets. Its fields are: .Bl -tag -width "uint32_t ip_plength" -offset indent .It Vt uint8_t ip_ver IP version of the packet, 4 for IPv4 packets and 6 for IPv6 packets. .It Vt uint32_t ip_plength IP payload size. This does not include the size of the IP header or IPv6 option headers. .It Vt string ip_saddr IP source address. .It Vt string ip_daddr IP destination address. .El .Pp The .Vt udpsinfo_t argument contains the state of the UDP connection associated with the packet. Its fields are: .Bl -tag -width "uintptr_t udps_addr" -offset indent .It Vt uintptr_t udps_addr Pointer to the .Vt struct inpcb containing the IP state for the associated socket. .It Vt uint16_t udps_lport Local UDP port. .It Vt uint16_t udps_rport Remote UDP port. .It Vt string udps_laddr Local IPv4 or IPv6 address. .It Vt string udps_raddr Remote IPv4 or IPv6 address. .El .Pp The .Vt udpinfo_t argument is the raw UDP header of the packet, with all fields in host order. Its fields are: .Bl -tag -width "struct udphdr *udp_hdr" -offset indent .It Vt uint16_t udp_sport Source UDP port. .It Vt uint16_t udp_dport Destination UDP port. .It Vt uint16_t udp_length Length of the UDP header and payload, in bytes. .It Vt uint16_t udp_checksum A checksum of the UDP header and payload, or 0 if no checksum was calculated. .It Vt struct udphdr *udp_hdr A pointer to the raw UDP header. .El .Sh FILES .Bl -tag -width "/usr/lib/dtrace/udp.d" -compact .It Pa /usr/lib/dtrace/udp.d DTrace type and translator definitions for the .Nm udp provider. .El .Sh EXAMPLES The following script counts transmitted packets by destination port. .Bd -literal -offset indent udp:::send { @num[args[4]->udp_dport] = count(); } .Ed .Pp This script will print some details of each UDP packet as it is sent or received by the kernel: .Bd -literal -offset indent #pragma D option quiet #pragma D option switchrate=10Hz dtrace:::BEGIN { printf(" %10s %36s %-36s %6s\\n", "DELTA(us)", "SOURCE", "DEST", "BYTES"); last = timestamp; } udp:::send { this->elapsed = (timestamp - last) / 1000; self->dest = strjoin(strjoin(args[2]->ip_daddr, ":"), lltostr(args[4]->udp_dport)); printf(" %10d %30s:%-5d -> %-36s %6d\\n", this->elapsed, args[2]->ip_saddr, args[4]->udp_sport, self->dest, args[4]->udp_length); last = timestamp; } udp:::receive { this->elapsed = (timestamp - last) / 1000; self->dest = strjoin(strjoin(args[2]->ip_saddr, ":"), lltostr(args[4]->udp_sport)); printf(" %10d %30s:%-5d <- %-36s %6d\\n", this->elapsed, args[2]->ip_daddr, args[4]->udp_dport, self->dest, args[4]->udp_length); last = timestamp; } .Ed .Sh COMPATIBILITY This provider is compatible with the .Nm udp provider in Solaris. .Sh SEE ALSO .Xr dtrace 1 , .Xr dtrace_ip 4 , +.Xr dtrace_sctp 4 , .Xr dtrace_tcp 4 , +.Xr dtrace_udplite 4 , .Xr udp 4 , .Xr SDT 9 .Sh HISTORY The .Nm udp provider first appeared in .Fx 10.0. .Sh AUTHORS This manual page was written by .An Mark Johnston Aq Mt markj@FreeBSD.org . Index: head/share/man/man4/dtrace_udplite.4 =================================================================== --- head/share/man/man4/dtrace_udplite.4 (nonexistent) +++ head/share/man/man4/dtrace_udplite.4 (revision 337018) @@ -0,0 +1,204 @@ +.\" Copyright (c) 2015 Mark Johnston +.\" Copyright (c) 2018 Michael Tuexen +.\" All rights reserved. +.\" +.\" 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$ +.\" +.Dd August 1, 2018 +.Dt DTRACE_UDPLITE 4 +.Os +.Sh NAME +.Nm dtrace_udplite +.Nd a DTrace provider for tracing events related to the UDP-Lite protocol +.Sh SYNOPSIS +.Fn udplite:::receive "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "udplitesinfo_t *" \ + "udpliteinfo_t *" +.Fn udplite:::send "pktinfo_t *" "csinfo_t *" "ipinfo_t *" "udplitesinfo_t *" \ + "udpliteinfo_t *" +.Sh DESCRIPTION +The DTrace +.Nm udplite +provider allows users to trace events in the +.Xr udplite 4 +protocol implementation. +The +.Fn udplite:::send +probe fires whenever the kernel prepares to transmit a UDP-Lite packet, and the +.Fn udplite:::receive +probe fires whenever the kernel receives a UDP-Lite packet, unless +the UDP-Lite header is incomplete, +the destination port is 0, +the length field is invalid, +or the checksum is wrong. +The arguments to these probes can be used to obtain detailed information about +the IP and UDP-Lite headers of the corresponding packet. +.Sh ARGUMENTS +The +.Vt pktinfo_t +argument is currently unimplemented and is included for compatibility with other +implementations of this provider. +Its fields are: +.Bl -tag -width "uintptr_t pkt_addr" -offset indent +.It Vt uintptr_t pkt_addr +Always set to 0. +.El +.Pp +The +.Vt csinfo_t +argument is currently unimplemented and is included for compatibility with other +implementations of this provider. +Its fields are: +.Bl -tag -width "uintptr_t cs_addr" -offset indent +.It Vt uintptr_t cs_addr +Always set to 0. +.It Vt uint64_t cs_cid +A pointer to the +.Vt struct inpcb +for this packet, or +.Dv NULL . +.It Vt pid_t cs_pid +Always set to 0. +.El +.Pp +The +.Vt ipinfo_t +argument contains IP fields common to both IPv4 and IPv6 packets. +Its fields are: +.Bl -tag -width "uint32_t ip_plength" -offset indent +.It Vt uint8_t ip_ver +IP version of the packet, 4 for IPv4 packets and 6 for IPv6 packets. +.It Vt uint32_t ip_plength +IP payload size. +This does not include the size of the IP header or IPv6 option headers. +.It Vt string ip_saddr +IP source address. +.It Vt string ip_daddr +IP destination address. +.El +.Pp +The +.Vt udplitesinfo_t +argument contains the state of the UDP-Lite connection associated with the packet. +Its fields are: +.Bl -tag -width "uintptr_t udplites_addr" -offset indent +.It Vt uintptr_t udplites_addr +Pointer to the +.Vt struct inpcb +containing the IP state for the associated socket. +.It Vt uint16_t udplites_lport +Local UDP-Lite port. +.It Vt uint16_t udplites_rport +Remote UDP-Lite port. +.It Vt string udplites_laddr +Local IPv4 or IPv6 address. +.It Vt string udplites_raddr +Remote IPv4 or IPv6 address. +.El +.Pp +The +.Vt udpliteinfo_t +argument is the raw UDP-Lite header of the packet, with all fields in host order. +Its fields are: +.Bl -tag -width "struct udplitehdr *udplite_hdr" -offset indent +.It Vt uint16_t udplite_sport +Source UDP-Lite port. +.It Vt uint16_t udplite_dport +Destination UDP-Lite port. +.It Vt uint16_t udplite_coverage +Checksum coverage of the UDP-Lite header, in bytes, or 0 for full coverage. +.It Vt uint16_t udplite_checksum +A checksum of the UDP-Lite header and payload, or 0 if no checksum was calculated. +.It Vt struct udplitehdr *udplite_hdr +A pointer to the raw UDP-Lite header. +.El +.Sh FILES +.Bl -tag -width "/usr/lib/dtrace/udplite.d" -compact +.It Pa /usr/lib/dtrace/udplite.d +DTrace type and translator definitions for the +.Nm udplite +provider. +.El +.Sh EXAMPLES +The following script counts transmitted packets by destination port. +.Bd -literal -offset indent +udplite:::send +{ + @num[args[4]->udplite_dport] = count(); +} +.Ed +.Pp +This script will print some details of each UDP-Lite packet as it is sent or received +by the kernel: +.Bd -literal -offset indent +#pragma D option quiet +#pragma D option switchrate=10Hz + +dtrace:::BEGIN +{ + printf(" %10s %36s %-36s %6s\\n", "DELTA(us)", "SOURCE", + "DEST", "COV"); + last = timestamp; +} + +udplite:::send +{ + this->elapsed = (timestamp - last) / 1000; + self->dest = strjoin(strjoin(args[2]->ip_daddr, ":"), + lltostr(args[4]->udplite_dport)); + printf(" %10d %30s:%-5d -> %-36s %6d\\n", this->elapsed, + args[2]->ip_saddr, args[4]->udplite_sport, + self->dest, args[4]->udplite_coverage); + last = timestamp; +} + +udplite:::receive +{ + this->elapsed = (timestamp - last) / 1000; + self->dest = strjoin(strjoin(args[2]->ip_saddr, ":"), + lltostr(args[4]->udplite_sport)); + printf(" %10d %30s:%-5d <- %-36s %6d\\n", this->elapsed, + args[2]->ip_daddr, args[4]->udplite_dport, + self->dest, args[4]->udplite_coverage); + last = timestamp; +} +.Ed +.Sh SEE ALSO +.Xr dtrace 1 , +.Xr dtrace_ip 4 , +.Xr dtrace_sctp 4 , +.Xr dtrace_tcp 4 , +.Xr dtrace_udp 4 , +.Xr udplite 4 , +.Xr SDT 9 +.Sh HISTORY +The +.Nm udplite +provider first appeared in +.Fx +12.0. +.Sh AUTHORS +This manual page was written by +.An Mark Johnston Aq Mt markj@FreeBSD.org +and +.An Michael Tuexen Aq Mt tuexen@FreeBSD.org . Property changes on: head/share/man/man4/dtrace_udplite.4 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/netinet/in_kdtrace.c =================================================================== --- head/sys/netinet/in_kdtrace.c (revision 337017) +++ head/sys/netinet/in_kdtrace.c (revision 337018) @@ -1,157 +1,172 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * 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 #include #include SDT_PROVIDER_DEFINE(ip); SDT_PROVIDER_DEFINE(tcp); SDT_PROVIDER_DEFINE(udp); +SDT_PROVIDER_DEFINE(udplite); SDT_PROBE_DEFINE6_XLATE(ip, , , 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, "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, "void *", "pktinfo_t *", "struct tcpcb *", "csinfo_t *", "struct mbuf *", "ipinfo_t *", "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfoh_t *"); SDT_PROBE_DEFINE5_XLATE(tcp, , , accept__refused, "void *", "pktinfo_t *", "struct tcpcb *", "csinfo_t *", "struct mbuf *", "ipinfo_t *", "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfo_t *"); SDT_PROBE_DEFINE5_XLATE(tcp, , , connect__established, "void *", "pktinfo_t *", "struct tcpcb *", "csinfo_t *", "struct mbuf *", "ipinfo_t *", "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfoh_t *"); SDT_PROBE_DEFINE5_XLATE(tcp, , , connect__refused, "void *", "pktinfo_t *", "struct tcpcb *", "csinfo_t *", "struct mbuf *", "ipinfo_t *", "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfoh_t *"); SDT_PROBE_DEFINE5_XLATE(tcp, , , 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, "void *", "pktinfo_t *", "struct tcpcb *", "csinfo_t *", "struct mbuf *", "ipinfo_t *", "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfoh_t *"); SDT_PROBE_DEFINE5_XLATE(tcp, , , send, "void *", "pktinfo_t *", "struct tcpcb *", "csinfo_t *", "uint8_t *", "ipinfo_t *", "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfo_t *"); SDT_PROBE_DEFINE1_XLATE(tcp, , , siftr, "struct pkt_node *", "siftrinfo_t *"); SDT_PROBE_DEFINE3_XLATE(tcp, , , debug__input, "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfoh_t *", "uint8_t *", "ipinfo_t *"); SDT_PROBE_DEFINE3_XLATE(tcp, , , debug__output, "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfo_t *", "struct mbuf *", "ipinfo_t *"); SDT_PROBE_DEFINE2_XLATE(tcp, , , debug__user, "struct tcpcb *", "tcpsinfo_t *" , "int", "int"); SDT_PROBE_DEFINE3_XLATE(tcp, , , debug__drop, "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfoh_t *", "struct mbuf *", "ipinfo_t *"); SDT_PROBE_DEFINE6_XLATE(tcp, , , state__change, "void *", "void *", "struct tcpcb *", "csinfo_t *", "void *", "void *", "struct tcpcb *", "tcpsinfo_t *", "void *", "void *", "int", "tcplsinfo_t *"); SDT_PROBE_DEFINE6_XLATE(tcp, , , receive__autoresize, "void *", "void *", "struct tcpcb *", "csinfo_t *", "struct mbuf *", "ipinfo_t *", "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfoh_t *", "int", "int"); SDT_PROBE_DEFINE5_XLATE(udp, , , 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, "void *", "pktinfo_t *", "struct inpcb *", "csinfo_t *", "uint8_t *", "ipinfo_t *", "struct inpcb *", "udpsinfo_t *", "struct udphdr *", "udpinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(udplite, , , receive, + "void *", "pktinfo_t *", + "struct inpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct inpcb *", "udplitesinfo_t *", + "struct udphdr *", "udpliteinfo_t *"); + +SDT_PROBE_DEFINE5_XLATE(udplite, , , send, + "void *", "pktinfo_t *", + "struct inpcb *", "csinfo_t *", + "uint8_t *", "ipinfo_t *", + "struct inpcb *", "udplitesinfo_t *", + "struct udphdr *", "udpliteinfo_t *"); Index: head/sys/netinet/in_kdtrace.h =================================================================== --- head/sys/netinet/in_kdtrace.h (revision 337017) +++ head/sys/netinet/in_kdtrace.h (revision 337018) @@ -1,75 +1,81 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * 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 UDPLITE_PROBE(probe, arg0, arg1, arg2, arg3, arg4) \ + SDT_PROBE5(udplite, , , probe, arg0, arg1, arg2, arg3, arg4) #define TCP_PROBE1(probe, arg0) \ SDT_PROBE1(tcp, , , probe, arg0) #define TCP_PROBE2(probe, arg0, arg1) \ SDT_PROBE2(tcp, , , probe, arg0, arg1) #define TCP_PROBE3(probe, arg0, arg1, arg2) \ SDT_PROBE3(tcp, , , probe, arg0, arg1, arg2) #define TCP_PROBE4(probe, arg0, arg1, arg2, arg3) \ SDT_PROBE4(tcp, , , probe, arg0, arg1, arg2, arg3) #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_PROVIDER_DECLARE(udplite); 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, , , siftr); SDT_PROBE_DECLARE(tcp, , , state__change); SDT_PROBE_DECLARE(tcp, , , debug__input); SDT_PROBE_DECLARE(tcp, , , debug__output); SDT_PROBE_DECLARE(tcp, , , debug__user); SDT_PROBE_DECLARE(tcp, , , debug__drop); SDT_PROBE_DECLARE(tcp, , , receive__autoresize); SDT_PROBE_DECLARE(udp, , , receive); SDT_PROBE_DECLARE(udp, , , send); + +SDT_PROBE_DECLARE(udplite, , , receive); +SDT_PROBE_DECLARE(udplite, , , send); #endif Index: head/sys/netinet/udp_usrreq.c =================================================================== --- head/sys/netinet/udp_usrreq.c (revision 337017) +++ head/sys/netinet/udp_usrreq.c (revision 337018) @@ -1,1804 +1,1823 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 * The Regents of the University of California. * Copyright (c) 2008 Robert N. M. Watson * Copyright (c) 2010-2011 Juniper Networks, Inc. * Copyright (c) 2014 Kevin Lo * All rights reserved. * * Portions of this software were developed by Robert N. M. Watson under * contract to Juniper Networks, Inc. * * 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. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 */ #include __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" #include "opt_rss.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef INET6 #include #endif #include #include #include #include #ifdef INET6 #include #endif #include #include #include #include #include #include #include /* * UDP and UDP-Lite protocols implementation. * Per RFC 768, August, 1980. * Per RFC 3828, July, 2004. */ /* * BSD 4.2 defaulted the udp checksum to be off. Turning off udp checksums * removes the only data integrity mechanism for packets and malformed * packets that would otherwise be discarded due to bad checksums, and may * cause problems (especially for NFS data blocks). */ VNET_DEFINE(int, udp_cksum) = 1; SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(udp_cksum), 0, "compute udp checksum"); int udp_log_in_vain = 0; SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW, &udp_log_in_vain, 0, "Log all incoming UDP packets"); VNET_DEFINE(int, udp_blackhole) = 0; SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(udp_blackhole), 0, "Do not send port unreachables for refused connects"); u_long udp_sendspace = 9216; /* really max datagram size */ SYSCTL_ULONG(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW, &udp_sendspace, 0, "Maximum outgoing UDP datagram size"); u_long udp_recvspace = 40 * (1024 + #ifdef INET6 sizeof(struct sockaddr_in6) #else sizeof(struct sockaddr_in) #endif ); /* 40 1K datagrams */ SYSCTL_ULONG(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW, &udp_recvspace, 0, "Maximum space for incoming UDP datagrams"); VNET_DEFINE(struct inpcbhead, udb); /* from udp_var.h */ VNET_DEFINE(struct inpcbinfo, udbinfo); VNET_DEFINE(struct inpcbhead, ulitecb); VNET_DEFINE(struct inpcbinfo, ulitecbinfo); VNET_DEFINE_STATIC(uma_zone_t, udpcb_zone); #define V_udpcb_zone VNET(udpcb_zone) #ifndef UDBHASHSIZE #define UDBHASHSIZE 128 #endif VNET_PCPUSTAT_DEFINE(struct udpstat, udpstat); /* from udp_var.h */ VNET_PCPUSTAT_SYSINIT(udpstat); SYSCTL_VNET_PCPUSTAT(_net_inet_udp, UDPCTL_STATS, stats, struct udpstat, udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)"); #ifdef VIMAGE VNET_PCPUSTAT_SYSUNINIT(udpstat); #endif /* VIMAGE */ #ifdef INET static void udp_detach(struct socket *so); static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *); #endif static void udp_zone_change(void *tag) { uma_zone_set_max(V_udbinfo.ipi_zone, maxsockets); uma_zone_set_max(V_udpcb_zone, maxsockets); } static int udp_inpcb_init(void *mem, int size, int flags) { struct inpcb *inp; inp = mem; INP_LOCK_INIT(inp, "inp", "udpinp"); return (0); } static int udplite_inpcb_init(void *mem, int size, int flags) { struct inpcb *inp; inp = mem; INP_LOCK_INIT(inp, "inp", "udpliteinp"); return (0); } void udp_init(void) { /* * For now default to 2-tuple UDP hashing - until the fragment * reassembly code can also update the flowid. * * Once we can calculate the flowid that way and re-establish * a 4-tuple, flip this to 4-tuple. */ in_pcbinfo_init(&V_udbinfo, "udp", &V_udb, UDBHASHSIZE, UDBHASHSIZE, "udp_inpcb", udp_inpcb_init, IPI_HASHFIELDS_2TUPLE); V_udpcb_zone = uma_zcreate("udpcb", sizeof(struct udpcb), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); uma_zone_set_max(V_udpcb_zone, maxsockets); uma_zone_set_warning(V_udpcb_zone, "kern.ipc.maxsockets limit reached"); EVENTHANDLER_REGISTER(maxsockets_change, udp_zone_change, NULL, EVENTHANDLER_PRI_ANY); } void udplite_init(void) { in_pcbinfo_init(&V_ulitecbinfo, "udplite", &V_ulitecb, UDBHASHSIZE, UDBHASHSIZE, "udplite_inpcb", udplite_inpcb_init, IPI_HASHFIELDS_2TUPLE); } /* * Kernel module interface for updating udpstat. The argument is an index * into udpstat treated as an array of u_long. While this encodes the * general layout of udpstat into the caller, it doesn't encode its location, * so that future changes to add, for example, per-CPU stats support won't * cause binary compatibility problems for kernel modules. */ void kmod_udpstat_inc(int statnum) { counter_u64_add(VNET(udpstat)[statnum], 1); } int udp_newudpcb(struct inpcb *inp) { struct udpcb *up; up = uma_zalloc(V_udpcb_zone, M_NOWAIT | M_ZERO); if (up == NULL) return (ENOBUFS); inp->inp_ppcb = up; return (0); } void udp_discardcb(struct udpcb *up) { uma_zfree(V_udpcb_zone, up); } #ifdef VIMAGE static void udp_destroy(void *unused __unused) { in_pcbinfo_destroy(&V_udbinfo); uma_zdestroy(V_udpcb_zone); } VNET_SYSUNINIT(udp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, udp_destroy, NULL); static void udplite_destroy(void *unused __unused) { in_pcbinfo_destroy(&V_ulitecbinfo); } VNET_SYSUNINIT(udplite, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, udplite_destroy, NULL); #endif #ifdef INET /* * Subroutine of udp_input(), which appends the provided mbuf chain to the * passed pcb/socket. The caller must provide a sockaddr_in via udp_in that * contains the source address. If the socket ends up being an IPv6 socket, * udp_append() will convert to a sockaddr_in6 before passing the address * into the socket code. * * In the normal case udp_append() will return 0, indicating that you * must unlock the inp. However if a tunneling protocol is in place we increment * the inpcb refcnt and unlock the inp, on return from the tunneling protocol we * then decrement the reference count. If the inp_rele returns 1, indicating the * inp is gone, we return that to the caller to tell them *not* to unlock * the inp. In the case of multi-cast this will cause the distribution * to stop (though most tunneling protocols known currently do *not* use * multicast). */ static int udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, struct sockaddr_in *udp_in) { struct sockaddr *append_sa; struct socket *so; struct mbuf *tmpopts, *opts = NULL; #ifdef INET6 struct sockaddr_in6 udp_in6; #endif struct udpcb *up; INP_LOCK_ASSERT(inp); /* * Engage the tunneling protocol. */ up = intoudpcb(inp); if (up->u_tun_func != NULL) { in_pcbref(inp); INP_RUNLOCK(inp); (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&udp_in[0], up->u_tun_ctx); INP_RLOCK(inp); return (in_pcbrele_rlocked(inp)); } off += sizeof(struct udphdr); #if defined(IPSEC) || defined(IPSEC_SUPPORT) /* Check AH/ESP integrity. */ if (IPSEC_ENABLED(ipv4) && IPSEC_CHECK_POLICY(ipv4, n, inp) != 0) { m_freem(n); return (0); } if (up->u_flags & UF_ESPINUDP) {/* IPSec UDP encaps. */ if (IPSEC_ENABLED(ipv4) && UDPENCAP_INPUT(n, off, AF_INET) != 0) return (0); /* Consumed. */ } #endif /* IPSEC */ #ifdef MAC if (mac_inpcb_check_deliver(inp, n) != 0) { m_freem(n); return (0); } #endif /* MAC */ if (inp->inp_flags & INP_CONTROLOPTS || inp->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) { #ifdef INET6 if (inp->inp_vflag & INP_IPV6) (void)ip6_savecontrol_v4(inp, n, &opts, NULL); else #endif /* INET6 */ ip_savecontrol(inp, &opts, ip, n); } if ((inp->inp_vflag & INP_IPV4) && (inp->inp_flags2 & INP_ORIGDSTADDR)) { tmpopts = sbcreatecontrol((caddr_t)&udp_in[1], sizeof(struct sockaddr_in), IP_ORIGDSTADDR, IPPROTO_IP); if (tmpopts) { if (opts) { tmpopts->m_next = opts; opts = tmpopts; } else opts = tmpopts; } } #ifdef INET6 if (inp->inp_vflag & INP_IPV6) { bzero(&udp_in6, sizeof(udp_in6)); udp_in6.sin6_len = sizeof(udp_in6); udp_in6.sin6_family = AF_INET6; in6_sin_2_v4mapsin6(&udp_in[0], &udp_in6); append_sa = (struct sockaddr *)&udp_in6; } else #endif /* INET6 */ append_sa = (struct sockaddr *)&udp_in[0]; m_adj(n, off); so = inp->inp_socket; SOCKBUF_LOCK(&so->so_rcv); if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) { SOCKBUF_UNLOCK(&so->so_rcv); m_freem(n); if (opts) m_freem(opts); UDPSTAT_INC(udps_fullsock); } else sorwakeup_locked(so); return (0); } int udp_input(struct mbuf **mp, int *offp, int proto) { struct ip *ip; struct udphdr *uh; struct ifnet *ifp; struct inpcb *inp; uint16_t len, ip_len; struct inpcbinfo *pcbinfo; struct ip save_ip; struct sockaddr_in udp_in[2]; struct mbuf *m; struct m_tag *fwd_tag; struct epoch_tracker et; int cscov_partial, iphlen; m = *mp; iphlen = *offp; ifp = m->m_pkthdr.rcvif; *mp = NULL; UDPSTAT_INC(udps_ipackets); /* * Strip IP options, if any; should skip this, make available to * user, and use on returned packets, but we don't yet have a way to * check the checksum with options still present. */ if (iphlen > sizeof (struct ip)) { ip_stripoptions(m); iphlen = sizeof(struct ip); } /* * Get IP and UDP header together in first mbuf. */ ip = mtod(m, struct ip *); if (m->m_len < iphlen + sizeof(struct udphdr)) { if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == NULL) { UDPSTAT_INC(udps_hdrops); return (IPPROTO_DONE); } ip = mtod(m, struct ip *); } uh = (struct udphdr *)((caddr_t)ip + iphlen); cscov_partial = (proto == IPPROTO_UDPLITE) ? 1 : 0; /* * Destination port of 0 is illegal, based on RFC768. */ if (uh->uh_dport == 0) goto badunlocked; /* * Construct sockaddr format source address. Stuff source address * and datagram in user buffer. */ bzero(&udp_in[0], sizeof(struct sockaddr_in) * 2); udp_in[0].sin_len = sizeof(struct sockaddr_in); udp_in[0].sin_family = AF_INET; udp_in[0].sin_port = uh->uh_sport; udp_in[0].sin_addr = ip->ip_src; udp_in[1].sin_len = sizeof(struct sockaddr_in); udp_in[1].sin_family = AF_INET; udp_in[1].sin_port = uh->uh_dport; udp_in[1].sin_addr = ip->ip_dst; /* * Make mbuf data length reflect UDP length. If not enough data to * reflect UDP length, drop. */ len = ntohs((u_short)uh->uh_ulen); ip_len = ntohs(ip->ip_len) - iphlen; if (proto == IPPROTO_UDPLITE && (len == 0 || len == ip_len)) { /* Zero means checksum over the complete packet. */ if (len == 0) len = ip_len; cscov_partial = 0; } if (ip_len != len) { if (len > ip_len || len < sizeof(struct udphdr)) { UDPSTAT_INC(udps_badlen); goto badunlocked; } if (proto == IPPROTO_UDP) m_adj(m, len - ip_len); } /* * Save a copy of the IP header in case we want restore it for * sending an ICMP error message in response. */ if (!V_udp_blackhole) save_ip = *ip; else memset(&save_ip, 0, sizeof(save_ip)); /* * Checksum extended UDP header and data. */ if (uh->uh_sum) { u_short uh_sum; if ((m->m_pkthdr.csum_flags & CSUM_DATA_VALID) && !cscov_partial) { if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) uh_sum = m->m_pkthdr.csum_data; else uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htonl((u_short)len + m->m_pkthdr.csum_data + proto)); uh_sum ^= 0xffff; } else { char b[9]; bcopy(((struct ipovly *)ip)->ih_x1, b, 9); bzero(((struct ipovly *)ip)->ih_x1, 9); ((struct ipovly *)ip)->ih_len = (proto == IPPROTO_UDP) ? uh->uh_ulen : htons(ip_len); uh_sum = in_cksum(m, len + sizeof (struct ip)); bcopy(b, ((struct ipovly *)ip)->ih_x1, 9); } if (uh_sum) { UDPSTAT_INC(udps_badsum); m_freem(m); return (IPPROTO_DONE); } } else { if (proto == IPPROTO_UDP) { UDPSTAT_INC(udps_nosum); } else { /* UDPLite requires a checksum */ /* XXX: What is the right UDPLite MIB counter here? */ m_freem(m); return (IPPROTO_DONE); } } pcbinfo = udp_get_inpcbinfo(proto); if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || in_broadcast(ip->ip_dst, ifp)) { struct inpcb *last; struct inpcbhead *pcblist; struct ip_moptions *imo; INP_INFO_RLOCK_ET(pcbinfo, et); pcblist = udp_get_pcblist(proto); last = NULL; CK_LIST_FOREACH(inp, pcblist, inp_list) { if (inp->inp_lport != uh->uh_dport) continue; #ifdef INET6 if ((inp->inp_vflag & INP_IPV4) == 0) continue; #endif if (inp->inp_laddr.s_addr != INADDR_ANY && inp->inp_laddr.s_addr != ip->ip_dst.s_addr) continue; if (inp->inp_faddr.s_addr != INADDR_ANY && inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; if (inp->inp_fport != 0 && inp->inp_fport != uh->uh_sport) continue; INP_RLOCK(inp); /* * XXXRW: Because we weren't holding either the inpcb * or the hash lock when we checked for a match * before, we should probably recheck now that the * inpcb lock is held. */ /* * Handle socket delivery policy for any-source * and source-specific multicast. [RFC3678] */ imo = inp->inp_moptions; if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { struct sockaddr_in group; int blocked; if (imo == NULL) { INP_RUNLOCK(inp); continue; } bzero(&group, sizeof(struct sockaddr_in)); group.sin_len = sizeof(struct sockaddr_in); group.sin_family = AF_INET; group.sin_addr = ip->ip_dst; blocked = imo_multi_filter(imo, ifp, (struct sockaddr *)&group, (struct sockaddr *)&udp_in[0]); if (blocked != MCAST_PASS) { if (blocked == MCAST_NOTGMEMBER) IPSTAT_INC(ips_notmember); if (blocked == MCAST_NOTSMEMBER || blocked == MCAST_MUTED) UDPSTAT_INC(udps_filtermcast); INP_RUNLOCK(inp); continue; } } if (last != NULL) { struct mbuf *n; if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) { - UDP_PROBE(receive, NULL, last, ip, - last, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, ip, + last, uh); + else + UDP_PROBE(receive, NULL, last, ip, last, + uh); if (udp_append(last, ip, n, iphlen, udp_in)) { goto inp_lost; } } INP_RUNLOCK(last); } last = inp; /* * Don't look for additional matches if this one does * not have either the SO_REUSEPORT or SO_REUSEADDR * socket options set. This heuristic avoids * searching through all pcbs in the common case of a * non-shared port. It assumes that an application * will never clear these options after setting them. */ if ((last->inp_socket->so_options & (SO_REUSEPORT|SO_REUSEPORT_LB|SO_REUSEADDR)) == 0) break; } if (last == NULL) { /* * No matching pcb found; discard datagram. (No need * to send an ICMP Port Unreachable for a broadcast * or multicast datgram.) */ UDPSTAT_INC(udps_noportbcast); if (inp) INP_RUNLOCK(inp); INP_INFO_RUNLOCK_ET(pcbinfo, et); goto badunlocked; } - UDP_PROBE(receive, NULL, last, ip, last, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, ip, last, uh); + else + UDP_PROBE(receive, NULL, last, ip, last, uh); if (udp_append(last, ip, m, iphlen, udp_in) == 0) INP_RUNLOCK(last); inp_lost: INP_INFO_RUNLOCK_ET(pcbinfo, et); return (IPPROTO_DONE); } /* * Locate pcb for datagram. */ /* * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. */ if ((m->m_flags & M_IP_NEXTHOP) && (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) { struct sockaddr_in *next_hop; next_hop = (struct sockaddr_in *)(fwd_tag + 1); /* * Transparently forwarded. Pretend to be the destination. * Already got one like this? */ inp = in_pcblookup_mbuf(pcbinfo, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, INPLOOKUP_RLOCKPCB, ifp, m); if (!inp) { /* * It's new. Try to find the ambushing socket. * Because we've rewritten the destination address, * any hardware-generated hash is ignored. */ inp = in_pcblookup(pcbinfo, ip->ip_src, uh->uh_sport, next_hop->sin_addr, next_hop->sin_port ? htons(next_hop->sin_port) : uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, ifp); } /* Remove the tag from the packet. We don't need it anymore. */ m_tag_delete(m, fwd_tag); m->m_flags &= ~M_IP_NEXTHOP; } else inp = in_pcblookup_mbuf(pcbinfo, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, ifp, m); if (inp == NULL) { if (udp_log_in_vain) { char src[INET_ADDRSTRLEN]; char dst[INET_ADDRSTRLEN]; log(LOG_INFO, "Connection attempt to UDP %s:%d from %s:%d\n", inet_ntoa_r(ip->ip_dst, dst), ntohs(uh->uh_dport), inet_ntoa_r(ip->ip_src, src), ntohs(uh->uh_sport)); } - UDP_PROBE(receive, NULL, NULL, ip, NULL, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, NULL, ip, NULL, uh); + else + UDP_PROBE(receive, NULL, NULL, ip, NULL, uh); UDPSTAT_INC(udps_noport); if (m->m_flags & (M_BCAST | M_MCAST)) { UDPSTAT_INC(udps_noportbcast); goto badunlocked; } if (V_udp_blackhole) goto badunlocked; if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0) goto badunlocked; *ip = save_ip; icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); return (IPPROTO_DONE); } /* * Check the minimum TTL for socket. */ INP_RLOCK_ASSERT(inp); if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) { - UDP_PROBE(receive, NULL, inp, ip, inp, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, inp, ip, inp, uh); + else + UDP_PROBE(receive, NULL, inp, ip, inp, uh); INP_RUNLOCK(inp); m_freem(m); return (IPPROTO_DONE); } if (cscov_partial) { struct udpcb *up; up = intoudpcb(inp); if (up->u_rxcslen == 0 || up->u_rxcslen > len) { INP_RUNLOCK(inp); m_freem(m); return (IPPROTO_DONE); } } - UDP_PROBE(receive, NULL, inp, ip, inp, uh); + if (proto == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, inp, ip, inp, uh); + else + UDP_PROBE(receive, NULL, inp, ip, inp, uh); if (udp_append(inp, ip, m, iphlen, udp_in) == 0) INP_RUNLOCK(inp); return (IPPROTO_DONE); badunlocked: m_freem(m); return (IPPROTO_DONE); } #endif /* INET */ /* * Notify a udp user of an asynchronous error; just wake up so that they can * collect error status. */ struct inpcb * udp_notify(struct inpcb *inp, int errno) { /* * While udp_ctlinput() always calls udp_notify() with a read lock * when invoking it directly, in_pcbnotifyall() currently uses write * locks due to sharing code with TCP. For now, accept either a read * or a write lock, but a read lock is sufficient. */ INP_LOCK_ASSERT(inp); if ((errno == EHOSTUNREACH || errno == ENETUNREACH || errno == EHOSTDOWN) && inp->inp_route.ro_rt) { RTFREE(inp->inp_route.ro_rt); inp->inp_route.ro_rt = (struct rtentry *)NULL; } inp->inp_socket->so_error = errno; sorwakeup(inp->inp_socket); sowwakeup(inp->inp_socket); return (inp); } #ifdef INET static void udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip, struct inpcbinfo *pcbinfo) { struct ip *ip = vip; struct udphdr *uh; struct in_addr faddr; struct inpcb *inp; faddr = ((struct sockaddr_in *)sa)->sin_addr; if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY) return; if (PRC_IS_REDIRECT(cmd)) { /* signal EHOSTDOWN, as it flushes the cached route */ in_pcbnotifyall(&V_udbinfo, faddr, EHOSTDOWN, udp_notify); return; } /* * Hostdead is ugly because it goes linearly through all PCBs. * * XXX: We never get this from ICMP, otherwise it makes an excellent * DoS attack on machines with many connections. */ if (cmd == PRC_HOSTDEAD) ip = NULL; else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) return; if (ip != NULL) { uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport, ip->ip_src, uh->uh_sport, INPLOOKUP_RLOCKPCB, NULL); if (inp != NULL) { INP_RLOCK_ASSERT(inp); if (inp->inp_socket != NULL) { udp_notify(inp, inetctlerrmap[cmd]); } INP_RUNLOCK(inp); } else { inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport, ip->ip_src, uh->uh_sport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL); if (inp != NULL) { struct udpcb *up; void *ctx; udp_tun_icmp_t func; up = intoudpcb(inp); ctx = up->u_tun_ctx; func = up->u_icmp_func; INP_RUNLOCK(inp); if (func != NULL) (*func)(cmd, sa, vip, ctx); } } } else in_pcbnotifyall(pcbinfo, faddr, inetctlerrmap[cmd], udp_notify); } void udp_ctlinput(int cmd, struct sockaddr *sa, void *vip) { return (udp_common_ctlinput(cmd, sa, vip, &V_udbinfo)); } void udplite_ctlinput(int cmd, struct sockaddr *sa, void *vip) { return (udp_common_ctlinput(cmd, sa, vip, &V_ulitecbinfo)); } #endif /* INET */ static int udp_pcblist(SYSCTL_HANDLER_ARGS) { int error, i, n; struct inpcb *inp, **inp_list; inp_gen_t gencnt; struct xinpgen xig; struct epoch_tracker et; /* * The process of preparing the PCB list is too time-consuming and * resource-intensive to repeat twice on every request. */ if (req->oldptr == 0) { n = V_udbinfo.ipi_count; n += imax(n / 8, 10); req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xinpcb); return (0); } if (req->newptr != 0) return (EPERM); /* * OK, now we're committed to doing something. */ INP_INFO_RLOCK_ET(&V_udbinfo, et); gencnt = V_udbinfo.ipi_gencnt; n = V_udbinfo.ipi_count; INP_INFO_RUNLOCK_ET(&V_udbinfo, et); error = sysctl_wire_old_buffer(req, 2 * (sizeof xig) + n * sizeof(struct xinpcb)); if (error != 0) return (error); xig.xig_len = sizeof xig; xig.xig_count = n; xig.xig_gen = gencnt; xig.xig_sogen = so_gencnt; error = SYSCTL_OUT(req, &xig, sizeof xig); if (error) return (error); inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK); if (inp_list == NULL) return (ENOMEM); INP_INFO_RLOCK_ET(&V_udbinfo, et); for (inp = CK_LIST_FIRST(V_udbinfo.ipi_listhead), i = 0; inp && i < n; inp = CK_LIST_NEXT(inp, inp_list)) { INP_WLOCK(inp); if (inp->inp_gencnt <= gencnt && cr_canseeinpcb(req->td->td_ucred, inp) == 0) { in_pcbref(inp); inp_list[i++] = inp; } INP_WUNLOCK(inp); } INP_INFO_RUNLOCK_ET(&V_udbinfo, et); n = i; error = 0; for (i = 0; i < n; i++) { inp = inp_list[i]; INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt) { struct xinpcb xi; in_pcbtoxinpcb(inp, &xi); INP_RUNLOCK(inp); error = SYSCTL_OUT(req, &xi, sizeof xi); } else INP_RUNLOCK(inp); } INP_INFO_WLOCK(&V_udbinfo); for (i = 0; i < n; i++) { inp = inp_list[i]; INP_RLOCK(inp); if (!in_pcbrele_rlocked(inp)) INP_RUNLOCK(inp); } INP_INFO_WUNLOCK(&V_udbinfo); if (!error) { /* * Give the user an updated idea of our state. If the * generation differs from what we told her before, she knows * that something happened while we were processing this * request, and it might be necessary to retry. */ INP_INFO_RLOCK_ET(&V_udbinfo, et); xig.xig_gen = V_udbinfo.ipi_gencnt; xig.xig_sogen = so_gencnt; xig.xig_count = V_udbinfo.ipi_count; INP_INFO_RUNLOCK_ET(&V_udbinfo, et); error = SYSCTL_OUT(req, &xig, sizeof xig); } free(inp_list, M_TEMP); return (error); } SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLTYPE_OPAQUE | CTLFLAG_RD, NULL, 0, udp_pcblist, "S,xinpcb", "List of active UDP sockets"); #ifdef INET static int udp_getcred(SYSCTL_HANDLER_ARGS) { struct xucred xuc; struct sockaddr_in addrs[2]; struct inpcb *inp; int error; error = priv_check(req->td, PRIV_NETINET_GETCRED); if (error) return (error); error = SYSCTL_IN(req, addrs, sizeof(addrs)); if (error) return (error); inp = in_pcblookup(&V_udbinfo, addrs[1].sin_addr, addrs[1].sin_port, addrs[0].sin_addr, addrs[0].sin_port, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL); if (inp != NULL) { INP_RLOCK_ASSERT(inp); if (inp->inp_socket == NULL) error = ENOENT; if (error == 0) error = cr_canseeinpcb(req->td->td_ucred, inp); if (error == 0) cru2x(inp->inp_cred, &xuc); INP_RUNLOCK(inp); } else error = ENOENT; if (error == 0) error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred)); return (error); } SYSCTL_PROC(_net_inet_udp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, udp_getcred, "S,xucred", "Get the xucred of a UDP connection"); #endif /* INET */ int udp_ctloutput(struct socket *so, struct sockopt *sopt) { struct inpcb *inp; struct udpcb *up; int isudplite, error, optval; error = 0; isudplite = (so->so_proto->pr_protocol == IPPROTO_UDPLITE) ? 1 : 0; inp = sotoinpcb(so); KASSERT(inp != NULL, ("%s: inp == NULL", __func__)); INP_WLOCK(inp); if (sopt->sopt_level != so->so_proto->pr_protocol) { #ifdef INET6 if (INP_CHECK_SOCKAF(so, AF_INET6)) { INP_WUNLOCK(inp); error = ip6_ctloutput(so, sopt); } #endif #if defined(INET) && defined(INET6) else #endif #ifdef INET { INP_WUNLOCK(inp); error = ip_ctloutput(so, sopt); } #endif return (error); } switch (sopt->sopt_dir) { case SOPT_SET: switch (sopt->sopt_name) { #if defined(IPSEC) || defined(IPSEC_SUPPORT) #ifdef INET case UDP_ENCAP: if (!IPSEC_ENABLED(ipv4)) { INP_WUNLOCK(inp); return (ENOPROTOOPT); } error = UDPENCAP_PCBCTL(inp, sopt); break; #endif /* INET */ #endif /* IPSEC */ case UDPLITE_SEND_CSCOV: case UDPLITE_RECV_CSCOV: if (!isudplite) { INP_WUNLOCK(inp); error = ENOPROTOOPT; break; } INP_WUNLOCK(inp); error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval)); if (error != 0) break; inp = sotoinpcb(so); KASSERT(inp != NULL, ("%s: inp == NULL", __func__)); INP_WLOCK(inp); up = intoudpcb(inp); KASSERT(up != NULL, ("%s: up == NULL", __func__)); if ((optval != 0 && optval < 8) || (optval > 65535)) { INP_WUNLOCK(inp); error = EINVAL; break; } if (sopt->sopt_name == UDPLITE_SEND_CSCOV) up->u_txcslen = optval; else up->u_rxcslen = optval; INP_WUNLOCK(inp); break; default: INP_WUNLOCK(inp); error = ENOPROTOOPT; break; } break; case SOPT_GET: switch (sopt->sopt_name) { #if defined(IPSEC) || defined(IPSEC_SUPPORT) #ifdef INET case UDP_ENCAP: if (!IPSEC_ENABLED(ipv4)) { INP_WUNLOCK(inp); return (ENOPROTOOPT); } error = UDPENCAP_PCBCTL(inp, sopt); break; #endif /* INET */ #endif /* IPSEC */ case UDPLITE_SEND_CSCOV: case UDPLITE_RECV_CSCOV: if (!isudplite) { INP_WUNLOCK(inp); error = ENOPROTOOPT; break; } up = intoudpcb(inp); KASSERT(up != NULL, ("%s: up == NULL", __func__)); if (sopt->sopt_name == UDPLITE_SEND_CSCOV) optval = up->u_txcslen; else optval = up->u_rxcslen; INP_WUNLOCK(inp); error = sooptcopyout(sopt, &optval, sizeof(optval)); break; default: INP_WUNLOCK(inp); error = ENOPROTOOPT; break; } break; } return (error); } #ifdef INET #define UH_WLOCKED 2 #define UH_RLOCKED 1 #define UH_UNLOCKED 0 static int udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct thread *td) { struct udpiphdr *ui; int len = m->m_pkthdr.len; struct in_addr faddr, laddr; struct cmsghdr *cm; struct inpcbinfo *pcbinfo; struct sockaddr_in *sin, src; struct epoch_tracker et; int cscov_partial = 0; int error = 0; int ipflags; u_short fport, lport; int unlock_udbinfo, unlock_inp; u_char tos; uint8_t pr; uint16_t cscov = 0; uint32_t flowid = 0; uint8_t flowtype = M_HASHTYPE_NONE; /* * udp_output() may need to temporarily bind or connect the current * inpcb. As such, we don't know up front whether we will need the * pcbinfo lock or not. Do any work to decide what is needed up * front before acquiring any locks. */ if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) { if (control) m_freem(control); m_freem(m); return (EMSGSIZE); } src.sin_family = 0; sin = (struct sockaddr_in *)addr; if (sin == NULL || (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) { INP_WLOCK(inp); unlock_inp = UH_WLOCKED; } else { INP_RLOCK(inp); unlock_inp = UH_RLOCKED; } tos = inp->inp_ip_tos; if (control != NULL) { /* * XXX: Currently, we assume all the optional information is * stored in a single mbuf. */ if (control->m_next) { if (unlock_inp == UH_WLOCKED) INP_WUNLOCK(inp); else INP_RUNLOCK(inp); m_freem(control); m_freem(m); return (EINVAL); } for (; control->m_len > 0; control->m_data += CMSG_ALIGN(cm->cmsg_len), control->m_len -= CMSG_ALIGN(cm->cmsg_len)) { cm = mtod(control, struct cmsghdr *); if (control->m_len < sizeof(*cm) || cm->cmsg_len == 0 || cm->cmsg_len > control->m_len) { error = EINVAL; break; } if (cm->cmsg_level != IPPROTO_IP) continue; switch (cm->cmsg_type) { case IP_SENDSRCADDR: if (cm->cmsg_len != CMSG_LEN(sizeof(struct in_addr))) { error = EINVAL; break; } bzero(&src, sizeof(src)); src.sin_family = AF_INET; src.sin_len = sizeof(src); src.sin_port = inp->inp_lport; src.sin_addr = *(struct in_addr *)CMSG_DATA(cm); break; case IP_TOS: if (cm->cmsg_len != CMSG_LEN(sizeof(u_char))) { error = EINVAL; break; } tos = *(u_char *)CMSG_DATA(cm); break; case IP_FLOWID: if (cm->cmsg_len != CMSG_LEN(sizeof(uint32_t))) { error = EINVAL; break; } flowid = *(uint32_t *) CMSG_DATA(cm); break; case IP_FLOWTYPE: if (cm->cmsg_len != CMSG_LEN(sizeof(uint32_t))) { error = EINVAL; break; } flowtype = *(uint32_t *) CMSG_DATA(cm); break; #ifdef RSS case IP_RSSBUCKETID: if (cm->cmsg_len != CMSG_LEN(sizeof(uint32_t))) { error = EINVAL; break; } /* This is just a placeholder for now */ break; #endif /* RSS */ default: error = ENOPROTOOPT; break; } if (error) break; } m_freem(control); } if (error) { if (unlock_inp == UH_WLOCKED) INP_WUNLOCK(inp); else INP_RUNLOCK(inp); m_freem(m); return (error); } /* * Depending on whether or not the application has bound or connected * the socket, we may have to do varying levels of work. The optimal * case is for a connected UDP socket, as a global lock isn't * required at all. * * In order to decide which we need, we require stability of the * inpcb binding, which we ensure by acquiring a read lock on the * inpcb. This doesn't strictly follow the lock order, so we play * the trylock and retry game; note that we may end up with more * conservative locks than required the second time around, so later * assertions have to accept that. Further analysis of the number of * misses under contention is required. * * XXXRW: Check that hash locking update here is correct. */ pr = inp->inp_socket->so_proto->pr_protocol; pcbinfo = udp_get_inpcbinfo(pr); sin = (struct sockaddr_in *)addr; if (sin != NULL && (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) { INP_HASH_WLOCK(pcbinfo); unlock_udbinfo = UH_WLOCKED; } else if ((sin != NULL && ( (sin->sin_addr.s_addr == INADDR_ANY) || (sin->sin_addr.s_addr == INADDR_BROADCAST) || (inp->inp_laddr.s_addr == INADDR_ANY) || (inp->inp_lport == 0))) || (src.sin_family == AF_INET)) { INP_HASH_RLOCK_ET(pcbinfo, et); unlock_udbinfo = UH_RLOCKED; } else unlock_udbinfo = UH_UNLOCKED; /* * If the IP_SENDSRCADDR control message was specified, override the * source address for this datagram. Its use is invalidated if the * address thus specified is incomplete or clobbers other inpcbs. */ laddr = inp->inp_laddr; lport = inp->inp_lport; if (src.sin_family == AF_INET) { INP_HASH_LOCK_ASSERT(pcbinfo); if ((lport == 0) || (laddr.s_addr == INADDR_ANY && src.sin_addr.s_addr == INADDR_ANY)) { error = EINVAL; goto release; } error = in_pcbbind_setup(inp, (struct sockaddr *)&src, &laddr.s_addr, &lport, td->td_ucred); if (error) goto release; } /* * If a UDP socket has been connected, then a local address/port will * have been selected and bound. * * If a UDP socket has not been connected to, then an explicit * destination address must be used, in which case a local * address/port may not have been selected and bound. */ if (sin != NULL) { INP_LOCK_ASSERT(inp); if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto release; } /* * Jail may rewrite the destination address, so let it do * that before we use it. */ error = prison_remote_ip4(td->td_ucred, &sin->sin_addr); if (error) goto release; /* * If a local address or port hasn't yet been selected, or if * the destination address needs to be rewritten due to using * a special INADDR_ constant, invoke in_pcbconnect_setup() * to do the heavy lifting. Once a port is selected, we * commit the binding back to the socket; we also commit the * binding of the address if in jail. * * If we already have a valid binding and we're not * requesting a destination address rewrite, use a fast path. */ if (inp->inp_laddr.s_addr == INADDR_ANY || inp->inp_lport == 0 || sin->sin_addr.s_addr == INADDR_ANY || sin->sin_addr.s_addr == INADDR_BROADCAST) { INP_HASH_LOCK_ASSERT(pcbinfo); error = in_pcbconnect_setup(inp, addr, &laddr.s_addr, &lport, &faddr.s_addr, &fport, NULL, td->td_ucred); if (error) goto release; /* * XXXRW: Why not commit the port if the address is * !INADDR_ANY? */ /* Commit the local port if newly assigned. */ if (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0) { INP_WLOCK_ASSERT(inp); INP_HASH_WLOCK_ASSERT(pcbinfo); /* * Remember addr if jailed, to prevent * rebinding. */ if (prison_flag(td->td_ucred, PR_IP4)) inp->inp_laddr = laddr; inp->inp_lport = lport; if (in_pcbinshash(inp) != 0) { inp->inp_lport = 0; error = EAGAIN; goto release; } inp->inp_flags |= INP_ANONPORT; } } else { faddr = sin->sin_addr; fport = sin->sin_port; } } else { INP_LOCK_ASSERT(inp); faddr = inp->inp_faddr; fport = inp->inp_fport; if (faddr.s_addr == INADDR_ANY) { error = ENOTCONN; goto release; } } /* * Calculate data length and get a mbuf for UDP, IP, and possible * link-layer headers. Immediate slide the data pointer back forward * since we won't use that space at this layer. */ M_PREPEND(m, sizeof(struct udpiphdr) + max_linkhdr, M_NOWAIT); if (m == NULL) { error = ENOBUFS; goto release; } m->m_data += max_linkhdr; m->m_len -= max_linkhdr; m->m_pkthdr.len -= max_linkhdr; /* * Fill in mbuf with extended UDP header and addresses and length put * into network format. */ ui = mtod(m, struct udpiphdr *); bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */ ui->ui_v = IPVERSION << 4; ui->ui_pr = pr; ui->ui_src = laddr; ui->ui_dst = faddr; ui->ui_sport = lport; ui->ui_dport = fport; ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr)); if (pr == IPPROTO_UDPLITE) { struct udpcb *up; uint16_t plen; up = intoudpcb(inp); cscov = up->u_txcslen; plen = (u_short)len + sizeof(struct udphdr); if (cscov >= plen) cscov = 0; ui->ui_len = htons(plen); ui->ui_ulen = htons(cscov); /* * For UDP-Lite, checksum coverage length of zero means * the entire UDPLite packet is covered by the checksum. */ cscov_partial = (cscov == 0) ? 0 : 1; } /* * Set the Don't Fragment bit in the IP header. */ if (inp->inp_flags & INP_DONTFRAG) { struct ip *ip; ip = (struct ip *)&ui->ui_i; ip->ip_off |= htons(IP_DF); } ipflags = 0; if (inp->inp_socket->so_options & SO_DONTROUTE) ipflags |= IP_ROUTETOIF; if (inp->inp_socket->so_options & SO_BROADCAST) ipflags |= IP_ALLOWBROADCAST; if (inp->inp_flags & INP_ONESBCAST) ipflags |= IP_SENDONES; #ifdef MAC mac_inpcb_create_mbuf(inp, m); #endif /* * Set up checksum and output datagram. */ ui->ui_sum = 0; if (pr == IPPROTO_UDPLITE) { if (inp->inp_flags & INP_ONESBCAST) faddr.s_addr = INADDR_BROADCAST; if (cscov_partial) { if ((ui->ui_sum = in_cksum(m, sizeof(struct ip) + cscov)) == 0) ui->ui_sum = 0xffff; } else { if ((ui->ui_sum = in_cksum(m, sizeof(struct udpiphdr) + len)) == 0) ui->ui_sum = 0xffff; } } else if (V_udp_cksum) { if (inp->inp_flags & INP_ONESBCAST) faddr.s_addr = INADDR_BROADCAST; ui->ui_sum = in_pseudo(ui->ui_src.s_addr, faddr.s_addr, htons((u_short)len + sizeof(struct udphdr) + pr)); m->m_pkthdr.csum_flags = CSUM_UDP; m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); } ((struct ip *)ui)->ip_len = htons(sizeof(struct udpiphdr) + len); ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */ ((struct ip *)ui)->ip_tos = tos; /* XXX */ UDPSTAT_INC(udps_opackets); /* * Setup flowid / RSS information for outbound socket. * * Once the UDP code decides to set a flowid some other way, * this allows the flowid to be overridden by userland. */ if (flowtype != M_HASHTYPE_NONE) { m->m_pkthdr.flowid = flowid; M_HASHTYPE_SET(m, flowtype); #ifdef RSS } else { uint32_t hash_val, hash_type; /* * Calculate an appropriate RSS hash for UDP and * UDP Lite. * * The called function will take care of figuring out * whether a 2-tuple or 4-tuple hash is required based * on the currently configured scheme. * * Later later on connected socket values should be * cached in the inpcb and reused, rather than constantly * re-calculating it. * * UDP Lite is a different protocol number and will * likely end up being hashed as a 2-tuple until * RSS / NICs grow UDP Lite protocol awareness. */ if (rss_proto_software_hash_v4(faddr, laddr, fport, lport, pr, &hash_val, &hash_type) == 0) { m->m_pkthdr.flowid = hash_val; M_HASHTYPE_SET(m, hash_type); } #endif } #ifdef RSS /* * Don't override with the inp cached flowid value. * * Depending upon the kind of send being done, the inp * flowid/flowtype values may actually not be appropriate * for this particular socket send. * * We should either leave the flowid at zero (which is what is * currently done) or set it to some software generated * hash value based on the packet contents. */ ipflags |= IP_NODEFAULTFLOWID; #endif /* RSS */ if (unlock_udbinfo == UH_WLOCKED) INP_HASH_WUNLOCK(pcbinfo); else if (unlock_udbinfo == UH_RLOCKED) INP_HASH_RUNLOCK_ET(pcbinfo, et); - UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u); + if (pr == IPPROTO_UDPLITE) + UDPLITE_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u); + else + UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u); error = ip_output(m, inp->inp_options, (unlock_inp == UH_WLOCKED ? &inp->inp_route : NULL), ipflags, inp->inp_moptions, inp); if (unlock_inp == UH_WLOCKED) INP_WUNLOCK(inp); else INP_RUNLOCK(inp); return (error); release: if (unlock_udbinfo == UH_WLOCKED) { KASSERT(unlock_inp == UH_WLOCKED, ("%s: excl udbinfo lock, shared inp lock", __func__)); INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); } else if (unlock_udbinfo == UH_RLOCKED) { KASSERT(unlock_inp == UH_RLOCKED, ("%s: shared udbinfo lock, excl inp lock", __func__)); INP_HASH_RUNLOCK_ET(pcbinfo, et); INP_RUNLOCK(inp); } else if (unlock_inp == UH_WLOCKED) INP_WUNLOCK(inp); else INP_RUNLOCK(inp); m_freem(m); return (error); } static void udp_abort(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_abort: inp == NULL")); INP_WLOCK(inp); if (inp->inp_faddr.s_addr != INADDR_ANY) { INP_HASH_WLOCK(pcbinfo); in_pcbdisconnect(inp); inp->inp_laddr.s_addr = INADDR_ANY; INP_HASH_WUNLOCK(pcbinfo); soisdisconnected(so); } INP_WUNLOCK(inp); } static int udp_attach(struct socket *so, int proto, struct thread *td) { static uint32_t udp_flowid; struct inpcb *inp; struct inpcbinfo *pcbinfo; int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp == NULL, ("udp_attach: inp != NULL")); error = soreserve(so, udp_sendspace, udp_recvspace); if (error) return (error); INP_INFO_WLOCK(pcbinfo); error = in_pcballoc(so, pcbinfo); if (error) { INP_INFO_WUNLOCK(pcbinfo); return (error); } inp = sotoinpcb(so); inp->inp_vflag |= INP_IPV4; inp->inp_ip_ttl = V_ip_defttl; inp->inp_flowid = atomic_fetchadd_int(&udp_flowid, 1); inp->inp_flowtype = M_HASHTYPE_OPAQUE; error = udp_newudpcb(inp); if (error) { in_pcbdetach(inp); in_pcbfree(inp); INP_INFO_WUNLOCK(pcbinfo); return (error); } INP_WUNLOCK(inp); INP_INFO_WUNLOCK(pcbinfo); return (0); } #endif /* INET */ int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, udp_tun_icmp_t i, void *ctx) { struct inpcb *inp; struct udpcb *up; KASSERT(so->so_type == SOCK_DGRAM, ("udp_set_kernel_tunneling: !dgram")); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_set_kernel_tunneling: inp == NULL")); INP_WLOCK(inp); up = intoudpcb(inp); if ((up->u_tun_func != NULL) || (up->u_icmp_func != NULL)) { INP_WUNLOCK(inp); return (EBUSY); } up->u_tun_func = f; up->u_icmp_func = i; up->u_tun_ctx = ctx; INP_WUNLOCK(inp); return (0); } #ifdef INET static int udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { struct inpcb *inp; struct inpcbinfo *pcbinfo; int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_bind: inp == NULL")); INP_WLOCK(inp); INP_HASH_WLOCK(pcbinfo); error = in_pcbbind(inp, nam, td->td_ucred); INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); return (error); } static void udp_close(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_close: inp == NULL")); INP_WLOCK(inp); if (inp->inp_faddr.s_addr != INADDR_ANY) { INP_HASH_WLOCK(pcbinfo); in_pcbdisconnect(inp); inp->inp_laddr.s_addr = INADDR_ANY; INP_HASH_WUNLOCK(pcbinfo); soisdisconnected(so); } INP_WUNLOCK(inp); } static int udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { struct inpcb *inp; struct inpcbinfo *pcbinfo; struct sockaddr_in *sin; int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_connect: inp == NULL")); INP_WLOCK(inp); if (inp->inp_faddr.s_addr != INADDR_ANY) { INP_WUNLOCK(inp); return (EISCONN); } sin = (struct sockaddr_in *)nam; error = prison_remote_ip4(td->td_ucred, &sin->sin_addr); if (error != 0) { INP_WUNLOCK(inp); return (error); } INP_HASH_WLOCK(pcbinfo); error = in_pcbconnect(inp, nam, td->td_ucred); INP_HASH_WUNLOCK(pcbinfo); if (error == 0) soisconnected(so); INP_WUNLOCK(inp); return (error); } static void udp_detach(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; struct udpcb *up; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_detach: inp == NULL")); KASSERT(inp->inp_faddr.s_addr == INADDR_ANY, ("udp_detach: not disconnected")); INP_INFO_WLOCK(pcbinfo); INP_WLOCK(inp); up = intoudpcb(inp); KASSERT(up != NULL, ("%s: up == NULL", __func__)); inp->inp_ppcb = NULL; in_pcbdetach(inp); in_pcbfree(inp); INP_INFO_WUNLOCK(pcbinfo); udp_discardcb(up); } static int udp_disconnect(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_disconnect: inp == NULL")); INP_WLOCK(inp); if (inp->inp_faddr.s_addr == INADDR_ANY) { INP_WUNLOCK(inp); return (ENOTCONN); } INP_HASH_WLOCK(pcbinfo); in_pcbdisconnect(inp); inp->inp_laddr.s_addr = INADDR_ANY; INP_HASH_WUNLOCK(pcbinfo); SOCK_LOCK(so); so->so_state &= ~SS_ISCONNECTED; /* XXX */ SOCK_UNLOCK(so); INP_WUNLOCK(inp); return (0); } static int udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct thread *td) { struct inpcb *inp; inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_send: inp == NULL")); return (udp_output(inp, m, addr, control, td)); } #endif /* INET */ int udp_shutdown(struct socket *so) { struct inpcb *inp; inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_shutdown: inp == NULL")); INP_WLOCK(inp); socantsendmore(so); INP_WUNLOCK(inp); return (0); } #ifdef INET struct pr_usrreqs udp_usrreqs = { .pru_abort = udp_abort, .pru_attach = udp_attach, .pru_bind = udp_bind, .pru_connect = udp_connect, .pru_control = in_control, .pru_detach = udp_detach, .pru_disconnect = udp_disconnect, .pru_peeraddr = in_getpeeraddr, .pru_send = udp_send, .pru_soreceive = soreceive_dgram, .pru_sosend = sosend_dgram, .pru_shutdown = udp_shutdown, .pru_sockaddr = in_getsockaddr, .pru_sosetlabel = in_pcbsosetlabel, .pru_close = udp_close, }; #endif /* INET */ Index: head/sys/netinet/udplite.h =================================================================== --- head/sys/netinet/udplite.h (revision 337017) +++ head/sys/netinet/udplite.h (revision 337018) @@ -1,38 +1,49 @@ /*- * Copyright (c) 2014, Kevin Lo * All rights reserved. * * 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 REGENTS 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 REGENTS 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 _NETINET_UDPLITE_H_ #define _NETINET_UDPLITE_H_ +/* + * UDP-Lite protocol header. + * Per RFC 3828, July, 2004. + */ +struct udplitehdr { + u_short udplite_sport; /* UDO-Lite source port */ + u_short udplite_dport; /* UDP-Lite destination port */ + u_short udplite_coverage; /* UDP-Lite checksum coverage */ + u_short udplite_checksum; /* UDP-Lite checksum */ +}; + /* * User-settable options (used with setsockopt). */ #define UDPLITE_SEND_CSCOV 2 /* Sender checksum coverage. */ #define UDPLITE_RECV_CSCOV 4 /* Receiver checksum coverage. */ #endif /* !_NETINET_UDPLITE_H_ */ Index: head/sys/netinet6/udp6_usrreq.c =================================================================== --- head/sys/netinet6/udp6_usrreq.c (revision 337017) +++ head/sys/netinet6/udp6_usrreq.c (revision 337018) @@ -1,1331 +1,1347 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * Copyright (c) 2010-2011 Juniper Networks, Inc. * Copyright (c) 2014 Kevin Lo * All rights reserved. * * Portions of this software were developed by Robert N. M. Watson under * contract to Juniper Networks, Inc. * * 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. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. * * $KAME: udp6_usrreq.c,v 1.27 2001/05/21 05:45:10 jinmei Exp $ * $KAME: udp6_output.c,v 1.31 2001/05/21 16:39:15 jinmei Exp $ */ /*- * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 * The Regents of the University of California. * All rights reserved. * * 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. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 */ #include __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ipsec.h" #include "opt_rss.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ extern struct protosw inetsw[]; static void udp6_detach(struct socket *so); static int udp6_append(struct inpcb *inp, struct mbuf *n, int off, struct sockaddr_in6 *fromsa) { struct socket *so; struct mbuf *opts = NULL, *tmp_opts; struct udpcb *up; INP_LOCK_ASSERT(inp); /* * Engage the tunneling protocol. */ up = intoudpcb(inp); if (up->u_tun_func != NULL) { in_pcbref(inp); INP_RUNLOCK(inp); (*up->u_tun_func)(n, off, inp, (struct sockaddr *)&fromsa[0], up->u_tun_ctx); INP_RLOCK(inp); return (in_pcbrele_rlocked(inp)); } #if defined(IPSEC) || defined(IPSEC_SUPPORT) /* Check AH/ESP integrity. */ if (IPSEC_ENABLED(ipv6)) { if (IPSEC_CHECK_POLICY(ipv6, n, inp) != 0) { m_freem(n); return (0); } } #endif /* IPSEC */ #ifdef MAC if (mac_inpcb_check_deliver(inp, n) != 0) { m_freem(n); return (0); } #endif opts = NULL; if (inp->inp_flags & INP_CONTROLOPTS || inp->inp_socket->so_options & SO_TIMESTAMP) ip6_savecontrol(inp, n, &opts); if ((inp->inp_vflag & INP_IPV6) && (inp->inp_flags2 & INP_ORIGDSTADDR)) { tmp_opts = sbcreatecontrol((caddr_t)&fromsa[1], sizeof(struct sockaddr_in6), IPV6_ORIGDSTADDR, IPPROTO_IPV6); if (tmp_opts) { if (opts) { tmp_opts->m_next = opts; opts = tmp_opts; } else opts = tmp_opts; } } m_adj(n, off + sizeof(struct udphdr)); so = inp->inp_socket; SOCKBUF_LOCK(&so->so_rcv); if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&fromsa[0], n, opts) == 0) { SOCKBUF_UNLOCK(&so->so_rcv); m_freem(n); if (opts) m_freem(opts); UDPSTAT_INC(udps_fullsock); } else sorwakeup_locked(so); return (0); } int udp6_input(struct mbuf **mp, int *offp, int proto) { struct mbuf *m = *mp; struct ifnet *ifp; struct ip6_hdr *ip6; struct udphdr *uh; struct inpcb *inp; struct inpcbinfo *pcbinfo; struct udpcb *up; int off = *offp; int cscov_partial; int plen, ulen; struct epoch_tracker et; struct sockaddr_in6 fromsa[2]; struct m_tag *fwd_tag; uint16_t uh_sum; uint8_t nxt; ifp = m->m_pkthdr.rcvif; #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); ip6 = mtod(m, struct ip6_hdr *); uh = (struct udphdr *)((caddr_t)ip6 + off); #else IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(*uh)); if (!uh) return (IPPROTO_DONE); ip6 = mtod(m, struct ip6_hdr *); #endif UDPSTAT_INC(udps_ipackets); /* * Destination port of 0 is illegal, based on RFC768. */ if (uh->uh_dport == 0) goto badunlocked; plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6); ulen = ntohs((u_short)uh->uh_ulen); nxt = proto; cscov_partial = (nxt == IPPROTO_UDPLITE) ? 1 : 0; if (nxt == IPPROTO_UDPLITE) { /* Zero means checksum over the complete packet. */ if (ulen == 0) ulen = plen; if (ulen == plen) cscov_partial = 0; if ((ulen < sizeof(struct udphdr)) || (ulen > plen)) { /* XXX: What is the right UDPLite MIB counter? */ goto badunlocked; } if (uh->uh_sum == 0) { /* XXX: What is the right UDPLite MIB counter? */ goto badunlocked; } } else { if ((ulen < sizeof(struct udphdr)) || (plen != ulen)) { UDPSTAT_INC(udps_badlen); goto badunlocked; } if (uh->uh_sum == 0) { UDPSTAT_INC(udps_nosum); goto badunlocked; } } if ((m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) && !cscov_partial) { if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) uh_sum = m->m_pkthdr.csum_data; else uh_sum = in6_cksum_pseudo(ip6, ulen, nxt, m->m_pkthdr.csum_data); uh_sum ^= 0xffff; } else uh_sum = in6_cksum_partial(m, nxt, off, plen, ulen); if (uh_sum != 0) { UDPSTAT_INC(udps_badsum); goto badunlocked; } /* * Construct sockaddr format source address. */ init_sin6(&fromsa[0], m, 0); fromsa[0].sin6_port = uh->uh_sport; init_sin6(&fromsa[1], m, 1); fromsa[1].sin6_port = uh->uh_dport; pcbinfo = udp_get_inpcbinfo(nxt); if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { struct inpcb *last; struct inpcbhead *pcblist; struct ip6_moptions *imo; INP_INFO_RLOCK_ET(pcbinfo, et); /* * In the event that laddr should be set to the link-local * address (this happens in RIPng), the multicast address * specified in the received packet will not match laddr. To * handle this situation, matching is relaxed if the * receiving interface is the same as one specified in the * socket and if the destination multicast address matches * one of the multicast groups specified in the socket. */ /* * KAME note: traditionally we dropped udpiphdr from mbuf * here. We need udphdr for IPsec processing so we do that * later. */ pcblist = udp_get_pcblist(nxt); last = NULL; CK_LIST_FOREACH(inp, pcblist, inp_list) { if ((inp->inp_vflag & INP_IPV6) == 0) continue; if (inp->inp_lport != uh->uh_dport) continue; if (inp->inp_fport != 0 && inp->inp_fport != uh->uh_sport) continue; if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &ip6->ip6_dst)) continue; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &ip6->ip6_src) || inp->inp_fport != uh->uh_sport) continue; } /* * XXXRW: Because we weren't holding either the inpcb * or the hash lock when we checked for a match * before, we should probably recheck now that the * inpcb lock is (supposed to be) held. */ /* * Handle socket delivery policy for any-source * and source-specific multicast. [RFC3678] */ imo = inp->in6p_moptions; if (imo && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { struct sockaddr_in6 mcaddr; int blocked; INP_RLOCK(inp); if (__predict_false(inp->inp_flags2 & INP_FREED)) { INP_RUNLOCK(inp); continue; } bzero(&mcaddr, sizeof(struct sockaddr_in6)); mcaddr.sin6_len = sizeof(struct sockaddr_in6); mcaddr.sin6_family = AF_INET6; mcaddr.sin6_addr = ip6->ip6_dst; blocked = im6o_mc_filter(imo, ifp, (struct sockaddr *)&mcaddr, (struct sockaddr *)&fromsa[0]); if (blocked != MCAST_PASS) { if (blocked == MCAST_NOTGMEMBER) IP6STAT_INC(ip6s_notmember); if (blocked == MCAST_NOTSMEMBER || blocked == MCAST_MUTED) UDPSTAT_INC(udps_filtermcast); INP_RUNLOCK(inp); /* XXX */ continue; } INP_RUNLOCK(inp); } if (last != NULL) { struct mbuf *n; if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) { INP_RLOCK(last); if (__predict_true(last->inp_flags2 & INP_FREED) == 0) { - UDP_PROBE(receive, NULL, last, ip6, - last, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, + ip6, last, uh); + else + UDP_PROBE(receive, NULL, last, + ip6, last, uh); if (udp6_append(last, n, off, fromsa)) goto inp_lost; } INP_RUNLOCK(last); } } last = inp; /* * Don't look for additional matches if this one does * not have either the SO_REUSEPORT or SO_REUSEADDR * socket options set. This heuristic avoids * searching through all pcbs in the common case of a * non-shared port. It assumes that an application * will never clear these options after setting them. */ if ((last->inp_socket->so_options & (SO_REUSEPORT|SO_REUSEPORT_LB|SO_REUSEADDR)) == 0) break; } if (last == NULL) { /* * No matching pcb found; discard datagram. (No need * to send an ICMP Port Unreachable for a broadcast * or multicast datgram.) */ UDPSTAT_INC(udps_noport); UDPSTAT_INC(udps_noportmcast); goto badheadlocked; } INP_RLOCK(last); if (__predict_true(last->inp_flags2 & INP_FREED) == 0) { - UDP_PROBE(receive, NULL, last, ip6, last, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, last, ip6, last, uh); + else + UDP_PROBE(receive, NULL, last, ip6, last, uh); if (udp6_append(last, m, off, fromsa) == 0) INP_RUNLOCK(last); } else INP_RUNLOCK(last); INP_INFO_RUNLOCK_ET(pcbinfo, et); inp_lost: return (IPPROTO_DONE); } /* * Locate pcb for datagram. */ /* * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. */ if ((m->m_flags & M_IP6_NEXTHOP) && (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) { struct sockaddr_in6 *next_hop6; next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1); /* * Transparently forwarded. Pretend to be the destination. * Already got one like this? */ inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src, uh->uh_sport, &ip6->ip6_dst, uh->uh_dport, INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m); if (!inp) { /* * It's new. Try to find the ambushing socket. * Because we've rewritten the destination address, * any hardware-generated hash is ignored. */ inp = in6_pcblookup(pcbinfo, &ip6->ip6_src, uh->uh_sport, &next_hop6->sin6_addr, next_hop6->sin6_port ? htons(next_hop6->sin6_port) : uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif); } /* Remove the tag from the packet. We don't need it anymore. */ m_tag_delete(m, fwd_tag); m->m_flags &= ~M_IP6_NEXTHOP; } else inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_src, uh->uh_sport, &ip6->ip6_dst, uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m); if (inp == NULL) { if (udp_log_in_vain) { char ip6bufs[INET6_ADDRSTRLEN]; char ip6bufd[INET6_ADDRSTRLEN]; log(LOG_INFO, "Connection attempt to UDP [%s]:%d from [%s]:%d\n", ip6_sprintf(ip6bufd, &ip6->ip6_dst), ntohs(uh->uh_dport), ip6_sprintf(ip6bufs, &ip6->ip6_src), ntohs(uh->uh_sport)); } - UDP_PROBE(receive, NULL, NULL, ip6, NULL, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, NULL, ip6, NULL, uh); + else + UDP_PROBE(receive, NULL, NULL, ip6, NULL, uh); UDPSTAT_INC(udps_noport); if (m->m_flags & M_MCAST) { printf("UDP6: M_MCAST is set in a unicast packet.\n"); UDPSTAT_INC(udps_noportmcast); goto badunlocked; } if (V_udp_blackhole) goto badunlocked; icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); return (IPPROTO_DONE); } INP_RLOCK_ASSERT(inp); up = intoudpcb(inp); if (cscov_partial) { if (up->u_rxcslen == 0 || up->u_rxcslen > ulen) { INP_RUNLOCK(inp); m_freem(m); return (IPPROTO_DONE); } } - UDP_PROBE(receive, NULL, inp, ip6, inp, uh); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(receive, NULL, inp, ip6, inp, uh); + else + UDP_PROBE(receive, NULL, inp, ip6, inp, uh); if (udp6_append(inp, m, off, fromsa) == 0) INP_RUNLOCK(inp); return (IPPROTO_DONE); badheadlocked: INP_INFO_RUNLOCK_ET(pcbinfo, et); badunlocked: if (m) m_freem(m); return (IPPROTO_DONE); } static void udp6_common_ctlinput(int cmd, struct sockaddr *sa, void *d, struct inpcbinfo *pcbinfo) { struct udphdr uh; struct ip6_hdr *ip6; struct mbuf *m; int off = 0; struct ip6ctlparam *ip6cp = NULL; const struct sockaddr_in6 *sa6_src = NULL; void *cmdarg; struct inpcb *(*notify)(struct inpcb *, int) = udp_notify; struct udp_portonly { u_int16_t uh_sport; u_int16_t uh_dport; } *uhp; if (sa->sa_family != AF_INET6 || sa->sa_len != sizeof(struct sockaddr_in6)) return; if ((unsigned)cmd >= PRC_NCMDS) return; if (PRC_IS_REDIRECT(cmd)) notify = in6_rtchange, d = NULL; else if (cmd == PRC_HOSTDEAD) d = NULL; else if (inet6ctlerrmap[cmd] == 0) return; /* if the parameter is from icmp6, decode it. */ if (d != NULL) { ip6cp = (struct ip6ctlparam *)d; m = ip6cp->ip6c_m; ip6 = ip6cp->ip6c_ip6; off = ip6cp->ip6c_off; cmdarg = ip6cp->ip6c_cmdarg; sa6_src = ip6cp->ip6c_src; } else { m = NULL; ip6 = NULL; cmdarg = NULL; sa6_src = &sa6_any; } if (ip6) { /* * XXX: We assume that when IPV6 is non NULL, * M and OFF are valid. */ /* Check if we can safely examine src and dst ports. */ if (m->m_pkthdr.len < off + sizeof(*uhp)) return; bzero(&uh, sizeof(uh)); m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); if (!PRC_IS_REDIRECT(cmd)) { /* Check to see if its tunneled */ struct inpcb *inp; inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_dst, uh.uh_dport, &ip6->ip6_src, uh.uh_sport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m); if (inp != NULL) { struct udpcb *up; up = intoudpcb(inp); if (up->u_icmp_func) { /* Yes it is. */ INP_RUNLOCK(inp); (*up->u_icmp_func)(cmd, (struct sockaddr *)ip6cp->ip6c_src, d, up->u_tun_ctx); return; } else { /* Can't find it. */ INP_RUNLOCK(inp); } } } (void)in6_pcbnotify(pcbinfo, sa, uh.uh_dport, (struct sockaddr *)ip6cp->ip6c_src, uh.uh_sport, cmd, cmdarg, notify); } else (void)in6_pcbnotify(pcbinfo, sa, 0, (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); } void udp6_ctlinput(int cmd, struct sockaddr *sa, void *d) { return (udp6_common_ctlinput(cmd, sa, d, &V_udbinfo)); } void udplite6_ctlinput(int cmd, struct sockaddr *sa, void *d) { return (udp6_common_ctlinput(cmd, sa, d, &V_ulitecbinfo)); } static int udp6_getcred(SYSCTL_HANDLER_ARGS) { struct xucred xuc; struct sockaddr_in6 addrs[2]; struct inpcb *inp; int error; error = priv_check(req->td, PRIV_NETINET_GETCRED); if (error) return (error); if (req->newlen != sizeof(addrs)) return (EINVAL); if (req->oldlen != sizeof(struct xucred)) return (EINVAL); error = SYSCTL_IN(req, addrs, sizeof(addrs)); if (error) return (error); if ((error = sa6_embedscope(&addrs[0], V_ip6_use_defzone)) != 0 || (error = sa6_embedscope(&addrs[1], V_ip6_use_defzone)) != 0) { return (error); } inp = in6_pcblookup(&V_udbinfo, &addrs[1].sin6_addr, addrs[1].sin6_port, &addrs[0].sin6_addr, addrs[0].sin6_port, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL); if (inp != NULL) { INP_RLOCK_ASSERT(inp); if (inp->inp_socket == NULL) error = ENOENT; if (error == 0) error = cr_canseesocket(req->td->td_ucred, inp->inp_socket); if (error == 0) cru2x(inp->inp_cred, &xuc); INP_RUNLOCK(inp); } else error = ENOENT; if (error == 0) error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred)); return (error); } SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW, 0, 0, udp6_getcred, "S,xucred", "Get the xucred of a UDP6 connection"); static int udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6, struct mbuf *control, struct thread *td) { u_int32_t ulen = m->m_pkthdr.len; u_int32_t plen = sizeof(struct udphdr) + ulen; struct ip6_hdr *ip6; struct udphdr *udp6; struct in6_addr *laddr, *faddr, in6a; struct sockaddr_in6 *sin6 = NULL; int cscov_partial = 0; int scope_ambiguous = 0; u_short fport; int error = 0; uint8_t nxt; uint16_t cscov = 0; struct ip6_pktopts *optp, opt; int af = AF_INET6, hlen = sizeof(struct ip6_hdr); int flags; struct sockaddr_in6 tmp; INP_WLOCK_ASSERT(inp); INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); if (addr6) { /* addr6 has been validated in udp6_send(). */ sin6 = (struct sockaddr_in6 *)addr6; /* protect *sin6 from overwrites */ tmp = *sin6; sin6 = &tmp; /* * Application should provide a proper zone ID or the use of * default zone IDs should be enabled. Unfortunately, some * applications do not behave as it should, so we need a * workaround. Even if an appropriate ID is not determined, * we'll see if we can determine the outgoing interface. If we * can, determine the zone ID based on the interface below. */ if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone) scope_ambiguous = 1; if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0) return (error); } nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? IPPROTO_UDP : IPPROTO_UDPLITE; if (control) { if ((error = ip6_setpktopts(control, &opt, inp->in6p_outputopts, td->td_ucred, nxt)) != 0) goto release; optp = &opt; } else optp = inp->in6p_outputopts; if (sin6) { faddr = &sin6->sin6_addr; /* * Since we saw no essential reason for calling in_pcbconnect, * we get rid of such kind of logic, and call in6_selectsrc * and in6_pcbsetport in order to fill in the local address * and the local port. */ if (sin6->sin6_port == 0) { error = EADDRNOTAVAIL; goto release; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { /* how about ::ffff:0.0.0.0 case? */ error = EISCONN; goto release; } fport = sin6->sin6_port; /* allow 0 port */ if (IN6_IS_ADDR_V4MAPPED(faddr)) { if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) { /* * I believe we should explicitly discard the * packet when mapped addresses are disabled, * rather than send the packet as an IPv6 one. * If we chose the latter approach, the packet * might be sent out on the wire based on the * default route, the situation which we'd * probably want to avoid. * (20010421 jinmei@kame.net) */ error = EINVAL; goto release; } if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) && !IN6_IS_ADDR_V4MAPPED(&inp->in6p_laddr)) { /* * when remote addr is an IPv4-mapped address, * local addr should not be an IPv6 address, * since you cannot determine how to map IPv6 * source address to IPv4. */ error = EINVAL; goto release; } af = AF_INET; } if (!IN6_IS_ADDR_V4MAPPED(faddr)) { error = in6_selectsrc_socket(sin6, optp, inp, td->td_ucred, scope_ambiguous, &in6a, NULL); if (error) goto release; laddr = &in6a; } else laddr = &inp->in6p_laddr; /* XXX */ if (laddr == NULL) { if (error == 0) error = EADDRNOTAVAIL; goto release; } if (inp->inp_lport == 0 && (error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0) { /* Undo an address bind that may have occurred. */ inp->in6p_laddr = in6addr_any; goto release; } } else { if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { error = ENOTCONN; goto release; } if (IN6_IS_ADDR_V4MAPPED(&inp->in6p_faddr)) { if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) { /* * XXX: this case would happen when the * application sets the V6ONLY flag after * connecting the foreign address. * Such applications should be fixed, * so we bark here. */ log(LOG_INFO, "udp6_output: IPV6_V6ONLY " "option was set for a connected socket\n"); error = EINVAL; goto release; } else af = AF_INET; } laddr = &inp->in6p_laddr; faddr = &inp->in6p_faddr; fport = inp->inp_fport; } if (af == AF_INET) hlen = sizeof(struct ip); /* * Calculate data length and get a mbuf * for UDP and IP6 headers. */ M_PREPEND(m, hlen + sizeof(struct udphdr), M_NOWAIT); if (m == NULL) { error = ENOBUFS; goto release; } /* * Stuff checksum and output datagram. */ udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen); udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */ udp6->uh_dport = fport; if (nxt == IPPROTO_UDPLITE) { struct udpcb *up; up = intoudpcb(inp); cscov = up->u_txcslen; if (cscov >= plen) cscov = 0; udp6->uh_ulen = htons(cscov); /* * For UDP-Lite, checksum coverage length of zero means * the entire UDPLite packet is covered by the checksum. */ cscov_partial = (cscov == 0) ? 0 : 1; } else if (plen <= 0xffff) udp6->uh_ulen = htons((u_short)plen); else udp6->uh_ulen = 0; udp6->uh_sum = 0; switch (af) { case AF_INET6: ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = inp->inp_flow & IPV6_FLOWINFO_MASK; ip6->ip6_vfc &= ~IPV6_VERSION_MASK; ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_plen = htons((u_short)plen); ip6->ip6_nxt = nxt; ip6->ip6_hlim = in6_selecthlim(inp, NULL); ip6->ip6_src = *laddr; ip6->ip6_dst = *faddr; if (cscov_partial) { if ((udp6->uh_sum = in6_cksum_partial(m, nxt, sizeof(struct ip6_hdr), plen, cscov)) == 0) udp6->uh_sum = 0xffff; } else { udp6->uh_sum = in6_cksum_pseudo(ip6, plen, nxt, 0); m->m_pkthdr.csum_flags = CSUM_UDP_IPV6; m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); } #ifdef RSS { uint32_t hash_val, hash_type; uint8_t pr; pr = inp->inp_socket->so_proto->pr_protocol; /* * Calculate an appropriate RSS hash for UDP and * UDP Lite. * * The called function will take care of figuring out * whether a 2-tuple or 4-tuple hash is required based * on the currently configured scheme. * * Later later on connected socket values should be * cached in the inpcb and reused, rather than constantly * re-calculating it. * * UDP Lite is a different protocol number and will * likely end up being hashed as a 2-tuple until * RSS / NICs grow UDP Lite protocol awareness. */ if (rss_proto_software_hash_v6(faddr, laddr, fport, inp->inp_lport, pr, &hash_val, &hash_type) == 0) { m->m_pkthdr.flowid = hash_val; M_HASHTYPE_SET(m, hash_type); } } #endif flags = 0; #ifdef RSS /* * Don't override with the inp cached flowid. * * Until the whole UDP path is vetted, it may actually * be incorrect. */ flags |= IP_NODEFAULTFLOWID; #endif - UDP_PROBE(send, NULL, inp, ip6, inp, udp6); + if (nxt == IPPROTO_UDPLITE) + UDPLITE_PROBE(send, NULL, inp, ip6, inp, udp6); + else + UDP_PROBE(send, NULL, inp, ip6, inp, udp6); UDPSTAT_INC(udps_opackets); error = ip6_output(m, optp, &inp->inp_route6, flags, inp->in6p_moptions, NULL, inp); break; case AF_INET: error = EAFNOSUPPORT; goto release; } goto releaseopt; release: m_freem(m); releaseopt: if (control) { ip6_clearpktopts(&opt, -1); m_freem(control); } return (error); } static void udp6_abort(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_abort: inp == NULL")); INP_WLOCK(inp); #ifdef INET if (inp->inp_vflag & INP_IPV4) { struct pr_usrreqs *pru; uint8_t nxt; nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? IPPROTO_UDP : IPPROTO_UDPLITE; INP_WUNLOCK(inp); pru = inetsw[ip_protox[nxt]].pr_usrreqs; (*pru->pru_abort)(so); return; } #endif if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { INP_HASH_WLOCK(pcbinfo); in6_pcbdisconnect(inp); inp->in6p_laddr = in6addr_any; INP_HASH_WUNLOCK(pcbinfo); soisdisconnected(so); } INP_WUNLOCK(inp); } static int udp6_attach(struct socket *so, int proto, struct thread *td) { struct inpcb *inp; struct inpcbinfo *pcbinfo; int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp == NULL, ("udp6_attach: inp != NULL")); if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { error = soreserve(so, udp_sendspace, udp_recvspace); if (error) return (error); } INP_INFO_WLOCK(pcbinfo); error = in_pcballoc(so, pcbinfo); if (error) { INP_INFO_WUNLOCK(pcbinfo); return (error); } inp = (struct inpcb *)so->so_pcb; inp->inp_vflag |= INP_IPV6; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) inp->inp_vflag |= INP_IPV4; inp->in6p_hops = -1; /* use kernel default */ inp->in6p_cksum = -1; /* just to be sure */ /* * XXX: ugly!! * IPv4 TTL initialization is necessary for an IPv6 socket as well, * because the socket may be bound to an IPv6 wildcard address, * which may match an IPv4-mapped IPv6 address. */ inp->inp_ip_ttl = V_ip_defttl; error = udp_newudpcb(inp); if (error) { in_pcbdetach(inp); in_pcbfree(inp); INP_INFO_WUNLOCK(pcbinfo); return (error); } INP_WUNLOCK(inp); INP_INFO_WUNLOCK(pcbinfo); return (0); } static int udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { struct inpcb *inp; struct inpcbinfo *pcbinfo; int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_bind: inp == NULL")); INP_WLOCK(inp); INP_HASH_WLOCK(pcbinfo); inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { struct sockaddr_in6 *sin6_p; sin6_p = (struct sockaddr_in6 *)nam; if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) inp->inp_vflag |= INP_IPV4; #ifdef INET else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) { struct sockaddr_in sin; in6_sin6_2_sin(&sin, sin6_p); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; error = in_pcbbind(inp, (struct sockaddr *)&sin, td->td_ucred); goto out; } #endif } error = in6_pcbbind(inp, nam, td->td_ucred); #ifdef INET out: #endif INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); return (error); } static void udp6_close(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_close: inp == NULL")); INP_WLOCK(inp); #ifdef INET if (inp->inp_vflag & INP_IPV4) { struct pr_usrreqs *pru; uint8_t nxt; nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? IPPROTO_UDP : IPPROTO_UDPLITE; INP_WUNLOCK(inp); pru = inetsw[ip_protox[nxt]].pr_usrreqs; (*pru->pru_disconnect)(so); return; } #endif if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { INP_HASH_WLOCK(pcbinfo); in6_pcbdisconnect(inp); inp->in6p_laddr = in6addr_any; INP_HASH_WUNLOCK(pcbinfo); soisdisconnected(so); } INP_WUNLOCK(inp); } static int udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { struct inpcb *inp; struct inpcbinfo *pcbinfo; struct sockaddr_in6 *sin6; int error; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); sin6 = (struct sockaddr_in6 *)nam; KASSERT(inp != NULL, ("udp6_connect: inp == NULL")); /* * XXXRW: Need to clarify locking of v4/v6 flags. */ INP_WLOCK(inp); #ifdef INET if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { struct sockaddr_in sin; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { error = EINVAL; goto out; } if ((inp->inp_vflag & INP_IPV4) == 0) { error = EAFNOSUPPORT; goto out; } if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto out; } in6_sin6_2_sin(&sin, sin6); inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; error = prison_remote_ip4(td->td_ucred, &sin.sin_addr); if (error != 0) goto out; INP_HASH_WLOCK(pcbinfo); error = in_pcbconnect(inp, (struct sockaddr *)&sin, td->td_ucred); INP_HASH_WUNLOCK(pcbinfo); if (error == 0) soisconnected(so); goto out; } else { if ((inp->inp_vflag & INP_IPV6) == 0) { error = EAFNOSUPPORT; goto out; } } #endif if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { error = EISCONN; goto out; } inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr); if (error != 0) goto out; INP_HASH_WLOCK(pcbinfo); error = in6_pcbconnect(inp, nam, td->td_ucred); INP_HASH_WUNLOCK(pcbinfo); if (error == 0) soisconnected(so); out: INP_WUNLOCK(inp); return (error); } static void udp6_detach(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; struct udpcb *up; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_detach: inp == NULL")); INP_INFO_WLOCK(pcbinfo); INP_WLOCK(inp); up = intoudpcb(inp); KASSERT(up != NULL, ("%s: up == NULL", __func__)); in_pcbdetach(inp); in_pcbfree(inp); INP_INFO_WUNLOCK(pcbinfo); udp_discardcb(up); } static int udp6_disconnect(struct socket *so) { struct inpcb *inp; struct inpcbinfo *pcbinfo; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL")); INP_WLOCK(inp); #ifdef INET if (inp->inp_vflag & INP_IPV4) { struct pr_usrreqs *pru; uint8_t nxt; nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? IPPROTO_UDP : IPPROTO_UDPLITE; INP_WUNLOCK(inp); pru = inetsw[ip_protox[nxt]].pr_usrreqs; (void)(*pru->pru_disconnect)(so); return (0); } #endif if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { INP_WUNLOCK(inp); return (ENOTCONN); } INP_HASH_WLOCK(pcbinfo); in6_pcbdisconnect(inp); inp->in6p_laddr = in6addr_any; INP_HASH_WUNLOCK(pcbinfo); SOCK_LOCK(so); so->so_state &= ~SS_ISCONNECTED; /* XXX */ SOCK_UNLOCK(so); INP_WUNLOCK(inp); return (0); } static int udp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, struct mbuf *control, struct thread *td) { struct inpcb *inp; struct inpcbinfo *pcbinfo; int error = 0; pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_send: inp == NULL")); INP_WLOCK(inp); if (addr) { if (addr->sa_len != sizeof(struct sockaddr_in6)) { error = EINVAL; goto bad; } if (addr->sa_family != AF_INET6) { error = EAFNOSUPPORT; goto bad; } } #ifdef INET if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { int hasv4addr; struct sockaddr_in6 *sin6 = NULL; if (addr == NULL) hasv4addr = (inp->inp_vflag & INP_IPV4); else { sin6 = (struct sockaddr_in6 *)addr; hasv4addr = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ? 1 : 0; } if (hasv4addr) { struct pr_usrreqs *pru; uint8_t nxt; nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? IPPROTO_UDP : IPPROTO_UDPLITE; /* * XXXRW: We release UDP-layer locks before calling * udp_send() in order to avoid recursion. However, * this does mean there is a short window where inp's * fields are unstable. Could this lead to a * potential race in which the factors causing us to * select the UDPv4 output routine are invalidated? */ INP_WUNLOCK(inp); if (sin6) in6_sin6_2_sin_in_sock(addr); pru = inetsw[ip_protox[nxt]].pr_usrreqs; /* addr will just be freed in sendit(). */ return ((*pru->pru_send)(so, flags, m, addr, control, td)); } } #endif #ifdef MAC mac_inpcb_create_mbuf(inp, m); #endif INP_HASH_WLOCK(pcbinfo); error = udp6_output(inp, m, addr, control, td); INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); return (error); bad: INP_WUNLOCK(inp); m_freem(m); return (error); } struct pr_usrreqs udp6_usrreqs = { .pru_abort = udp6_abort, .pru_attach = udp6_attach, .pru_bind = udp6_bind, .pru_connect = udp6_connect, .pru_control = in6_control, .pru_detach = udp6_detach, .pru_disconnect = udp6_disconnect, .pru_peeraddr = in6_mapped_peeraddr, .pru_send = udp6_send, .pru_shutdown = udp_shutdown, .pru_sockaddr = in6_mapped_sockaddr, .pru_soreceive = soreceive_dgram, .pru_sosend = sosend_dgram, .pru_sosetlabel = in_pcbsosetlabel, .pru_close = udp6_close };