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;
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
00053 if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
00054 return;
00055 } else {
00056
00057 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
00058 return;
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;
00107
00108 if (byebye) {
00109 wps_er_ap_remove(er, &addr.sin_addr);
00110 return;
00111 }
00112
00113 if (!location)
00114 return;
00115
00116 if (max_age < 1)
00117 return;
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