Fix several bugs in sctp_bindx():

* Set errno to EAFNOSUPPORT if an address is provided which is neither
  AF_INET nor AF_INET6.
* Don't modify the arguments.
* Don't smash the stack when provided with a non-zero port.
* Handle the case correctly where the first address provided is
  an IPv6 address.

MFC after: 3 days
This commit is contained in:
Michael Tuexen 2014-01-04 11:39:59 +00:00
parent 5d9306834b
commit 1dd0c90501

View File

@ -233,19 +233,11 @@ sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, int flags)
break;
default:
/* Invalid address family specified. */
errno = EINVAL;
errno = EAFNOSUPPORT;
return (-1);
}
sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
}
/*
* Now if there was a port mentioned, assure that the first address
* has that port to make sure it fails or succeeds correctly.
*/
if (sport) {
sin = (struct sockaddr_in *)sa;
sin->sin_port = sport;
}
argsz = sizeof(struct sctp_getaddresses) +
sizeof(struct sockaddr_storage);
if ((gaddrs = (struct sctp_getaddresses *)malloc(argsz)) == NULL) {
@ -257,6 +249,23 @@ sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, int flags)
memset(gaddrs, 0, argsz);
gaddrs->sget_assoc_id = 0;
memcpy(gaddrs->addr, sa, sa->sa_len);
/*
* Now, if there was a port mentioned, assure that the first
* address has that port to make sure it fails or succeeds
* correctly.
*/
if ((i == 0) && (sport != 0)) {
switch (gaddrs->addr->sa_family) {
case AF_INET:
sin = (struct sockaddr_in *)gaddrs->addr;
sin->sin_port = sport;
break;
case AF_INET6:
sin6 = (struct sockaddr_in6 *)gaddrs->addr;
sin6->sin6_port = sport;
break;
}
}
if (setsockopt(sd, IPPROTO_SCTP, flags, gaddrs,
(socklen_t) argsz) != 0) {
free(gaddrs);