svn commit: r265946 - in stable/10: lib/libc/net sys/netinet sys/netinet6 sys/sys

Bjoern A. Zeeb bz at FreeBSD.org
Sat Aug 16 13:18:14 UTC 2014


On 13 May 2014, at 06:05 , Kevin Lo <kevlo at FreeBSD.org> wrote:

> Author: kevlo
> Date: Tue May 13 06:05:53 2014
> New Revision: 265946
> URL: http://svnweb.freebsd.org/changeset/base/265946
> 
> Log:
>  MFC r264212,r264213,r264248,r265776,r265811,r265909:

Just for the records;  this commit also merged unrelated r259887:

 Add more (IPv6) related Internet Protocols:
 - Host Identity Protocol (RFC5201)
 - Shim6 Protocol (RFC5533)
 - 2x experimentation and testing (RFC3692, RFC4727)

 This does not indicate interest to implement/support these protocols,
 but they are part of the "IPv6 Extension Header Types" [1] based on RFC7045
 and might thus be needed by filtering and next header parsing
 implementations.

 References:	[1] http://www.iana.org/assignments/ipv6-parameters
 Obtained from:	http://www.iana.org/assignments/protocol-numbers

> 
>  - Add support for UDP-Lite protocol (RFC 3828) to IPv4 and IPv6 stacks.
>    Tested with vlc and a test suite [1].
>    [1] http://www.erg.abdn.ac.uk/~gerrit/udp-lite/files/udplite_linux.tar.gz
> 
>    Reviewed by:	jhb, glebius, adrian
> 
>  - Fix a logic bug which prevented the sending of UDP packet with 0 checksum.
> 
>  - Disable TX checksum offload for UDP-Lite completely. It wasn't used for
>    partial checksum coverage, but even for full checksum coverage it doesn't
>    work.
> 
> Added:
>  stable/10/sys/netinet/udplite.h
>     - copied unchanged from r264212, head/sys/netinet/udplite.h
> Modified:
>  stable/10/lib/libc/net/getaddrinfo.c
>  stable/10/sys/netinet/in.c
>  stable/10/sys/netinet/in.h
>  stable/10/sys/netinet/in_pcb.c
>  stable/10/sys/netinet/in_proto.c
>  stable/10/sys/netinet/udp_usrreq.c
>  stable/10/sys/netinet/udp_var.h
>  stable/10/sys/netinet6/in6_ifattach.c
>  stable/10/sys/netinet6/in6_proto.c
>  stable/10/sys/netinet6/udp6_usrreq.c
>  stable/10/sys/netinet6/udp6_var.h
>  stable/10/sys/sys/param.h
> Directory Properties:
>  stable/10/   (props changed)
> 
> Modified: stable/10/lib/libc/net/getaddrinfo.c
> ==============================================================================
> --- stable/10/lib/libc/net/getaddrinfo.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/lib/libc/net/getaddrinfo.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -170,12 +170,14 @@ static const struct explore explore[] = 
> 	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, 0x07 },
> 	{ PF_INET6, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
> 	{ PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
> +	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDPLITE, 0x03 },
> 	{ PF_INET6, SOCK_RAW, ANY, 0x05 },
> #endif
> 	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0x07 },
> 	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, 0x07 },
> 	{ PF_INET, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
> 	{ PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
> +	{ PF_INET, SOCK_DGRAM, IPPROTO_UDPLITE, 0x03 },
> 	{ PF_INET, SOCK_RAW, ANY, 0x05 },
> 	{ -1, 0, 0, 0 },
> };
> @@ -1477,6 +1479,9 @@ get_port(struct addrinfo *ai, const char
> 		case IPPROTO_SCTP:
> 			proto = "sctp";
> 			break;
> +		case IPPROTO_UDPLITE:
> +			proto = "udplite";
> +			break;
> 		default:
> 			proto = NULL;
> 			break;
> 
> Modified: stable/10/sys/netinet/in.c
> ==============================================================================
> --- stable/10/sys/netinet/in.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet/in.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -1167,6 +1167,7 @@ in_ifdetach(struct ifnet *ifp)
> 
> 	in_pcbpurgeif0(&V_ripcbinfo, ifp);
> 	in_pcbpurgeif0(&V_udbinfo, ifp);
> +	in_pcbpurgeif0(&V_ulitecbinfo, ifp);
> 	in_purgemaddrs(ifp);
> }
> 
> 
> Modified: stable/10/sys/netinet/in.h
> ==============================================================================
> --- stable/10/sys/netinet/in.h	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet/in.h	Tue May 13 06:05:53 2014	(r265946)
> @@ -237,12 +237,17 @@ __END_DECLS
> #define	IPPROTO_IPCOMP		108		/* payload compression (IPComp) */
> #define	IPPROTO_SCTP		132		/* SCTP */
> #define	IPPROTO_MH		135		/* IPv6 Mobility Header */
> +#define	IPPROTO_UDPLITE		136		/* UDP-Lite */
> +#define	IPPROTO_HIP		139		/* IP6 Host Identity Protocol */
> +#define	IPPROTO_SHIM6		140		/* IP6 Shim6 Protocol */
> /* 101-254: Partly Unassigned */
> #define	IPPROTO_PIM		103		/* Protocol Independent Mcast */
> #define	IPPROTO_CARP		112		/* CARP */
> #define	IPPROTO_PGM		113		/* PGM */
> #define	IPPROTO_MPLS		137		/* MPLS-in-IP */
> #define	IPPROTO_PFSYNC		240		/* PFSYNC */
> +#define	IPPROTO_RESERVED_253	253		/* Reserved */
> +#define	IPPROTO_RESERVED_254	254		/* Reserved */
> /* 255: Reserved */
> /* BSD Private, local use, namespace incursion, no longer used */
> #define	IPPROTO_OLD_DIVERT	254		/* OLD divert pseudo-proto */
> 
> Modified: stable/10/sys/netinet/in_pcb.c
> ==============================================================================
> --- stable/10/sys/netinet/in_pcb.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet/in_pcb.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -386,13 +386,14 @@ in_pcb_lport(struct inpcb *inp, struct i
> 		lastport = &pcbinfo->ipi_lastport;
> 	}
> 	/*
> -	 * For UDP, use random port allocation as long as the user
> +	 * For UDP(-Lite), use random port allocation as long as the user
> 	 * allows it.  For TCP (and as of yet unknown) connections,
> 	 * use random port allocation only if the user allows it AND
> 	 * ipport_tick() allows it.
> 	 */
> 	if (V_ipport_randomized &&
> -		(!V_ipport_stoprandom || pcbinfo == &V_udbinfo))
> +		(!V_ipport_stoprandom || pcbinfo == &V_udbinfo ||
> +		pcbinfo == &V_ulitecbinfo))
> 		dorandom = 1;
> 	else
> 		dorandom = 0;
> @@ -402,8 +403,8 @@ in_pcb_lport(struct inpcb *inp, struct i
> 	 */
> 	if (first == last)
> 		dorandom = 0;
> -	/* Make sure to not include UDP packets in the count. */
> -	if (pcbinfo != &V_udbinfo)
> +	/* Make sure to not include UDP(-Lite) packets in the count. */
> +	if (pcbinfo != &V_udbinfo || pcbinfo != &V_ulitecbinfo)
> 		V_ipport_tcpallocs++;
> 	/*
> 	 * Instead of having two loops further down counting up or down
> 
> Modified: stable/10/sys/netinet/in_proto.c
> ==============================================================================
> --- stable/10/sys/netinet/in_proto.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet/in_proto.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -184,6 +184,20 @@ struct protosw inetsw[] = {
> },
> #endif /* SCTP */
> {
> +	.pr_type =		SOCK_DGRAM,
> +	.pr_domain =		&inetdomain,
> +	.pr_protocol =		IPPROTO_UDPLITE,
> +	.pr_flags =		PR_ATOMIC|PR_ADDR,
> +	.pr_input =		udp_input,
> +	.pr_ctlinput =		udplite_ctlinput,
> +	.pr_ctloutput =		udp_ctloutput,
> +	.pr_init =		udplite_init,
> +#ifdef VIMAGE
> +	.pr_destroy =		udplite_destroy,
> +#endif
> +	.pr_usrreqs =		&udp_usrreqs
> +},
> +{
> 	.pr_type =		SOCK_RAW,
> 	.pr_domain =		&inetdomain,
> 	.pr_protocol =		IPPROTO_RAW,
> 
> Modified: stable/10/sys/netinet/udp_usrreq.c
> ==============================================================================
> --- stable/10/sys/netinet/udp_usrreq.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet/udp_usrreq.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -3,6 +3,7 @@
>  *	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
> @@ -87,6 +88,7 @@ __FBSDID("$FreeBSD$");
> #endif
> #include <netinet/udp.h>
> #include <netinet/udp_var.h>
> +#include <netinet/udplite.h>
> 
> #ifdef IPSEC
> #include <netipsec/ipsec.h>
> @@ -98,8 +100,9 @@ __FBSDID("$FreeBSD$");
> #include <security/mac/mac_framework.h>
> 
> /*
> - * UDP protocol implementation.
> + * UDP and UDP-Lite protocols implementation.
>  * Per RFC 768, August, 1980.
> + * Per RFC 3828, July, 2004.
>  */
> 
> /*
> @@ -139,6 +142,8 @@ SYSCTL_ULONG(_net_inet_udp, UDPCTL_RECVS
> 
> VNET_DEFINE(struct inpcbhead, udb);		/* from udp_var.h */
> VNET_DEFINE(struct inpcbinfo, udbinfo);
> +VNET_DEFINE(struct inpcbhead, ulitecb);
> +VNET_DEFINE(struct inpcbinfo, ulitecbinfo);
> static VNET_DEFINE(uma_zone_t, udpcb_zone);
> #define	V_udpcb_zone			VNET(udpcb_zone)
> 
> @@ -187,6 +192,16 @@ udp_inpcb_init(void *mem, int size, int 
> 	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)
> {
> @@ -202,6 +217,15 @@ udp_init(void)
> 	    EVENTHANDLER_PRI_ANY);
> }
> 
> +void
> +udplite_init(void)
> +{
> +
> +	in_pcbinfo_init(&V_ulitecbinfo, "udplite", &V_ulitecb, UDBHASHSIZE,
> +	    UDBHASHSIZE, "udplite_inpcb", udplite_inpcb_init, NULL,
> +	    UMA_ZONE_NOFREE, 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
> @@ -243,6 +267,13 @@ udp_destroy(void)
> 	in_pcbinfo_destroy(&V_udbinfo);
> 	uma_zdestroy(V_udpcb_zone);
> }
> +
> +void
> +udplite_destroy(void)
> +{
> +
> +	in_pcbinfo_destroy(&V_ulitecbinfo);
> +}
> #endif
> 
> #ifdef INET
> @@ -346,9 +377,12 @@ udp_input(struct mbuf *m, int off)
> 	struct ifnet *ifp;
> 	struct inpcb *inp;
> 	uint16_t len, ip_len;
> +	struct inpcbinfo *pcbinfo;
> 	struct ip save_ip;
> 	struct sockaddr_in udp_in;
> 	struct m_tag *fwd_tag;
> +	int cscov_partial;
> +	uint8_t pr;
> 
> 	ifp = m->m_pkthdr.rcvif;
> 	UDPSTAT_INC(udps_ipackets);
> @@ -368,13 +402,15 @@ udp_input(struct mbuf *m, int off)
> 	 */
> 	ip = mtod(m, struct ip *);
> 	if (m->m_len < iphlen + sizeof(struct udphdr)) {
> -		if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
> +		if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == NULL) {
> 			UDPSTAT_INC(udps_hdrops);
> 			return;
> 		}
> 		ip = mtod(m, struct ip *);
> 	}
> 	uh = (struct udphdr *)((caddr_t)ip + iphlen);
> +	pr = ip->ip_p;
> +	cscov_partial = (pr == IPPROTO_UDPLITE) ? 1 : 0;
> 
> 	/*
> 	 * Destination port of 0 is illegal, based on RFC768.
> @@ -398,12 +434,18 @@ udp_input(struct mbuf *m, int off)
> 	 */
> 	len = ntohs((u_short)uh->uh_ulen);
> 	ip_len = ntohs(ip->ip_len) - iphlen;
> +	if (pr == IPPROTO_UDPLITE && len == 0) {
> +		/* Zero means checksum over the complete packet. */
> +		len = ip_len;
> +		cscov_partial = 0;
> +	}
> 	if (ip_len != len) {
> 		if (len > ip_len || len < sizeof(struct udphdr)) {
> 			UDPSTAT_INC(udps_badlen);
> 			goto badunlocked;
> 		}
> -		m_adj(m, len - ip_len);
> +		if (pr == IPPROTO_UDP)
> +			m_adj(m, len - ip_len);
> 	}
> 
> 	/*
> @@ -421,20 +463,22 @@ udp_input(struct mbuf *m, int off)
> 	if (uh->uh_sum) {
> 		u_short uh_sum;
> 
> -		if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
> +		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 + IPPROTO_UDP));
> +				    m->m_pkthdr.csum_data + pr));
> 			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 = uh->uh_ulen;
> +			((struct ipovly *)ip)->ih_len = (pr == 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);
> 		}
> @@ -446,14 +490,17 @@ udp_input(struct mbuf *m, int off)
> 	} else
> 		UDPSTAT_INC(udps_nosum);
> 
> +	pcbinfo = get_inpcbinfo(pr);
> 	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(&V_udbinfo);
> +		INP_INFO_RLOCK(pcbinfo);
> +		pcblist = get_pcblist(pr);
> 		last = NULL;
> -		LIST_FOREACH(inp, &V_udb, inp_list) {
> +		LIST_FOREACH(inp, pcblist, inp_list) {
> 			if (inp->inp_lport != uh->uh_dport)
> 				continue;
> #ifdef INET6
> @@ -539,12 +586,12 @@ udp_input(struct mbuf *m, int off)
> 			UDPSTAT_INC(udps_noportbcast);
> 			if (inp)
> 				INP_RUNLOCK(inp);
> -			INP_INFO_RUNLOCK(&V_udbinfo);
> +			INP_INFO_RUNLOCK(pcbinfo);
> 			goto badunlocked;
> 		}
> 		udp_append(last, ip, m, iphlen, &udp_in);
> 		INP_RUNLOCK(last);
> -		INP_INFO_RUNLOCK(&V_udbinfo);
> +		INP_INFO_RUNLOCK(pcbinfo);
> 		return;
> 	}
> 
> @@ -565,7 +612,7 @@ udp_input(struct mbuf *m, int off)
> 		 * Transparently forwarded. Pretend to be the destination.
> 		 * Already got one like this?
> 		 */
> -		inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
> +		inp = in_pcblookup_mbuf(pcbinfo, ip->ip_src, uh->uh_sport,
> 		    ip->ip_dst, uh->uh_dport, INPLOOKUP_RLOCKPCB, ifp, m);
> 		if (!inp) {
> 			/*
> @@ -573,7 +620,7 @@ udp_input(struct mbuf *m, int off)
> 			 * Because we've rewritten the destination address,
> 			 * any hardware-generated hash is ignored.
> 			 */
> -			inp = in_pcblookup(&V_udbinfo, ip->ip_src,
> +			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 |
> @@ -583,7 +630,7 @@ udp_input(struct mbuf *m, int off)
> 		m_tag_delete(m, fwd_tag);
> 		m->m_flags &= ~M_IP_NEXTHOP;
> 	} else
> -		inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
> +		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) {
> @@ -619,6 +666,16 @@ udp_input(struct mbuf *m, int off)
> 		m_freem(m);
> 		return;
> 	}
> +	if (cscov_partial) {
> +		struct udpcb *up;
> +
> +		up = intoudpcb(inp);
> +		if (up->u_rxcslen > len) {
> +			INP_RUNLOCK(inp);
> +			m_freem(m);
> +			return;
> +		}
> +	}
> 
> 	UDP_PROBE(receive, NULL, inp, ip, inp, uh);
> 	udp_append(inp, ip, m, iphlen, &udp_in);
> @@ -653,8 +710,9 @@ udp_notify(struct inpcb *inp, int errno)
> }
> 
> #ifdef INET
> -void
> -udp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
> +static void
> +udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip,
> +    struct inpcbinfo *pcbinfo)
> {
> 	struct ip *ip = vip;
> 	struct udphdr *uh;
> @@ -683,7 +741,7 @@ udp_ctlinput(int cmd, struct sockaddr *s
> 		return;
> 	if (ip != NULL) {
> 		uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
> -		inp = in_pcblookup(&V_udbinfo, faddr, uh->uh_dport,
> +		inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport,
> 		    ip->ip_src, uh->uh_sport, INPLOOKUP_RLOCKPCB, NULL);
> 		if (inp != NULL) {
> 			INP_RLOCK_ASSERT(inp);
> @@ -693,9 +751,22 @@ udp_ctlinput(int cmd, struct sockaddr *s
> 			INP_RUNLOCK(inp);
> 		}
> 	} else
> -		in_pcbnotifyall(&V_udbinfo, faddr, inetctlerrmap[cmd],
> +		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
> @@ -851,16 +922,16 @@ SYSCTL_PROC(_net_inet_udp, OID_AUTO, get
> int
> udp_ctloutput(struct socket *so, struct sockopt *sopt)
> {
> -	int error = 0, optval;
> 	struct inpcb *inp;
> -#ifdef IPSEC_NAT_T
> 	struct udpcb *up;
> -#endif
> +	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 != IPPROTO_UDP) {
> +	if (sopt->sopt_level != so->so_proto->pr_protocol) {
> #ifdef INET6
> 		if (INP_CHECK_SOCKAF(so, AF_INET6)) {
> 			INP_WUNLOCK(inp);
> @@ -918,6 +989,34 @@ udp_ctloutput(struct socket *so, struct 
> 			}
> 			INP_WUNLOCK(inp);
> 			break;
> +		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) {
> +				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;
> @@ -935,6 +1034,22 @@ udp_ctloutput(struct socket *so, struct 
> 			error = sooptcopyout(sopt, &optval, sizeof optval);
> 			break;
> #endif
> +		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;
> @@ -957,12 +1072,16 @@ udp_output(struct inpcb *inp, struct mbu
> 	int len = m->m_pkthdr.len;
> 	struct in_addr faddr, laddr;
> 	struct cmsghdr *cm;
> +	struct inpcbinfo *pcbinfo;
> 	struct sockaddr_in *sin, src;
> +	int cscov_partial = 0;
> 	int error = 0;
> 	int ipflags;
> 	u_short fport, lport;
> 	int unlock_udbinfo;
> 	u_char tos;
> +	uint8_t pr;
> +	uint16_t cscov = 0;
> 
> 	/*
> 	 * udp_output() may need to temporarily bind or connect the current
> @@ -1057,12 +1176,14 @@ udp_output(struct inpcb *inp, struct mbu
> 	 *
> 	 * XXXRW: Check that hash locking update here is correct.
> 	 */
> +	pr = inp->inp_socket->so_proto->pr_protocol;
> +	pcbinfo = get_inpcbinfo(pr);
> 	sin = (struct sockaddr_in *)addr;
> 	if (sin != NULL &&
> 	    (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) {
> 		INP_RUNLOCK(inp);
> 		INP_WLOCK(inp);
> -		INP_HASH_WLOCK(&V_udbinfo);
> +		INP_HASH_WLOCK(pcbinfo);
> 		unlock_udbinfo = UH_WLOCKED;
> 	} else if ((sin != NULL && (
> 	    (sin->sin_addr.s_addr == INADDR_ANY) ||
> @@ -1070,7 +1191,7 @@ udp_output(struct inpcb *inp, struct mbu
> 	    (inp->inp_laddr.s_addr == INADDR_ANY) ||
> 	    (inp->inp_lport == 0))) ||
> 	    (src.sin_family == AF_INET)) {
> -		INP_HASH_RLOCK(&V_udbinfo);
> +		INP_HASH_RLOCK(pcbinfo);
> 		unlock_udbinfo = UH_RLOCKED;
> 	} else
> 		unlock_udbinfo = UH_UNLOCKED;
> @@ -1083,7 +1204,7 @@ udp_output(struct inpcb *inp, struct mbu
> 	laddr = inp->inp_laddr;
> 	lport = inp->inp_lport;
> 	if (src.sin_family == AF_INET) {
> -		INP_HASH_LOCK_ASSERT(&V_udbinfo);
> +		INP_HASH_LOCK_ASSERT(pcbinfo);
> 		if ((lport == 0) ||
> 		    (laddr.s_addr == INADDR_ANY &&
> 		     src.sin_addr.s_addr == INADDR_ANY)) {
> @@ -1134,7 +1255,7 @@ udp_output(struct inpcb *inp, struct mbu
> 		    inp->inp_lport == 0 ||
> 		    sin->sin_addr.s_addr == INADDR_ANY ||
> 		    sin->sin_addr.s_addr == INADDR_BROADCAST) {
> -			INP_HASH_LOCK_ASSERT(&V_udbinfo);
> +			INP_HASH_LOCK_ASSERT(pcbinfo);
> 			error = in_pcbconnect_setup(inp, addr, &laddr.s_addr,
> 			    &lport, &faddr.s_addr, &fport, NULL,
> 			    td->td_ucred);
> @@ -1149,7 +1270,7 @@ udp_output(struct inpcb *inp, struct mbu
> 			if (inp->inp_laddr.s_addr == INADDR_ANY &&
> 			    inp->inp_lport == 0) {
> 				INP_WLOCK_ASSERT(inp);
> -				INP_HASH_WLOCK_ASSERT(&V_udbinfo);
> +				INP_HASH_WLOCK_ASSERT(pcbinfo);
> 				/*
> 				 * Remember addr if jailed, to prevent
> 				 * rebinding.
> @@ -1198,13 +1319,30 @@ udp_output(struct inpcb *inp, struct mbu
> 	 */
> 	ui = mtod(m, struct udpiphdr *);
> 	bzero(ui->ui_x1, sizeof(ui->ui_x1));	/* XXX still needed? */
> -	ui->ui_v = IPVERSION << 4;
> -	ui->ui_pr = IPPROTO_UDP;
> +	ui->ui_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;
> +	} else
> +		ui->ui_v = IPVERSION << 4;
> 
> 	/*
> 	 * Set the Don't Fragment bit in the IP header.
> @@ -1231,24 +1369,34 @@ udp_output(struct inpcb *inp, struct mbu
> 	/*
> 	 * Set up checksum and output datagram.
> 	 */
> -	if (V_udp_cksum) {
> +	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) + IPPROTO_UDP));
> +		    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);
> -	} else
> -		ui->ui_sum = 0;
> +	}
> 	((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);
> 
> 	if (unlock_udbinfo == UH_WLOCKED)
> -		INP_HASH_WUNLOCK(&V_udbinfo);
> +		INP_HASH_WUNLOCK(pcbinfo);
> 	else if (unlock_udbinfo == UH_RLOCKED)
> -		INP_HASH_RUNLOCK(&V_udbinfo);
> +		INP_HASH_RUNLOCK(pcbinfo);
> 	UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u);
> 	error = ip_output(m, inp->inp_options, NULL, ipflags,
> 	    inp->inp_moptions, inp);
> @@ -1260,10 +1408,10 @@ udp_output(struct inpcb *inp, struct mbu
> 
> release:
> 	if (unlock_udbinfo == UH_WLOCKED) {
> -		INP_HASH_WUNLOCK(&V_udbinfo);
> +		INP_HASH_WUNLOCK(pcbinfo);
> 		INP_WUNLOCK(inp);
> 	} else if (unlock_udbinfo == UH_RLOCKED) {
> -		INP_HASH_RUNLOCK(&V_udbinfo);
> +		INP_HASH_RUNLOCK(pcbinfo);
> 		INP_RUNLOCK(inp);
> 	} else
> 		INP_RUNLOCK(inp);
> @@ -1410,15 +1558,17 @@ static void
> udp_abort(struct socket *so)
> {
> 	struct inpcb *inp;
> +	struct inpcbinfo *pcbinfo;
> 
> +	pcbinfo = 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(&V_udbinfo);
> +		INP_HASH_WLOCK(pcbinfo);
> 		in_pcbdisconnect(inp);
> 		inp->inp_laddr.s_addr = INADDR_ANY;
> -		INP_HASH_WUNLOCK(&V_udbinfo);
> +		INP_HASH_WUNLOCK(pcbinfo);
> 		soisdisconnected(so);
> 	}
> 	INP_WUNLOCK(inp);
> @@ -1428,17 +1578,19 @@ static int
> udp_attach(struct socket *so, int proto, struct thread *td)
> {
> 	struct inpcb *inp;
> +	struct inpcbinfo *pcbinfo;
> 	int error;
> 
> +	pcbinfo = 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(&V_udbinfo);
> -	error = in_pcballoc(so, &V_udbinfo);
> +	INP_INFO_WLOCK(pcbinfo);
> +	error = in_pcballoc(so, pcbinfo);
> 	if (error) {
> -		INP_INFO_WUNLOCK(&V_udbinfo);
> +		INP_INFO_WUNLOCK(pcbinfo);
> 		return (error);
> 	}
> 
> @@ -1450,12 +1602,12 @@ udp_attach(struct socket *so, int proto,
> 	if (error) {
> 		in_pcbdetach(inp);
> 		in_pcbfree(inp);
> -		INP_INFO_WUNLOCK(&V_udbinfo);
> +		INP_INFO_WUNLOCK(pcbinfo);
> 		return (error);
> 	}
> 
> 	INP_WUNLOCK(inp);
> -	INP_INFO_WUNLOCK(&V_udbinfo);
> +	INP_INFO_WUNLOCK(pcbinfo);
> 	return (0);
> }
> #endif /* INET */
> @@ -1486,14 +1638,16 @@ static int
> udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
> {
> 	struct inpcb *inp;
> +	struct inpcbinfo *pcbinfo;
> 	int error;
> 
> +	pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
> 	inp = sotoinpcb(so);
> 	KASSERT(inp != NULL, ("udp_bind: inp == NULL"));
> 	INP_WLOCK(inp);
> -	INP_HASH_WLOCK(&V_udbinfo);
> +	INP_HASH_WLOCK(pcbinfo);
> 	error = in_pcbbind(inp, nam, td->td_ucred);
> -	INP_HASH_WUNLOCK(&V_udbinfo);
> +	INP_HASH_WUNLOCK(pcbinfo);
> 	INP_WUNLOCK(inp);
> 	return (error);
> }
> @@ -1502,15 +1656,17 @@ static void
> udp_close(struct socket *so)
> {
> 	struct inpcb *inp;
> +	struct inpcbinfo *pcbinfo;
> 
> +	pcbinfo = 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(&V_udbinfo);
> +		INP_HASH_WLOCK(pcbinfo);
> 		in_pcbdisconnect(inp);
> 		inp->inp_laddr.s_addr = INADDR_ANY;
> -		INP_HASH_WUNLOCK(&V_udbinfo);
> +		INP_HASH_WUNLOCK(pcbinfo);
> 		soisdisconnected(so);
> 	}
> 	INP_WUNLOCK(inp);
> @@ -1520,9 +1676,11 @@ static int
> udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
> {
> 	struct inpcb *inp;
> -	int error;
> +	struct inpcbinfo *pcbinfo;
> 	struct sockaddr_in *sin;
> +	int error;
> 
> +	pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
> 	inp = sotoinpcb(so);
> 	KASSERT(inp != NULL, ("udp_connect: inp == NULL"));
> 	INP_WLOCK(inp);
> @@ -1536,9 +1694,9 @@ udp_connect(struct socket *so, struct so
> 		INP_WUNLOCK(inp);
> 		return (error);
> 	}
> -	INP_HASH_WLOCK(&V_udbinfo);
> +	INP_HASH_WLOCK(pcbinfo);
> 	error = in_pcbconnect(inp, nam, td->td_ucred);
> -	INP_HASH_WUNLOCK(&V_udbinfo);
> +	INP_HASH_WUNLOCK(pcbinfo);
> 	if (error == 0)
> 		soisconnected(so);
> 	INP_WUNLOCK(inp);
> @@ -1549,20 +1707,22 @@ static void
> udp_detach(struct socket *so)
> {
> 	struct inpcb *inp;
> +	struct inpcbinfo *pcbinfo;
> 	struct udpcb *up;
> 
> +	pcbinfo = 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(&V_udbinfo);
> +	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(&V_udbinfo);
> +	INP_INFO_WUNLOCK(pcbinfo);
> 	udp_discardcb(up);
> }
> 
> @@ -1570,7 +1730,9 @@ static int
> udp_disconnect(struct socket *so)
> {
> 	struct inpcb *inp;
> +	struct inpcbinfo *pcbinfo;
> 
> +	pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
> 	inp = sotoinpcb(so);
> 	KASSERT(inp != NULL, ("udp_disconnect: inp == NULL"));
> 	INP_WLOCK(inp);
> @@ -1578,10 +1740,10 @@ udp_disconnect(struct socket *so)
> 		INP_WUNLOCK(inp);
> 		return (ENOTCONN);
> 	}
> -	INP_HASH_WLOCK(&V_udbinfo);
> +	INP_HASH_WLOCK(pcbinfo);
> 	in_pcbdisconnect(inp);
> 	inp->inp_laddr.s_addr = INADDR_ANY;
> -	INP_HASH_WUNLOCK(&V_udbinfo);
> +	INP_HASH_WUNLOCK(pcbinfo);
> 	SOCK_LOCK(so);
> 	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
> 	SOCK_UNLOCK(so);
> 
> Modified: stable/10/sys/netinet/udp_var.h
> ==============================================================================
> --- stable/10/sys/netinet/udp_var.h	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet/udp_var.h	Tue May 13 06:05:53 2014	(r265946)
> @@ -63,6 +63,8 @@ typedef void(*udp_tun_func_t)(struct mbu
> struct udpcb {
> 	udp_tun_func_t	u_tun_func;	/* UDP kernel tunneling callback. */
> 	u_int		u_flags;	/* Generic UDP flags. */
> +	uint16_t	u_rxcslen;	/* Coverage for incoming datagrams. */
> +	uint16_t	u_txcslen;	/* Coverage for outgoing datagrams. */
> };
> 
> #define	intoudpcb(ip)	((struct udpcb *)(ip)->inp_ppcb)
> @@ -130,8 +132,12 @@ SYSCTL_DECL(_net_inet_udp);
> extern struct pr_usrreqs	udp_usrreqs;
> VNET_DECLARE(struct inpcbhead, udb);
> VNET_DECLARE(struct inpcbinfo, udbinfo);
> +VNET_DECLARE(struct inpcbhead, ulitecb);
> +VNET_DECLARE(struct inpcbinfo, ulitecbinfo);
> #define	V_udb			VNET(udb)
> #define	V_udbinfo		VNET(udbinfo)
> +#define	V_ulitecb		VNET(ulitecb)
> +#define	V_ulitecbinfo		VNET(ulitecbinfo)
> 
> extern u_long			udp_sendspace;
> extern u_long			udp_recvspace;
> @@ -141,20 +147,37 @@ VNET_DECLARE(int, udp_blackhole);
> #define	V_udp_blackhole		VNET(udp_blackhole)
> extern int			udp_log_in_vain;
> 
> -int		 udp_newudpcb(struct inpcb *);
> -void		 udp_discardcb(struct udpcb *);
> -
> -void		 udp_ctlinput(int, struct sockaddr *, void *);
> -int		 udp_ctloutput(struct socket *, struct sockopt *);
> -void		 udp_init(void);
> +static __inline struct inpcbinfo *
> +get_inpcbinfo(uint8_t protocol)
> +{
> +	return (protocol == IPPROTO_UDP) ? &V_udbinfo : &V_ulitecbinfo;
> +}
> +
> +static __inline struct inpcbhead *
> +get_pcblist(uint8_t protocol)
> +{
> +	return (protocol == IPPROTO_UDP) ? &V_udb : &V_ulitecb;
> +}
> +
> +int		udp_newudpcb(struct inpcb *);
> +void		udp_discardcb(struct udpcb *);
> +
> +void		udp_ctlinput(int, struct sockaddr *, void *);
> +void		udplite_ctlinput(int, struct sockaddr *, void *);
> +int		udp_ctloutput(struct socket *, struct sockopt *);
> +void		udp_init(void);
> +void		udplite_init(void);
> #ifdef VIMAGE
> -void		 udp_destroy(void);
> +void		udp_destroy(void);
> +void		udplite_destroy(void);
> #endif
> -void		 udp_input(struct mbuf *, int);
> +void		udp_input(struct mbuf *, int);
> +void		udplite_input(struct mbuf *, int);
> struct inpcb	*udp_notify(struct inpcb *inp, int errno);
> -int		 udp_shutdown(struct socket *so);
> +int		udp_shutdown(struct socket *so);
> 
> -int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f);
> -#endif
> +int		udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f);
> 
> -#endif
> +#endif /* _KERNEL */
> +
> +#endif /* _NETINET_UDP_VAR_H_ */
> 
> Copied: stable/10/sys/netinet/udplite.h (from r264212, head/sys/netinet/udplite.h)
> ==============================================================================
> --- /dev/null	00:00:00 1970	(empty, because file is newly added)
> +++ stable/10/sys/netinet/udplite.h	Tue May 13 06:05:53 2014	(r265946, copy of r264212, head/sys/netinet/udplite.h)
> @@ -0,0 +1,38 @@
> +/*-
> + * 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_
> +
> +/* 
> + * 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_ */
> 
> Modified: stable/10/sys/netinet6/in6_ifattach.c
> ==============================================================================
> --- stable/10/sys/netinet6/in6_ifattach.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet6/in6_ifattach.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -856,6 +856,7 @@ in6_ifdetach(struct ifnet *ifp)
> 	}
> 
> 	in6_pcbpurgeif0(&V_udbinfo, ifp);
> +	in6_pcbpurgeif0(&V_ulitecbinfo, ifp);
> 	in6_pcbpurgeif0(&V_ripcbinfo, ifp);
> 	/* leave from all multicast groups joined */
> 	in6_purgemaddrs(ifp);
> 
> Modified: stable/10/sys/netinet6/in6_proto.c
> ==============================================================================
> --- stable/10/sys/netinet6/in6_proto.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet6/in6_proto.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -207,13 +207,26 @@ struct ip6protosw inet6sw[] = {
> 	.pr_protocol =		IPPROTO_SCTP,
> 	.pr_flags =		PR_WANTRCVD,
> 	.pr_input =		sctp6_input,
> -	.pr_ctlinput =	sctp6_ctlinput,
> +	.pr_ctlinput =		sctp6_ctlinput,
> 	.pr_ctloutput =		sctp_ctloutput,
> 	.pr_drain =		sctp_drain,
> 	.pr_usrreqs =		&sctp6_usrreqs
> },
> #endif /* SCTP */
> {
> +	.pr_type =		SOCK_DGRAM,
> +	.pr_domain =		&inet6domain,
> +	.pr_protocol =		IPPROTO_UDPLITE,
> +	.pr_flags =		PR_ATOMIC|PR_ADDR,
> +	.pr_input =		udp6_input,
> +	.pr_ctlinput =		udplite6_ctlinput,
> +	.pr_ctloutput =		udp_ctloutput,
> +#ifndef INET	/* Do not call initialization twice. */
> +	.pr_init =		udplite_init,
> +#endif
> +	.pr_usrreqs =		&udp6_usrreqs,
> +},
> +{
> 	.pr_type =		SOCK_RAW,
> 	.pr_domain =		&inet6domain,
> 	.pr_protocol =		IPPROTO_RAW,
> 
> Modified: stable/10/sys/netinet6/udp6_usrreq.c
> ==============================================================================
> --- stable/10/sys/netinet6/udp6_usrreq.c	Tue May 13 05:26:43 2014	(r265945)
> +++ stable/10/sys/netinet6/udp6_usrreq.c	Tue May 13 06:05:53 2014	(r265946)
> @@ -1,6 +1,7 @@
> /*-
>  * 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
> @@ -109,6 +110,7 @@ __FBSDID("$FreeBSD$");
> #include <netinet/ip_var.h>
> #include <netinet/udp.h>
> #include <netinet/udp_var.h>
> +#include <netinet/udplite.h>
> 
> #include <netinet6/ip6protosw.h>
> #include <netinet6/ip6_var.h>
> @@ -181,12 +183,15 @@ udp6_input(struct mbuf **mp, int *offp, 
> 	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 sockaddr_in6 fromsa;
> 	struct m_tag *fwd_tag;
> 	uint16_t uh_sum;
> +	uint8_t nxt;
> 
> 	ifp = m->m_pkthdr.rcvif;
> 	ip6 = mtod(m, struct ip6_hdr *);
> @@ -218,6 +223,13 @@ udp6_input(struct mbuf **mp, int *offp, 
> 	plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6);
> 	ulen = ntohs((u_short)uh->uh_ulen);
> 
> +	nxt = ip6->ip6_nxt;
> +	cscov_partial = (nxt == IPPROTO_UDPLITE) ? 1 : 0;
> +	if (nxt == IPPROTO_UDPLITE && ulen == 0) {
> +		/* Zero means checksum over the complete packet. */
> +		ulen = plen;
> +		cscov_partial = 0;
> +	}
> 
> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
> 

— 
Bjoern A. Zeeb             "Come on. Learn, goddamn it.", WarGames, 1983




More information about the svn-src-all mailing list