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.c559
1 files changed, 246 insertions, 313 deletions
diff --git a/freebsd/sys/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c
index 16b9e4fd..0551d48b 100644
--- a/freebsd/sys/netinet6/sctp6_usrreq.c
+++ b/freebsd/sys/netinet6/sctp6_usrreq.c
@@ -2,16 +2,18 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
+ * this list of conditions and the following disclaimer.
*
* b) 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.
+ * the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
@@ -29,17 +31,17 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* $KAME: sctp6_usrreq.c,v 1.38 2005/08/24 08:08:56 suz Exp $ */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <netinet/sctp_os.h>
+#ifdef INET6
#include <sys/proc.h>
#include <netinet/sctp_pcb.h>
#include <netinet/sctp_header.h>
#include <netinet/sctp_var.h>
-#if defined(INET6)
+#ifdef INET6
#include <netinet6/sctp6_var.h>
#endif
#include <netinet/sctp_sysctl.h>
@@ -58,7 +60,7 @@ __FBSDID("$FreeBSD$");
#ifdef IPSEC
#include <netipsec/ipsec.h>
-#if defined(INET6)
+#ifdef INET6
#include <netipsec/ipsec6.h>
#endif /* INET6 */
#endif /* IPSEC */
@@ -66,222 +68,140 @@ __FBSDID("$FreeBSD$");
extern struct protosw inetsw[];
int
-sctp6_input(struct mbuf **i_pak, int *offp, int proto)
+sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
{
struct mbuf *m;
+ int iphlen;
+ uint32_t vrf_id;
+ uint8_t ecn_bits;
+ struct sockaddr_in6 src, dst;
struct ip6_hdr *ip6;
struct sctphdr *sh;
- struct sctp_inpcb *in6p = NULL;
- struct sctp_nets *net;
- int refcount_up = 0;
- uint32_t vrf_id = 0;
-
-#ifdef IPSEC
- struct inpcb *in6p_ip;
-
-#endif
struct sctp_chunkhdr *ch;
- int length, offset, iphlen;
- uint8_t ecn_bits;
- struct sctp_tcb *stcb = NULL;
- int pkt_len = 0;
+ int length, offset;
#if !defined(SCTP_WITH_NO_CSUM)
- uint32_t check, calc_check;
+ uint8_t compute_crc;
#endif
- int off = *offp;
- uint16_t port = 0;
+ uint32_t mflowid;
+ uint8_t use_mflowid;
- /* get the VRF and table id's */
+ iphlen = *offp;
if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
SCTP_RELEASE_PKT(*i_pak);
- return (-1);
+ return (IPPROTO_DONE);
}
m = SCTP_HEADER_TO_CHAIN(*i_pak);
- pkt_len = SCTP_HEADER_LEN((*i_pak));
-
-#ifdef SCTP_PACKET_LOGGING
- sctp_packet_log(m, pkt_len);
+#ifdef SCTP_MBUF_LOGGING
+ /* Log in any input mbufs */
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+ struct mbuf *mat;
+
+ for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
+ if (SCTP_BUF_IS_EXTENDED(mat)) {
+ sctp_log_mb(mat, SCTP_MBUF_INPUT);
+ }
+ }
+ }
#endif
+#ifdef SCTP_PACKET_LOGGING
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
+ sctp_packet_log(m);
+ }
+#endif
+ SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+ "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
+ m->m_pkthdr.len,
+ if_name(m->m_pkthdr.rcvif),
+ m->m_pkthdr.csum_flags);
+ if (m->m_flags & M_FLOWID) {
+ mflowid = m->m_pkthdr.flowid;
+ use_mflowid = 1;
+ } else {
+ mflowid = 0;
+ use_mflowid = 0;
+ }
+ SCTP_STAT_INCR(sctps_recvpackets);
+ 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 *);
- /* Ensure that (sctphdr + sctp_chunkhdr) in a row. */
- IP6_EXTHDR_GET(sh, struct sctphdr *, m, off,
- (int)(sizeof(*sh) + sizeof(*ch)));
+ 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;
+ return (IPPROTO_DONE);
}
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
- iphlen = off;
- offset = iphlen + sizeof(*sh) + sizeof(*ch);
- SCTPDBG(SCTP_DEBUG_INPUT1,
- "sctp6_input() length:%d iphlen:%d\n", pkt_len, iphlen);
-
-
-#if defined(NFAITH) && NFAITH > 0
-
- if (faithprefix_p != NULL && (*faithprefix_p) (&ip6->ip6_dst)) {
+ offset -= sizeof(struct sctp_chunkhdr);
+ memset(&src, 0, sizeof(struct sockaddr_in6));
+ src.sin6_family = AF_INET6;
+ src.sin6_len = sizeof(struct sockaddr_in6);
+ src.sin6_port = sh->src_port;
+ src.sin6_addr = ip6->ip6_src;
+ if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
+ goto out;
+ }
+ memset(&dst, 0, sizeof(struct sockaddr_in6));
+ dst.sin6_family = AF_INET6;
+ dst.sin6_len = sizeof(struct sockaddr_in6);
+ dst.sin6_port = sh->dest_port;
+ dst.sin6_addr = ip6->ip6_dst;
+ if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
+ goto out;
+ }
+ if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) {
/* XXX send icmp6 host/port unreach? */
- goto bad;
+ goto out;
+ }
+ length = ntohs(ip6->ip6_plen) + iphlen;
+ /* Validate mbuf chain length with IP payload length. */
+ if (SCTP_HEADER_LEN(m) != length) {
+ SCTPDBG(SCTP_DEBUG_INPUT1,
+ "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
+ SCTP_STAT_INCR(sctps_hdrops);
+ goto out;
}
-#endif /* NFAITH defined and > 0 */
- SCTP_STAT_INCR(sctps_recvpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
- SCTPDBG(SCTP_DEBUG_INPUT1, "V6 input gets a packet iphlen:%d pktlen:%d\n",
- iphlen, pkt_len);
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- /* No multi-cast support in SCTP */
- goto bad;
+ goto out;
}
- /* destination port of 0 is illegal, based on RFC2960. */
- if (sh->dest_port == 0)
- goto bad;
-
- SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
- "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
- m->m_pkthdr.len,
- if_name(m->m_pkthdr.rcvif),
- m->m_pkthdr.csum_flags);
+ ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_recvnocrc);
#else
if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
SCTP_STAT_INCR(sctps_recvhwcrc);
- goto sctp_skip_csum;
- }
- check = sh->checksum; /* save incoming checksum */
- if ((check == 0) && (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback)) &&
- (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ip6->ip6_dst))) {
- SCTP_STAT_INCR(sctps_recvnocrc);
- goto sctp_skip_csum;
- }
- sh->checksum = 0; /* prepare for calc */
- calc_check = sctp_calculate_cksum(m, iphlen);
- SCTP_STAT_INCR(sctps_recvswcrc);
- if (calc_check != check) {
- SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p phlen:%d\n",
- calc_check, check, m, iphlen);
- stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &in6p, &net, vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(in6p, stcb, net, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- /* in6p's ref-count increased && stcb locked */
- if ((in6p) && (stcb)) {
- sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
- sctp_chunk_output((struct sctp_inpcb *)in6p, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
- } else if ((in6p != NULL) && (stcb == NULL)) {
- refcount_up = 1;
- }
- SCTP_STAT_INCR(sctps_badsum);
- SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
- goto bad;
+ compute_crc = 0;
+ } else {
+ SCTP_STAT_INCR(sctps_recvswcrc);
+ compute_crc = 1;
}
- sh->checksum = calc_check;
-
-sctp_skip_csum:
#endif
- net = NULL;
- /*
- * Locate pcb and tcb for datagram sctp_findassociation_addr() wants
- * IP/SCTP/first chunk header...
- */
- stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
- sh, ch, &in6p, &net, vrf_id);
- if ((net) && (port)) {
- if (net->port == 0) {
- sctp_pathmtu_adjustment(in6p, stcb, net, net->mtu - sizeof(struct udphdr));
- }
- net->port = port;
- }
- /* in6p's ref-count increased */
- if (in6p == NULL) {
- struct sctp_init_chunk *init_chk, chunk_buf;
-
- SCTP_STAT_INCR(sctps_noport);
- if (ch->chunk_type == SCTP_INITIATION) {
- /*
- * we do a trick here to get the INIT tag, dig in
- * and get the tag from the INIT and put it in the
- * common header.
- */
- init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
- iphlen + sizeof(*sh), sizeof(*init_chk),
- (uint8_t *) & chunk_buf);
- if (init_chk)
- sh->v_tag = init_chk->init.initiate_tag;
- else
- sh->v_tag = 0;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
- sctp_send_shutdown_complete2(m, iphlen, sh, vrf_id, port);
- goto bad;
- }
- if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
- goto bad;
- }
- if (ch->chunk_type != SCTP_ABORT_ASSOCIATION)
- sctp_send_abort(m, iphlen, sh, 0, NULL, vrf_id, port);
- goto bad;
- } else if (stcb == NULL) {
- refcount_up = 1;
- }
-#ifdef IPSEC
- /*
- * Check AH/ESP integrity.
- */
- in6p_ip = (struct inpcb *)in6p;
- if (in6p_ip && (ipsec6_in_reject(m, in6p_ip))) {
-/* XXX */
- MODULE_GLOBAL(ipsec6stat).in_polvio++;
- goto bad;
- }
-#endif /* IPSEC */
-
- /*
- * CONTROL chunk processing
- */
- offset -= sizeof(*ch);
- ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
-
- /* Length now holds the total packet length payload + iphlen */
- length = ntohs(ip6->ip6_plen) + iphlen;
-
- /* sa_ignore NO_NULL_CHK */
- sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
- in6p, stcb, net, ecn_bits, vrf_id, port);
- /* inp's ref-count reduced && stcb unlocked */
- /* XXX this stuff below gets moved to appropriate parts later... */
- if (m)
+ sctp_common_input_processing(&m, iphlen, offset, length,
+ (struct sockaddr *)&src,
+ (struct sockaddr *)&dst,
+ sh, ch,
+#if !defined(SCTP_WITH_NO_CSUM)
+ compute_crc,
+#endif
+ ecn_bits,
+ use_mflowid, mflowid,
+ vrf_id, port);
+out:
+ if (m) {
sctp_m_freem(m);
- if ((in6p) && refcount_up) {
- /* reduce ref-count */
- SCTP_INP_WLOCK(in6p);
- SCTP_INP_DECR_REF(in6p);
- SCTP_INP_WUNLOCK(in6p);
- }
- return IPPROTO_DONE;
-
-bad:
- if (stcb) {
- SCTP_TCB_UNLOCK(stcb);
}
- if ((in6p) && refcount_up) {
- /* reduce ref-count */
- SCTP_INP_WLOCK(in6p);
- SCTP_INP_DECR_REF(in6p);
- SCTP_INP_WUNLOCK(in6p);
- }
- if (m)
- sctp_m_freem(m);
- return IPPROTO_DONE;
+ return (IPPROTO_DONE);
}
+int
+sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
+{
+ return (sctp6_input_with_port(i_pak, offp, 0));
+}
+
static void
sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6,
struct sctphdr *sh, struct sctp_tcb *stcb, struct sctp_nets *net)
@@ -367,14 +287,12 @@ sctp6_notify(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
- /* protection */
- int reason;
-
+ /* protection */
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(sh == NULL) || (to == NULL)) {
if (stcb)
@@ -408,36 +326,10 @@ sctp6_notify(struct sctp_inpcb *inp,
*/
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
- SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
- net->error_count,
- net->failure_threshold,
- net);
-
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
- /*
- * JRS 5/14/07 - If a destination is unreachable,
- * the PF bit is turned off. This allows an
- * unambiguous use of the PF bit for destinations
- * that are reachable but potentially failed. If the
- * destination is set to the unreachable state, also
- * set the destination to the PF state.
- */
- /*
- * Add debug message here if destination is not in
- * PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off == 1) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
- net);
- }
- net->error_count = net->failure_threshold + 1;
+ net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
- stcb, SCTP_FAILED_THRESHOLD,
- (void *)net, SCTP_SO_NOT_LOCKED);
+ stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
} else if ((icmph->icmp6_code == ICMP_UNREACH_PROTOCOL) ||
@@ -449,9 +341,8 @@ sctp6_notify(struct sctp_inpcb *inp,
* now is dead. In either case treat it like a OOTB abort
* with no TCB
*/
- reason = SCTP_PEER_FAULTY;
- sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -460,7 +351,7 @@ sctp6_notify(struct sctp_inpcb *inp,
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
#endif
@@ -524,8 +415,8 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
final.sin6_family = AF_INET6;
final.sin6_addr = ((struct sockaddr_in6 *)pktdst)->sin6_addr;
final.sin6_port = sh.dest_port;
- stcb = sctp_findassociation_addr_sa((struct sockaddr *)ip6cp->ip6c_src,
- (struct sockaddr *)&final,
+ stcb = sctp_findassociation_addr_sa((struct sockaddr *)&final,
+ (struct sockaddr *)ip6cp->ip6c_src,
&inp, &net, 1, vrf_id);
/* inp's ref-count increased && stcb locked */
if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
@@ -593,8 +484,8 @@ sctp6_getcred(SYSCTL_HANDLER_ARGS)
if (error)
return (error);
- stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[0]),
- sin6tosa(&addrs[1]),
+ stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
+ sin6tosa(&addrs[0]),
&inp, &net, 1, vrf_id);
if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
if ((inp != NULL) && (stcb == NULL)) {
@@ -642,7 +533,7 @@ sctp6_abort(struct socket *so)
uint32_t flags;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return;
}
@@ -678,7 +569,7 @@ sctp_must_try_again:
}
static int
-sctp6_attach(struct socket *so, int proto, struct thread *p)
+sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
{
struct in6pcb *inp6;
int error;
@@ -688,16 +579,16 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp != NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
if (error)
- return error;
+ return (error);
}
error = sctp_inpcb_alloc(so, vrf_id);
if (error)
- return error;
+ return (error);
inp = (struct sctp_inpcb *)so->so_pcb;
SCTP_INP_WLOCK(inp);
inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6; /* I'm v6! */
@@ -719,7 +610,7 @@ sctp6_attach(struct socket *so, int proto, struct thread *p)
* sctp_attach()?
*/
SCTP_INP_WUNLOCK(inp);
- return 0;
+ return (0);
}
static int
@@ -730,68 +621,94 @@ sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
int error;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (addr) {
- if ((addr->sa_family == AF_INET6) &&
- (addr->sa_len != sizeof(struct sockaddr_in6))) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
- }
- if ((addr->sa_family == AF_INET) &&
- (addr->sa_len != sizeof(struct sockaddr_in))) {
+ switch (addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (addr->sa_len != sizeof(struct sockaddr_in)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (addr->sa_len != sizeof(struct sockaddr_in6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+ default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
inp6 = (struct in6pcb *)inp;
inp6->inp_vflag &= ~INP_IPV4;
inp6->inp_vflag |= INP_IPV6;
if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
- if (addr->sa_family == AF_INET) {
+ 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;
- } else {
- struct sockaddr_in6 *sin6_p;
-
- sin6_p = (struct sockaddr_in6 *)addr;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6_p;
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
- inp6->inp_vflag |= INP_IPV4;
- } else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
- struct sockaddr_in sin;
+ sin6_p = (struct sockaddr_in6 *)addr;
- in6_sin6_2_sin(&sin, sin6_p);
- inp6->inp_vflag |= INP_IPV4;
- inp6->inp_vflag &= ~INP_IPV6;
- error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
- return error;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
+ inp6->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;
+ error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
+ return (error);
+ }
+#endif
+ break;
}
+#endif
+ default:
+ break;
}
} else if (addr != NULL) {
+ struct sockaddr_in6 *sin6_p;
+
/* IPV6_V6ONLY socket */
+#ifdef INET
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;
- } else {
- struct sockaddr_in6 *sin6_p;
-
- sin6_p = (struct sockaddr_in6 *)addr;
+ return (EINVAL);
+ }
+#endif
+ sin6_p = (struct sockaddr_in6 *)addr;
- if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
- /* 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;
- }
+ if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
+ /* 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 = sctp_inpcb_bind(so, addr, NULL, p);
- return error;
+ return (error);
}
@@ -837,7 +754,7 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
}
SCTP_RELEASE_PKT(m);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
inp6 = (struct in6pcb *)inp;
/*
@@ -866,11 +783,11 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
*/
if (addr->sa_family == AF_INET) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
@@ -879,12 +796,12 @@ sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
/* convert v4-mapped into v4 addr and send */
in6_sin6_2_sin(&sin, sin6);
- return sctp_sendm(so, flags, m, (struct sockaddr *)&sin,
- control, p);
+ return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin,
+ control, p));
} else {
/* mapped addresses aren't enabled */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
#endif /* INET */
@@ -940,11 +857,11 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sockaddr_in6 *sin6;
struct sockaddr_storage ss;
-#endif /* INET */
+#endif
inp6 = (struct in6pcb *)so->so_pcb;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == 0) {
+ if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
return (ECONNRESET); /* I made the same as TCP since we are
* not setup? */
@@ -953,14 +870,28 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
- if ((addr->sa_family == AF_INET6) && (addr->sa_len != sizeof(struct sockaddr_in6))) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return (EINVAL);
- }
- if ((addr->sa_family == AF_INET) && (addr->sa_len != sizeof(struct sockaddr_in))) {
+ switch (addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (addr->sa_len != sizeof(struct sockaddr_in)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (addr->sa_len != sizeof(struct sockaddr_in6)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
+ return (EINVAL);
+ }
+ break;
+#endif
+ default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return (EINVAL);
}
+
vrf_id = inp->def_vrf_id;
SCTP_ASOC_CREATE_LOCK(inp);
SCTP_INP_RLOCK(inp);
@@ -995,13 +926,13 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
}
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
@@ -1014,12 +945,10 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_INP_RUNLOCK(inp);
SCTP_ASOC_CREATE_UNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
- } else
+ }
#endif /* INET */
- addr = addr; /* for true v6 address case */
-
/* Now do we connect? */
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -1067,7 +996,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
- return error;
+ return (error);
}
static int
@@ -1083,9 +1012,9 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
/*
* Do the malloc first in case it blocks.
*/
- SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
+ SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
if (sin6 == NULL)
- return ENOMEM;
+ return (ENOMEM);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
@@ -1093,7 +1022,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
if (inp == NULL) {
SCTP_FREE_SONAME(sin6);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
- return ECONNRESET;
+ return (ECONNRESET);
}
SCTP_INP_RLOCK(inp);
sin6->sin6_port = inp->sctp_lport;
@@ -1155,7 +1084,7 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
SCTP_FREE_SONAME(sin6);
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
- return ENOENT;
+ return (ENOENT);
}
}
SCTP_INP_RUNLOCK(inp);
@@ -1171,36 +1100,28 @@ sctp6_getaddr(struct socket *so, struct sockaddr **addr)
static int
sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)*addr;
+ struct sockaddr_in6 *sin6;
int fnd;
struct sockaddr_in6 *sin_a6;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
-
int error;
- /*
- * Do the malloc first in case it blocks.
- */
- inp = (struct sctp_inpcb *)so->so_pcb;
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
- /* UDP type and listeners will drop out here */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
- return (ENOTCONN);
- }
+ /* Do the malloc first in case it blocks. */
SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
if (sin6 == NULL)
return (ENOMEM);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
- /* We must recapture incase we blocked */
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp == NULL) {
+ if ((inp == NULL) ||
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
+ /* UDP type and listeners will drop out here */
SCTP_FREE_SONAME(sin6);
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
- return ECONNRESET;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
+ return (ENOTCONN);
}
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -1211,7 +1132,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
if (stcb == NULL) {
SCTP_FREE_SONAME(sin6);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
- return ECONNRESET;
+ return (ECONNRESET);
}
fnd = 0;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -1228,7 +1149,7 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
/* No IPv4 address */
SCTP_FREE_SONAME(sin6);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
- return ENOENT;
+ return (ENOENT);
}
if ((error = sa6_recoverscope(sin6)) != 0)
return (error);
@@ -1239,16 +1160,20 @@ sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
static int
sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
{
+#ifdef INET
struct sockaddr *addr;
+
+#endif
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
if (inp6 == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
/* allow v6 addresses precedence */
error = sctp6_getaddr(so, nam);
+#ifdef INET
if (error) {
/* try v4 next if v6 failed */
error = sctp_ingetaddr(so, nam);
@@ -1262,9 +1187,9 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
-
}
}
+#endif
return (error);
}
@@ -1272,22 +1197,27 @@ sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
static int
sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
{
- struct sockaddr *addr = *nam;
+#ifdef INET
+ struct sockaddr *addr;
+
+#endif
struct in6pcb *inp6 = sotoin6pcb(so);
int error;
if (inp6 == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
- return EINVAL;
+ return (EINVAL);
}
/* allow v6 addresses precedence */
error = sctp6_peeraddr(so, nam);
+#ifdef INET
if (error) {
/* try v4 next if v6 failed */
error = sctp_peeraddr(so, nam);
if (error) {
return (error);
}
+ addr = *nam;
/* if I'm V6ONLY, convert it to v4-mapped */
if (SCTP_IPV6_V6ONLY(inp6)) {
struct sockaddr_in6 sin6;
@@ -1296,7 +1226,8 @@ sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
}
}
- return error;
+#endif
+ return (error);
}
struct pr_usrreqs sctp6_usrreqs = {
@@ -1319,3 +1250,5 @@ struct pr_usrreqs sctp6_usrreqs = {
.pru_sosend = sctp_sosend,
.pru_soreceive = sctp_soreceive
};
+
+#endif