wps_er_ssdp.c

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

Generated on Sat Nov 21 23:16:55 2009 for hostapd by  doxygen 1.6.1