On 13 May 2014, at 06:05 , Kevin Lo <ke...@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


_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to