From c64686229f12c2fed7096181e67886cb6409e449 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 28 Apr 2013 21:56:24 +0300 Subject: [PATCH] WPS ER: Allow UPnP interface to be forced "WPS_ER_START ifname=" can now be used to force a specific interface to be used for UPnP operations. This is especially useful for automated test cases where the lo interface can now be used easily to perform ER operations. Signed-hostap: Jouni Malinen --- src/wps/wps_er.c | 20 ++++++++++++++++++-- src/wps/wps_er.h | 1 + src/wps/wps_er_ssdp.c | 4 +++- src/wps/wps_upnp_i.h | 2 +- src/wps/wps_upnp_ssdp.c | 25 ++++++++++++++++++++++--- 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index 18df20b39..56949970b 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -1271,6 +1271,22 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) /* Limit event_id to < 32 bits to avoid issues with atoi() */ er->event_id &= 0x0fffffff; + if (filter && os_strncmp(filter, "ifname=", 7) == 0) { + const char *pos, *end; + pos = filter + 7; + end = os_strchr(pos, ' '); + if (end) { + size_t len = end - pos; + os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ? + len + 1 : sizeof(er->ifname)); + filter = end + 1; + } else { + os_strlcpy(er->ifname, pos, sizeof(er->ifname)); + filter = NULL; + } + er->forced_ifname = 1; + } + if (filter) { if (inet_aton(filter, &er->filter_addr) == 0) { wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter " @@ -1281,10 +1297,10 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections " "with %s", filter); } - if (get_netif_info(ifname, &er->ip_addr, &er->ip_addr_text, + if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, er->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " - "for %s. Does it have IP address?", ifname); + "for %s. Does it have IP address?", er->ifname); wps_er_deinit(er, NULL, NULL); return NULL; } diff --git a/src/wps/wps_er.h b/src/wps/wps_er.h index 611964741..4b48ff6ad 100644 --- a/src/wps/wps_er.h +++ b/src/wps/wps_er.h @@ -76,6 +76,7 @@ struct wps_er_ap_settings { struct wps_er { struct wps_context *wps; char ifname[17]; + int forced_ifname; u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */ char *ip_addr_text; /* IP address of network i.f. we use */ unsigned ip_addr; /* IP address of network i.f. we use (host order) */ diff --git a/src/wps/wps_er_ssdp.c b/src/wps/wps_er_ssdp.c index f9f6e6c1a..e381fecbd 100644 --- a/src/wps/wps_er_ssdp.c +++ b/src/wps/wps_er_ssdp.c @@ -166,7 +166,9 @@ int wps_er_ssdp_init(struct wps_er *er) return -1; } - er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr); + er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr, + er->forced_ifname ? + er->ifname : NULL); if (er->multicast_sd < 0) { wpa_printf(MSG_INFO, "WPS ER: Failed to open multicast socket " "for SSDP"); diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h index 7f3c56109..5c39f7efe 100644 --- a/src/wps/wps_upnp_i.h +++ b/src/wps/wps_upnp_i.h @@ -171,7 +171,7 @@ void ssdp_listener_stop(struct upnp_wps_device_sm *sm); int ssdp_listener_start(struct upnp_wps_device_sm *sm); int ssdp_listener_open(void); int add_ssdp_network(const char *net_if); -int ssdp_open_multicast_sock(u32 ip_addr); +int ssdp_open_multicast_sock(u32 ip_addr, const char *forced_ifname); int ssdp_open_multicast(struct upnp_wps_device_sm *sm); /* wps_upnp_web.c */ diff --git a/src/wps/wps_upnp_ssdp.c b/src/wps/wps_upnp_ssdp.c index 17a82074a..416961cc0 100644 --- a/src/wps/wps_upnp_ssdp.c +++ b/src/wps/wps_upnp_ssdp.c @@ -3,7 +3,7 @@ * Copyright (c) 2000-2003 Intel Corporation * Copyright (c) 2006-2007 Sony Corporation * Copyright (c) 2008-2009 Atheros Communications - * Copyright (c) 2009, Jouni Malinen + * Copyright (c) 2009-2013, Jouni Malinen * * See wps_upnp.c for more details on licensing and code history. */ @@ -13,6 +13,9 @@ #include #include #include +#ifdef __linux__ +#include +#endif /* __linux__ */ #include "common.h" #include "uuid.h" @@ -854,7 +857,7 @@ fail: } -int ssdp_open_multicast_sock(u32 ip_addr) +int ssdp_open_multicast_sock(u32 ip_addr, const char *forced_ifname) { int sd; /* per UPnP-arch-DeviceArchitecture, 1. Discovery, keep IP packet @@ -865,6 +868,22 @@ int ssdp_open_multicast_sock(u32 ip_addr) if (sd < 0) return -1; + if (forced_ifname) { +#ifdef __linux__ + struct ifreq req; + os_memset(&req, 0, sizeof(req)); + os_strlcpy(req.ifr_name, forced_ifname, sizeof(req.ifr_name)); + if (setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, &req, + sizeof(req)) < 0) { + wpa_printf(MSG_INFO, "WPS UPnP: Failed to bind " + "multicast socket to ifname %s: %s", + forced_ifname, strerror(errno)); + close(sd); + return -1; + } +#endif /* __linux__ */ + } + #if 0 /* maybe ok if we sometimes block on writes */ if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) { close(sd); @@ -924,7 +943,7 @@ int ssdp_open_multicast_sock(u32 ip_addr) */ int ssdp_open_multicast(struct upnp_wps_device_sm *sm) { - sm->multicast_sd = ssdp_open_multicast_sock(sm->ip_addr); + sm->multicast_sd = ssdp_open_multicast_sock(sm->ip_addr, NULL); if (sm->multicast_sd < 0) return -1; return 0;