summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6/sctp6_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet6/sctp6_usrreq.c')
-rw-r--r--freebsd/sys/netinet6/sctp6_usrreq.c73
1 files changed, 36 insertions, 37 deletions
diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c
index 3465f3c3..d3421894 100644
--- a/freebsd/sys/netinet6/sctp6_usrreq.c
+++ b/freebsd/sys/netinet6/sctp6_usrreq.c
@@ -107,13 +107,15 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
/* Get IP, SCTP, and first chunk header together in the first mbuf. */
offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
- ip6 = mtod(m, struct ip6_hdr *);
- IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen,
- (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
- if (sh == NULL) {
- SCTP_STAT_INCR(sctps_hdrops);
- return (IPPROTO_DONE);
+ if (m->m_len < offset) {
+ m = m_pullup(m, offset);
+ if (m == NULL) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ return (IPPROTO_DONE);
+ }
}
+ ip6 = mtod(m, struct ip6_hdr *);
+ sh = (struct sctphdr *)(mtod(m, caddr_t) + iphlen);
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
offset -= sizeof(struct sctp_chunkhdr);
memset(&src, 0, sizeof(struct sockaddr_in6));
@@ -522,7 +524,6 @@ sctp_must_try_again:
static int
sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
{
- struct in6pcb *inp6;
int error;
struct sctp_inpcb *inp;
uint32_t vrf_id = SCTP_DEFAULT_VRFID;
@@ -544,18 +545,17 @@ sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNU
inp = (struct sctp_inpcb *)so->so_pcb;
SCTP_INP_WLOCK(inp);
inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6; /* I'm v6! */
- inp6 = (struct in6pcb *)inp;
- inp6->inp_vflag |= INP_IPV6;
- inp6->in6p_hops = -1; /* use kernel default */
- inp6->in6p_cksum = -1; /* just to be sure */
+ inp->ip_inp.inp.inp_vflag |= INP_IPV6;
+ inp->ip_inp.inp.in6p_hops = -1; /* use kernel default */
+ inp->ip_inp.inp.in6p_cksum = -1; /* just to be sure */
#ifdef INET
/*
* XXX: ugly!! IPv4 TTL initialization is necessary for an IPv6
* socket as well, because the socket may be bound to an IPv6
* wildcard address, which may match an IPv4-mapped IPv6 address.
*/
- inp6->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
+ inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
#endif
SCTP_INP_WUNLOCK(inp);
return (0);
@@ -565,8 +565,8 @@ static int
sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
{
struct sctp_inpcb *inp;
- struct in6pcb *inp6;
int error;
+ u_char vflagsav;
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
@@ -597,16 +597,16 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
return (EINVAL);
}
}
- inp6 = (struct in6pcb *)inp;
- inp6->inp_vflag &= ~INP_IPV4;
- inp6->inp_vflag |= INP_IPV6;
- if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
+ vflagsav = inp->ip_inp.inp.inp_vflag;
+ inp->ip_inp.inp.inp_vflag &= ~INP_IPV4;
+ inp->ip_inp.inp.inp_vflag |= INP_IPV6;
+ if ((addr != NULL) && (SCTP_IPV6_V6ONLY(&inp->ip_inp.inp) == 0)) {
switch (addr->sa_family) {
#ifdef INET
case AF_INET:
/* binding v4 addr to v6 socket, so reset flags */
- inp6->inp_vflag |= INP_IPV4;
- inp6->inp_vflag &= ~INP_IPV6;
+ inp->ip_inp.inp.inp_vflag |= INP_IPV4;
+ inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
break;
#endif
#ifdef INET6
@@ -617,17 +617,17 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
sin6_p = (struct sockaddr_in6 *)addr;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
- inp6->inp_vflag |= INP_IPV4;
+ inp->ip_inp.inp.inp_vflag |= INP_IPV4;
}
#ifdef INET
if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
struct sockaddr_in sin;
in6_sin6_2_sin(&sin, sin6_p);
- inp6->inp_vflag |= INP_IPV4;
- inp6->inp_vflag &= ~INP_IPV6;
+ inp->ip_inp.inp.inp_vflag |= INP_IPV4;
+ inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
- return (error);
+ goto out;
}
#endif
break;
@@ -644,7 +644,8 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
if (addr->sa_family == AF_INET) {
/* can't bind v4 addr to v6 only socket! */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ goto out;
}
#endif
sin6_p = (struct sockaddr_in6 *)addr;
@@ -653,10 +654,14 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
/* can't bind v4-mapped addrs either! */
/* NOTE: we don't support SIIT */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return (EINVAL);
+ error = EINVAL;
+ goto out;
}
}
error = sctp_inpcb_bind(so, addr, NULL, p);
+out:
+ if (error != 0)
+ inp->ip_inp.inp.inp_vflag = vflagsav;
return (error);
}
@@ -687,7 +692,6 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
struct mbuf *control, struct thread *p)
{
struct sctp_inpcb *inp;
- struct in6pcb *inp6;
#ifdef INET
struct sockaddr_in6 *sin6;
@@ -704,7 +708,6 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
- inp6 = (struct in6pcb *)inp;
/*
* For the TCP model we may get a NULL addr, if we are a connected
* socket thats ok.
@@ -724,7 +727,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
}
#ifdef INET
sin6 = (struct sockaddr_in6 *)addr;
- if (SCTP_IPV6_V6ONLY(inp6)) {
+ if (SCTP_IPV6_V6ONLY(inp)) {
/*
* if IPV6_V6ONLY flag, we discard datagrams destined to a
* v4 addr or v4-mapped addr
@@ -793,14 +796,10 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
#ifdef INET
- struct in6pcb *inp6;
struct sockaddr_in6 *sin6;
union sctp_sockstore store;
#endif
-#ifdef INET
- inp6 = (struct in6pcb *)so->so_pcb;
-#endif
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
@@ -858,7 +857,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
}
#ifdef INET
sin6 = (struct sockaddr_in6 *)addr;
- if (SCTP_IPV6_V6ONLY(inp6)) {
+ if (SCTP_IPV6_V6ONLY(inp)) {
/*
* if IPV6_V6ONLY flag, ignore connections destined to a v4
* addr or v4-mapped addr
@@ -1100,10 +1099,10 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
static int
sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
{
- struct in6pcb *inp6 = sotoin6pcb(so);
+ struct inpcb *inp = sotoinpcb(so);
int error;
- if (inp6 == NULL) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
@@ -1136,10 +1135,10 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
static int
sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
{
- struct in6pcb *inp6 = sotoin6pcb(so);
+ struct inpcb *inp = sotoinpcb(so);
int error;
- if (inp6 == NULL) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}