summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_input.c
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2012-06-25 19:13:43 +0000
committertuexen <tuexen@FreeBSD.org>2012-06-25 19:13:43 +0000
commit108138a99779b4a03621cfa0cb0f187b1ac0b90d (patch)
tree6ad830e7ccd58d134be97a58bb70b26ac1581436 /sys/netinet/sctp_input.c
parent85590af6fa7e8cead37c00e128451fe7558cf305 (diff)
downloadFreeBSD-src-108138a99779b4a03621cfa0cb0f187b1ac0b90d.zip
FreeBSD-src-108138a99779b4a03621cfa0cb0f187b1ac0b90d.tar.gz
Unify sctp_input() and sctp6_input().
MFC after: 3 days
Diffstat (limited to 'sys/netinet/sctp_input.c')
-rw-r--r--sys/netinet/sctp_input.c112
1 files changed, 35 insertions, 77 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index ab3d33d..3e6f312 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -5885,12 +5885,12 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
uint8_t ecn_bits;
struct ip *ip;
struct sctphdr *sh;
+ struct sctp_chunkhdr *ch;
struct sctp_inpcb *inp = NULL;
- struct sctp_nets *net;
struct sctp_tcb *stcb = NULL;
- struct sctp_chunkhdr *ch;
+ struct sctp_nets *net = NULL;
int refcount_up = 0;
- int length, mlen, offset;
+ int length, offset;
uint32_t mflowid;
uint8_t use_mflowid;
@@ -5899,19 +5899,12 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
#endif
+ iphlen = off;
if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
SCTP_RELEASE_PKT(i_pak);
return;
}
- mlen = SCTP_HEADER_LEN(i_pak);
- iphlen = off;
m = SCTP_HEADER_TO_CHAIN(i_pak);
-
- net = NULL;
- SCTP_STAT_INCR(sctps_recvpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
-
-
#ifdef SCTP_MBUF_LOGGING
/* Log in any input mbufs */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
@@ -5925,8 +5918,9 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
}
#endif
#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
sctp_packet_log(m);
+ }
#endif
if (m->m_flags & M_FLOWID) {
mflowid = m->m_pkthdr.flowid;
@@ -5935,17 +5929,11 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
mflowid = 0;
use_mflowid = 0;
}
- /*
- * Must take out the iphlen, since mlen expects this (only effect lb
- * case)
- */
- mlen -= iphlen;
-
- /*
- * Get IP, SCTP, and first chunk header together in first mbuf.
- */
+ SCTP_STAT_INCR(sctps_recvpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
+ /* Get IP, SCTP, and first chunk header together in the first mbuf. */
ip = mtod(m, struct ip *);
- offset = iphlen + sizeof(*sh) + sizeof(*ch);
+ offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
if (SCTP_BUF_LEN(m) < offset) {
if ((m = m_pullup(m, offset)) == 0) {
SCTP_STAT_INCR(sctps_hdrops);
@@ -5953,28 +5941,26 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
}
ip = mtod(m, struct ip *);
}
- /* validate mbuf chain length with IP payload length */
- if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) {
+ sh = (struct sctphdr *)((caddr_t)ip + iphlen);
+ ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
+ offset -= sizeof(struct sctp_chunkhdr);
+ length = ip->ip_len + iphlen;
+ /* Validate mbuf chain length with IP payload length. */
+ if (SCTP_HEADER_LEN(i_pak) != length) {
+ SCTPDBG(SCTP_DEBUG_INPUT1,
+ "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(i_pak));
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
}
- sh = (struct sctphdr *)((caddr_t)ip + iphlen);
- ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(*sh));
- SCTPDBG(SCTP_DEBUG_INPUT1,
- "sctp_input() length:%d iphlen:%d\n", mlen, iphlen);
-
/* SCTP does not allow broadcasts or multicasts */
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
goto bad;
}
if (SCTP_IS_IT_BROADCAST(ip->ip_dst, m)) {
- /*
- * We only look at broadcast if its a front state, All
- * others we will not have a tcb for anyway.
- */
goto bad;
}
- /* validate SCTP checksum */
+ 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,
@@ -5985,21 +5971,18 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
#else
if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
SCTP_STAT_INCR(sctps_recvhwcrc);
- goto sctp_skip_csum_4;
+ goto sctp_skip_csum;
}
- check = sh->checksum; /* save incoming checksum */
- sh->checksum = 0; /* prepare for calc */
+ 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, mlen, iphlen);
-
- stcb = sctp_findassociation_addr(m,
- offset - sizeof(*ch),
- sh, ch, &inp, &net,
- vrf_id);
+ calc_check, check, m, length, iphlen);
+ stcb = sctp_findassociation_addr(m, offset,
+ sh, ch, &inp, &net, vrf_id);
if ((net) && (port)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
@@ -6013,7 +5996,7 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
#endif
}
if ((inp) && (stcb)) {
- sctp_send_packet_dropped(stcb, net, m, mlen + iphlen, iphlen, 1);
+ 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;
@@ -6022,18 +6005,14 @@ sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
goto bad;
}
-sctp_skip_csum_4:
+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;
}
- /*
- * Locate pcb and tcb for datagram sctp_findassociation_addr() wants
- * IP/SCTP/first chunk header...
- */
- stcb = sctp_findassociation_addr(m, offset - sizeof(*ch),
+ stcb = sctp_findassociation_addr(m, offset,
sh, ch, &inp, &net, vrf_id);
if ((net) && (port)) {
if (net->port == 0) {
@@ -6047,27 +6026,10 @@ sctp_skip_csum_4:
net->flowidset = 1;
#endif
}
- /* inp's ref-count increased && stcb locked */
if (inp == NULL) {
- struct sctp_init_chunk *init_chk, chunk_buf;
-
SCTP_STAT_INCR(sctps_noport);
if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0)
goto bad;
- SCTPDBG(SCTP_DEBUG_INPUT1,
- "Sending a ABORT from packet entry!\n");
- 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 != NULL)
- sh->v_tag = init_chk->init.initiate_tag;
- }
if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
sctp_send_shutdown_complete2(m, sh,
use_mflowid, mflowid,
@@ -6091,7 +6053,7 @@ sctp_skip_csum_4:
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.
*/
@@ -6100,28 +6062,22 @@ sctp_skip_csum_4:
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
}
-#endif /* IPSEC */
-
- /*
- * common chunk processing
- */
- length = ip->ip_len + iphlen;
- offset -= sizeof(struct sctp_chunkhdr);
+#endif
ecn_bits = ip->ip_tos;
-
/* sa_ignore NO_NULL_CHK */
sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
inp, stcb, net, ecn_bits,
use_mflowid, mflowid,
vrf_id, port);
- /* inp's ref-count reduced && stcb unlocked */
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:
@@ -6130,7 +6086,9 @@ bad:
}
if ((inp) && (refcount_up)) {
/* reduce ref-count */
+ SCTP_INP_WLOCK(inp);
SCTP_INP_DECR_REF(inp);
+ SCTP_INP_WUNLOCK(inp);
}
if (m) {
sctp_m_freem(m);
OpenPOWER on IntegriCloud