diff options
author | tuexen <tuexen@FreeBSD.org> | 2014-01-07 23:51:41 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2014-01-07 23:51:41 +0000 |
commit | c4f2c365c9e2791fc74b817c70f98dc2846e5cbd (patch) | |
tree | 08f533859e3ba8e260b03630fd02138405478d98 /lib | |
parent | 624cda0839e8304fdd1091289e62b9caab51b889 (diff) | |
download | FreeBSD-src-c4f2c365c9e2791fc74b817c70f98dc2846e5cbd.zip FreeBSD-src-c4f2c365c9e2791fc74b817c70f98dc2846e5cbd.tar.gz |
MFC r260257:
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.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/sctp_sys_calls.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c index fda9676..a7da95c 100644 --- a/lib/libc/net/sctp_sys_calls.c +++ b/lib/libc/net/sctp_sys_calls.c @@ -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); |