svn commit: r297855 - head/sys/netinet
Michael Tuexen
tuexen at FreeBSD.org
Tue Apr 12 11:48:55 UTC 2016
Author: tuexen
Date: Tue Apr 12 11:48:54 2016
New Revision: 297855
URL: https://svnweb.freebsd.org/changeset/base/297855
Log:
When processing an ICMP packet containing an SCTP packet, it
is required to check the verification tag. However, this
requires the verification tag to be not 0. Enforce this.
For packets with a verification tag of 0, we need to
check it it contains an INIT chunk and use the initiate
tag for the validation. This will be a separate commit,
since it touches also other code.
MFC after: 1 week
Modified:
head/sys/netinet/sctp_usrreq.c
head/sys/netinet/sctp_var.h
Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c Tue Apr 12 11:48:50 2016 (r297854)
+++ head/sys/netinet/sctp_usrreq.c Tue Apr 12 11:48:54 2016 (r297855)
@@ -147,26 +147,19 @@ static void
sctp_notify_mbuf(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net,
- struct ip *ip,
- struct sctphdr *sh)
+ struct ip *ip)
{
struct icmp *icmph;
int totsz, tmr_stopped = 0;
uint16_t nxtsz;
/* protection */
- if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
- (ip == NULL) || (sh == NULL)) {
+ if ((inp == NULL) || (stcb == NULL) || (net == NULL) || (ip == NULL)) {
if (stcb != NULL) {
SCTP_TCB_UNLOCK(stcb);
}
return;
}
- /* First job is to verify the vtag matches what I would send */
- if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
- SCTP_TCB_UNLOCK(stcb);
- return;
- }
icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
sizeof(struct ip)));
if (icmph->icmp_type != ICMP_UNREACH) {
@@ -213,10 +206,9 @@ sctp_notify_mbuf(struct sctp_inpcb *inp,
SCTP_TCB_UNLOCK(stcb);
}
-void
+static void
sctp_notify(struct sctp_inpcb *inp,
struct ip *ip,
- struct sctphdr *sh,
struct sockaddr *to,
struct sctp_tcb *stcb,
struct sctp_nets *net)
@@ -228,17 +220,11 @@ sctp_notify(struct sctp_inpcb *inp,
struct icmp *icmph;
/* protection */
- if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
- (sh == NULL) || (to == NULL)) {
+ if ((inp == NULL) || (stcb == NULL) || (net == NULL) || (to == NULL)) {
if (stcb)
SCTP_TCB_UNLOCK(stcb);
return;
}
- /* First job is to verify the vtag matches what I would send */
- if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
- SCTP_TCB_UNLOCK(stcb);
- return;
- }
icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
sizeof(struct ip)));
if (icmph->icmp_type != ICMP_UNREACH) {
@@ -304,10 +290,7 @@ sctp_notify(struct sctp_inpcb *inp,
#ifdef INET
void
-sctp_ctlinput(cmd, sa, vip)
- int cmd;
- struct sockaddr *sa;
- void *vip;
+sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
{
struct ip *ip = vip;
struct sctphdr *sh;
@@ -348,14 +331,37 @@ sctp_ctlinput(cmd, sa, vip)
stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
(struct sockaddr *)&from,
&inp, &net, 1, vrf_id);
- if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
+ if ((stcb != NULL) &&
+ (inp != NULL) &&
+ (inp->sctp_socket != NULL)) {
+ /* Check the verification tag */
+ if (ntohl(sh->v_tag) != 0) {
+ /*
+ * This must be the verification tag used
+ * for sending out packets. We don't
+ * consider packets reflecting the
+ * verification tag.
+ */
+ if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
+ SCTP_TCB_UNLOCK(stcb);
+ return;
+ }
+ } else {
+ /*
+ * In this case we could check if we got an
+ * INIT chunk and if the initiate tag
+ * matches. But this is not there yet...
+ */
+ SCTP_TCB_UNLOCK(stcb);
+ return;
+ }
if (cmd != PRC_MSGSIZE) {
- sctp_notify(inp, ip, sh,
+ sctp_notify(inp, ip,
(struct sockaddr *)&to, stcb,
net);
} else {
/* handle possible ICMP size messages */
- sctp_notify_mbuf(inp, stcb, net, ip, sh);
+ sctp_notify_mbuf(inp, stcb, net, ip);
}
} else {
if ((stcb == NULL) && (inp != NULL)) {
Modified: head/sys/netinet/sctp_var.h
==============================================================================
--- head/sys/netinet/sctp_var.h Tue Apr 12 11:48:50 2016 (r297854)
+++ head/sys/netinet/sctp_var.h Tue Apr 12 11:48:54 2016 (r297855)
@@ -344,10 +344,6 @@ void sctp_init(void);
void sctp_finish(void);
int sctp_flush(struct socket *, int);
int sctp_shutdown(struct socket *);
-void
-sctp_notify(struct sctp_inpcb *, struct ip *ip, struct sctphdr *,
- struct sockaddr *, struct sctp_tcb *,
- struct sctp_nets *);
int
sctp_bindx(struct socket *, int, struct sockaddr_storage *,
int, int, struct proc *);
More information about the svn-src-head
mailing list