ptp-helper: Fix interface listing and MAC retrieval on OSX

This commit is contained in:
Sebastian Dröge 2015-06-04 18:00:50 +02:00
parent 957a81eef9
commit d33784ccd0

View file

@ -41,6 +41,11 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <string.h> #include <string.h>
#ifdef __APPLE__
#include <ifaddrs.h>
#include <net/if_dl.h>
#endif
#ifdef HAVE_PTP_HELPER_SETUID #ifdef HAVE_PTP_HELPER_SETUID
#include <grp.h> #include <grp.h>
#include <pwd.h> #include <pwd.h>
@ -235,6 +240,7 @@ setup_sockets (void)
/* Probe all non-loopback interfaces */ /* Probe all non-loopback interfaces */
if (!ifaces) { if (!ifaces) {
#ifndef __APPLE__
struct ifreq ifr; struct ifreq ifr;
struct ifconf ifc; struct ifconf ifc;
gchar buf[8192]; gchar buf[8192];
@ -242,39 +248,56 @@ setup_sockets (void)
ifc.ifc_len = sizeof (buf); ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf; ifc.ifc_buf = buf;
if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) { if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) {
struct ifreq *it = ifc.ifc_req; guint i, idx = 0;
const struct ifreq *const end =
it + (ifc.ifc_len / sizeof (struct ifreq));
guint idx = 0;
probed_ifaces = g_new0 (gchar *, ifc.ifc_len + 1); probed_ifaces = g_new0 (gchar *, ifc.ifc_len + 1);
for (; it != end; ++it) { for (i = 0; i < ifc.ifc_len / sizeof (struct ifreq); i++) {
strcpy (ifr.ifr_name, it->ifr_name); strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name);
if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) { if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) {
if ((ifr.ifr_flags & IFF_LOOPBACK)) if ((ifr.ifr_flags & IFF_LOOPBACK))
continue; continue;
probed_ifaces[idx] = g_strdup (it->ifr_name); probed_ifaces[idx] = g_strdup (ifc.ifc_req[i].ifr_name);
idx++; idx++;
} else { } else {
g_warning ("can't get flags of interface '%s'", it->ifr_name); g_warning ("can't get flags of interface '%s'",
probed_ifaces[idx] = g_strdup (it->ifr_name); ifc.ifc_req[i].ifr_name);
probed_ifaces[idx] = g_strdup (ifc.ifc_req[i].ifr_name);
idx++; idx++;
} }
}
if (idx != 0) if (idx != 0)
ifaces = probed_ifaces; ifaces = probed_ifaces;
} }
} }
#else
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs (&ifaddr) != -1) {
GPtrArray *arr;
arr = g_ptr_array_new ();
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if ((ifa->ifa_flags & IFF_LOOPBACK))
continue;
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK)
continue;
g_ptr_array_add (arr, g_strdup (ifa->ifa_name));
}
freeifaddrs (ifaddr);
g_ptr_array_add (arr, NULL);
ifaces = probed_ifaces = (gchar **) g_ptr_array_free (arr, FALSE);
}
#endif
}
/* Get a clock id from the MAC address if none was given */ /* Get a clock id from the MAC address if none was given */
if (clock_id == (guint64) - 1) { if (clock_id == (guint64) - 1) {
gboolean success = FALSE; gboolean success = FALSE;
/* FIXME: On Apple platforms use IOKit APIs to iterate
* network interfaces and get MAC addresses. Think different!
*/
#ifndef __APPLE__ #ifndef __APPLE__
struct ifreq ifr; struct ifreq ifr;
@ -305,12 +328,10 @@ setup_sockets (void)
ifc.ifc_len = sizeof (buf); ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf; ifc.ifc_buf = buf;
if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) { if (ioctl (g_socket_get_fd (socket_event), SIOCGIFCONF, &ifc) != -1) {
struct ifreq *it = ifc.ifc_req; guint i;
const struct ifreq *const end =
it + (ifc.ifc_len / sizeof (struct ifreq));
for (; it != end; ++it) { for (i = 0; i < ifc.ifc_len / sizeof (struct ifreq); i++) {
strcpy (ifr.ifr_name, it->ifr_name); strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name);
if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) { if (ioctl (g_socket_get_fd (socket_event), SIOCGIFFLAGS, &ifr) == 0) {
if ((ifr.ifr_flags & IFF_LOOPBACK)) if ((ifr.ifr_flags & IFF_LOOPBACK))
continue; continue;
@ -329,11 +350,61 @@ setup_sockets (void)
break; break;
} }
} else { } else {
g_warning ("can't get flags of interface '%s'", it->ifr_name); g_warning ("can't get flags of interface '%s'",
ifc.ifc_req[i].ifr_name);
} }
} }
} }
} }
#else
struct ifaddrs *ifaddr, *ifa;
if (getifaddrs (&ifaddr) != -1) {
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr;
guint8 mac_addr[6];
if ((ifa->ifa_flags & IFF_LOOPBACK))
continue;
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_LINK)
continue;
if (ifaces) {
gchar **p = ifaces;
gboolean found = FALSE;
while (*p) {
if (strcmp (*p, ifa->ifa_name) == 0) {
found = TRUE;
break;
}
p++;
}
if (!found)
continue;
}
if (sdl->sdl_alen != 6)
continue;
memcpy (mac_addr, LLADDR (sdl), sdl->sdl_alen);
clock_id_array[0] = mac_addr[0];
clock_id_array[1] = mac_addr[1];
clock_id_array[2] = mac_addr[2];
clock_id_array[3] = 0xff;
clock_id_array[4] = 0xfe;
clock_id_array[5] = mac_addr[3];
clock_id_array[6] = mac_addr[4];
clock_id_array[7] = mac_addr[5];
success = TRUE;
break;
}
freeifaddrs (ifaddr);
}
#endif #endif
if (!success) { if (!success) {
@ -356,18 +427,22 @@ setup_sockets (void)
while (*ptr) { while (*ptr) {
gint c = 0; gint c = 0;
if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, *ptr, if (!g_socket_join_multicast_group (socket_event, mcast_addr, FALSE, *ptr,
&err)) &err)
g_warning ("Couldn't join multicast group on interface '%s': %s", && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE))
*ptr, err->message); g_warning ("Couldn't join multicast group on interface '%s': %s", *ptr,
err->message);
else else
c++; c++;
g_clear_error (&err);
if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE, if (!g_socket_join_multicast_group (socket_general, mcast_addr, FALSE,
*ptr, &err)) *ptr, &err)
g_warning ("Couldn't join multicast group on interface '%s': %s", && !g_error_matches (err, G_IO_ERROR, G_IO_ERROR_ADDRESS_IN_USE))
*ptr, err->message); g_warning ("Couldn't join multicast group on interface '%s': %s", *ptr,
err->message);
else else
c++; c++;
g_clear_error (&err);
if (c == 2) if (c == 2)
success = TRUE; success = TRUE;