net: fix broken dccp_available_ccids()
authorGerrit Renker <grenker@cscs.ch>
Sat, 13 Mar 2010 12:08:32 +0000 (13:08 +0100)
committerAndre Noll <maan@systemlinux.org>
Sat, 13 Mar 2010 12:08:32 +0000 (13:08 +0100)
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
dccp_send.c
net.c
net.h

index a0f8371efae6b0974a4f9c88ef1365b208a48eda..c22fa84d461ed48a7a35c980ad32b8c8129b65c8 100644 (file)
@@ -105,10 +105,11 @@ err:
  */
 static bool dccp_recv_ccid_support_check(struct dccp_recv_args_info *conf)
 {
  */
 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++) {
                return false;
 
        for (i = 0; i < conf->ccid_given; i++) {
index 7d8967cca6f9ad47dc5b8578b350fd81d2ad49d8..e90c63c4c9f3527b6d65f06d252940a0ba2cab05 100644 (file)
@@ -140,12 +140,13 @@ static int dccp_com_allow(struct sender_command_data *scd)
  */
 static const char *dccp_list_available_ccids(void)
 {
  */
 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];
        /* 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++)
                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 b9729b6988f894a3e346a591b477ed0fb9012149..f34ab8522eaf7b36b1bc5996c226cc5cd8b0bcb0 100644 (file)
--- 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;
                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);
                        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.
  */
  *
  * 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,
 
        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",
                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 e9974d1c342316c4f6073b5f4afb8895143dc5d6..4eb79a82db9c303a7afd4c5e3ff13428ef79f0c0 100644 (file)
--- 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
  */
 /** 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);