summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoritojun <itojun@openbsd.org>2002-06-07 21:47:44 +0000
committeritojun <itojun@openbsd.org>2002-06-07 21:47:44 +0000
commitf5bfbd04b056528d09e9d1629c1c25897adfa054 (patch)
treec52bdff416387dfb43654c26037d803ec26c2d9d
parentin pf_route{6}, do not pass thru pf_test again if the outgoing (diff)
downloadwireguard-openbsd-f5bfbd04b056528d09e9d1629c1c25897adfa054.tar.xz
wireguard-openbsd-f5bfbd04b056528d09e9d1629c1c25897adfa054.zip
move IPV6_CHECKSUM processing to ip6_raw_ctloutput(). bunch of KNFs.
rip6 stats. sync w/kame
-rw-r--r--sys/netinet6/in6_proto.c4
-rw-r--r--sys/netinet6/ip6_output.c106
-rw-r--r--sys/netinet6/ip6_var.h3
-rw-r--r--sys/netinet6/raw_ip6.c99
-rw-r--r--sys/netinet6/raw_ip6.h54
5 files changed, 196 insertions, 70 deletions
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index 78fdd828cd6..ce8714aa930 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_proto.c,v 1.35 2002/06/07 15:27:58 itojun Exp $ */
+/* $OpenBSD: in6_proto.c,v 1.36 2002/06/07 21:47:44 itojun Exp $ */
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
/*
@@ -142,7 +142,7 @@ struct ip6protosw inet6sw[] = {
0, 0, 0, 0,
},
{ SOCK_RAW, &inet6domain, IPPROTO_ICMPV6, PR_ATOMIC|PR_ADDR,
- icmp6_input, rip6_output, 0, rip6_ctloutput,
+ icmp6_input, rip6_output, rip6_ctlinput, rip6_ctloutput,
rip6_usrreq,
icmp6_init, icmp6_fasttimo, 0, 0,
icmp6_sysctl,
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index d91106adde3..23510d0f23d 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_output.c,v 1.64 2002/06/07 15:27:58 itojun Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.65 2002/06/07 21:47:44 itojun Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@@ -1232,7 +1232,6 @@ ip6_ctloutput(op, so, level, optname, mp)
case IPV6_PKTINFO:
case IPV6_HOPLIMIT:
case IPV6_RTHDR:
- case IPV6_CHECKSUM:
case IPV6_FAITH:
case IPV6_V6ONLY:
if (optlen != sizeof(int)) {
@@ -1289,10 +1288,6 @@ do { \
OPTSET(IN6P_RTHDR);
break;
- case IPV6_CHECKSUM:
- inp->in6p_cksum = optval;
- break;
-
case IPV6_FAITH:
OPTSET(IN6P_FAITH);
break;
@@ -1461,7 +1456,6 @@ do { \
case IPV6_PKTINFO:
case IPV6_HOPLIMIT:
case IPV6_RTHDR:
- case IPV6_CHECKSUM:
case IPV6_FAITH:
case IPV6_V6ONLY:
case IPV6_PORTRANGE:
@@ -1505,10 +1499,6 @@ do { \
optval = OPTBIT(IN6P_RTHDR);
break;
- case IPV6_CHECKSUM:
- optval = inp->in6p_cksum;
- break;
-
case IPV6_FAITH:
optval = OPTBIT(IN6P_FAITH);
break;
@@ -1610,6 +1600,82 @@ do { \
return(error);
}
+int
+ip6_raw_ctloutput(op, so, level, optname, mp)
+ int op;
+ struct socket *so;
+ int level, optname;
+ struct mbuf **mp;
+{
+ int error = 0, optval, optlen;
+ const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
+ struct inpcb *inp = sotoinpcb(so);
+ struct mbuf *m = *mp;
+
+ optlen = m ? m->m_len : 0;
+
+ if (level != IPPROTO_IPV6) {
+ if (op == PRCO_SETOPT && *mp)
+ (void)m_free(*mp);
+ return(EINVAL);
+ }
+
+ switch (optname) {
+ case IPV6_CHECKSUM:
+ /*
+ * For ICMPv6 sockets, no modification allowed for checksum
+ * offset, permit "no change" values to help existing apps.
+ *
+ * XXX 2292bis says: "An attempt to set IPV6_CHECKSUM
+ * for an ICMPv6 socket will fail."
+ * The current behavior does not meet 2292bis.
+ */
+ switch (op) {
+ case PRCO_SETOPT:
+ if (optlen != sizeof(int)) {
+ error = EINVAL;
+ break;
+ }
+ optval = *mtod(m, int *);
+ if ((optval % 2) != 0) {
+ /* the API assumes even offset values */
+ error = EINVAL;
+ } else if (so->so_proto->pr_protocol ==
+ IPPROTO_ICMPV6) {
+ if (optval != icmp6off)
+ error = EINVAL;
+ } else
+ inp->in6p_cksum = optval;
+ break;
+
+ case PRCO_GETOPT:
+ if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
+ optval = icmp6off;
+ else
+ optval = inp->in6p_cksum;
+
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(int);
+ *mtod(m, int *) = optval;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ break;
+
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+
+ if (op == PRCO_SETOPT && m)
+ (void)m_free(m);
+
+ return(error);
+}
+
/*
* Set up IP6 options in pcb for insertion in output packets.
* Store in mbuf with pointer in pcbopt, adding pseudo-option
@@ -2253,27 +2319,23 @@ ip6_splithdr(m, exthdrs)
/*
* Compute IPv6 extension header length.
*/
-# define in6pcb inpcb
-# define in6p_outputopts inp_outputopts6
int
-ip6_optlen(in6p)
- struct in6pcb *in6p;
+ip6_optlen(inp)
+ struct inpcb *inp;
{
int len;
- if (!in6p->in6p_outputopts)
+ if (!inp->inp_outputopts6)
return 0;
len = 0;
#define elen(x) \
(((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
- len += elen(in6p->in6p_outputopts->ip6po_hbh);
- len += elen(in6p->in6p_outputopts->ip6po_dest1);
- len += elen(in6p->in6p_outputopts->ip6po_rthdr);
- len += elen(in6p->in6p_outputopts->ip6po_dest2);
+ len += elen(inp->inp_outputopts6->ip6po_hbh);
+ len += elen(inp->inp_outputopts6->ip6po_dest1);
+ len += elen(inp->inp_outputopts6->ip6po_rthdr);
+ len += elen(inp->inp_outputopts6->ip6po_dest2);
return len;
#undef elen
}
-# undef in6pcb
-# undef in6p_outputopts
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 22592543b0c..55753fa0aa4 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_var.h,v 1.17 2002/06/07 15:27:58 itojun Exp $ */
+/* $OpenBSD: ip6_var.h,v 1.18 2002/06/07 21:47:44 itojun Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
@@ -259,6 +259,7 @@ int ip6_output(struct mbuf *, struct ip6_pktopts *,
struct route_in6 *, int,
struct ip6_moptions *, struct ifnet **);
int ip6_ctloutput(int, struct socket *, int, int, struct mbuf **);
+int ip6_raw_ctloutput(int, struct socket *, int, int, struct mbuf **);
int ip6_setpktoptions(struct mbuf *, struct ip6_pktopts *, int);
int ip6_optlen(struct inpcb *);
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 933c0d25cab..6a0516d7270 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip6.c,v 1.10 2002/03/19 01:39:04 itojun Exp $ */
+/* $OpenBSD: raw_ip6.c,v 1.11 2002/06/07 21:47:44 itojun Exp $ */
/* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */
/*
@@ -92,6 +92,7 @@
#ifdef ENABLE_DEFAULT_SCOPE
#include <netinet6/scope6_var.h>
#endif
+#include <netinet6/raw_ip6.h>
#include <machine/stdarg.h>
@@ -124,6 +125,8 @@
struct inpcbtable rawin6pcbtable;
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
+struct rip6stat rip6stat;
+
/*
* Initialize raw connection block queue.
*/
@@ -151,6 +154,8 @@ rip6_input(mp, offp, proto)
struct sockaddr_in6 rip6src;
struct mbuf *opts = NULL;
+ rip6stat.rip6s_ipackets++;
+
#if defined(NFAITH) && 0 < NFAITH
if (m->m_pkthdr.rcvif) {
if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
@@ -188,16 +193,18 @@ rip6_input(mp, offp, proto)
in6p->in6p_ip6.ip6_nxt != proto)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
- !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
+ !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
- !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
- continue;
- if (in6p->in6p_cksum != -1
- && in6_cksum(m, ip6->ip6_nxt, *offp, m->m_pkthdr.len - *offp))
- {
- /* XXX bark something */
+ !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
continue;
+ if (in6p->in6p_cksum != -1) {
+ rip6stat.rip6s_isum++;
+ if (in6_cksum(m, ip6->ip6_nxt, *offp,
+ m->m_pkthdr.len - *offp)) {
+ rip6stat.rip6s_badsum++;
+ continue;
+ }
}
if (last) {
struct mbuf *n;
@@ -207,12 +214,12 @@ rip6_input(mp, offp, proto)
/* strip intermediate headers */
m_adj(n, *offp);
if (sbappendaddr(&last->in6p_socket->so_rcv,
- (struct sockaddr *)&rip6src,
- n, opts) == 0) {
+ (struct sockaddr *)&rip6src, n, opts) == 0) {
/* should notify about lost packet */
m_freem(n);
if (opts)
m_freem(opts);
+ rip6stat.rip6s_fullsock++;
} else
sorwakeup(last->in6p_socket);
opts = NULL;
@@ -226,21 +233,25 @@ rip6_input(mp, offp, proto)
/* strip intermediate headers */
m_adj(m, *offp);
if (sbappendaddr(&last->in6p_socket->so_rcv,
- (struct sockaddr *)&rip6src, m, opts) == 0) {
+ (struct sockaddr *)&rip6src, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
+ rip6stat.rip6s_fullsock++;
} else
sorwakeup(last->in6p_socket);
} else {
+ rip6stat.rip6s_nosock++;
+ if (m->m_flags & M_MCAST)
+ rip6stat.rip6s_nosockmcast++;
if (proto == IPPROTO_NONE)
m_freem(m);
else {
char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_protounknown);
icmp6_error(m, ICMP6_PARAM_PROB,
- ICMP6_PARAMPROB_NEXTHEADER,
- prvnxtp - mtod(m, char *));
+ ICMP6_PARAMPROB_NEXTHEADER,
+ prvnxtp - mtod(m, char *));
}
ip6stat.ip6s_delivered--;
}
@@ -331,7 +342,7 @@ rip6_ctlinput(cmd, sa, d)
/*
* Depending on the value of "valid" and routing table
* size (mtudisc_{hi,lo}wat), we will:
- * - recalcurate the new MTU and create the
+ * - recalculate the new MTU and create the
* corresponding routing entry, or
* - ignore the MTU change notification.
*/
@@ -431,10 +442,8 @@ rip6_output(struct mbuf *m, ...)
struct in6_addr *in6a;
if ((in6a = in6_selectsrc(dstsock, optp,
- in6p->in6p_moptions,
- &in6p->in6p_route,
- &in6p->in6p_laddr,
- &error)) == 0) {
+ in6p->in6p_moptions, &in6p->in6p_route,
+ &in6p->in6p_laddr, &error)) == 0) {
if (error == 0)
error = EADDRNOTAVAIL;
goto bad;
@@ -489,7 +498,8 @@ rip6_output(struct mbuf *m, ...)
if (oifp)
icmp6_ifoutstat_inc(oifp, type, code);
icmp6stat.icp6s_outhist[type]++;
- }
+ } else
+ rip6stat.rip6s_opackets++;
goto freectl;
@@ -509,11 +519,11 @@ rip6_output(struct mbuf *m, ...)
* Raw IPv6 socket option processing.
*/
int
-rip6_ctloutput(op, so, level, optname, m)
+rip6_ctloutput(op, so, level, optname, mp)
int op;
struct socket *so;
int level, optname;
- struct mbuf **m;
+ struct mbuf **mp;
{
int error = 0;
@@ -528,29 +538,31 @@ rip6_ctloutput(op, so, level, optname, m)
case MRT6_DEL_MFC:
case MRT6_PIM:
if (op == PRCO_SETOPT) {
- error = ip6_mrouter_set(optname, so, *m);
- if (*m)
- (void)m_free(*m);
- } else if (op == PRCO_GETOPT) {
- error = ip6_mrouter_get(optname, so, m);
- } else
+ error = ip6_mrouter_set(optname, so, *mp);
+ if (*mp)
+ (void)m_free(*mp);
+ } else if (op == PRCO_GETOPT)
+ error = ip6_mrouter_get(optname, so, mp);
+ else
error = EINVAL;
return (error);
+ case IPV6_CHECKSUM:
+ return (ip6_raw_ctloutput(op, so, level, optname, mp));
+ default:
+ return (ip6_ctloutput(op, so, level, optname, mp));
}
- return (ip6_ctloutput(op, so, level, optname, m));
- /* NOTREACHED */
case IPPROTO_ICMPV6:
/*
* XXX: is it better to call icmp6_ctloutput() directly
* from protosw?
*/
- return(icmp6_ctloutput(op, so, level, optname, m));
+ return (icmp6_ctloutput(op, so, level, optname, mp));
default:
- if (op == PRCO_SETOPT && *m)
- (void)m_free(*m);
- return(EINVAL);
+ if (op == PRCO_SETOPT && *mp)
+ m_free(*mp);
+ return EINVAL;
}
}
@@ -576,7 +588,7 @@ rip6_usrreq(so, req, m, nam, control, p)
if (req == PRU_CONTROL)
return (in6_control(so, (u_long)m, (caddr_t)nam,
- (struct ifnet *)control, p));
+ (struct ifnet *)control, p));
switch (req) {
case PRU_ATTACH:
@@ -602,7 +614,7 @@ rip6_usrreq(so, req, m, nam, control, p)
in6p->in6p_cksum = -1;
MALLOC(in6p->in6p_icmp6filt, struct icmp6_filter *,
- sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
+ sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
if (in6p->in6p_icmp6filt == NULL) {
in6_pcbdetach(in6p);
error = ENOMEM;
@@ -652,7 +664,7 @@ rip6_usrreq(so, req, m, nam, control, p)
#ifdef ENABLE_DEFAULT_SCOPE
if (addr->sin6_scope_id == 0) /* not change if specified */
addr->sin6_scope_id =
- scope6_addr2default(&addr->sin6_addr);
+ scope6_addr2default(&addr->sin6_addr);
#endif
/*
* we don't support mapped address here, it would confuse
@@ -674,8 +686,7 @@ rip6_usrreq(so, req, m, nam, control, p)
error = EADDRNOTAVAIL;
break;
}
- if (ia &&
- ((struct in6_ifaddr *)ia)->ia6_flags &
+ if (ia && ((struct in6_ifaddr *)ia)->ia6_flags &
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
error = EADDRNOTAVAIL;
@@ -713,16 +724,14 @@ rip6_usrreq(so, req, m, nam, control, p)
sin6 = *addr;
addr = &sin6;
addr->sin6_scope_id =
- scope6_addr2default(&addr->sin6_addr);
+ scope6_addr2default(&addr->sin6_addr);
}
#endif
/* Source address selection. XXX: need pcblookup? */
in6a = in6_selectsrc(addr, in6p->in6p_outputopts,
- in6p->in6p_moptions,
- &in6p->in6p_route,
- &in6p->in6p_laddr,
- &error);
+ in6p->in6p_moptions, &in6p->in6p_route,
+ &in6p->in6p_laddr, &error);
if (in6a == NULL) {
if (error == 0)
error = EADDRNOTAVAIL;
@@ -764,7 +773,7 @@ rip6_usrreq(so, req, m, nam, control, p)
tmp.sin6_family = AF_INET6;
tmp.sin6_len = sizeof(struct sockaddr_in6);
bcopy(&in6p->in6p_faddr, &tmp.sin6_addr,
- sizeof(struct in6_addr));
+ sizeof(struct in6_addr));
dst = &tmp;
} else {
if (nam == NULL) {
@@ -787,7 +796,7 @@ rip6_usrreq(so, req, m, nam, control, p)
#ifdef ENABLE_DEFAULT_SCOPE
if (dst->sin6_scope_id == 0) {
dst->sin6_scope_id =
- scope6_addr2default(&dst->sin6_addr);
+ scope6_addr2default(&dst->sin6_addr);
}
#endif
error = rip6_output(m, so, dst, control);
diff --git a/sys/netinet6/raw_ip6.h b/sys/netinet6/raw_ip6.h
new file mode 100644
index 00000000000..c3d2556f640
--- /dev/null
+++ b/sys/netinet6/raw_ip6.h
@@ -0,0 +1,54 @@
+/* $OpenBSD: raw_ip6.h,v 1.1 2002/06/07 21:47:44 itojun Exp $ */
+/* $KAME: raw_ip6.h,v 1.2 2001/05/27 13:28:35 itojun Exp $ */
+
+/*
+ * Copyright (C) 2001 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NETINET6_RAW_IP6_H_
+#define _NETINET6_RAW_IP6_H_
+
+/*
+ * ICMPv6 stat is counted separately. see netinet/icmp6.h
+ */
+struct rip6stat {
+ u_quad_t rip6s_ipackets; /* total input packets */
+ u_quad_t rip6s_isum; /* input checksum computations */
+ u_quad_t rip6s_badsum; /* of above, checksum error */
+ u_quad_t rip6s_nosock; /* no matching socket */
+ u_quad_t rip6s_nosockmcast; /* of above, arrived as multicast */
+ u_quad_t rip6s_fullsock; /* not delivered, input socket full */
+
+ u_quad_t rip6s_opackets; /* total output packets */
+};
+
+#ifdef _KERNEL
+extern struct rip6stat rip6stat;
+#endif
+
+#endif