sync IPV6_CHECKSUM handling with kame.
This commit is contained in:
parent
f8af64685c
commit
a1e0f0f9a7
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_output.c,v 1.52 2002/06/07 17:13:56 itojun Exp $ */
|
||||
/* $NetBSD: ip6_output.c,v 1.53 2002/06/07 22:03:02 itojun Exp $ */
|
||||
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -66,7 +66,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.52 2002/06/07 17:13:56 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.53 2002/06/07 22:03:02 itojun Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -1550,6 +1550,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 in6pcb *in6p = sotoin6pcb(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
|
||||
in6p->in6p_cksum = optval;
|
||||
break;
|
||||
|
||||
case PRCO_GETOPT:
|
||||
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
|
||||
optval = icmp6off;
|
||||
else
|
||||
optval = in6p->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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_var.h,v 1.19 2002/05/28 03:04:07 itojun Exp $ */
|
||||
/* $NetBSD: ip6_var.h,v 1.20 2002/06/07 22:03:02 itojun Exp $ */
|
||||
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -264,6 +264,7 @@ int ip6_output __P((struct mbuf *, struct ip6_pktopts *,
|
|||
struct route_in6 *, int,
|
||||
struct ip6_moptions *, struct ifnet **));
|
||||
int ip6_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
|
||||
int ip6_raw_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
|
||||
int ip6_setpktoptions __P((struct mbuf *, struct ip6_pktopts *, int));
|
||||
int ip6_optlen __P((struct in6pcb *));
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: raw_ip6.c,v 1.42 2002/03/19 01:21:19 itojun Exp $ */
|
||||
/* $NetBSD: raw_ip6.c,v 1.43 2002/06/07 22:03:02 itojun Exp $ */
|
||||
/* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -66,7 +66,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.42 2002/03/19 01:21:19 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.43 2002/06/07 22:03:02 itojun Exp $");
|
||||
|
||||
#include "opt_ipsec.h"
|
||||
|
||||
|
@ -209,8 +209,7 @@ 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)
|
||||
|
@ -325,8 +324,7 @@ rip6_ctlinput(cmd, sa, d)
|
|||
* from icmp6_notify_error()
|
||||
*/
|
||||
in6p = NULL;
|
||||
in6p = in6_pcblookup_connect(&rawin6pcb,
|
||||
&sa6->sin6_addr, 0,
|
||||
in6p = in6_pcblookup_connect(&rawin6pcb, &sa6->sin6_addr, 0,
|
||||
(struct in6_addr *)&sa6_src->sin6_addr, 0, 0);
|
||||
#if 0
|
||||
if (!in6p) {
|
||||
|
@ -458,11 +456,8 @@ rip6_output(m, va_alist)
|
|||
{
|
||||
struct in6_addr *in6a;
|
||||
|
||||
if ((in6a = in6_selectsrc(dstsock, optp,
|
||||
in6p->in6p_moptions,
|
||||
&in6p->in6p_route,
|
||||
&in6p->in6p_laddr,
|
||||
&error)) == 0) {
|
||||
if ((in6a = in6_selectsrc(dstsock, optp, in6p->in6p_moptions,
|
||||
&in6p->in6p_route, &in6p->in6p_laddr, &error)) == 0) {
|
||||
if (error == 0)
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
|
@ -554,10 +549,6 @@ rip6_ctloutput(op, so, level, optname, mp)
|
|||
struct mbuf **mp;
|
||||
{
|
||||
int error = 0;
|
||||
int optval;
|
||||
struct in6pcb *in6p;
|
||||
struct mbuf *m;
|
||||
const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
|
||||
|
||||
switch (level) {
|
||||
case IPPROTO_IPV6:
|
||||
|
@ -579,38 +570,7 @@ rip6_ctloutput(op, so, level, optname, mp)
|
|||
error = EINVAL;
|
||||
return (error);
|
||||
case IPV6_CHECKSUM:
|
||||
/*
|
||||
* for ICMPv6 sockets, no modification allowed for
|
||||
* checksum offset, permit "no change" values to
|
||||
* help existing apps.
|
||||
*/
|
||||
in6p = sotoin6pcb(so);
|
||||
error = 0;
|
||||
if (op == PRCO_SETOPT) {
|
||||
m = *mp;
|
||||
if (m && m->m_len == sizeof(int)) {
|
||||
optval = *mtod(m, int *);
|
||||
if (so->so_proto->pr_protocol ==
|
||||
IPPROTO_ICMPV6) {
|
||||
if (optval != icmp6off)
|
||||
error = EINVAL;
|
||||
} else
|
||||
in6p->in6p_cksum = optval;
|
||||
} else
|
||||
error = EINVAL;
|
||||
if (m)
|
||||
m_free(m);
|
||||
} else if (op == PRCO_GETOPT) {
|
||||
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
|
||||
optval = icmp6off;
|
||||
else
|
||||
optval = in6p->in6p_cksum;
|
||||
*mp = m = m_get(M_WAIT, MT_SOOPTS);
|
||||
m->m_len = sizeof(int);
|
||||
*mtod(m, int *) = optval;
|
||||
} else
|
||||
error = EINVAL;
|
||||
return error;
|
||||
return (ip6_raw_ctloutput(op, so, level, optname, mp));
|
||||
default:
|
||||
return (ip6_ctloutput(op, so, level, optname, mp));
|
||||
}
|
||||
|
@ -801,10 +761,8 @@ rip6_usrreq(so, req, m, nam, control, p)
|
|||
|
||||
/* 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;
|
||||
|
|
Loading…
Reference in New Issue