summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorkevlo <kevlo@FreeBSD.org>2014-05-13 06:05:53 +0000
committerkevlo <kevlo@FreeBSD.org>2014-05-13 06:05:53 +0000
commit69da76e9e5a9758fee9f8286827143e4608bb87a (patch)
tree9eae681ae0fb7e2b696040fefa6df9b3b66c7360 /sys/netinet6
parentab793415d02166fdd7cfea2301a03a903362e3f9 (diff)
downloadFreeBSD-src-69da76e9e5a9758fee9f8286827143e4608bb87a.zip
FreeBSD-src-69da76e9e5a9758fee9f8286827143e4608bb87a.tar.gz
MFC r264212,r264213,r264248,r265776,r265811,r265909:
- 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.
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6_ifattach.c1
-rw-r--r--sys/netinet6/in6_proto.c15
-rw-r--r--sys/netinet6/udp6_usrreq.c168
-rw-r--r--sys/netinet6/udp6_var.h1
4 files changed, 140 insertions, 45 deletions
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index a6134d1..5196101 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -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);
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index b0631ae..428121f 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -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,
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 7df0db7..faa6427 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -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, int proto)
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, 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;
@@ -227,19 +239,22 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
* Checksum extended UDP header and data.
*/
if (uh->uh_sum == 0) {
- UDPSTAT_INC(udps_nosum);
- goto badunlocked;
+ if (ulen > plen || ulen < sizeof(struct udphdr)) {
+ UDPSTAT_INC(udps_nosum);
+ 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);
@@ -252,11 +267,13 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
init_sin6(&fromsa, m);
fromsa.sin6_port = uh->uh_sport;
+ pcbinfo = get_inpcbinfo(nxt);
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
@@ -272,8 +289,9 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
* here. We need udphdr for IPsec processing so we do that
* later.
*/
+ pcblist = get_pcblist(nxt);
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)
@@ -378,7 +396,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);
UDP_PROBE(receive, NULL, last, ip6, last, uh);
if (up->u_tun_func == NULL) {
@@ -409,8 +427,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) {
/*
@@ -418,7 +436,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 |
@@ -428,7 +446,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);
@@ -459,6 +477,13 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
}
INP_RLOCK_ASSERT(inp);
up = intoudpcb(inp);
+ if (cscov_partial) {
+ if (up->u_rxcslen > ulen) {
+ INP_RUNLOCK(inp);
+ m_freem(m);
+ return (IPPROTO_DONE);
+ }
+ }
UDP_PROBE(receive, NULL, inp, ip6, inp, uh);
if (up->u_tun_func == NULL) {
udp6_append(inp, m, off, &fromsa);
@@ -473,15 +498,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;
@@ -537,14 +563,28 @@ udp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
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)
{
@@ -602,9 +642,12 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
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;
@@ -761,10 +804,25 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
/*
* Stuff checksum and output datagram.
*/
+ nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ?
+ IPPROTO_UDP : IPPROTO_UDPLITE;
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 (nxt == IPPROTO_UDPLITE) {
+ struct udpcb *up;
+
+ up = intoudpcb(inp);
+ cscov = up->u_txcslen;
+ if (cscov >= plen)
+ cscov = 0;
+ udp6->uh_ulen = htons(cscov);
+ /*
+ * For UDP-Lite, checksum coverage length of zero means
+ * the entire UDPLite packet is covered by the checksum.
+ */
+ cscov_partial = (cscov == 0) ? 0 : 1;
+ } else if (plen <= 0xffff)
udp6->uh_ulen = htons((u_short)plen);
else
udp6->uh_ulen = 0;
@@ -777,14 +835,20 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
ip6->ip6_plen = htons((u_short)plen);
- ip6->ip6_nxt = IPPROTO_UDP;
+ 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;
@@ -814,7 +878,9 @@ static void
udp6_abort(struct socket *so)
{
struct inpcb *inp;
+ struct inpcbinfo *pcbinfo;
+ pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_abort: inp == NULL"));
@@ -830,10 +896,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(pcbinfo);
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
- INP_HASH_WUNLOCK(&V_udbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
soisdisconnected(so);
}
INP_WUNLOCK(inp);
@@ -843,8 +909,10 @@ static int
udp6_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, ("udp6_attach: inp != NULL"));
@@ -853,10 +921,10 @@ udp6_attach(struct socket *so, int proto, struct thread *td)
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;
@@ -877,11 +945,11 @@ udp6_attach(struct socket *so, int proto, struct thread *td)
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);
}
@@ -889,13 +957,15 @@ static int
udp6_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, ("udp6_bind: inp == NULL"));
INP_WLOCK(inp);
- INP_HASH_WLOCK(&V_udbinfo);
+ INP_HASH_WLOCK(pcbinfo);
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
@@ -923,7 +993,7 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
#ifdef INET
out:
#endif
- INP_HASH_WUNLOCK(&V_udbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
INP_WUNLOCK(inp);
return (error);
}
@@ -932,7 +1002,9 @@ static void
udp6_close(struct socket *so)
{
struct inpcb *inp;
+ struct inpcbinfo *pcbinfo;
+ pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_close: inp == NULL"));
@@ -947,10 +1019,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(pcbinfo);
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
- INP_HASH_WUNLOCK(&V_udbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
soisdisconnected(so);
}
INP_WUNLOCK(inp);
@@ -960,9 +1032,11 @@ static int
udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
struct inpcb *inp;
+ struct inpcbinfo *pcbinfo;
struct sockaddr_in6 *sin6;
int error;
+ pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
inp = sotoinpcb(so);
sin6 = (struct sockaddr_in6 *)nam;
KASSERT(inp != NULL, ("udp6_connect: inp == NULL"));
@@ -989,10 +1063,10 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
error = prison_remote_ip4(td->td_ucred, &sin.sin_addr);
if (error != 0)
goto out;
- INP_HASH_WLOCK(&V_udbinfo);
+ INP_HASH_WLOCK(pcbinfo);
error = in_pcbconnect(inp, (struct sockaddr *)&sin,
td->td_ucred);
- INP_HASH_WUNLOCK(&V_udbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
if (error == 0)
soisconnected(so);
goto out;
@@ -1007,9 +1081,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr);
if (error != 0)
goto out;
- INP_HASH_WLOCK(&V_udbinfo);
+ INP_HASH_WLOCK(pcbinfo);
error = in6_pcbconnect(inp, nam, td->td_ucred);
- INP_HASH_WUNLOCK(&V_udbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
if (error == 0)
soisconnected(so);
out:
@@ -1021,18 +1095,20 @@ static void
udp6_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, ("udp6_detach: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
+ INP_INFO_WLOCK(pcbinfo);
INP_WLOCK(inp);
up = intoudpcb(inp);
KASSERT(up != NULL, ("%s: up == NULL", __func__));
in_pcbdetach(inp);
in_pcbfree(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
+ INP_INFO_WUNLOCK(pcbinfo);
udp_discardcb(up);
}
@@ -1040,8 +1116,10 @@ static int
udp6_disconnect(struct socket *so)
{
struct inpcb *inp;
+ struct inpcbinfo *pcbinfo;
int error;
+ pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL"));
@@ -1062,10 +1140,10 @@ udp6_disconnect(struct socket *so)
goto out;
}
- INP_HASH_WLOCK(&V_udbinfo);
+ INP_HASH_WLOCK(pcbinfo);
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
- INP_HASH_WUNLOCK(&V_udbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTED; /* XXX */
SOCK_UNLOCK(so);
@@ -1079,8 +1157,10 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
struct sockaddr *addr, struct mbuf *control, struct thread *td)
{
struct inpcb *inp;
+ struct inpcbinfo *pcbinfo;
int error = 0;
+ pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_send: inp == NULL"));
@@ -1132,9 +1212,9 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
#ifdef MAC
mac_inpcb_create_mbuf(inp, m);
#endif
- INP_HASH_WLOCK(&V_udbinfo);
+ INP_HASH_WLOCK(pcbinfo);
error = udp6_output(inp, m, addr, control, td);
- INP_HASH_WUNLOCK(&V_udbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
#ifdef INET
#endif
INP_WUNLOCK(inp);
diff --git a/sys/netinet6/udp6_var.h b/sys/netinet6/udp6_var.h
index ae53c5a..cdab98b 100644
--- a/sys/netinet6/udp6_var.h
+++ b/sys/netinet6/udp6_var.h
@@ -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
OpenPOWER on IntegriCloud