diff options
author | 2002-06-07 21:47:44 +0000 | |
---|---|---|
committer | 2002-06-07 21:47:44 +0000 | |
commit | f5bfbd04b056528d09e9d1629c1c25897adfa054 (patch) | |
tree | c52bdff416387dfb43654c26037d803ec26c2d9d | |
parent | in pf_route{6}, do not pass thru pf_test again if the outgoing (diff) | |
download | wireguard-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.c | 4 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 106 | ||||
-rw-r--r-- | sys/netinet6/ip6_var.h | 3 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 99 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.h | 54 |
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 |