svn commit: r252896 - in stable/9/sys: netinet netinet6
Michael Tuexen
tuexen at FreeBSD.org
Sat Jul 6 20:35:22 UTC 2013
Author: tuexen
Date: Sat Jul 6 20:35:21 2013
New Revision: 252896
URL: http://svnweb.freebsd.org/changeset/base/252896
Log:
MFC r238003, r239091:
Move common code parts to sctp_common_input_processing().
Fix a bug found by dim@:
Don't use an uninitilized variable, if INVARIANTS is on and an illegal
packet with destination 0 is received.
Modified:
stable/9/sys/netinet/sctp_input.c
stable/9/sys/netinet/sctp_input.h
stable/9/sys/netinet6/sctp6_usrreq.c
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/netinet/sctp_input.c
==============================================================================
--- stable/9/sys/netinet/sctp_input.c Sat Jul 6 20:31:22 2013 (r252895)
+++ stable/9/sys/netinet/sctp_input.c Sat Jul 6 20:35:21 2013 (r252896)
@@ -5588,26 +5588,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 = NULL, *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) {
@@ -5626,10 +5741,11 @@ sctp_common_input_processing(struct mbuf
* 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)) {
@@ -5669,21 +5785,19 @@ sctp_common_input_processing(struct mbuf
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;
}
}
@@ -5693,7 +5807,7 @@ sctp_common_input_processing(struct mbuf
* 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
@@ -5747,8 +5861,7 @@ sctp_common_input_processing(struct mbuf
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 */
@@ -5756,8 +5869,7 @@ sctp_common_input_processing(struct mbuf
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:
@@ -5775,7 +5887,8 @@ sctp_common_input_processing(struct mbuf
* The association aborted, NO UNLOCK needed since
* the association is destroyed.
*/
- goto out_now;
+ stcb = NULL;
+ goto out;
}
data_processed = 1;
/*
@@ -5832,10 +5945,20 @@ trigger_send:
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;
}
@@ -5865,18 +5988,14 @@ sctp_input_with_port(struct mbuf *i_pak,
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)) {
@@ -5901,6 +6020,11 @@ sctp_input_with_port(struct mbuf *i_pak,
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;
@@ -5934,161 +6058,42 @@ sctp_input_with_port(struct mbuf *i_pak,
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);
}
Modified: stable/9/sys/netinet/sctp_input.h
==============================================================================
--- stable/9/sys/netinet/sctp_input.h Sat Jul 6 20:31:22 2013 (r252895)
+++ stable/9/sys/netinet/sctp_input.h Sat Jul 6 20:35:21 2013 (r252896)
@@ -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);
Modified: stable/9/sys/netinet6/sctp6_usrreq.c
==============================================================================
--- stable/9/sys/netinet6/sctp6_usrreq.c Sat Jul 6 20:31:22 2013 (r252895)
+++ stable/9/sys/netinet6/sctp6_usrreq.c Sat Jul 6 20:35:21 2013 (r252896)
@@ -70,24 +70,20 @@ sctp6_input(struct mbuf **i_pak, int *of
{
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;
@@ -113,6 +109,11 @@ sctp6_input(struct mbuf **i_pak, int *of
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;
@@ -123,8 +124,8 @@ sctp6_input(struct mbuf **i_pak, int *of
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) {
@@ -139,7 +140,7 @@ sctp6_input(struct mbuf **i_pak, int *of
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;
@@ -147,165 +148,46 @@ sctp6_input(struct mbuf **i_pak, int *of
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);
}
More information about the svn-src-stable-9
mailing list