Query on appllying a complex diff/patch

sossego

Retired from the forums
The patch refers to three different files in the source.
Here is the file:
Code:
Index: lib/libc/net/getaddrinfo.c
===================================================================
--- lib/libc/net/getaddrinfo.c	(revision 248811)
+++ lib/libc/net/getaddrinfo.c	(working copy)
@@ -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 },
 };
@@ -1476,6 +1478,9 @@ get_port(struct addrinfo *ai, const char *servname
 		case IPPROTO_SCTP:
 			proto = "sctp";
 			break;
+		case IPPROTO_UDPLITE:
+			proto = "udplite";
+			break;
 		default:
 			proto = NULL;
 			break;
Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c	(revision 248811)
+++ sys/netinet/in.c	(working copy)
@@ -1205,6 +1205,7 @@ in_ifdetach(struct ifnet *ifp)
 
 	in_pcbpurgeif0(&V_ripcbinfo, ifp);
 	in_pcbpurgeif0(&V_udbinfo, ifp);
+	in_pcbpurgeif0(&V_ulitecbinfo, ifp);
 	in_purgemaddrs(ifp);
 }
 
Index: sys/netinet/in.h
===================================================================
--- sys/netinet/in.h	(revision 248811)
+++ sys/netinet/in.h	(working copy)
@@ -237,6 +237,7 @@ __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		/* UDPLite */
 /* 101-254: Partly Unassigned */
 #define	IPPROTO_PIM		103		/* Protocol Independent Mcast */
 #define	IPPROTO_CARP		112		/* CARP */
Index: sys/netinet/in_pcb.c
===================================================================
--- sys/netinet/in_pcb.c	(revision 248811)
+++ sys/netinet/in_pcb.c	(working copy)
@@ -390,13 +390,14 @@ in_pcb_lport(struct inpcb *inp, struct in_addr *la
 		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;
@@ -406,8 +407,8 @@ in_pcb_lport(struct inpcb *inp, struct in_addr *la
 	 */
 	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
Index: sys/netinet/in_proto.c
===================================================================
--- sys/netinet/in_proto.c	(revision 248811)
+++ sys/netinet/in_proto.c	(working copy)
@@ -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,
@@ -370,6 +384,7 @@ SYSCTL_NODE(_net_inet, IPPROTO_TCP,	tcp,	CTLFLAG_R
 #ifdef SCTP
 SYSCTL_NODE(_net_inet, IPPROTO_SCTP,	sctp,	CTLFLAG_RW, 0,	"SCTP");
 #endif
+SYSCTL_NODE(_net_inet, IPPROTO_UDPLITE,	udplite,CTLFLAG_RW, 0,	"UDPLite");
 SYSCTL_NODE(_net_inet, IPPROTO_IGMP,	igmp,	CTLFLAG_RW, 0,	"IGMP");
 #ifdef IPSEC
 /* XXX no protocol # to use, pick something "reserved" */
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c	(revision 248811)
+++ sys/netinet/udp_usrreq.c	(working copy)
@@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$");
 #endif
 #include <netinet/udp.h>
 #include <netinet/udp_var.h>
+#include <netinet/udplite.h>
 
 #ifdef IPSEC
 #include <netipsec/ipsec.h>
@@ -131,13 +132,18 @@ u_long	udp_recvspace = 40 * (1024 +
 #endif
 				      );
 
+
 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);
 static VNET_DEFINE(uma_zone_t, udpcb_zone);
-#define	V_udpcb_zone			VNET(udpcb_zone)
+static VNET_DEFINE(uma_zone_t, udplitecb_zone);
+#define	V_udpcb_zone		VNET(udpcb_zone)
+#define	V_udplitecb_zone	VNET(udplitecb_zone)
 
 #ifndef UDBHASHSIZE
 #define	UDBHASHSIZE	128
@@ -167,10 +173,16 @@ static void
 udp_zone_change(void *tag)
 {
 
-	uma_zone_set_max(V_udbinfo.ipi_zone, maxsockets);
-	uma_zone_set_max(V_udpcb_zone, maxsockets);
+	udp_common_zone_change(V_udbinfo, V_udpcb_zone);
 }
 
+static void
+udplite_zone_change(void *tag)
+{
+
+	udp_common_zone_change(V_ulitecbinfo, V_udplitecb_zone);
+}
+
 static int
 udp_inpcb_init(void *mem, int size, int flags)
 {
@@ -181,21 +193,34 @@ udp_inpcb_init(void *mem, int size, int flags)
 	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)
 {
-
-	in_pcbinfo_init(&V_udbinfo, "udp", &V_udb, UDBHASHSIZE, UDBHASHSIZE,
-	    "udp_inpcb", udp_inpcb_init, NULL, UMA_ZONE_NOFREE,
-	    IPI_HASHFIELDS_2TUPLE);
-	V_udpcb_zone = uma_zcreate("udpcb", sizeof(struct udpcb),
-	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
-	uma_zone_set_max(V_udpcb_zone, maxsockets);
-	uma_zone_set_warning(V_udpcb_zone, "kern.ipc.maxsockets limit reached");
+	udp_common_init(&V_udbinfo, "udp", &V_udb, "udp_inpcb", udp_inpcb_init,
+	    V_udpcb_zone, "udpcb");
 	EVENTHANDLER_REGISTER(maxsockets_change, udp_zone_change, NULL,
 	    EVENTHANDLER_PRI_ANY);
 }
 
+void
+udplite_init(void)
+{
+	udp_common_init(&V_ulitecbinfo, "udplite", &V_ulitecb, "udplite_inpcb",
+	    udplite_inpcb_init, V_udplitecb_zone, "udplitecb");
+	EVENTHANDLER_REGISTER(maxsockets_change, udplite_zone_change, NULL,
+	    EVENTHANDLER_PRI_ANY);
+}
+
 /*
  * Kernel module interface for updating udpstat.  The argument is an index
  * into udpstat treated as an array of u_long.  While this encodes the
@@ -215,7 +240,10 @@ udp_newudpcb(struct inpcb *inp)
 {
 	struct udpcb *up;
 
-	up = uma_zalloc(V_udpcb_zone, M_NOWAIT | M_ZERO);
+	if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP)
+		up = uma_zalloc(V_udpcb_zone, M_NOWAIT | M_ZERO);
+	else
+		up = uma_zalloc(V_udplitecb_zone, M_NOWAIT | M_ZERO);
 	if (up == NULL)
 		return (ENOBUFS);
 	inp->inp_ppcb = up;
@@ -223,10 +251,12 @@ udp_newudpcb(struct inpcb *inp)
 }
 
 void
-udp_discardcb(struct udpcb *up)
+udp_discardcb(struct udpcb *up, int isudp)
 {
-
-	uma_zfree(V_udpcb_zone, up);
+	if (isudp)
+		uma_zfree(V_udpcb_zone, up);
+	else
+		uma_zfree(V_udplitecb_zone, up);
 }
 
 #ifdef VIMAGE
@@ -234,9 +264,15 @@ void
 udp_destroy(void)
 {
 
-	in_pcbinfo_destroy(&V_udbinfo);
-	uma_zdestroy(V_udpcb_zone);
+	udp_common_destroy(&V_udbinfo, V_udpcb_zone);
 }
+
+void
+udplite_destroy(void)
+{
+
+	udp_common_destroy(&V_ulitecbinfo, V_udplitecb_zone);
+}
 #endif
 
 #ifdef INET
@@ -339,10 +375,13 @@ udp_input(struct mbuf *m, int off)
 	struct udphdr *uh;
 	struct ifnet *ifp;
 	struct inpcb *inp;
+	struct inpcbinfo *pcbinfo;
 	uint16_t len, ip_len;
 	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);
@@ -362,14 +401,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.
 	 */
@@ -392,12 +432,19 @@ 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);
 	}
 
 	/*
@@ -415,20 +462,24 @@ 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;
+			if (pr == IPPROTO_UDP)
+				((struct ipovly *)ip)->ih_len = uh->uh_ulen;
+			else
+				((struct ipovly *)ip)->ih_len = htons(ip_len);
 			uh_sum = in_cksum(m, len + sizeof (struct ip));
 			bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
 		}
@@ -440,14 +491,18 @@ udp_input(struct mbuf *m, int off)
 	} else
 		UDPSTAT_INC(udps_nosum);
 
+	pcbinfo = (pr == IPPROTO_UDP) ? &V_udbinfo : &V_ulitecbinfo;
+
 	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 = (pr == IPPROTO_UDP) ? &V_udb : &V_ulitecb;
 		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
@@ -533,12 +588,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;
 	}
 
@@ -559,7 +614,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) {
 			/*
@@ -567,7 +622,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 |
@@ -577,7 +632,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) {
@@ -613,6 +668,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_append(inp, ip, m, iphlen, &udp_in);
 	INP_RUNLOCK(inp);
 	return;
@@ -644,9 +709,9 @@ udp_notify(struct inpcb *inp, int errno)
 	return (inp);
 }
 
-#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;
@@ -675,7 +740,7 @@ udp_notify(struct inpcb *inp, int errno)
 		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);
@@ -685,9 +750,23 @@ udp_notify(struct inpcb *inp, int errno)
 			INP_RUNLOCK(inp);
 		}
 	} else
-		in_pcbnotifyall(&V_udbinfo, faddr, inetctlerrmap[cmd],
+		in_pcbnotifyall(pcbinfo, faddr, inetctlerrmap[cmd],
 		    udp_notify);
+	return;
 }
+
+#ifdef INET
+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
@@ -843,16 +922,16 @@ SYSCTL_PROC(_net_inet_udp, OID_AUTO, getcred,
 int
 udp_ctloutput(struct socket *so, struct sockopt *sopt)
 {
-	int error = 0, optval;
+	int isudplite, error, optval;
 	struct inpcb *inp;
-#ifdef IPSEC_NAT_T
 	struct udpcb *up;
-#endif
 
+	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);
@@ -910,7 +989,33 @@ udp_ctloutput(struct socket *so, struct sockopt *s
 			}
 			INP_WUNLOCK(inp);
 			break;
+		case UDPLITE_SEND_CSCOV:
+		case UDPLITE_RECV_CSCOV:
+			if (!isudplite)
+				goto bad_setoptname;
+			INP_WUNLOCK(inp);
+			error = sooptcopyin(sopt, &optval, sizeof(optval),
+			    sizeof(optval));
+			if (error)
+				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) {
+				error = EINVAL;
+				INP_WUNLOCK(inp);
+				break;
+			}
+			if (sopt->sopt_name == UDPLITE_SEND_CSCOV)
+				up->u_txcslen = optval;
+			else
+				up->u_rxcslen = optval;
+			INP_WUNLOCK(inp);
+			break;
 		default:
+bad_setoptname:
 			INP_WUNLOCK(inp);
 			error = ENOPROTOOPT;
 			break;
@@ -927,7 +1032,21 @@ udp_ctloutput(struct socket *so, struct sockopt *s
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 #endif
+		case UDPLITE_SEND_CSCOV:
+		case UDPLITE_RECV_CSCOV:
+			if (!isudplite)
+				goto bad_getoptname;
+			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:
+bad_getoptname:
 			INP_WUNLOCK(inp);
 			error = ENOPROTOOPT;
 			break;
@@ -949,12 +1068,16 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 	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
@@ -1049,12 +1172,13 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 	 *
 	 * XXXRW: Check that hash locking update here is correct.
 	 */
+	pcbinfo = inp->inp_pcbinfo;
 	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) ||
@@ -1062,7 +1186,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 	    (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;
@@ -1075,7 +1199,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 	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)) {
@@ -1126,7 +1250,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 		    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);
@@ -1141,7 +1265,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 			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.
@@ -1188,15 +1312,35 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 	 * Fill in mbuf with extended UDP header and addresses and length put
 	 * into network format.
 	 */
+	pr = IPPROTO_UDP;
 	ui = mtod(m, struct udpiphdr *);
 	bzero(ui->ui_x1, sizeof(ui->ui_x1));	/* XXX still needed? */
-	ui->ui_pr = IPPROTO_UDP;
 	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 (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDPLITE) {
+		struct udpcb *up;
+		uint16_t plen;
+
+		pr = IPPROTO_UDPLITE;
+		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 UDPLite, checksum coverage length of zero means
+		 * the entire UDPLite packet is covered by the checksum.
+		 */
+		cscov_partial = (cscov == 0) ? 0 : 1;
+	}
+	ui->ui_pr = pr;
+
 	/*
 	 * Set the Don't Fragment bit in the IP header.
 	 */
@@ -1222,24 +1366,29 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 	/*
 	 * Set up checksum and output datagram.
 	 */
-	if (V_udp_cksum) {
+	ui->ui_sum = 0;
+	if (cscov_partial) {
 		if (inp->inp_flags & INP_ONESBCAST)
 			faddr.s_addr = INADDR_BROADCAST;
+		if ((ui->ui_sum = in_cksum(m, sizeof(struct ip) + cscov)) == 0)
+			ui->ui_sum = 0xffff;
+	} else if (V_udp_cksum || !cscov_partial) {
+		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);
 	error = ip_output(m, inp->inp_options, NULL, ipflags,
 	    inp->inp_moptions, inp);
 	if (unlock_udbinfo == UH_WLOCKED)
@@ -1250,10 +1399,10 @@ udp_output(struct inpcb *inp, struct mbuf *m, stru
 
 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);
@@ -1405,10 +1554,10 @@ udp_abort(struct socket *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(inp->inp_pcbinfo);
 		in_pcbdisconnect(inp);
 		inp->inp_laddr.s_addr = INADDR_ANY;
-		INP_HASH_WUNLOCK(&V_udbinfo);
+		INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 		soisdisconnected(so);
 	}
 	INP_WUNLOCK(inp);
@@ -1418,17 +1567,23 @@ static int
 udp_attach(struct socket *so, int proto, struct thread *td)
 {
 	struct inpcb *inp;
+        struct inpcbinfo *pcbinfo;
 	int error;
 
+	if (so->so_proto->pr_protocol == IPPROTO_UDP)
+		pcbinfo = &V_udbinfo;
+	else
+		pcbinfo = &V_ulitecbinfo;
+
 	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);
 	}
 
@@ -1440,13 +1595,14 @@ udp_attach(struct socket *so, int proto, struct th
 	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 */
 
@@ -1481,9 +1637,9 @@ udp_bind(struct socket *so, struct sockaddr *nam,
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_bind: inp == NULL"));
 	INP_WLOCK(inp);
-	INP_HASH_WLOCK(&V_udbinfo);
+	INP_HASH_WLOCK(inp->inp_pcbinfo);
 	error = in_pcbbind(inp, nam, td->td_ucred);
-	INP_HASH_WUNLOCK(&V_udbinfo);
+	INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 	INP_WUNLOCK(inp);
 	return (error);
 }
@@ -1497,10 +1653,10 @@ udp_close(struct socket *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(inp->inp_pcbinfo);
 		in_pcbdisconnect(inp);
 		inp->inp_laddr.s_addr = INADDR_ANY;
-		INP_HASH_WUNLOCK(&V_udbinfo);
+		INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 		soisdisconnected(so);
 	}
 	INP_WUNLOCK(inp);
@@ -1526,9 +1682,9 @@ udp_connect(struct socket *so, struct sockaddr *na
 		INP_WUNLOCK(inp);
 		return (error);
 	}
-	INP_HASH_WLOCK(&V_udbinfo);
+	INP_HASH_WLOCK(inp->inp_pcbinfo);
 	error = in_pcbconnect(inp, nam, td->td_ucred);
-	INP_HASH_WUNLOCK(&V_udbinfo);
+	INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 	if (error == 0)
 		soisconnected(so);
 	INP_WUNLOCK(inp);
@@ -1540,20 +1696,23 @@ udp_detach(struct socket *so)
 {
 	struct inpcb *inp;
 	struct udpcb *up;
+	int isudp;
 
+	isudp = (so->so_proto->pr_protocol == IPPROTO_UDP) ? 1 : 0;
+
 	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(inp->inp_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);
-	udp_discardcb(up);
+	INP_INFO_WUNLOCK(inp->inp_pcbinfo);
+	udp_discardcb(up, isudp);
 }
 
 static int
@@ -1568,10 +1727,10 @@ udp_disconnect(struct socket *so)
 		INP_WUNLOCK(inp);
 		return (ENOTCONN);
 	}
-	INP_HASH_WLOCK(&V_udbinfo);
+	INP_HASH_WLOCK(inp->inp_pcbinfo);
 	in_pcbdisconnect(inp);
 	inp->inp_laddr.s_addr = INADDR_ANY;
-	INP_HASH_WUNLOCK(&V_udbinfo);
+	INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 	SOCK_LOCK(so);
 	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
 	SOCK_UNLOCK(so);
@@ -1622,4 +1781,5 @@ struct pr_usrreqs udp_usrreqs = {
 	.pru_sosetlabel =	in_pcbsosetlabel,
 	.pru_close =		udp_close,
 };
+
 #endif /* INET */
Index: sys/netinet/udp_var.h
===================================================================
--- sys/netinet/udp_var.h	(revision 248811)
+++ sys/netinet/udp_var.h	(working copy)
@@ -62,10 +62,12 @@ typedef void(*udp_tun_func_t)(struct mbuf *, int o
 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)
-#define	sotoudpcb(so)	(intoudpcb(sotoinpcb(so)))
+#define	intoudpcb(ip)		((struct udpcb *)(ip)->inp_ppcb)
+#define	sotoudpcb(so)		(intoudpcb(sotoinpcb(so)))
 
 				/* IPsec: ESP in UDP tunneling: */
 #define	UF_ESPINUDP_NON_IKE	0x00000001	/* w/ non-IKE marker .. */
@@ -93,6 +95,33 @@ struct udpstat {
 	u_long	udps_filtermcast;	/* blocked by multicast filter */
 };
 
+/* 
+ * Protocol control blocks management functions.
+ */
+#define UDP_PCBINFO_INIT(pcbinfo, pcbname, listhead, inpcbzone_name,\
+	inpcbzone_init) { \
+	in_pcbinfo_init(pcbinfo, pcbname, listhead, UDBHASHSIZE, UDBHASHSIZE,\
+	    inpcbzone_name, inpcbzone_init, NULL, UMA_ZONE_NOFREE,\
+	    IPI_HASHFIELDS_2TUPLE); \
+}
+
+#define	UDP_PCBINFO_DESTROY(pcbinfo) { \
+	in_pcbinfo_destroy(pcbinfo); \
+}
+
+/*
+ * Zone allocation functions.
+ */
+#define	UDP_ZONE_INIT(zone, zone_name) { \
+	zone = uma_zcreate(zone_name, sizeof(struct udpcb), NULL, NULL, NULL,\
+	    NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); \
+	uma_zone_set_max(zone, maxsockets); \
+	uma_zone_set_warning(zone, "kern.ipc.maxsockets limit reached"); \
+}
+
+#define	UDP_ZONE_DESTROY(zone)	uma_zdestroy(zone)
+
+
 #ifdef _KERNEL
 /*
  * In-kernel consumers can use these accessor macros directly to update
@@ -134,8 +163,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;
@@ -147,20 +180,41 @@ 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 *);
+int		udp_newudpcb(struct inpcb *);
+void		udp_discardcb(struct udpcb *, int);
 
-void		 udp_ctlinput(int, struct sockaddr *, void *);
-int		 udp_ctloutput(struct socket *, struct sockopt *);
-void		 udp_init(void);
+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
 
-#endif
+#define	udp_common_init(pcbinfo, pcbname, listhead, inpcbzone_name,\
+	inpcbzone_init, zone, zone_name) { \
+	UDP_PCBINFO_INIT(pcbinfo, pcbname, listhead, inpcbzone_name,\
+	    inpcbzone_init); \
+	UDP_ZONE_INIT(zone, zone_name); \
+}
+
+#define	udp_common_destroy(pcbinfo, zone) { \
+	UDP_PCBINFO_DESTROY(pcbinfo); \
+	UDP_ZONE_DESTROY(zone); \
+}
+
+#define	udp_common_zone_change(_pcbinfo, _zone) { \
+        uma_zone_set_max((_pcbinfo).ipi_zone, maxsockets); \
+        uma_zone_set_max((_zone), maxsockets); \
+}
+#endif /* _KERNEL */
+
+#endif /* _NETINET_UDP_VAR_H_ */
Index: sys/netinet/udplite.h
===================================================================
--- sys/netinet/udplite.h	(revision 0)
+++ sys/netinet/udplite.h	(working copy)
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2013, 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_ */
Index: sys/netinet6/in6_ifattach.c
===================================================================
--- sys/netinet6/in6_ifattach.c	(revision 248811)
+++ sys/netinet6/in6_ifattach.c	(working copy)
@@ -837,6 +837,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);
Index: sys/netinet6/in6_proto.c
===================================================================
--- sys/netinet6/in6_proto.c	(revision 248811)
+++ sys/netinet6/in6_proto.c	(working copy)
@@ -218,6 +218,19 @@ struct ip6protosw inet6sw[] = {
 },
 #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,
@@ -453,6 +466,7 @@ SYSCTL_NODE(_net_inet6,	IPPROTO_TCP,	tcp6,	CTLFLAG
 #ifdef SCTP
 SYSCTL_NODE(_net_inet6,	IPPROTO_SCTP,	sctp6,	CTLFLAG_RW, 0,	"SCTP6");
 #endif
+SYSCTL_NODE(_net_inet6,	IPPROTO_UDPLITE,udplite6,CTLFLAG_RW, 0,	"UDPLITE6");
 #ifdef IPSEC
 SYSCTL_NODE(_net_inet6,	IPPROTO_ESP,	ipsec6,	CTLFLAG_RW, 0,	"IPSEC6");
 #endif /* IPSEC */
Index: sys/netinet6/udp6_usrreq.c
===================================================================
--- sys/netinet6/udp6_usrreq.c	(revision 248811)
+++ sys/netinet6/udp6_usrreq.c	(working copy)
@@ -106,6 +106,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>
@@ -178,11 +179,14 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 	struct ip6_hdr *ip6;
 	struct udphdr *uh;
 	struct inpcb *inp;
-	struct udpcb *up;
+	struct inpcbinfo *pcbinfo;
+	struct udpcb *up = NULL;
 	int off = *offp;
+	int cscov_partial;
 	int plen, ulen;
 	struct sockaddr_in6 fromsa;
 	struct m_tag *fwd_tag;
+	uint8_t nxt;
 	uint16_t uh_sum;
 
 	ifp = m->m_pkthdr.rcvif;
@@ -215,9 +219,19 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 	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;
+	}
+
 	if (plen != ulen) {
-		UDPSTAT_INC(udps_badlen);
-		goto badunlocked;
+		if (ulen > plen || ulen < sizeof(struct udphdr)) {
+			UDPSTAT_INC(udps_badlen);
+			goto badunlocked;
+		}
 	}
 
 	/*
@@ -228,15 +242,16 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 		goto badunlocked;
 	}
 
-	if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) {
+	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,
-			    IPPROTO_UDP, m->m_pkthdr.csum_data);
+			uh_sum = in6_cksum_pseudo(ip6, ulen, nxt,
+			    m->m_pkthdr.csum_data);
 		uh_sum ^= 0xffff;
 	} else
-		uh_sum = in6_cksum(m, IPPROTO_UDP, off, ulen);
+		uh_sum = in6_cksum(m, nxt, off, ulen);
 
 	if (uh_sum != 0) {
 		UDPSTAT_INC(udps_badsum);
@@ -249,11 +264,13 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 	init_sin6(&fromsa, m);
 	fromsa.sin6_port = uh->uh_sport;
 
+	pcbinfo = (nxt == IPPROTO_UDP) ? &V_udbinfo : &V_ulitecbinfo;
 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
 		struct inpcb *last;
+		struct inpcbhead *pcblist;
 		struct ip6_moptions *imo;
 
-		INP_INFO_RLOCK(&V_udbinfo);
+		INP_INFO_RLOCK(pcbinfo);
 		/*
 		 * In the event that laddr should be set to the link-local
 		 * address (this happens in RIPng), the multicast address
@@ -269,8 +286,9 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 		 * here.  We need udphdr for IPsec processing so we do that
 		 * later.
 		 */
+		pcblist = (nxt == IPPROTO_UDP) ? &V_udb : &V_ulitecb;
 		last = NULL;
-		LIST_FOREACH(inp, &V_udb, inp_list) {
+		LIST_FOREACH(inp, pcblist, inp_list) {
 			if ((inp->inp_vflag & INP_IPV6) == 0)
 				continue;
 			if (inp->inp_lport != uh->uh_dport)
@@ -375,7 +393,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 			goto badheadlocked;
 		}
 		INP_RLOCK(last);
-		INP_INFO_RUNLOCK(&V_udbinfo);
+		INP_INFO_RUNLOCK(pcbinfo);
 		up = intoudpcb(last);
 		if (up->u_tun_func == NULL) {
 			udp6_append(last, m, off, &fromsa);
@@ -405,8 +423,8 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 		 * Transparently forwarded. Pretend to be the destination.
 		 * Already got one like this?
 		 */
-		inp = in6_pcblookup_mbuf(&V_udbinfo,
-		    &ip6->ip6_src, uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
+		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) {
 			/*
@@ -414,7 +432,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 			 * Because we've rewritten the destination address,
 			 * any hardware-generated hash is ignored.
 			 */
-			inp = in6_pcblookup(&V_udbinfo, &ip6->ip6_src,
+			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 |
@@ -424,7 +442,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 		m_tag_delete(m, fwd_tag);
 		m->m_flags &= ~M_IP6_NEXTHOP;
 	} else
-		inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src,
+		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);
@@ -454,7 +472,14 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 		return (IPPROTO_DONE);
 	}
 	INP_RLOCK_ASSERT(inp);
-	up = intoudpcb(inp);
+	if (cscov_partial) {
+		up = intoudpcb(inp);
+		if (up->u_rxcslen > ulen) {
+			INP_RUNLOCK(inp);
+			m_freem(m);
+			return (IPPROTO_DONE);
+		}
+	}
 	if (up->u_tun_func == NULL) {
 		udp6_append(inp, m, off, &fromsa);
 	} else {
@@ -468,15 +493,16 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
 	return (IPPROTO_DONE);
 
 badheadlocked:
-	INP_INFO_RUNLOCK(&V_udbinfo);
+	INP_INFO_RUNLOCK(pcbinfo);
 badunlocked:
 	if (m)
 		m_freem(m);
 	return (IPPROTO_DONE);
 }
 
-void
-udp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
+static void
+udp6_common_ctlinput(int cmd, struct sockaddr *sa, void *d,
+    struct inpcbinfo *pcbinfo)
 {
 	struct udphdr uh;
 	struct ip6_hdr *ip6;
@@ -532,14 +558,26 @@ badunlocked:
 		bzero(&uh, sizeof(uh));
 		m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
 
-		(void) in6_pcbnotify(&V_udbinfo, sa, uh.uh_dport,
+		(void) in6_pcbnotify(pcbinfo, sa, uh.uh_dport,
 		    (struct sockaddr *)ip6cp->ip6c_src, uh.uh_sport, cmd,
 		    cmdarg, notify);
 	} else
-		(void) in6_pcbnotify(&V_udbinfo, sa, 0,
+		(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)
 {
@@ -597,9 +635,12 @@ udp6_output(struct inpcb *inp, struct mbuf *m, str
 	struct in6_addr *laddr, *faddr, in6a;
 	struct sockaddr_in6 *sin6 = NULL;
 	struct ifnet *oifp = 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;
@@ -756,13 +797,29 @@ udp6_output(struct inpcb *inp, struct mbuf *m, str
 	/*
 	 * Stuff checksum and output datagram.
 	 */
+	nxt = IPPROTO_UDP;
 	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 (plen <= 0xffff)
+	if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDPLITE) {
+		struct udpcb *up;
+
+		nxt = IPPROTO_UDPLITE;
+		up = intoudpcb(inp);
+		cscov = up->u_txcslen;
+		if (cscov >= plen)
+			cscov = 0;
+		udp6->uh_ulen = htons(cscov);
+
+		/* For UDPLite, 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) {
@@ -771,17 +828,22 @@ udp6_output(struct inpcb *inp, struct mbuf *m, str
 		ip6->ip6_flow	= inp->inp_flow & IPV6_FLOWINFO_MASK;
 		ip6->ip6_vfc	&= ~IPV6_VERSION_MASK;
 		ip6->ip6_vfc	|= IPV6_VERSION;
-#if 0				/* ip6_plen will be filled in ip6_output. */
-		ip6->ip6_plen	= htons((u_short)plen);
-#endif
-		ip6->ip6_nxt	= IPPROTO_UDP;
+		if (nxt == IPPROTO_UDPLITE)
+			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;
 
-		udp6->uh_sum = in6_cksum_pseudo(ip6, plen, IPPROTO_UDP, 0);
-		m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
-		m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+		if (cscov_partial) {
+			if ((udp6->uh_sum = in6_cksum(m, 0,
+			    sizeof(struct ip6_hdr), 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);
+		}
 
 		flags = 0;
 
@@ -826,10 +888,10 @@ udp6_abort(struct socket *so)
 
 	INP_WLOCK(inp);
 	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
-		INP_HASH_WLOCK(&V_udbinfo);
+		INP_HASH_WLOCK(inp->inp_pcbinfo);
 		in6_pcbdisconnect(inp);
 		inp->in6p_laddr = in6addr_any;
-		INP_HASH_WUNLOCK(&V_udbinfo);
+		INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 		soisdisconnected(so);
 	}
 	INP_WUNLOCK(inp);
@@ -839,8 +901,13 @@ static int
 udp6_attach(struct socket *so, int proto, struct thread *td)
 {
 	struct inpcb *inp;
+	struct inpcbinfo *pcbinfo;
 	int error;
 
+	if (so->so_proto->pr_protocol == IPPROTO_UDP)
+		pcbinfo = &V_udbinfo;
+	 else
+		pcbinfo = &V_ulitecbinfo;
 	inp = sotoinpcb(so);
 	KASSERT(inp == NULL, ("udp6_attach: inp != NULL"));
 
@@ -849,10 +916,10 @@ udp6_attach(struct socket *so, int proto, struct t
 		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);
 	}
 	inp = (struct inpcb *)so->so_pcb;
@@ -873,11 +940,11 @@ udp6_attach(struct socket *so, int proto, struct t
 	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);
 }
 
@@ -891,7 +958,7 @@ udp6_bind(struct socket *so, struct sockaddr *nam,
 	KASSERT(inp != NULL, ("udp6_bind: inp == NULL"));
 
 	INP_WLOCK(inp);
-	INP_HASH_WLOCK(&V_udbinfo);
+	INP_HASH_WLOCK(inp->inp_pcbinfo);
 	inp->inp_vflag &= ~INP_IPV4;
 	inp->inp_vflag |= INP_IPV6;
 	if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
@@ -919,7 +986,7 @@ udp6_bind(struct socket *so, struct sockaddr *nam,
 #ifdef INET
 out:
 #endif
-	INP_HASH_WUNLOCK(&V_udbinfo);
+	INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 	INP_WUNLOCK(inp);
 	return (error);
 }
@@ -943,10 +1010,10 @@ udp6_close(struct socket *so)
 #endif
 	INP_WLOCK(inp);
 	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
-		INP_HASH_WLOCK(&V_udbinfo);
+		INP_HASH_WLOCK(inp->inp_pcbinfo);
 		in6_pcbdisconnect(inp);
 		inp->in6p_laddr = in6addr_any;
-		INP_HASH_WUNLOCK(&V_udbinfo);
+		INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 		soisdisconnected(so);
 	}
 	INP_WUNLOCK(inp);
@@ -985,10 +1052,10 @@ udp6_connect(struct socket *so, struct sockaddr *n
 		error = prison_remote_ip4(td->td_ucred, &sin.sin_addr);
 		if (error != 0)
 			goto out;
-		INP_HASH_WLOCK(&V_udbinfo);
+		INP_HASH_WLOCK(inp->inp_pcbinfo);
 		error = in_pcbconnect(inp, (struct sockaddr *)&sin,
 		    td->td_ucred);
-		INP_HASH_WUNLOCK(&V_udbinfo);
+		INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 		if (error == 0)
 			soisconnected(so);
 		goto out;
@@ -1003,9 +1070,9 @@ udp6_connect(struct socket *so, struct sockaddr *n
 	error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr);
 	if (error != 0)
 		goto out;
-	INP_HASH_WLOCK(&V_udbinfo);
+	INP_HASH_WLOCK(inp->inp_pcbinfo);
 	error = in6_pcbconnect(inp, nam, td->td_ucred);
-	INP_HASH_WUNLOCK(&V_udbinfo);
+	INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 	if (error == 0)
 		soisconnected(so);
 out:
@@ -1018,18 +1085,21 @@ udp6_detach(struct socket *so)
 {
 	struct inpcb *inp;
 	struct udpcb *up;
+	int isudp;
 
+	isudp = (so->so_proto->pr_protocol == IPPROTO_UDP) ? 1 : 0;
+
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp6_detach: inp == NULL"));
 
-	INP_INFO_WLOCK(&V_udbinfo);
+	INP_INFO_WLOCK(inp->inp_pcbinfo);
 	INP_WLOCK(inp);
 	up = intoudpcb(inp);
 	KASSERT(up != NULL, ("%s: up == NULL", __func__));
 	in_pcbdetach(inp);
 	in_pcbfree(inp);
-	INP_INFO_WUNLOCK(&V_udbinfo);
-	udp_discardcb(up);
+	INP_INFO_WUNLOCK(inp->inp_pcbinfo);
+	udp_discardcb(up, isudp);
 }
 
 static int
@@ -1058,10 +1128,10 @@ udp6_disconnect(struct socket *so)
 		goto out;
 	}
 
-	INP_HASH_WLOCK(&V_udbinfo);
+	INP_HASH_WLOCK(inp->inp_pcbinfo);
 	in6_pcbdisconnect(inp);
 	inp->in6p_laddr = in6addr_any;
-	INP_HASH_WUNLOCK(&V_udbinfo);
+	INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 	SOCK_LOCK(so);
 	so->so_state &= ~SS_ISCONNECTED;		/* XXX */
 	SOCK_UNLOCK(so);
@@ -1128,9 +1198,9 @@ udp6_send(struct socket *so, int flags, struct mbu
 #ifdef MAC
 	mac_inpcb_create_mbuf(inp, m);
 #endif
-	INP_HASH_WLOCK(&V_udbinfo);
+	INP_HASH_WLOCK(inp->inp_pcbinfo);
 	error = udp6_output(inp, m, addr, control, td);
-	INP_HASH_WUNLOCK(&V_udbinfo);
+	INP_HASH_WUNLOCK(inp->inp_pcbinfo);
 #ifdef INET
 #endif	
 	INP_WUNLOCK(inp);
Index: sys/netinet6/udp6_var.h
===================================================================
--- sys/netinet6/udp6_var.h	(revision 248811)
+++ sys/netinet6/udp6_var.h	(working copy)
@@ -69,6 +69,7 @@ SYSCTL_DECL(_net_inet6_udp6);
 extern struct pr_usrreqs	udp6_usrreqs;
 
 void	udp6_ctlinput(int, struct sockaddr *, void *);
+void	udplite6_ctlinput(int, struct sockaddr *, void *);
 int	udp6_input(struct mbuf **, int *, int);
 #endif
Is this just a cut and snip from the lines?
 
A patch for three files is just three single-file patches combined. The file to be patched is identified by the Index: line (preferentially) or the --- and +++ lines.

The last question is not clear, but lines with a - are removed and lines with a + are added.
 
The file would be patched from /usr/src since the full directory listing is missing, I assume.
troll_root@/usr/src #patch -p $DA_BIZNESS right?
 
I also believe that cutting at each reference of Index* and then applying the patch within that subdirectory would be better.
 
sossego said:
The file would be patched from /usr/src since the full directory listing is missing, I assume.

Yes.

troll_root@/usr/src #patch -p $DA_BIZNESS right?

-p is only needed if the patch file has a different path to the files. It may be only habit, but mostly patch is used with redirected input:
patch < patchfile

Any more, I generally use svn diff and svn patch. If your /usr/src is a Subversion checkout, the second of those will work.
 
I am a bit impatient and there is no verbose option to watch the patching. I would rather do that or the original cut into three parts.
Sorry, @wblock, but, I am also afraid of screwing up. This method makes it easier for me. So, would the idea work despite the semi complexity?
 
Last edited by a moderator:
The patching process is taking longer than expected. I've used CTRL+C a few times and restarted the process. So, what am I doing wrong?
 
Back
Top