WPS ER: Move SSDP functionality into a separate file
authorJouni Malinen <j@w1.fi>
Sat, 21 Nov 2009 15:26:23 +0000 (17:26 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 21 Nov 2009 15:26:23 +0000 (17:26 +0200)
src/wps/wps_er.c
src/wps/wps_er.h [new file with mode: 0644]
src/wps/wps_er_ssdp.c [new file with mode: 0644]
wpa_supplicant/Makefile

index 21fec3d..3c94bec 100644 (file)
 #include "wps_i.h"
 #include "wps_upnp.h"
 #include "wps_upnp_i.h"
+#include "wps_er.h"
 
 
-/* TODO:
- * send notification of new AP device with wpa_msg
- * re-send notifications with wpa_msg if ER re-started (to update wpa_gui-qt4)
- * (also re-send SSDP M-SEARCH in this case to find new APs)
- * parse UPnP event messages
- */
-
 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx);
 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx);
-
-
-struct wps_er_sta {
-       struct wps_er_sta *next;
-       struct wps_er_ap *ap;
-       u8 addr[ETH_ALEN];
-       u16 config_methods;
-       u8 uuid[WPS_UUID_LEN];
-       u8 pri_dev_type[8];
-       u16 dev_passwd_id;
-       int m1_received;
-       char *manufacturer;
-       char *model_name;
-       char *model_number;
-       char *serial_number;
-       char *dev_name;
-       struct wps_data *wps;
-       struct http_client *http;
-};
-
-struct wps_er_ap {
-       struct wps_er_ap *next;
-       struct wps_er *er;
-       struct wps_er_sta *sta; /* list of STAs/Enrollees using this AP */
-       struct in_addr addr;
-       char *location;
-       struct http_client *http;
-       struct wps_data *wps;
-
-       u8 uuid[WPS_UUID_LEN];
-       u8 pri_dev_type[8];
-       u8 wps_state;
-       u8 mac_addr[ETH_ALEN];
-       char *friendly_name;
-       char *manufacturer;
-       char *manufacturer_url;
-       char *model_description;
-       char *model_name;
-       char *model_number;
-       char *model_url;
-       char *serial_number;
-       char *udn;
-       char *upc;
-
-       char *scpd_url;
-       char *control_url;
-       char *event_sub_url;
-
-       int subscribed;
-       unsigned int id;
-
-       struct wps_credential *ap_settings;
-
-       void (*m1_handler)(struct wps_er_ap *ap, struct wpabuf *m1);
-};
-
-struct wps_er {
-       struct wps_context *wps;
-       char ifname[17];
-       char *mac_addr_text; /* mac addr of network i.f. we use */
-       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) */
-       int multicast_sd;
-       int ssdp_sd;
-       struct wps_er_ap *ap;
-       struct http_server *http_srv;
-       int http_port;
-       unsigned int next_ap_id;
-};
-
-
 static void wps_er_ap_process(struct wps_er_ap *ap, struct wpabuf *msg);
 static int wps_er_send_get_device_info(struct wps_er_ap *ap,
                                       void (*m1_handler)(struct wps_er_ap *ap,
@@ -502,9 +424,8 @@ static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c,
 }
 
 
-static void wps_er_ap_add(struct wps_er *er, const u8 *uuid,
-                         struct in_addr *addr,
-                         const char *location, int max_age)
+void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr,
+                  const char *location, int max_age)
 {
        struct wps_er_ap *ap;
 
@@ -542,7 +463,7 @@ static void wps_er_ap_add(struct wps_er *er, const u8 *uuid,
 }
 
 
-static void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr)
+void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr)
 {
        struct wps_er_ap *prev = NULL, *ap = er->ap;
 
@@ -576,138 +497,6 @@ static void wps_er_ap_remove_all(struct wps_er *er)
 }
 
 
-static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
-{
-       struct wps_er *er = eloop_ctx;
-       struct sockaddr_in addr; /* client address */
-       socklen_t addr_len;
-       int nread;
-       char buf[MULTICAST_MAX_READ], *pos, *pos2, *start;
-       int wfa = 0, byebye = 0;
-       int max_age = -1;
-       char *location = NULL;
-       u8 uuid[WPS_UUID_LEN];
-
-       addr_len = sizeof(addr);
-       nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
-                        (struct sockaddr *) &addr, &addr_len);
-       if (nread <= 0)
-               return;
-       buf[nread] = '\0';
-
-       wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
-                  inet_ntoa(addr.sin_addr));
-       wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
-                         (u8 *) buf, nread);
-
-       if (sd == er->multicast_sd) {
-               /* Reply to M-SEARCH */
-               if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
-                       return; /* unexpected response header */
-       } else {
-               /* Unsolicited message (likely NOTIFY or M-SEARCH) */
-               if (os_strncmp(buf, "NOTIFY ", 7) != 0)
-                       return; /* only process notifications */
-       }
-
-       os_memset(uuid, 0, sizeof(uuid));
-
-       for (start = buf; start && *start; start = pos) {
-               pos = os_strchr(start, '\n');
-               if (pos) {
-                       if (pos[-1] == '\r')
-                               pos[-1] = '\0';
-                       *pos++ = '\0';
-               }
-               if (os_strstr(start, "schemas-wifialliance-org:device:"
-                             "WFADevice:1"))
-                       wfa = 1;
-               if (os_strstr(start, "schemas-wifialliance-org:service:"
-                             "WFAWLANConfig:1"))
-                       wfa = 1;
-               if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
-                       start += 9;
-                       while (*start == ' ')
-                               start++;
-                       location = start;
-               } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
-                       if (os_strstr(start, "ssdp:byebye"))
-                               byebye = 1;
-               } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
-                       start += 9;
-                       while (*start == ' ')
-                               start++;
-                       pos2 = os_strstr(start, "max-age=");
-                       if (pos2 == NULL)
-                               continue;
-                       pos2 += 8;
-                       max_age = atoi(pos2);
-               } else if (os_strncasecmp(start, "USN:", 4) == 0) {
-                       start += 4;
-                       pos2 = os_strstr(start, "uuid:");
-                       if (pos2) {
-                               pos2 += 5;
-                               while (*pos2 == ' ')
-                                       pos2++;
-                               uuid_str2bin(pos2, uuid);
-                       }
-               }
-       }
-
-       if (!wfa)
-               return; /* Not WPS advertisement/reply */
-
-       if (byebye) {
-               wps_er_ap_remove(er, &addr.sin_addr);
-               return;
-       }
-
-       if (!location)
-               return; /* Unknown location */
-
-       if (max_age < 1)
-               return; /* No max-age reported */
-
-       wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
-                  "(packet source: %s  max-age: %d)",
-                  location, inet_ntoa(addr.sin_addr), max_age);
-
-       wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age);
-}
-
-
-static void wps_er_send_ssdp_msearch(struct wps_er *er)
-{
-       struct wpabuf *msg;
-       struct sockaddr_in dest;
-
-       msg = wpabuf_alloc(500);
-       if (msg == NULL)
-               return;
-
-       wpabuf_put_str(msg,
-                      "M-SEARCH * HTTP/1.1\r\n"
-                      "HOST: 239.255.255.250:1900\r\n"
-                      "MAN: \"ssdp:discover\"\r\n"
-                      "MX: 3\r\n"
-                      "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
-                      "\r\n"
-                      "\r\n");
-
-       os_memset(&dest, 0, sizeof(dest));
-       dest.sin_family = AF_INET;
-       dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
-       dest.sin_port = htons(UPNP_MULTICAST_PORT);
-
-       if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
-                  (struct sockaddr *) &dest, sizeof(dest)) < 0)
-               wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
-                          "%d (%s)", errno, strerror(errno));
-
-       wpabuf_free(msg);
-}
-
-
 static void http_put_date(struct wpabuf *buf)
 {
        wpabuf_put_str(buf, "Date: ");
@@ -1261,26 +1050,7 @@ wps_er_init(struct wps_context *wps, const char *ifname)
                return NULL;
        }
 
-       if (add_ssdp_network(ifname)) {
-               wps_er_deinit(er);
-               return NULL;
-       }
-
-       er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr);
-       if (er->multicast_sd < 0) {
-               wps_er_deinit(er);
-               return NULL;
-       }
-
-       er->ssdp_sd = ssdp_listener_open();
-       if (er->ssdp_sd < 0) {
-               wps_er_deinit(er);
-               return NULL;
-       }
-       if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
-                               wps_er_ssdp_rx, er, NULL) ||
-           eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
-                               wps_er_ssdp_rx, er, NULL)) {
+       if (wps_er_ssdp_init(er) < 0) {
                wps_er_deinit(er);
                return NULL;
        }
@@ -1297,8 +1067,6 @@ wps_er_init(struct wps_context *wps, const char *ifname)
                   "mac_addr=%s)",
                   er->ifname, er->ip_addr_text, er->mac_addr_text);
 
-       wps_er_send_ssdp_msearch(er);
-
        return er;
 }
 
@@ -1324,14 +1092,7 @@ void wps_er_deinit(struct wps_er *er)
                return;
        http_server_deinit(er->http_srv);
        wps_er_ap_remove_all(er);
-       if (er->multicast_sd >= 0) {
-               eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
-               close(er->multicast_sd);
-       }
-       if (er->ssdp_sd >= 0) {
-               eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
-               close(er->ssdp_sd);
-       }
+       wps_er_ssdp_deinit(er);
        os_free(er->ip_addr_text);
        os_free(er->mac_addr_text);
        os_free(er);
diff --git a/src/wps/wps_er.h b/src/wps/wps_er.h
new file mode 100644 (file)
index 0000000..cf2048c
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef WPS_ER_H
+#define WPS_ER_H
+
+struct wps_er_sta {
+       struct wps_er_sta *next;
+       struct wps_er_ap *ap;
+       u8 addr[ETH_ALEN];
+       u16 config_methods;
+       u8 uuid[WPS_UUID_LEN];
+       u8 pri_dev_type[8];
+       u16 dev_passwd_id;
+       int m1_received;
+       char *manufacturer;
+       char *model_name;
+       char *model_number;
+       char *serial_number;
+       char *dev_name;
+       struct wps_data *wps;
+       struct http_client *http;
+};
+
+struct wps_er_ap {
+       struct wps_er_ap *next;
+       struct wps_er *er;
+       struct wps_er_sta *sta; /* list of STAs/Enrollees using this AP */
+       struct in_addr addr;
+       char *location;
+       struct http_client *http;
+       struct wps_data *wps;
+
+       u8 uuid[WPS_UUID_LEN];
+       u8 pri_dev_type[8];
+       u8 wps_state;
+       u8 mac_addr[ETH_ALEN];
+       char *friendly_name;
+       char *manufacturer;
+       char *manufacturer_url;
+       char *model_description;
+       char *model_name;
+       char *model_number;
+       char *model_url;
+       char *serial_number;
+       char *udn;
+       char *upc;
+
+       char *scpd_url;
+       char *control_url;
+       char *event_sub_url;
+
+       int subscribed;
+       unsigned int id;
+
+       struct wps_credential *ap_settings;
+
+       void (*m1_handler)(struct wps_er_ap *ap, struct wpabuf *m1);
+};
+
+struct wps_er {
+       struct wps_context *wps;
+       char ifname[17];
+       char *mac_addr_text; /* mac addr of network i.f. we use */
+       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) */
+       int multicast_sd;
+       int ssdp_sd;
+       struct wps_er_ap *ap;
+       struct http_server *http_srv;
+       int http_port;
+       unsigned int next_ap_id;
+};
+
+
+/* wps_er.c */
+void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr,
+                  const char *location, int max_age);
+void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr);
+
+/* wps_er_ssdp.c */
+int wps_er_ssdp_init(struct wps_er *er);
+void wps_er_ssdp_deinit(struct wps_er *er);
+void wps_er_send_ssdp_msearch(struct wps_er *er);
+
+#endif /* WPS_ER_H */
diff --git a/src/wps/wps_er_ssdp.c b/src/wps/wps_er_ssdp.c
new file mode 100644 (file)
index 0000000..83879db
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Wi-Fi Protected Setup - External Registrar (SSDP)
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "uuid.h"
+#include "eloop.h"
+#include "wps_i.h"
+#include "wps_upnp.h"
+#include "wps_upnp_i.h"
+#include "wps_er.h"
+
+
+static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
+{
+       struct wps_er *er = eloop_ctx;
+       struct sockaddr_in addr; /* client address */
+       socklen_t addr_len;
+       int nread;
+       char buf[MULTICAST_MAX_READ], *pos, *pos2, *start;
+       int wfa = 0, byebye = 0;
+       int max_age = -1;
+       char *location = NULL;
+       u8 uuid[WPS_UUID_LEN];
+
+       addr_len = sizeof(addr);
+       nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
+                        (struct sockaddr *) &addr, &addr_len);
+       if (nread <= 0)
+               return;
+       buf[nread] = '\0';
+
+       wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
+                  inet_ntoa(addr.sin_addr));
+       wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
+                         (u8 *) buf, nread);
+
+       if (sd == er->multicast_sd) {
+               /* Reply to M-SEARCH */
+               if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
+                       return; /* unexpected response header */
+       } else {
+               /* Unsolicited message (likely NOTIFY or M-SEARCH) */
+               if (os_strncmp(buf, "NOTIFY ", 7) != 0)
+                       return; /* only process notifications */
+       }
+
+       os_memset(uuid, 0, sizeof(uuid));
+
+       for (start = buf; start && *start; start = pos) {
+               pos = os_strchr(start, '\n');
+               if (pos) {
+                       if (pos[-1] == '\r')
+                               pos[-1] = '\0';
+                       *pos++ = '\0';
+               }
+               if (os_strstr(start, "schemas-wifialliance-org:device:"
+                             "WFADevice:1"))
+                       wfa = 1;
+               if (os_strstr(start, "schemas-wifialliance-org:service:"
+                             "WFAWLANConfig:1"))
+                       wfa = 1;
+               if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
+                       start += 9;
+                       while (*start == ' ')
+                               start++;
+                       location = start;
+               } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
+                       if (os_strstr(start, "ssdp:byebye"))
+                               byebye = 1;
+               } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
+                       start += 9;
+                       while (*start == ' ')
+                               start++;
+                       pos2 = os_strstr(start, "max-age=");
+                       if (pos2 == NULL)
+                               continue;
+                       pos2 += 8;
+                       max_age = atoi(pos2);
+               } else if (os_strncasecmp(start, "USN:", 4) == 0) {
+                       start += 4;
+                       pos2 = os_strstr(start, "uuid:");
+                       if (pos2) {
+                               pos2 += 5;
+                               while (*pos2 == ' ')
+                                       pos2++;
+                               uuid_str2bin(pos2, uuid);
+                       }
+               }
+       }
+
+       if (!wfa)
+               return; /* Not WPS advertisement/reply */
+
+       if (byebye) {
+               wps_er_ap_remove(er, &addr.sin_addr);
+               return;
+       }
+
+       if (!location)
+               return; /* Unknown location */
+
+       if (max_age < 1)
+               return; /* No max-age reported */
+
+       wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
+                  "(packet source: %s  max-age: %d)",
+                  location, inet_ntoa(addr.sin_addr), max_age);
+
+       wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age);
+}
+
+
+void wps_er_send_ssdp_msearch(struct wps_er *er)
+{
+       struct wpabuf *msg;
+       struct sockaddr_in dest;
+
+       msg = wpabuf_alloc(500);
+       if (msg == NULL)
+               return;
+
+       wpabuf_put_str(msg,
+                      "M-SEARCH * HTTP/1.1\r\n"
+                      "HOST: 239.255.255.250:1900\r\n"
+                      "MAN: \"ssdp:discover\"\r\n"
+                      "MX: 3\r\n"
+                      "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
+                      "\r\n"
+                      "\r\n");
+
+       os_memset(&dest, 0, sizeof(dest));
+       dest.sin_family = AF_INET;
+       dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
+       dest.sin_port = htons(UPNP_MULTICAST_PORT);
+
+       if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
+                  (struct sockaddr *) &dest, sizeof(dest)) < 0)
+               wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
+                          "%d (%s)", errno, strerror(errno));
+
+       wpabuf_free(msg);
+}
+
+
+int wps_er_ssdp_init(struct wps_er *er)
+{
+       if (add_ssdp_network(er->ifname))
+               return -1;
+
+       er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr);
+       if (er->multicast_sd < 0)
+               return -1;
+
+       er->ssdp_sd = ssdp_listener_open();
+       if (er->ssdp_sd < 0)
+               return -1;
+
+       if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
+                               wps_er_ssdp_rx, er, NULL) ||
+           eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
+                               wps_er_ssdp_rx, er, NULL))
+               return -1;
+
+       wps_er_send_ssdp_msearch(er);
+
+       return 0;
+}
+
+
+void wps_er_ssdp_deinit(struct wps_er *er)
+{
+       if (er->multicast_sd >= 0) {
+               eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
+               close(er->multicast_sd);
+       }
+       if (er->ssdp_sd >= 0) {
+               eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
+               close(er->ssdp_sd);
+       }
+}
index 0879774..19621ec 100644 (file)
@@ -501,6 +501,7 @@ ifdef CONFIG_WPS_ER
 CONFIG_WPS_UPNP=y
 CFLAGS += -DCONFIG_WPS_ER
 OBJS += ../src/wps/wps_er.o
+OBJS += ../src/wps/wps_er_ssdp.o
 endif
 
 ifdef CONFIG_WPS_UPNP