00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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;
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
00052 if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
00053 return;
00054 } else {
00055
00056 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
00057 return;
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;
00111
00112 if (byebye) {
00113 wps_er_ap_remove(er, &addr.sin_addr);
00114 return;
00115 }
00116
00117 if (!location)
00118 return;
00119
00120 if (max_age < 1)
00121 return;
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 }