From 23f053fc0a392079213bf2f979b7c098baa9d30c Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sat, 13 Mar 2010 13:08:32 +0100 Subject: [PATCH] net: fix broken dccp_available_ccids() This fixes a dumb programming error in dccp_available_ccids(), where a pointer to 1-byte address was type cast to a socklent_t (typically 4 byte) pointer. Changed the interface to not expose internals of call. In addition, this patch adds a missing close() in the error path of makesock(). --- dccp_recv.c | 7 ++++--- dccp_send.c | 7 ++++--- net.c | 32 +++++++++++++++++++------------- net.h | 2 +- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/dccp_recv.c b/dccp_recv.c index a0f8371e..c22fa84d 100644 --- a/dccp_recv.c +++ b/dccp_recv.c @@ -105,10 +105,11 @@ err: */ static bool dccp_recv_ccid_support_check(struct dccp_recv_args_info *conf) { - uint8_t ccids[DCCP_MAX_HOST_CCIDS]; - uint8_t nccids = sizeof(ccids), i, j; + uint8_t *ccids; + int i, j, nccids; - if (dccp_available_ccids(ccids, &nccids) == NULL) + nccids = dccp_available_ccids(&ccids); + if (nccids <= 0) return false; for (i = 0; i < conf->ccid_given; i++) { diff --git a/dccp_send.c b/dccp_send.c index 7d8967cc..e90c63c4 100644 --- a/dccp_send.c +++ b/dccp_send.c @@ -140,12 +140,13 @@ static int dccp_com_allow(struct sender_command_data *scd) */ static const char *dccp_list_available_ccids(void) { - uint8_t ccids[DCCP_MAX_HOST_CCIDS]; - uint8_t nccids = sizeof(ccids), i, len; /* Worst case length: n * 3 digits + n-1 spaces + '\0' */ static char list[DCCP_MAX_HOST_CCIDS * 4]; + uint8_t *ccids; + int i, len, nccids; - if (dccp_available_ccids(ccids, &nccids) == NULL) { + nccids = dccp_available_ccids(&ccids); + if (nccids < 0) { snprintf(list, sizeof(list), "Unable to query available CCIDs"); } else { for (i = len = 0; i < nccids; i++) diff --git a/net.c b/net.c index b9729b69..f34ab852 100644 --- a/net.c +++ b/net.c @@ -436,6 +436,7 @@ int makesock(unsigned l4type, bool passive, if (passive && setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { rc = errno; + close(sockfd); PARA_ERROR_LOG("can not set SO_REUSEADDR: %s\n", strerror(rc)); return -ERRNO_TO_PARA_ERROR(rc); @@ -775,30 +776,35 @@ int para_accept(int fd, void *addr, socklen_t size) } /** - * Probe the list of DCCP CCIDs supported locally by the host. - * \param ccids Array to be filled in. - * \param nccids Length of \a ccids. - * \return Pointer to \a ccids, NULL on failure. + * Probe the list of DCCP CCIDs configured on this host. + * \param ccid_array Pointer to return statically allocated array in. + * \return Number of elements returned in \a ccid_array or error. * * NB: This feature is only available on Linux > 2.6.30; on older kernels * ENOPROTOOPT ("Protocol not available") will be returned. */ -const uint8_t *dccp_available_ccids(uint8_t *ccids, uint8_t *nccids) +int dccp_available_ccids(uint8_t **ccid_array) { - int fd = makesock(IPPROTO_DCCP, 1, NULL, 0, NULL); + static uint8_t ccids[DCCP_MAX_HOST_CCIDS]; + socklen_t nccids = sizeof(ccids); + int ret, fd; - if (fd < 0) - return NULL; + ret = fd = makesock(IPPROTO_DCCP, 1, NULL, 0, NULL); + if (ret < 0) + return ret; if (getsockopt(fd, SOL_DCCP, DCCP_SOCKOPT_AVAILABLE_CCIDS, - ccids, (socklen_t *)nccids) < 0) { + ccids, &nccids) < 0) { + ret = errno; + close(fd); PARA_ERROR_LOG("No DCCP_SOCKOPT_AVAILABLE_CCIDS: %s\n", - strerror(errno)); - *nccids = 0; + strerror(ret)); + return -ERRNO_TO_PARA_ERROR(ret); } - close(fd); - return *nccids ? ccids : NULL; + close(fd); + *ccid_array = ccids; + return nccids; } /** diff --git a/net.h b/net.h index e9974d1c..4eb79a82 100644 --- a/net.h +++ b/net.h @@ -152,4 +152,4 @@ int recv_pattern(int fd, const char *pattern, size_t bufsize); */ /** Hardcoded maximum number of separate CCID modules compiled into a host */ #define DCCP_MAX_HOST_CCIDS 20 -extern const uint8_t *dccp_available_ccids(uint8_t *ccids, uint8_t *nccids); +extern int dccp_available_ccids(uint8_t **ccid_array); -- 2.39.5