Skip to content

Commit

Permalink
qga: Move HW address getting to a separate function
Browse files Browse the repository at this point in the history
In the next patch FreeBSD support for guest-network-get-interfaces will be
added. Previously move Linux-specific code of HW address getting to a
separate functions and add a dumb function to commands-bsd.c.

Reviewed-by: Konstantin Kostiuk <kkostiuk@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
Signed-off-by: Konstantin Kostiuk <kkostiuk@redhat.com>
  • Loading branch information
AlexanderIvanov-Virtuozzo authored and kostyanf14 committed Oct 26, 2022
1 parent 4fd0642 commit a124109
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 42 deletions.
16 changes: 16 additions & 0 deletions qga/commands-bsd.c
Expand Up @@ -167,3 +167,19 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error **errp)
return NULL;
}
#endif /* CONFIG_FSFREEZE */

#ifdef HAVE_GETIFADDRS
/*
* Fill "buf" with MAC address by ifaddrs. Pointer buf must point to a
* buffer with ETHER_ADDR_LEN length at least.
*
* Returns false in case of an error, otherwise true. "obtained" arguument
* is true if a MAC address was obtained successful, otherwise false.
*/
bool guest_get_hw_addr(struct ifaddrs *ifa, unsigned char *buf,
bool *obtained, Error **errp)
{
*obtained = false;
return true;
}
#endif /* HAVE_GETIFADDRS */
6 changes: 6 additions & 0 deletions qga/commands-common.h
Expand Up @@ -56,6 +56,12 @@ int64_t qmp_guest_fsfreeze_do_freeze_list(bool has_mountpoints,
int qmp_guest_fsfreeze_do_thaw(Error **errp);
#endif /* CONFIG_FSFREEZE */

#ifdef HAVE_GETIFADDRS
#include <ifaddrs.h>
bool guest_get_hw_addr(struct ifaddrs *ifa, unsigned char *buf,
bool *obtained, Error **errp);
#endif

typedef struct GuestFileHandle GuestFileHandle;

GuestFileHandle *guest_file_handle_find(int64_t id, Error **errp);
Expand Down
98 changes: 56 additions & 42 deletions qga/commands-posix.c
Expand Up @@ -41,20 +41,12 @@
#endif
#endif

#ifdef __FreeBSD__
/*
* The code under HAVE_GETIFADDRS condition can't be compiled in FreeBSD.
* Fix it in one of the following patches.
*/
#undef HAVE_GETIFADDRS
#endif

#ifdef HAVE_GETIFADDRS
#include <arpa/inet.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <sys/types.h>
#include <ifaddrs.h>
#ifdef CONFIG_SOLARIS
#include <sys/sockio.h>
#endif
Expand Down Expand Up @@ -2889,6 +2881,57 @@ static int guest_get_network_stats(const char *name,
return -1;
}

#ifndef __FreeBSD__
/*
* Fill "buf" with MAC address by ifaddrs. Pointer buf must point to a
* buffer with ETHER_ADDR_LEN length at least.
*
* Returns false in case of an error, otherwise true. "obtained" argument
* is true if a MAC address was obtained successful, otherwise false.
*/
bool guest_get_hw_addr(struct ifaddrs *ifa, unsigned char *buf,
bool *obtained, Error **errp)
{
struct ifreq ifr;
int sock;

*obtained = false;

/* we haven't obtained HW address yet */
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
error_setg_errno(errp, errno, "failed to create socket");
return false;
}

memset(&ifr, 0, sizeof(ifr));
pstrcpy(ifr.ifr_name, IF_NAMESIZE, ifa->ifa_name);
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
/*
* We can't get the hw addr of this interface, but that's not a
* fatal error.
*/
if (errno == EADDRNOTAVAIL) {
/* The interface doesn't have a hw addr (e.g. loopback). */
g_debug("failed to get MAC address of %s: %s",
ifa->ifa_name, strerror(errno));
} else{
g_warning("failed to get MAC address of %s: %s",
ifa->ifa_name, strerror(errno));
}
} else {
#ifdef CONFIG_SOLARIS
memcpy(buf, &ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
#else
memcpy(buf, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
#endif
*obtained = true;
}
close(sock);
return true;
}
#endif /* __FreeBSD__ */

/*
* Build information about guest interfaces
*/
Expand All @@ -2909,9 +2952,8 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
GuestNetworkInterfaceStat *interface_stat = NULL;
char addr4[INET_ADDRSTRLEN];
char addr6[INET6_ADDRSTRLEN];
int sock;
struct ifreq ifr;
unsigned char *mac_addr;
unsigned char mac_addr[ETHER_ADDR_LEN];
bool obtained;
void *p;

g_debug("Processing %s interface", ifa->ifa_name);
Expand All @@ -2926,45 +2968,17 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
}

if (!info->has_hardware_address) {
/* we haven't obtained HW address yet */
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == -1) {
error_setg_errno(errp, errno, "failed to create socket");
if (!guest_get_hw_addr(ifa, mac_addr, &obtained, errp)) {
goto error;
}

memset(&ifr, 0, sizeof(ifr));
pstrcpy(ifr.ifr_name, IF_NAMESIZE, info->name);
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) {
/*
* We can't get the hw addr of this interface, but that's not a
* fatal error. Don't set info->hardware_address, but keep
* going.
*/
if (errno == EADDRNOTAVAIL) {
/* The interface doesn't have a hw addr (e.g. loopback). */
g_debug("failed to get MAC address of %s: %s",
ifa->ifa_name, strerror(errno));
} else{
g_warning("failed to get MAC address of %s: %s",
ifa->ifa_name, strerror(errno));
}

} else {
#ifdef CONFIG_SOLARIS
mac_addr = (unsigned char *) &ifr.ifr_addr.sa_data;
#else
mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
#endif
if (obtained) {
info->hardware_address =
g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",
(int) mac_addr[0], (int) mac_addr[1],
(int) mac_addr[2], (int) mac_addr[3],
(int) mac_addr[4], (int) mac_addr[5]);

info->has_hardware_address = true;
}
close(sock);
}

if (ifa->ifa_addr &&
Expand Down

0 comments on commit a124109

Please sign in to comment.