wps_er_ssdp.c
Go to the documentation of this file.
00001 /*
00002  * Wi-Fi Protected Setup - External Registrar (SSDP)
00003  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "uuid.h"
00019 #include "eloop.h"
00020 #include "wps_i.h"
00021 #include "wps_upnp.h"
00022 #include "wps_upnp_i.h"
00023 #include "wps_er.h"
00024 
00025 
00026 static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
00027 {
00028         struct wps_er *er = eloop_ctx;
00029         struct sockaddr_in addr; /* client address */
00030         socklen_t addr_len;
00031         int nread;
00032         char buf[MULTICAST_MAX_READ], *pos, *pos2, *start;
00033         int wfa = 0, byebye = 0;
00034         int max_age = -1;
00035         char *location = NULL;
00036         u8 uuid[WPS_UUID_LEN];
00037 
00038         addr_len = sizeof(addr);
00039         nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
00040                          (struct sockaddr *) &addr, &addr_len);
00041         if (nread <= 0)
00042                 return;
00043         buf[nread] = '\0';
00044 
00045         wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
00046                    inet_ntoa(addr.sin_addr));
00047         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
00048                           (u8 *) buf, nread);
00049 
00050         if (sd == er->multicast_sd) {
00051                 /* Reply to M-SEARCH */
00052                 if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
00053                         return; /* unexpected response header */
00054         } else {
00055                 /* Unsolicited message (likely NOTIFY or M-SEARCH) */
00056                 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
00057                         return; /* only process notifications */
00058         }
00059 
00060         os_memset(uuid, 0, sizeof(uuid));
00061 
00062         for (start = buf; start && *start; start = pos) {
00063                 pos = os_strchr(start, '\n');
00064                 if (pos) {
00065                         if (pos[-1] == '\r')
00066                                 pos[-1] = '\0';
00067                         *pos++ = '\0';
00068                 }
00069                 if (os_strstr(start, "schemas-wifialliance-org:device:"
00070                               "WFADevice:1"))
00071                         wfa = 1;
00072                 if (os_strstr(start, "schemas-wifialliance-org:service:"
00073                               "WFAWLANConfig:1"))
00074                         wfa = 1;
00075                 if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
00076                         start += 9;
00077                         while (*start == ' ')
00078                                 start++;
00079                         location = start;
00080                 } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
00081                         if (os_strstr(start, "ssdp:byebye"))
00082                                 byebye = 1;
00083                 } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
00084                         start += 9;
00085                         while (*start == ' ')
00086                                 start++;
00087                         pos2 = os_strstr(start, "max-age=");
00088                         if (pos2 == NULL)
00089                                 continue;
00090                         pos2 += 8;
00091                         max_age = atoi(pos2);
00092                 } else if (os_strncasecmp(start, "USN:", 4) == 0) {
00093                         start += 4;
00094                         pos2 = os_strstr(start, "uuid:");
00095                         if (pos2) {
00096                                 pos2 += 5;
00097                                 while (*pos2 == ' ')
00098                                         pos2++;
00099                                 if (uuid_str2bin(pos2, uuid) < 0) {
00100                                         wpa_printf(MSG_DEBUG, "WPS ER: "
00101                                                    "Invalid UUID in USN: %s",
00102                                                    pos2);
00103                                         return;
00104                                 }
00105                         }
00106                 }
00107         }
00108 
00109         if (!wfa)
00110                 return; /* Not WPS advertisement/reply */
00111 
00112         if (byebye) {
00113                 wps_er_ap_remove(er, &addr.sin_addr);
00114                 return;
00115         }
00116 
00117         if (!location)
00118                 return; /* Unknown location */
00119 
00120         if (max_age < 1)
00121                 return; /* No max-age reported */
00122 
00123         wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
00124                    "(packet source: %s  max-age: %d)",
00125                    location, inet_ntoa(addr.sin_addr), max_age);
00126 
00127         wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age);
00128 }
00129 
00130 
00131 void wps_er_send_ssdp_msearch(struct wps_er *er)
00132 {
00133         struct wpabuf *msg;
00134         struct sockaddr_in dest;
00135 
00136         msg = wpabuf_alloc(500);
00137         if (msg == NULL)
00138                 return;
00139 
00140         wpabuf_put_str(msg,
00141                        "M-SEARCH * HTTP/1.1\r\n"
00142                        "HOST: 239.255.255.250:1900\r\n"
00143                        "MAN: \"ssdp:discover\"\r\n"
00144                        "MX: 3\r\n"
00145                        "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
00146                        "\r\n"
00147                        "\r\n");
00148 
00149         os_memset(&dest, 0, sizeof(dest));
00150         dest.sin_family = AF_INET;
00151         dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
00152         dest.sin_port = htons(UPNP_MULTICAST_PORT);
00153 
00154         if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
00155                    (struct sockaddr *) &dest, sizeof(dest)) < 0)
00156                 wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
00157                            "%d (%s)", errno, strerror(errno));
00158 
00159         wpabuf_free(msg);
00160 }
00161 
00162 
00163 int wps_er_ssdp_init(struct wps_er *er)
00164 {
00165         if (add_ssdp_network(er->ifname))
00166                 return -1;
00167 
00168         er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr);
00169         if (er->multicast_sd < 0)
00170                 return -1;
00171 
00172         er->ssdp_sd = ssdp_listener_open();
00173         if (er->ssdp_sd < 0)
00174                 return -1;
00175 
00176         if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
00177                                 wps_er_ssdp_rx, er, NULL) ||
00178             eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
00179                                 wps_er_ssdp_rx, er, NULL))
00180                 return -1;
00181 
00182         wps_er_send_ssdp_msearch(er);
00183 
00184         return 0;
00185 }
00186 
00187 
00188 void wps_er_ssdp_deinit(struct wps_er *er)
00189 {
00190         if (er->multicast_sd >= 0) {
00191                 eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
00192                 close(er->multicast_sd);
00193         }
00194         if (er->ssdp_sd >= 0) {
00195                 eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
00196                 close(er->ssdp_sd);
00197         }
00198 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:36