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
This commit is contained in:
parent
003c82d713
commit
cf4476eb39
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297855
@ -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)) {
|
||||
|
@ -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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user