summaryrefslogtreecommitdiff
path: root/sys/netinet6
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6_pcb.c51
-rw-r--r--sys/netinet6/in6_proto.c11
-rw-r--r--sys/netinet6/tcp6_var.h7
-rw-r--r--sys/netinet6/udp6_usrreq.c13
4 files changed, 69 insertions, 13 deletions
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index acc155e9e6a6..d55ed96fee19 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -71,6 +71,7 @@
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@@ -90,6 +91,7 @@
#include <netinet/in_var.h>
#include <netinet/in_systm.h>
#include <netinet6/ip6.h>
+#include <netinet/ip_var.h>
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
#include <netinet/in_pcb.h>
@@ -211,7 +213,7 @@ in6_pcbbind(inp, nam, p)
return(EACCES);
if (so->so_cred->cr_uid != 0 &&
!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
- t = in6_pcblookup_local(inp->inp_pcbinfo,
+ t = in6_pcblookup_local(pcbinfo,
&sin6->sin6_addr, lport,
INPLOOKUP_WILDCARD);
if (t &&
@@ -222,11 +224,44 @@ in6_pcbbind(inp, nam, p)
(so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid))
return (EADDRINUSE);
+ if (ip6_mapped_addr_on != 0 &&
+ IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ struct sockaddr_in sin;
+
+ in6_sin6_2_sin(&sin, sin6);
+ t = in_pcblookup_local(pcbinfo,
+ sin.sin_addr, lport,
+ INPLOOKUP_WILDCARD);
+ if (t &&
+ (so->so_cred->cr_uid !=
+ t->inp_socket->so_cred->cr_uid) &&
+ (ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY ||
+ INP_SOCKAF(so) ==
+ INP_SOCKAF(t->inp_socket)))
+ return (EADDRINUSE);
+ }
}
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
lport, wild);
if (t && (reuseport & t->inp_socket->so_options) == 0)
return(EADDRINUSE);
+ if (ip6_mapped_addr_on != 0 &&
+ IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ struct sockaddr_in sin;
+
+ in6_sin6_2_sin(&sin, sin6);
+ t = in_pcblookup_local(pcbinfo, sin.sin_addr,
+ lport, wild);
+ if (t &&
+ (reuseport & t->inp_socket->so_options)
+ == 0 &&
+ (ntohl(t->inp_laddr.s_addr)
+ != INADDR_ANY ||
+ INP_SOCKAF(so) ==
+ INP_SOCKAF(t->inp_socket)))
+ return (EADDRINUSE);
+ }
}
inp->in6p_laddr = sin6->sin6_addr;
}
@@ -455,6 +490,12 @@ in6_pcbconnect(inp, nam, p)
* but if this line is missing, the garbage value remains.
*/
inp->in6p_flowinfo = sin6->sin6_flowinfo;
+#ifdef INET6
+ if ((inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) == 0 &&
+ ip6_auto_flowlable != 0)
+ inp->in6p_flowinfo |=
+ (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
+#endif
in_pcbrehash(inp);
return (0);
@@ -701,6 +742,14 @@ in6_pcbdetach(inp)
if (inp->in6p_route.ro_rt)
rtfree(inp->in6p_route.ro_rt);
ip6_freemoptions(inp->in6p_moptions);
+
+ /* Check and free IPv4 related resources in case of mapped addr */
+ if (inp->inp_options)
+ (void)m_free(inp->inp_options);
+ if (inp->inp_route.ro_rt)
+ rtfree(inp->inp_route.ro_rt);
+ ip_freemoptions(inp->inp_moptions);
+
inp->inp_vflag = 0;
zfreei(ipi->ipi_zone, inp);
}
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index 60c3fcf01723..ea43e53c277a 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -64,6 +64,7 @@
* @(#)in_proto.c 8.1 (Berkeley) 6/10/93
*/
+#include "opt_inet.h"
#include "opt_ipsec.h"
#include <sys/param.h>
@@ -144,6 +145,16 @@ struct ip6protosw inet6sw[] = {
0, 0, 0, 0,
&udp6_usrreqs,
},
+{ SOCK_STREAM, &inet6domain, IPPROTO_TCP, PR_CONNREQUIRED | PR_WANTRCVD,
+ tcp6_input, 0, tcp6_ctlinput, tcp_ctloutput,
+ 0,
+#ifdef INET /* don't call timeout routines twice */
+ tcp_init, 0, 0, tcp_drain,
+#else
+ tcp_init, 0, tcp_slowtimo, tcp_drain,
+#endif
+ &tcp6_usrreqs,
+},
{ SOCK_RAW, &inet6domain, IPPROTO_RAW, PR_ATOMIC | PR_ADDR,
rip6_input, rip6_output, 0, rip6_ctloutput,
0,
diff --git a/sys/netinet6/tcp6_var.h b/sys/netinet6/tcp6_var.h
index b2665c154588..820c49be741e 100644
--- a/sys/netinet6/tcp6_var.h
+++ b/sys/netinet6/tcp6_var.h
@@ -69,6 +69,11 @@
#define _NETINET_TCP6_VAR_H_
#ifdef _KERNEL
+#ifdef SYSCTL_DECL
+SYSCTL_DECL(_net_inet6_tcp6);
+#endif
+
+extern int tcp_v6mssdflt; /* XXX */
struct ip6_hdr;
void tcp6_ctlinput __P((int, struct sockaddr *, void *));
@@ -78,6 +83,6 @@ struct rtentry *tcp_rtlookup6 __P((struct inpcb *));
extern struct pr_usrreqs tcp6_usrreqs;
-#endif
+#endif /* _KERNEL */
#endif /* _NETINET_TCP6_VAR_H_ */
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 936bac9292fc..9e5c65da7a88 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -705,7 +705,6 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
inp = sotoinpcb(so);
if (inp == 0)
return EINVAL;
-
if (ip6_mapped_addr_on) {
struct sockaddr_in6 *sin6_p;
@@ -727,22 +726,14 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
return error;
}
}
-
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
return EISCONN;
s = splnet();
error = in6_pcbconnect(inp, nam, p);
- if (ip6_auto_flowlabel) {
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
- inp->in6p_flowinfo |=
- (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
- }
splx(s);
if (error == 0) {
- if (ip6_mapped_addr_on) { /* should be non mapped addr */
- inp->inp_vflag &= ~INP_IPV4;
- inp->inp_vflag |= INP_IPV6;
- }
+ inp->inp_vflag &= ~INP_IPV4;
+ inp->inp_vflag |= INP_IPV6;
soisconnected(so);
}
return error;