* Copyright (c) 2000-2003 Intel Corporation
* Copyright (c) 2006-2007 Sony Corporation
* Copyright (c) 2008-2009 Atheros Communications
- * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2009-2013, Jouni Malinen <j@w1.fi>
*
* See wps_upnp.c for more details on licensing and code history.
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <net/route.h>
+#ifdef __linux__
+#include <net/if.h>
+#endif /* __linux__ */
#include "common.h"
#include "uuid.h"
}
-/* No. of chars excluding trailing whitespace */
-static int line_length_stripped(const char *l)
-{
- const char *lp = l + line_length(l);
- while (lp > l && !isgraph(lp[-1]))
- lp--;
- return lp - l;
-}
-
-
static int str_starts(const char *str, const char *start)
{
return os_strncmp(str, start, os_strlen(start)) == 0;
struct wpabuf *msg;
char *NTString = "";
char uuid_string[80];
+ struct upnp_wps_device_interface *iface;
*islast = 0;
- uuid_bin2str(sm->wps->uuid, uuid_string, sizeof(uuid_string));
+ iface = dl_list_first(&sm->interfaces,
+ struct upnp_wps_device_interface, list);
+ if (!iface)
+ return NULL;
+ uuid_bin2str(iface->wps->uuid, uuid_string, sizeof(uuid_string));
msg = wpabuf_alloc(800); /* more than big enough */
if (msg == NULL)
- goto fail;
+ return NULL;
switch (a->type) {
case ADVERTISE_UP:
case ADVERTISE_DOWN:
*islast = 1;
return msg;
-
-fail:
- wpabuf_free(msg);
- return NULL;
}
* (see notes above)
*/
next_timeout_msec = 0;
- os_get_random((void *) &r, sizeof(r));
+ if (os_get_random((void *) &r, sizeof(r)) < 0)
+ r = 32768;
next_timeout_sec = UPNP_CACHE_SEC / 4 +
(((UPNP_CACHE_SEC / 4) * r) >> 16);
sm->advertise_count++;
#ifndef CONFIG_NO_STDOUT_DEBUG
const char *start = data;
#endif /* CONFIG_NO_STDOUT_DEBUG */
- const char *end;
int got_host = 0;
int got_st = 0, st_match = 0;
int got_man = 0;
/* Parse remaining lines */
for (; *data != '\0'; data += line_length(data)) {
- end = data + line_length_stripped(data);
if (token_eq(data, "host")) {
/* The host line indicates who the packet
* is addressed to... but do we really care?
}
if (str_starts(data, "uuid:")) {
char uuid_string[80];
+ struct upnp_wps_device_interface *iface;
+ iface = dl_list_first(
+ &sm->interfaces,
+ struct upnp_wps_device_interface,
+ list);
+ if (!iface)
+ continue;
data += os_strlen("uuid:");
- uuid_bin2str(sm->wps->uuid, uuid_string,
+ uuid_bin2str(iface->wps->uuid, uuid_string,
sizeof(uuid_string));
if (str_starts(data, uuid_string))
st_match = 1;
int sd;
sd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sd < 0)
- goto fail;
- if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0)
- goto fail;
- if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
+ if (sd < 0 ||
+ fcntl(sd, F_SETFL, O_NONBLOCK) != 0 ||
+ setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
goto fail;
os_memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
mcast_addr.imr_interface.s_addr = htonl(INADDR_ANY);
mcast_addr.imr_multiaddr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *) &mcast_addr, sizeof(mcast_addr)))
- goto fail;
- if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL,
+ (char *) &mcast_addr, sizeof(mcast_addr)) ||
+ setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof(ttl)))
goto 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
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)
+ if (fcntl(sd, F_SETFL, O_NONBLOCK) != 0) {
+ close(sd);
return -1;
+ }
#endif
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF,
&ip_addr, sizeof(ip_addr))) {
wpa_printf(MSG_DEBUG, "WPS: setsockopt(IP_MULTICAST_IF) %x: "
"%d (%s)", ip_addr, errno, strerror(errno));
+ close(sd);
return -1;
}
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof(ttl))) {
wpa_printf(MSG_DEBUG, "WPS: setsockopt(IP_MULTICAST_TTL): "
"%d (%s)", errno, strerror(errno));
+ close(sd);
return -1;
}
"WPS UPnP: setsockopt "
"IP_ADD_MEMBERSHIP errno %d (%s)",
errno, strerror(errno));
+ close(sd);
return -1;
}
}
*/
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;