Check for too short packets when using the receive threads.
Thanks to Ivan Fratric for reporting the issue.
@@ -371,10 +371,17 @@ recv_function_raw(void *arg)
} while (ncounter > 0);
}
+ offset = sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
+ if (SCTP_BUF_LEN(recvmbuf[0]) < offset) {
+ if ((recvmbuf[0] = m_pullup(recvmbuf[0], offset)) == NULL) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ continue;
+ }
+ }
iphdr = mtod(recvmbuf[0], struct ip *);
sh = (struct sctphdr *)((caddr_t)iphdr + sizeof(struct ip));
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
- offset = sizeof(struct ip) + sizeof(struct sctphdr);
+ offset -= sizeof(struct sctp_chunkhdr);
if (iphdr->ip_tos != 0) {
ecn = iphdr->ip_tos & 0x03;
@@ -579,9 +586,16 @@ recv_function_raw6(void *arg)
continue;
}
+ offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
+ if (SCTP_BUF_LEN(recvmbuf6[0]) < offset) {
+ if ((recvmbuf6[0] = m_pullup(recvmbuf6[0], offset)) == NULL) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ continue;
+ }
+ }
sh = mtod(recvmbuf6[0], struct sctphdr *);
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
- offset = sizeof(struct sctphdr);
+ offset -= sizeof(struct sctp_chunkhdr);
dst.sin6_family = AF_INET6;
#ifdef HAVE_SIN6_LEN
@@ -793,10 +807,17 @@ recv_function_udp(void *arg)
continue;
}
- /*offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);*/
+ offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
+ if (SCTP_BUF_LEN(udprecvmbuf[0]) < offset) {
+ if ((udprecvmbuf[0] = m_pullup(udprecvmbuf[0], offset)) == NULL) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ continue;
+ }
+ }
sh = mtod(udprecvmbuf[0], struct sctphdr *);
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
- offset = sizeof(struct sctphdr);
+ offset -= sizeof(struct sctp_chunkhdr);
+
port = src.sin_port;
src.sin_port = sh->src_port;
dst.sin_port = sh->dest_port;
@@ -981,9 +1002,16 @@ recv_function_udp6(void *arg)
continue;
}
+ offset = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
+ if (SCTP_BUF_LEN(udprecvmbuf6[0]) < offset) {
+ if ((udprecvmbuf6[0] = m_pullup(udprecvmbuf6[0], offset)) == NULL) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ continue;
+ }
+ }
sh = mtod(udprecvmbuf6[0], struct sctphdr *);
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
- offset = sizeof(struct sctphdr);
+ offset -= sizeof(struct sctp_chunkhdr);
port = src.sin6_port;
src.sin6_port = sh->src_port;
