diff options
author | ume <ume@FreeBSD.org> | 2001-06-11 12:39:29 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2001-06-11 12:39:29 +0000 |
commit | 832f8d224926758a9ae0b23a6b45353e44fbc87a (patch) | |
tree | a79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sys/netinet6/udp6_output.c | |
parent | 2693854b01a52b0395a91322aa3edf926bddff38 (diff) | |
download | FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz |
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some
critical problem after the snap was out were fixed.
There are many many changes since last KAME merge.
TODO:
- The definitions of SADB_* in sys/net/pfkeyv2.h are still different
from RFC2407/IANA assignment because of binary compatibility
issue. It should be fixed under 5-CURRENT.
- ip6po_m member of struct ip6_pktopts is no longer used. But, it
is still there because of binary compatibility issue. It should
be removed under 5-CURRENT.
Reviewed by: itojun
Obtained from: KAME
MFC after: 3 weeks
Diffstat (limited to 'sys/netinet6/udp6_output.c')
-rw-r--r-- | sys/netinet6/udp6_output.c | 67 |
1 files changed, 51 insertions, 16 deletions
diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c index ee05019..fd4d6f3 100644 --- a/sys/netinet6/udp6_output.c +++ b/sys/netinet6/udp6_output.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: udp6_output.c,v 1.14 2000/06/13 10:31:23 itojun Exp $ */ +/* $KAME: udp6_output.c,v 1.31 2001/05/21 16:39:15 jinmei Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -69,6 +69,7 @@ #include "opt_inet.h" #include <sys/param.h> +#include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/protosw.h> #include <sys/socket.h> @@ -120,22 +121,22 @@ int udp6_output(in6p, m, addr6, control, p) - register struct in6pcb *in6p; - register struct mbuf *m; + struct in6pcb *in6p; + struct mbuf *m; struct mbuf *control; struct sockaddr *addr6; struct proc *p; { - register u_int32_t ulen = m->m_pkthdr.len; + u_int32_t ulen = m->m_pkthdr.len; u_int32_t plen = sizeof(struct udphdr) + ulen; struct ip6_hdr *ip6; struct udphdr *udp6; - struct in6_addr *laddr, *faddr; + struct in6_addr *laddr, *faddr; u_short fport; int error = 0; struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts; int priv; - int af, hlen; + int af = AF_INET6, hlen = sizeof(struct ip6_hdr); int flags; struct sockaddr_in6 tmp; @@ -143,7 +144,7 @@ udp6_output(in6p, m, addr6, control, p) if (p && !suser(p)) priv = 1; if (control) { - if ((error = ip6_setpktoptions(control, &opt, priv)) != 0) + if ((error = ip6_setpktoptions(control, &opt, priv, 0)) != 0) goto release; in6p->in6p_outputopts = &opt; } @@ -164,6 +165,7 @@ udp6_output(in6p, m, addr6, control, p) } if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) { + /* how about ::ffff:0.0.0.0 case? */ error = EISCONN; goto release; } @@ -175,6 +177,24 @@ udp6_output(in6p, m, addr6, control, p) faddr = &sin6->sin6_addr; fport = sin6->sin6_port; /* allow 0 port */ + if (IN6_IS_ADDR_V4MAPPED(faddr)) { + if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY)) { + /* + * I believe we should explicitly discard the + * packet when mapped addresses are disabled, + * rather than send the packet as an IPv6 one. + * If we chose the latter approach, the packet + * might be sent out on the wire based on the + * default route, the situation which we'd + * probably want to avoid. + * (20010421 jinmei@kame.net) + */ + error = EINVAL; + goto release; + } else + af = AF_INET; + } + /* KAME hack: embed scopeid */ if (in6_embedscope(&sin6->sin6_addr, sin6, in6p, NULL) != 0) { error = EINVAL; @@ -187,7 +207,7 @@ udp6_output(in6p, m, addr6, control, p) &in6p->in6p_route, &in6p->in6p_laddr, &error); } else - laddr = &in6p->in6p_laddr; /*XXX*/ + laddr = &in6p->in6p_laddr; /* XXX */ if (laddr == NULL) { if (error == 0) error = EADDRNOTAVAIL; @@ -201,18 +221,29 @@ udp6_output(in6p, m, addr6, control, p) error = ENOTCONN; goto release; } + if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_faddr)) { + if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY)) { + /* + * XXX: this case would happen when the + * application sets the V6ONLY flag after + * connecting the foreign address. + * Such applications should be fixed, + * so we bark here. + */ + log(LOG_INFO, "udp6_output: IPV6_V6ONLY " + "option was set for a connected socket\n"); + error = EINVAL; + goto release; + } else + af = AF_INET; + } laddr = &in6p->in6p_laddr; faddr = &in6p->in6p_faddr; fport = in6p->in6p_fport; } - if (!IN6_IS_ADDR_V4MAPPED(faddr)) { - af = AF_INET6; - hlen = sizeof(struct ip6_hdr); - } else { - af = AF_INET; + if (af == AF_INET) hlen = sizeof(struct ip); - } /* * Calculate data length and get a mbuf @@ -261,10 +292,13 @@ udp6_output(in6p, m, addr6, control, p) udp6stat.udp6s_opackets++; #ifdef IPSEC - ipsec_setsocket(m, in6p->in6p_socket); + if (ipsec_setsocket(m, in6p->in6p_socket) != 0) { + error = ENOBUFS; + goto release; + } #endif /*IPSEC*/ error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route, - flags, in6p->in6p_moptions, NULL); + flags, in6p->in6p_moptions, NULL); break; case AF_INET: error = EAFNOSUPPORT; @@ -277,6 +311,7 @@ release: releaseopt: if (control) { + ip6_clearpktopts(in6p->in6p_outputopts, 0, -1); in6p->in6p_outputopts = stickyopt; m_freem(control); } |