Move common code parts to sctp_common_input_processing().

MFC after: 3 days
This commit is contained in:
Michael Tuexen 2012-07-02 16:44:09 +00:00
parent d8d544892c
commit a8775ad93d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=238003
3 changed files with 199 additions and 310 deletions

View File

@ -5590,26 +5590,141 @@ void
sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length,
struct sockaddr *src, struct sockaddr *dst,
struct sctphdr *sh, struct sctp_chunkhdr *ch,
struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net, uint8_t ecn_bits,
#if !defined(SCTP_WITH_NO_CSUM)
uint8_t compute_crc,
#endif
uint8_t ecn_bits,
uint8_t use_mflowid, uint32_t mflowid,
uint32_t vrf_id, uint16_t port)
{
/*
* Control chunk processing
*/
uint32_t high_tsn;
int fwd_tsn_seen = 0, data_processed = 0;
struct mbuf *m = *mm;
int un_sent;
int cnt_ctrl_ready = 0;
struct sctp_inpcb *inp, *inp_decr = NULL;
struct sctp_tcb *stcb = NULL;
struct sctp_nets *net;
SCTP_STAT_INCR(sctps_recvdatagrams);
#ifdef SCTP_AUDITING_ENABLED
sctp_audit_log(0xE0, 1);
sctp_auditing(0, inp, stcb, net);
#endif
#if !defined(SCTP_WITH_NO_CSUM)
if (compute_crc != 0) {
uint32_t check, calc_check;
check = sh->checksum;
sh->checksum = 0;
calc_check = sctp_calculate_cksum(m, iphlen);
sh->checksum = check;
if (calc_check != check) {
SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
calc_check, check, m, length, iphlen);
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
if ((net != NULL) && (port != 0)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
net->port = port;
}
if ((net != NULL) && (use_mflowid != 0)) {
net->flowid = mflowid;
#ifdef INVARIANTS
net->flowidset = 1;
#endif
}
if ((inp != NULL) && (stcb != NULL)) {
sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
} else if ((inp != NULL) && (stcb == NULL)) {
inp_decr = inp;
}
SCTP_STAT_INCR(sctps_badsum);
SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
goto out;
}
}
#endif
/* Destination port of 0 is illegal, based on RFC4960. */
if (sh->dest_port == 0) {
SCTP_STAT_INCR(sctps_hdrops);
goto out;
}
stcb = sctp_findassociation_addr(m, offset, src, dst,
sh, ch, &inp, &net, vrf_id);
if ((net != NULL) && (port != 0)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
net->port = port;
}
if ((net != NULL) && (use_mflowid != 0)) {
net->flowid = mflowid;
#ifdef INVARIANTS
net->flowidset = 1;
#endif
}
if (inp == NULL) {
SCTP_STAT_INCR(sctps_noport);
if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
goto out;
}
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
sctp_send_shutdown_complete2(src, dst, sh,
use_mflowid, mflowid,
vrf_id, port);
goto out;
}
if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
goto out;
}
if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
(ch->chunk_type != SCTP_INIT))) {
sctp_send_abort(m, iphlen, src, dst,
sh, 0, NULL,
use_mflowid, mflowid,
vrf_id, port);
}
}
goto out;
} else if (stcb == NULL) {
inp_decr = inp;
}
#ifdef IPSEC
/*-
* I very much doubt any of the IPSEC stuff will work but I have no
* idea, so I will leave it in place.
*/
if (inp != NULL) {
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
if (ipsec4_in_reject(m, &inp->ip_inp.inp)) {
MODULE_GLOBAL(ipsec4stat).in_polvio++;
SCTP_STAT_INCR(sctps_hdrops);
goto out;
}
break;
#endif
#ifdef INET6
case AF_INET6:
if (ipsec6_in_reject(m, &inp->ip_inp.inp)) {
MODULE_GLOBAL(ipsec6stat).in_polvio++;
SCTP_STAT_INCR(sctps_hdrops);
goto out;
}
break;
#endif
default:
break;
}
}
#endif
SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n",
m, iphlen, offset, length, stcb);
if (stcb) {
@ -5628,10 +5743,11 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
* NOT respond to any packet.. its OOTB.
*/
SCTP_TCB_UNLOCK(stcb);
stcb = NULL;
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
use_mflowid, mflowid,
vrf_id, port);
goto out_now;
goto out;
}
}
if (IS_SCTP_CONTROL(ch)) {
@ -5671,21 +5787,19 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
/* "silently" ignore */
SCTP_STAT_INCR(sctps_recvauthmissing);
SCTP_TCB_UNLOCK(stcb);
goto out_now;
goto out;
}
if (stcb == NULL) {
/* out of the blue DATA chunk */
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
use_mflowid, mflowid,
vrf_id, port);
goto out_now;
goto out;
}
if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
/* v_tag mismatch! */
SCTP_STAT_INCR(sctps_badvtag);
SCTP_TCB_UNLOCK(stcb);
goto out_now;
goto out;
}
}
@ -5695,7 +5809,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
* packet while processing control, or we're done with this
* packet (done or skip rest of data), so we drop it...
*/
goto out_now;
goto out;
}
/*
* DATA chunk processing
@ -5749,8 +5863,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp,
use_mflowid, mflowid,
vrf_id, port);
SCTP_TCB_UNLOCK(stcb);
goto out_now;
goto out;
/* sa_ignore NOTREACHED */
break;
case SCTP_STATE_EMPTY: /* should not happen */
@ -5758,8 +5871,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */
case SCTP_STATE_SHUTDOWN_ACK_SENT:
default:
SCTP_TCB_UNLOCK(stcb);
goto out_now;
goto out;
/* sa_ignore NOTREACHED */
break;
case SCTP_STATE_OPEN:
@ -5777,7 +5889,8 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
* The association aborted, NO UNLOCK needed since
* the association is destroyed.
*/
goto out_now;
stcb = NULL;
goto out;
}
data_processed = 1;
/*
@ -5834,10 +5947,20 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
sctp_audit_log(0xE0, 3);
sctp_auditing(2, inp, stcb, net);
#endif
SCTP_TCB_UNLOCK(stcb);
out_now:
out:
if (stcb != NULL) {
SCTP_TCB_UNLOCK(stcb);
}
if (inp_decr != NULL) {
/* reduce ref-count */
SCTP_INP_WLOCK(inp_decr);
SCTP_INP_DECR_REF(inp_decr);
SCTP_INP_WUNLOCK(inp_decr);
}
#ifdef INVARIANTS
sctp_validate_no_locks(inp);
if (inp != NULL) {
sctp_validate_no_locks(inp);
}
#endif
return;
}
@ -5867,18 +5990,14 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
struct ip *ip;
struct sctphdr *sh;
struct sctp_chunkhdr *ch;
struct sctp_inpcb *inp = NULL;
struct sctp_tcb *stcb = NULL;
struct sctp_nets *net = NULL;
int refcount_up = 0;
int length, offset;
uint32_t mflowid;
uint8_t use_mflowid;
#if !defined(SCTP_WITH_NO_CSUM)
uint32_t check, calc_check;
uint8_t compute_crc;
#endif
uint32_t mflowid;
uint8_t use_mflowid;
iphlen = off;
if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
@ -5903,6 +6022,11 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
sctp_packet_log(m);
}
#endif
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);
if (m->m_flags & M_FLOWID) {
mflowid = m->m_pkthdr.flowid;
use_mflowid = 1;
@ -5936,161 +6060,42 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
dst.sin_addr = ip->ip_dst;
length = ip->ip_len + iphlen;
/* Validate mbuf chain length with IP payload length. */
if (SCTP_HEADER_LEN(i_pak) != length) {
if (SCTP_HEADER_LEN(m) != length) {
SCTPDBG(SCTP_DEBUG_INPUT1,
"sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(i_pak));
"sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
goto out;
}
/* SCTP does not allow broadcasts or multicasts */
if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
goto bad;
goto out;
}
if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) {
goto bad;
goto out;
}
SCTPDBG(SCTP_DEBUG_INPUT1,
"sctp_input() length:%d iphlen:%d\n", length, iphlen);
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 = ip->ip_tos;
#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;
sh->checksum = 0;
calc_check = sctp_calculate_cksum(m, iphlen);
sh->checksum = check;
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 mlen:%d iphlen:%d\n",
calc_check, check, m, length, iphlen);
stcb = sctp_findassociation_addr(m, offset,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, ch, &inp, &net, vrf_id);
if ((net) && (port)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
net->port = port;
}
if ((net != NULL) && (use_mflowid != 0)) {
net->flowid = mflowid;
#ifdef INVARIANTS
net->flowidset = 1;
#endif
}
if ((inp) && (stcb)) {
sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
} else if ((inp != NULL) && (stcb == NULL)) {
refcount_up = 1;
}
SCTP_STAT_INCR(sctps_badsum);
SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
goto bad;
}
sctp_skip_csum:
#endif
/* destination port of 0 is illegal, based on RFC2960. */
if (sh->dest_port == 0) {
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
}
stcb = sctp_findassociation_addr(m, offset,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, ch, &inp, &net, vrf_id);
if ((net) && (port)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
net->port = port;
}
if ((net != NULL) && (use_mflowid != 0)) {
net->flowid = mflowid;
#ifdef INVARIANTS
net->flowidset = 1;
#endif
}
if (inp == NULL) {
SCTP_STAT_INCR(sctps_noport);
if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0)
goto bad;
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
sctp_send_shutdown_complete2((struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh,
use_mflowid, mflowid,
vrf_id, port);
goto bad;
}
if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
goto bad;
}
if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
(ch->chunk_type != SCTP_INIT))) {
sctp_send_abort(m, iphlen,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, 0, NULL,
use_mflowid, mflowid,
vrf_id, port);
}
}
goto bad;
} else if (stcb == NULL) {
refcount_up = 1;
}
#ifdef IPSEC
/*-
* I very much doubt any of the IPSEC stuff will work but I have no
* idea, so I will leave it in place.
*/
if (inp && ipsec4_in_reject(m, &inp->ip_inp.inp)) {
MODULE_GLOBAL(ipsec4stat).in_polvio++;
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
compute_crc = 0;
} else {
SCTP_STAT_INCR(sctps_recvswcrc);
compute_crc = 1;
}
#endif
ecn_bits = ip->ip_tos;
/* sa_ignore NO_NULL_CHK */
sctp_common_input_processing(&m, iphlen, offset, length,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, ch, inp, stcb, net, ecn_bits,
sh, ch,
#if !defined(SCTP_WITH_NO_CSUM)
compute_crc,
#endif
ecn_bits,
use_mflowid, mflowid,
vrf_id, port);
if (m) {
sctp_m_freem(m);
}
if ((inp) && (refcount_up)) {
/* reduce ref-count */
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
}
return;
bad:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
if ((inp) && (refcount_up)) {
/* reduce ref-count */
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
}
out:
if (m) {
sctp_m_freem(m);
}

View File

@ -41,8 +41,10 @@ void
sctp_common_input_processing(struct mbuf **, int, int, int,
struct sockaddr *, struct sockaddr *,
struct sctphdr *, struct sctp_chunkhdr *,
struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *, uint8_t,
#if !defined(SCTP_WITH_NO_CSUM)
uint8_t,
#endif
uint8_t,
uint8_t, uint32_t,
uint32_t, uint16_t);

View File

@ -69,24 +69,20 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
{
struct mbuf *m;
int iphlen;
uint32_t vrf_id = 0;
uint32_t vrf_id;
uint8_t ecn_bits;
struct sockaddr_in6 src, dst;
struct ip6_hdr *ip6;
struct sctphdr *sh;
struct sctp_chunkhdr *ch;
struct sctp_inpcb *inp = NULL;
struct sctp_tcb *stcb = NULL;
struct sctp_nets *net = NULL;
int refcount_up = 0;
int length, offset;
uint32_t mflowid;
uint8_t use_mflowid;
#if !defined(SCTP_WITH_NO_CSUM)
uint32_t check, calc_check;
uint8_t compute_crc;
#endif
uint32_t mflowid;
uint8_t use_mflowid;
uint16_t port = 0;
iphlen = *offp;
@ -112,6 +108,11 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
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;
@ -122,8 +123,8 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
SCTP_STAT_INCR(sctps_recvpackets);
SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
/* Get IP, SCTP, and first chunk header together in the first mbuf. */
ip6 = mtod(m, struct ip6_hdr *);
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) {
@ -138,7 +139,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
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 bad;
goto out;
}
memset(&dst, 0, sizeof(struct sockaddr_in6));
dst.sin6_family = AF_INET6;
@ -146,165 +147,46 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
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 bad;
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(*i_pak) != length) {
if (SCTP_HEADER_LEN(m) != length) {
SCTPDBG(SCTP_DEBUG_INPUT1,
"sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(*i_pak));
"sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
goto out;
}
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
goto bad;
goto out;
}
SCTPDBG(SCTP_DEBUG_INPUT1,
"sctp6_input() length:%d iphlen:%d\n", length, iphlen);
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);
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;
sh->checksum = 0;
calc_check = sctp_calculate_cksum(m, iphlen);
sh->checksum = check;
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 mlen:%d iphlen:%d\n",
calc_check, check, m, length, iphlen);
stcb = sctp_findassociation_addr(m, offset,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, ch, &inp, &net, vrf_id);
if ((net) && (port)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
net->port = port;
}
if ((net != NULL) && (use_mflowid != 0)) {
net->flowid = mflowid;
#ifdef INVARIANTS
net->flowidset = 1;
#endif
}
if ((inp) && (stcb)) {
sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
} else if ((inp != NULL) && (stcb == NULL)) {
refcount_up = 1;
}
SCTP_STAT_INCR(sctps_badsum);
SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
goto bad;
}
sctp_skip_csum:
#endif
/* destination port of 0 is illegal, based on RFC2960. */
if (sh->dest_port == 0) {
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
}
stcb = sctp_findassociation_addr(m, offset,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, ch, &inp, &net, vrf_id);
if ((net) && (port)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
net->port = port;
}
if ((net != NULL) && (use_mflowid != 0)) {
net->flowid = mflowid;
#ifdef INVARIANTS
net->flowidset = 1;
#endif
}
if (inp == NULL) {
SCTP_STAT_INCR(sctps_noport);
if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0)
goto bad;
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
sctp_send_shutdown_complete2((struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh,
use_mflowid, mflowid,
vrf_id, port);
goto bad;
}
if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
goto bad;
}
if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
(ch->chunk_type != SCTP_INIT))) {
sctp_send_abort(m, iphlen,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, 0, NULL,
use_mflowid, mflowid,
vrf_id, port);
}
}
goto bad;
} else if (stcb == NULL) {
refcount_up = 1;
}
#ifdef IPSEC
/*-
* I very much doubt any of the IPSEC stuff will work but I have no
* idea, so I will leave it in place.
*/
if (inp && ipsec6_in_reject(m, &inp->ip_inp.inp)) {
MODULE_GLOBAL(ipsec6stat).in_polvio++;
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
compute_crc = 0;
} else {
SCTP_STAT_INCR(sctps_recvswcrc);
compute_crc = 1;
}
#endif
ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
/* sa_ignore NO_NULL_CHK */
sctp_common_input_processing(&m, iphlen, offset, length,
(struct sockaddr *)&src,
(struct sockaddr *)&dst,
sh, ch, inp, stcb, net, ecn_bits,
sh, ch,
#if !defined(SCTP_WITH_NO_CSUM)
compute_crc,
#endif
ecn_bits,
use_mflowid, mflowid,
vrf_id, port);
if (m) {
sctp_m_freem(m);
}
if ((inp) && (refcount_up)) {
/* reduce ref-count */
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
}
return (IPPROTO_DONE);
bad:
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
}
if ((inp) && (refcount_up)) {
/* reduce ref-count */
SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
SCTP_INP_WUNLOCK(inp);
}
out:
if (m) {
sctp_m_freem(m);
}