Make sure that SCTP rejects broadcast, multicast and wildcard addresses
as remote addresses. Approved by: re MFC after: 1 month.
This commit is contained in:
parent
d2849f27bc
commit
92776dfd5a
@ -207,6 +207,7 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
|
||||
uint16_t param_type, param_length, aparam_length;
|
||||
struct sockaddr *sa;
|
||||
int zero_address = 0;
|
||||
int bad_address = 0;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in *sin;
|
||||
@ -239,6 +240,10 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_port = stcb->rport;
|
||||
sin->sin_addr.s_addr = v4addr->addr;
|
||||
if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
|
||||
IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
|
||||
bad_address = 1;;
|
||||
}
|
||||
if (sin->sin_addr.s_addr == INADDR_ANY)
|
||||
zero_address = 1;
|
||||
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
|
||||
@ -259,6 +264,9 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
|
||||
sin6->sin6_port = stcb->rport;
|
||||
memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
|
||||
sizeof(struct in6_addr));
|
||||
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
|
||||
bad_address = 1;
|
||||
}
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
|
||||
zero_address = 1;
|
||||
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
|
||||
@ -266,12 +274,8 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/*
|
||||
* XXX: Is this the correct error cause? Maybe
|
||||
* SCTP_CAUSE_INVALID_PARAM is a better choice.
|
||||
*/
|
||||
m_reply = sctp_asconf_error_response(aph->correlation_id,
|
||||
SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
|
||||
SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
|
||||
aparam_length);
|
||||
return m_reply;
|
||||
} /* end switch */
|
||||
@ -285,7 +289,11 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
|
||||
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
|
||||
}
|
||||
/* add the address */
|
||||
if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
|
||||
if (bad_address) {
|
||||
m_reply = sctp_asconf_error_response(aph->correlation_id,
|
||||
SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
|
||||
aparam_length);
|
||||
} else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
|
||||
SCTP_ADDR_DYNAMIC_ADDED) != 0) {
|
||||
SCTPDBG(SCTP_DEBUG_ASCONF1,
|
||||
"process_asconf_add_ip: error adding address\n");
|
||||
|
@ -3541,7 +3541,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
|
||||
(sin.sin_addr.s_addr == INADDR_BROADCAST) ||
|
||||
IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
|
||||
*error = EINVAL;
|
||||
return (-1);
|
||||
return (1);
|
||||
}
|
||||
if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, NULL,
|
||||
SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
|
||||
@ -3564,7 +3564,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) ||
|
||||
IN6_IS_ADDR_MULTICAST(&sin6.sin6_addr)) {
|
||||
*error = EINVAL;
|
||||
return (-1);
|
||||
return (1);
|
||||
}
|
||||
#ifdef INET
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
|
||||
@ -3573,7 +3573,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
|
||||
(sin.sin_addr.s_addr == INADDR_BROADCAST) ||
|
||||
IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
|
||||
*error = EINVAL;
|
||||
return (-1);
|
||||
return (1);
|
||||
}
|
||||
if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, NULL,
|
||||
SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
|
||||
|
@ -4332,7 +4332,10 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)firstaddr;
|
||||
if ((sin->sin_port == 0) || (sin->sin_addr.s_addr == 0)) {
|
||||
if ((ntohs(sin->sin_port) == 0) ||
|
||||
(sin->sin_addr.s_addr == INADDR_ANY) ||
|
||||
(sin->sin_addr.s_addr == INADDR_BROADCAST) ||
|
||||
IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
|
||||
/* Invalid address */
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
|
||||
@ -4349,8 +4352,9 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)firstaddr;
|
||||
if ((sin6->sin6_port == 0) ||
|
||||
(IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
|
||||
if ((ntohs(sin6->sin6_port) == 0) ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
|
||||
IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
|
||||
/* Invalid address */
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
|
||||
|
@ -560,7 +560,7 @@ sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
|
||||
struct sctp_inpcb *inp = NULL;
|
||||
int error;
|
||||
|
||||
#ifdef INET6
|
||||
#ifdef INET
|
||||
if (addr && addr->sa_family != AF_INET) {
|
||||
/* must be a v4 address! */
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
|
@ -6080,6 +6080,15 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
|
||||
struct sockaddr *sa;
|
||||
size_t incr = 0;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
||||
#endif
|
||||
|
||||
sa = addr;
|
||||
inp = stcb->sctp_ep;
|
||||
*error = 0;
|
||||
@ -6088,6 +6097,15 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
incr = sizeof(struct sockaddr_in);
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
if ((sin->sin_addr.s_addr == INADDR_ANY) ||
|
||||
(sin->sin_addr.s_addr == INADDR_BROADCAST) ||
|
||||
IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
|
||||
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
|
||||
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
|
||||
*error = EINVAL;
|
||||
goto out_now;
|
||||
}
|
||||
if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
|
||||
/* assoc gone no un-lock */
|
||||
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
|
||||
@ -6101,6 +6119,14 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
incr = sizeof(struct sockaddr_in6);
|
||||
sin6 = (struct sockaddr_in6 *)sa;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
|
||||
IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
|
||||
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
|
||||
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
|
||||
*error = EINVAL;
|
||||
goto out_now;
|
||||
}
|
||||
if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
|
||||
/* assoc gone no un-lock */
|
||||
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
|
||||
|
Loading…
Reference in New Issue
Block a user