From ae2c28677d51467a293871cdfa92b797d6376c88 Mon Sep 17 00:00:00 2001 From: Julian Oes Date: Fri, 8 Apr 2016 09:41:10 +0200 Subject: [PATCH] mavlink: adapt network detection for Mac, use heap It seems that Mac does not support the ioctl to check how big the ifconf buffer needs to be. Therefore we just have to make a guess. Alos, instead of allocating the variable size array on the stack, it's probably safer to use the heap. --- src/modules/mavlink/mavlink_main.cpp | 53 +++++++++++++++------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/modules/mavlink/mavlink_main.cpp b/src/modules/mavlink/mavlink_main.cpp index b9a94c6cd1..81776b520f 100644 --- a/src/modules/mavlink/mavlink_main.cpp +++ b/src/modules/mavlink/mavlink_main.cpp @@ -998,35 +998,47 @@ Mavlink::init_udp() } _src_addr.sin_port = htons(_remote_port); - // Find out the required size of the buffer first. - // We can get the number by providing NULL to ifc_req. struct ifconf ifconf; + int ret; + +#if defined(__APPLE__) && defined(__MACH__) + // On Mac, we can't determine the required buffer + // size in advance, so we just use what tends to work. + ifconf.ifc_len = 1024; +#else + // On Linux, we can determine the required size of the + // buffer first by providing NULL to ifc_req. ifconf.ifc_req = NULL; ifconf.ifc_len = 0; - int ret = ioctl(_socket_fd, SIOCGIFCONF, &ifconf); + ret = ioctl(_socket_fd, SIOCGIFCONF, &ifconf); if (ret != 0) { PX4_WARN("getting required buffer size failed"); return; } +#endif PX4_DEBUG("need to allocate %d bytes", ifconf.ifc_len); - // Allocate buffer as long as needed. - uint8_t ifreqs_buf[ifconf.ifc_len]; - memset(ifreqs_buf, 0, ifconf.ifc_len); - ifconf.ifc_req = (struct ifreq *)ifreqs_buf; + // Allocate buffer. + ifconf.ifc_req = (struct ifreq *)(new uint8_t[ifconf.ifc_len]); + if (ifconf.ifc_req == nullptr) { + PX4_ERR("Could not allocate ifconf buffer"); + return; + } + memset(ifconf.ifc_req, 0, ifconf.ifc_len); ret = ioctl(_socket_fd, SIOCGIFCONF, &ifconf); if (ret != 0) { - PX4_WARN("getting network config failed"); + PX4_ERR("getting network config failed"); + delete[] ifconf.ifc_req; return; } size_t offset = 0; // Later used to point to next network interface in buffer. - struct ifreq *cur_ifreq = (struct ifreq *)&ifreqs_buf[offset]; + struct ifreq *cur_ifreq = (struct ifreq *)&(((uint8_t *)ifconf.ifc_req)[offset]); // The ugly `for` construct is used because it allows to use // `continue` and `break`. @@ -1038,8 +1050,7 @@ Mavlink::init_udp() // sizeof sockaddr or ifr_addr.sa_len. offset += IF_NAMESIZE + (sizeof(struct sockaddr) > cur_ifreq->ifr_addr.sa_len ? - sizeof(struct sockaddr) : - cur_ifreq->ifr_addr.sa_len) + sizeof(struct sockaddr) : cur_ifreq->ifr_addr.sa_len) #else // On Linux, it's much easier to traverse the buffer, every entry // has the constant length. @@ -1048,14 +1059,7 @@ Mavlink::init_udp() ) { // Point to next network interface in buffer. - cur_ifreq = (struct ifreq *)&ifreqs_buf[offset]; - -#if defined(__APPLE__) && defined(__MACH__) - if (cur_ifreq->ifr_addr.sa_len == 0) { - // The current entry seems zero, we're probably through. - break; - } -#endif + cur_ifreq = (struct ifreq *)&(((uint8_t *)ifconf.ifc_req)[offset]); PX4_DEBUG("looking at %s", cur_ifreq->ifr_name); @@ -1073,7 +1077,7 @@ Mavlink::init_udp() strncpy(bc_ifreq.ifr_name, cur_ifreq->ifr_name, IF_NAMESIZE); ret = ioctl(_socket_fd, SIOCGIFBRDADDR, &bc_ifreq); if (ret != 0) { - PX4_INFO("getting broadcast address failed for %s", cur_ifreq->ifr_name); + PX4_DEBUG("getting broadcast address failed for %s", cur_ifreq->ifr_name); continue; } @@ -1105,13 +1109,14 @@ Mavlink::init_udp() } } - if (!_broadcast_address_found) { + if (_broadcast_address_found) { + _bcast_addr.sin_port = htons(_remote_port); + + } else { PX4_WARN("no broadcasting address found"); - return; } - _bcast_addr.sin_port = htons(_remote_port); - + delete[] ifconf.ifc_req; #endif }