Handle the case when calling the IPPROTO_SCTP level socket option
SCTP_STATUS on an association with no primary path (early state). This issue was found by running syzkaller. MFC after: 3 days
This commit is contained in:
parent
8124c05f2c
commit
49f1449309
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=344723
@ -2644,42 +2644,47 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
sstat->sstat_instrms = stcb->asoc.streamincnt;
|
||||
sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
|
||||
sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
|
||||
memcpy(&sstat->sstat_primary.spinfo_address,
|
||||
&stcb->asoc.primary_destination->ro._l_addr,
|
||||
((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
|
||||
net = stcb->asoc.primary_destination;
|
||||
((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
|
||||
/*
|
||||
* Again the user can get info from sctp_constants.h
|
||||
* for what the state of the network is.
|
||||
*/
|
||||
if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
|
||||
/* It's unconfirmed */
|
||||
sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
|
||||
} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
|
||||
/* It's active */
|
||||
sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
|
||||
} else {
|
||||
/* It's inactive */
|
||||
sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
|
||||
}
|
||||
sstat->sstat_primary.spinfo_cwnd = net->cwnd;
|
||||
sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
|
||||
sstat->sstat_primary.spinfo_rto = net->RTO;
|
||||
sstat->sstat_primary.spinfo_mtu = net->mtu;
|
||||
switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
|
||||
if (net != NULL) {
|
||||
memcpy(&sstat->sstat_primary.spinfo_address,
|
||||
&stcb->asoc.primary_destination->ro._l_addr,
|
||||
((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
|
||||
((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
|
||||
/*
|
||||
* Again the user can get info from
|
||||
* sctp_constants.h for what the state of
|
||||
* the network is.
|
||||
*/
|
||||
if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
|
||||
/* It's unconfirmed */
|
||||
sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
|
||||
} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
|
||||
/* It's active */
|
||||
sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
|
||||
} else {
|
||||
/* It's inactive */
|
||||
sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
|
||||
}
|
||||
sstat->sstat_primary.spinfo_cwnd = net->cwnd;
|
||||
sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
|
||||
sstat->sstat_primary.spinfo_rto = net->RTO;
|
||||
sstat->sstat_primary.spinfo_mtu = net->mtu;
|
||||
switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
|
||||
#if defined(INET)
|
||||
case AF_INET:
|
||||
sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
|
||||
break;
|
||||
case AF_INET:
|
||||
sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
|
||||
break;
|
||||
#endif
|
||||
#if defined(INET6)
|
||||
case AF_INET6:
|
||||
sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
|
||||
break;
|
||||
case AF_INET6:
|
||||
sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
memset(&sstat->sstat_primary, 0, sizeof(struct sctp_paddrinfo));
|
||||
}
|
||||
sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
|
Loading…
Reference in New Issue
Block a user