summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_usrreq.c')
-rw-r--r--sys/netinet/sctp_usrreq.c74
1 files changed, 43 insertions, 31 deletions
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 5f43234..81d2478 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -254,48 +254,49 @@ sctp_notify(struct sctp_inpcb *inp,
void
sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
{
- struct ip *ip = vip;
+ struct ip *outer_ip, *inner_ip;
struct sctphdr *sh;
- struct icmp *icmph;
- uint32_t vrf_id;
+ struct icmp *icmp;
+ struct sctp_inpcb *inp;
+ struct sctp_tcb *stcb;
+ struct sctp_nets *net;
+ struct sctp_init_chunk *ch;
+ struct sockaddr_in to, from;
- /* FIX, for non-bsd is this right? */
- vrf_id = SCTP_DEFAULT_VRFID;
if (sa->sa_family != AF_INET ||
((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
return;
}
if (PRC_IS_REDIRECT(cmd)) {
- ip = 0;
+ vip = NULL;
} else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
return;
}
- if (ip) {
- struct sctp_inpcb *inp = NULL;
- struct sctp_tcb *stcb = NULL;
- struct sctp_nets *net = NULL;
- struct sockaddr_in to, from;
-
- icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
- sizeof(struct ip)));
-
- sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
+ if (vip != NULL) {
+ inner_ip = (struct ip *)vip;
+ icmp = (struct icmp *)((caddr_t)inner_ip -
+ (sizeof(struct icmp) - sizeof(struct ip)));
+ outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip));
+ sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2));
bzero(&to, sizeof(to));
bzero(&from, sizeof(from));
from.sin_family = to.sin_family = AF_INET;
from.sin_len = to.sin_len = sizeof(to);
from.sin_port = sh->src_port;
- from.sin_addr = ip->ip_src;
+ from.sin_addr = inner_ip->ip_src;
to.sin_port = sh->dest_port;
- to.sin_addr = ip->ip_dst;
+ to.sin_addr = inner_ip->ip_dst;
/*
* 'to' holds the dest of the packet that failed to be sent.
* 'from' holds our local endpoint address. Thus we reverse
* the to and the from in the lookup.
*/
+ inp = NULL;
+ net = NULL;
stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
(struct sockaddr *)&from,
- &inp, &net, 1, vrf_id);
+ &inp, &net, 1,
+ SCTP_DEFAULT_VRFID);
if ((stcb != NULL) &&
(net != NULL) &&
(inp != NULL) &&
@@ -313,19 +314,30 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
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 (ntohs(outer_ip->ip_len) >=
+ sizeof(struct ip) +
+ 8 + (inner_ip->ip_hl << 2) + 20) {
+ /*
+ * In this case we can check if we
+ * got an INIT chunk and if the
+ * initiate tag matches.
+ */
+ ch = (struct sctp_init_chunk *)(sh + 1);
+ if ((ch->ch.chunk_type != SCTP_INITIATION) ||
+ (ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) {
+ SCTP_TCB_UNLOCK(stcb);
+ return;
+ }
+ } else {
+ SCTP_TCB_UNLOCK(stcb);
+ return;
+ }
}
sctp_notify(inp, stcb, net,
- icmph->icmp_type,
- icmph->icmp_code,
- ntohs(ip->ip_len),
- ntohs(icmph->icmp_nextmtu));
+ icmp->icmp_type,
+ icmp->icmp_code,
+ ntohs(inner_ip->ip_len),
+ ntohs(icmp->icmp_nextmtu));
} else {
if ((stcb == NULL) && (inp != NULL)) {
/* reduce ref-count */
@@ -457,7 +469,7 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS
uint32_t vrf_id = SCTP_DEFAULT_VRFID;
inp = (struct sctp_inpcb *)so->so_pcb;
- if (inp != 0) {
+ if (inp != NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
OpenPOWER on IntegriCloud