summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2011-06-16 15:36:09 +0000
committertuexen <tuexen@FreeBSD.org>2011-06-16 15:36:09 +0000
commit1c7060f746aa61b1e64ab5d7c28f505778df5341 (patch)
tree8f8d1f1a57df0cccb08a36cab3fe5617506e336b /lib
parent9edb76f49f5032758e6d132fd9ad6d736d9efcde (diff)
downloadFreeBSD-src-1c7060f746aa61b1e64ab5d7c28f505778df5341.zip
FreeBSD-src-1c7060f746aa61b1e64ab5d7c28f505778df5341.tar.gz
* Fix the handling of addresses in sctp_sendv().
* Add support for SCTP_SENDV_NOINFO. * Improve the error handling of sctp_sendv() and sctp_recv(). MFC after: 1 month
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/net/sctp_sys_calls.c125
1 files changed, 83 insertions, 42 deletions
diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c
index a450c17..c43243b 100644
--- a/lib/libc/net/sctp_sys_calls.c
+++ b/lib/libc/net/sctp_sys_calls.c
@@ -942,6 +942,12 @@ sctp_recvv(int sd,
struct sctp_rcvinfo *rcvinfo;
struct sctp_nxtinfo *nxtinfo;
+ if (((info != NULL) && (infolen == NULL)) |
+ ((info == NULL) && (infolen != NULL) && (*infolen != 0)) ||
+ ((info != NULL) && (infotype == NULL))) {
+ errno = EINVAL;
+ return (-1);
+ }
if (infotype) {
*infotype = SCTP_RECVV_NOINFO;
}
@@ -1017,16 +1023,22 @@ sctp_sendv(int sd,
{
ssize_t ret;
int i;
- size_t addr_len;
- struct sctp_sendv_spa *spa_info;
+ socklen_t addr_len;
struct msghdr msg;
+ in_port_t port;
+ struct sctp_sendv_spa *spa_info;
struct cmsghdr *cmsg;
char *cmsgbuf;
struct sockaddr *addr;
struct sockaddr_in *addr_in;
struct sockaddr_in6 *addr_in6;
- if ((addrcnt < 0) || (iovcnt < 0)) {
+ if ((addrcnt < 0) ||
+ (iovcnt < 0) ||
+ ((addr == NULL) && (addrcnt > 0)) ||
+ ((addr != NULL) && (addrcnt == 0)) ||
+ ((iov == NULL) && (iovcnt > 0)) ||
+ ((iov != NULL) && (iovcnt == 0))) {
errno = EINVAL;
return (-1);
}
@@ -1042,8 +1054,15 @@ sctp_sendv(int sd,
msg.msg_controllen = 0;
cmsg = (struct cmsghdr *)cmsgbuf;
switch (infotype) {
+ case SCTP_SENDV_NOINFO:
+ if ((infolen != 0) || (info != NULL)) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ break;
case SCTP_SENDV_SNDINFO:
- if (infolen < sizeof(struct sctp_sndinfo)) {
+ if ((info == NULL) || (infolen < sizeof(struct sctp_sndinfo))) {
free(cmsgbuf);
errno = EINVAL;
return (-1);
@@ -1056,7 +1075,7 @@ sctp_sendv(int sd,
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
break;
case SCTP_SENDV_PRINFO:
- if (infolen < sizeof(struct sctp_prinfo)) {
+ if ((info == NULL) || (infolen < sizeof(struct sctp_prinfo))) {
free(cmsgbuf);
errno = EINVAL;
return (-1);
@@ -1069,7 +1088,7 @@ sctp_sendv(int sd,
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
break;
case SCTP_SENDV_AUTHINFO:
- if (infolen < sizeof(struct sctp_authinfo)) {
+ if ((info == NULL) || (infolen < sizeof(struct sctp_authinfo))) {
free(cmsgbuf);
errno = EINVAL;
return (-1);
@@ -1082,7 +1101,7 @@ sctp_sendv(int sd,
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
break;
case SCTP_SENDV_SPA:
- if (infolen < sizeof(struct sctp_sendv_spa)) {
+ if ((info == NULL) || (infolen < sizeof(struct sctp_sendv_spa))) {
free(cmsgbuf);
errno = EINVAL;
return (-1);
@@ -1119,52 +1138,74 @@ sctp_sendv(int sd,
return (-1);
}
addr = addrs;
- if (addrcnt == 1) {
- msg.msg_name = addr;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ for (i = 0; i < addrcnt; i++) {
switch (addr->sa_family) {
case AF_INET:
- msg.msg_namelen = sizeof(struct sockaddr_in);
+ addr_len = (socklen_t) sizeof(struct sockaddr_in);
+ addr_in = (struct sockaddr_in *)addr;
+ if (addr_in->sin_len != addr_len) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ if (i == 0) {
+ port = addr_in->sin_port;
+ } else {
+ if (port == addr_in->sin_port) {
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_DSTADDRV4;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+ memcpy(CMSG_DATA(cmsg), &addr_in->sin_addr, sizeof(struct in_addr));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr)));
+ } else {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ }
break;
case AF_INET6:
- msg.msg_namelen = sizeof(struct sockaddr_in6);
+ addr_len = (socklen_t) sizeof(struct sockaddr_in6);
+ addr_in6 = (struct sockaddr_in6 *)addr;
+ if (addr_in6->sin6_len != addr_len) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ if (i == 0) {
+ port = addr_in6->sin6_port;
+ } else {
+ if (port == addr_in6->sin6_port) {
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_DSTADDRV6;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_addr));
+ memcpy(CMSG_DATA(cmsg), &addr_in6->sin6_addr, sizeof(struct in6_addr));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_addr));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr)));
+ } else {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ }
break;
default:
free(cmsgbuf);
errno = EINVAL;
return (-1);
}
- } else {
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- for (i = 0; i < addrcnt; i++) {
- switch (addr->sa_family) {
- case AF_INET:
- addr_len = sizeof(struct sockaddr_in);
- addr_in = (struct sockaddr_in *)addr;
- cmsg->cmsg_level = IPPROTO_SCTP;
- cmsg->cmsg_type = SCTP_DSTADDRV4;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
- memcpy(CMSG_DATA(cmsg), &addr_in->sin_addr, sizeof(struct in_addr));
- msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
- cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr)));
- break;
- case AF_INET6:
- addr_len = sizeof(struct sockaddr_in6);
- addr_in6 = (struct sockaddr_in6 *)addr;
- cmsg->cmsg_level = IPPROTO_SCTP;
- cmsg->cmsg_type = SCTP_DSTADDRV6;
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_addr));
- memcpy(CMSG_DATA(cmsg), &addr_in6->sin6_addr, sizeof(struct in6_addr));
- msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_addr));
- cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr)));
- break;
- default:
- free(cmsgbuf);
- errno = EINVAL;
- return (-1);
- }
- addr = (struct sockaddr *)((caddr_t)addr + addr_len);
+ if (i == 0) {
+ msg.msg_name = addr;
+ msg.msg_namelen = addr_len;
}
+ addr = (struct sockaddr *)((caddr_t)addr + addr_len);
+ }
+ if (msg.msg_controllen == 0) {
+ msg.msg_control = NULL;
}
if (msg.msg_controllen == 0) {
msg.msg_control = NULL;
OpenPOWER on IntegriCloud