summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Guiraud <christophe.guiraud@intel.com>2013-09-09 10:00:46 +0200
committerrmerlino <regis.merlino@intel.com>2013-12-12 14:54:21 +0100
commit93345aa14496ff074d05d19d747017ac01cd5433 (patch)
tree907a3ad4193fd350f0fa4d78a4d69a9ab205dcb7
parent344aafd8c04ddf9d0e8af7b0bca1307fec53b6a7 (diff)
downloaddleyna-server-93345aa14496ff074d05d19d747017ac01cd5433.tar.gz
[Device] Fix wake-on ip address used for broadcast
When the wake-on method is UDP broadcast, we now use the broadcast IP address of the active context newtork interface. if the broadcast IP address can't be retrieved, we use the IP address provided in the network interface info. Signed-off-by: Christophe Guiraud <christophe.guiraud@intel.com>
-rw-r--r--libdleyna/server/device.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/libdleyna/server/device.c b/libdleyna/server/device.c
index 2bb9901..b09814a 100644
--- a/libdleyna/server/device.c
+++ b/libdleyna/server/device.c
@@ -22,6 +22,15 @@
#include <string.h>
#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
#include <libgupnp/gupnp-error.h>
#include <libgupnp-dlna/gupnp-dlna-profile.h>
#include <libgupnp-dlna/gupnp-dlna-profile-guesser.h>
@@ -5996,6 +6005,70 @@ on_complete:
return error;
}
+static gboolean prv_get_interface_ip_address(struct sockaddr *sock_address,
+ gchar *host)
+{
+ socklen_t sock_len;
+ gint family;
+ gboolean res = FALSE;
+
+ family = sock_address->sa_family;
+
+ if (family != AF_INET && family != AF_INET6)
+ goto on_exit;
+
+ if (family == AF_INET)
+ sock_len = sizeof(struct sockaddr_in);
+ else
+ sock_len = sizeof(struct sockaddr_in6);
+
+ if (getnameinfo(sock_address, sock_len, host,
+ NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == 0) {
+ if (family == AF_INET6)
+ inet_ntop(AF_INET6, &sock_address, host, NI_MAXHOST);
+
+ res = TRUE;
+ }
+
+on_exit:
+ return res;
+}
+
+static gchar *prv_get_broadcast_ip_address(gchar *ip_address)
+{
+ struct ifaddrs *ifaddr;
+ struct ifaddrs *ifa;
+ char host[NI_MAXHOST];
+ gchar *broadcast_ip_address = NULL;
+
+ if (getifaddrs(&ifaddr) == -1) {
+ DLEYNA_LOG_WARNING("Failed to call getifaddrs");
+ goto on_exit;
+ }
+
+ ifa = ifaddr;
+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ if ((ifa->ifa_addr == NULL) ||
+ (!prv_get_interface_ip_address(ifa->ifa_addr, host)) ||
+ strcmp(host, ip_address))
+ continue;
+
+ if ((ifa->ifa_flags & IFF_BROADCAST) &&
+ (ifa->ifa_ifu.ifu_broadaddr != NULL) &&
+ prv_get_interface_ip_address(ifa->ifa_ifu.ifu_broadaddr,
+ host)) {
+ broadcast_ip_address = g_strdup(host);
+
+ break;
+ }
+ }
+
+ freeifaddrs(ifaddr);
+
+on_exit:
+
+ return broadcast_ip_address;
+}
void dls_device_wake(dls_client_t *client, dls_task_t *task)
{
@@ -6010,6 +6083,7 @@ void dls_device_wake(dls_client_t *client, dls_task_t *task)
gsize packet_len;
guint8 *packet = NULL;
gchar *wake_on_ip_address;
+ gchar *broadcast_ip_address = NULL;
DLEYNA_LOG_DEBUG("Enter");
@@ -6058,6 +6132,18 @@ void dls_device_wake(dls_client_t *client, dls_task_t *task)
DLEYNA_LOG_DEBUG("Context IP Address = %s", context->ip_address);
DLEYNA_LOG_DEBUG("Wake ON IP Address = %s", wake_on_ip_address);
+ if (broadcast) {
+ broadcast_ip_address = prv_get_broadcast_ip_address(
+ context->ip_address);
+
+ if (broadcast_ip_address != NULL) {
+ wake_on_ip_address = broadcast_ip_address;
+
+ DLEYNA_LOG_DEBUG("Use Broadcast IP Address = %s",
+ broadcast_ip_address);
+ }
+ }
+
host_inet_address = g_inet_address_new_from_string(wake_on_ip_address);
if (host_inet_address == NULL) {
@@ -6112,6 +6198,8 @@ on_complete:
(void) g_idle_add(dls_async_task_complete, cb_data);
on_exit:
+ g_free(broadcast_ip_address);
+
DLEYNA_LOG_DEBUG("Exit");
return;