WPS ER: Add STA/Enrollee entries and start processing EAP messages
[libeap.git] / src / wps / wps_er.c
1 /*
2  * Wi-Fi Protected Setup - External Registrar
3  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "uuid.h"
19 #include "eloop.h"
20 #include "httpread.h"
21 #include "http_client.h"
22 #include "http_server.h"
23 #include "upnp_xml.h"
24 #include "wps_i.h"
25 #include "wps_upnp.h"
26 #include "wps_upnp_i.h"
27
28
29 /* TODO:
30  * send notification of new AP device with wpa_msg
31  * re-send notifications with wpa_msg if ER re-started (to update wpa_gui-qt4)
32  * (also re-send SSDP M-SEARCH in this case to find new APs)
33  * parse UPnP event messages
34  */
35
36 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx);
37 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx);
38
39
40 struct wps_er_sta {
41         struct wps_er_sta *next;
42         struct wps_er_ap *ap;
43         u8 addr[ETH_ALEN];
44         u16 config_methods;
45         u8 uuid[WPS_UUID_LEN];
46         u8 pri_dev_type[8];
47         u16 dev_passwd_id;
48         int m1_received;
49         char *manufacturer;
50         char *model_name;
51         char *model_number;
52         char *serial_number;
53         char *dev_name;
54         struct wps_data *wps;
55         struct http_client *http;
56 };
57
58 struct wps_er_ap {
59         struct wps_er_ap *next;
60         struct wps_er *er;
61         struct wps_er_sta *sta; /* list of STAs/Enrollees using this AP */
62         struct in_addr addr;
63         char *location;
64         struct http_client *http;
65
66         char *friendly_name;
67         char *manufacturer;
68         char *manufacturer_url;
69         char *model_description;
70         char *model_name;
71         char *model_number;
72         char *model_url;
73         char *serial_number;
74         char *udn;
75         char *upc;
76
77         char *scpd_url;
78         char *control_url;
79         char *event_sub_url;
80
81         int subscribed;
82         unsigned int id;
83 };
84
85 struct wps_er {
86         struct wps_context *wps;
87         char ifname[17];
88         char *mac_addr_text; /* mac addr of network i.f. we use */
89         u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */
90         char *ip_addr_text; /* IP address of network i.f. we use */
91         unsigned ip_addr; /* IP address of network i.f. we use (host order) */
92         int multicast_sd;
93         int ssdp_sd;
94         struct wps_er_ap *ap;
95         struct http_server *http_srv;
96         int http_port;
97         unsigned int next_ap_id;
98 };
99
100
101 static struct wps_er_sta * wps_er_sta_get(struct wps_er_ap *ap, const u8 *addr)
102 {
103         struct wps_er_sta *sta = ap->sta;
104         while (sta) {
105                 if (os_memcmp(sta->addr, addr, ETH_ALEN) == 0)
106                         return sta;
107                 sta = sta->next;
108         }
109         return NULL;
110 }
111
112
113 static void wps_er_sta_free(struct wps_er_sta *sta)
114 {
115         if (sta->wps)
116                 wps_deinit(sta->wps);
117         os_free(sta->manufacturer);
118         os_free(sta->model_name);
119         os_free(sta->model_number);
120         os_free(sta->serial_number);
121         os_free(sta->dev_name);
122         http_client_free(sta->http);
123         eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
124         os_free(sta);
125 }
126
127
128 static void wps_er_sta_remove_all(struct wps_er_ap *ap)
129 {
130         struct wps_er_sta *prev, *sta;
131
132         sta = ap->sta;
133         ap->sta = NULL;
134
135         while (sta) {
136                 prev = sta;
137                 sta = sta->next;
138                 wps_er_sta_free(prev);
139         }
140 }
141
142
143 static void wps_er_pin_needed_cb(void *ctx, const u8 *uuid_e,
144                                  const struct wps_device_data *dev)
145 {
146         wpa_printf(MSG_DEBUG, "WPS ER: PIN needed");
147 }
148
149
150 static struct wps_er_ap * wps_er_ap_get(struct wps_er *er,
151                                         struct in_addr *addr)
152 {
153         struct wps_er_ap *ap;
154         for (ap = er->ap; ap; ap = ap->next) {
155                 if (ap->addr.s_addr == addr->s_addr)
156                         break;
157         }
158         return ap;
159 }
160
161
162 static struct wps_er_ap * wps_er_ap_get_id(struct wps_er *er, unsigned int id)
163 {
164         struct wps_er_ap *ap;
165         for (ap = er->ap; ap; ap = ap->next) {
166                 if (ap->id == id)
167                         break;
168         }
169         return ap;
170 }
171
172
173 static void wps_er_ap_free(struct wps_er *er, struct wps_er_ap *ap)
174 {
175         /* TODO: if ap->subscribed, unsubscribe from events if the AP is still
176          * alive */
177         wpa_printf(MSG_DEBUG, "WPS ER: Removing AP entry for %s (%s)",
178                    inet_ntoa(ap->addr), ap->location);
179         eloop_cancel_timeout(wps_er_ap_timeout, er, ap);
180         os_free(ap->location);
181         http_client_free(ap->http);
182
183         os_free(ap->friendly_name);
184         os_free(ap->manufacturer);
185         os_free(ap->manufacturer_url);
186         os_free(ap->model_description);
187         os_free(ap->model_name);
188         os_free(ap->model_number);
189         os_free(ap->model_url);
190         os_free(ap->serial_number);
191         os_free(ap->udn);
192         os_free(ap->upc);
193
194         os_free(ap->scpd_url);
195         os_free(ap->control_url);
196         os_free(ap->event_sub_url);
197
198         wps_er_sta_remove_all(ap);
199
200         os_free(ap);
201 }
202
203
204 static void wps_er_ap_timeout(void *eloop_data, void *user_ctx)
205 {
206         struct wps_er *er = eloop_data;
207         struct wps_er_ap *ap = user_ctx;
208         wpa_printf(MSG_DEBUG, "WPS ER: AP advertisement timed out");
209         wps_er_ap_free(er, ap);
210 }
211
212
213 static void wps_er_http_subscribe_cb(void *ctx, struct http_client *c,
214                                      enum http_client_event event)
215 {
216         struct wps_er_ap *ap = ctx;
217
218         switch (event) {
219         case HTTP_CLIENT_OK:
220                 wpa_printf(MSG_DEBUG, "WPS ER: Subscribed to events");
221                 break;
222         case HTTP_CLIENT_FAILED:
223         case HTTP_CLIENT_INVALID_REPLY:
224         case HTTP_CLIENT_TIMEOUT:
225                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to subscribe to events");
226                 break;
227         }
228         http_client_free(ap->http);
229         ap->http = NULL;
230 }
231
232
233 static void wps_er_subscribe(struct wps_er_ap *ap)
234 {
235         struct wpabuf *req;
236         struct sockaddr_in dst;
237         char *url, *path;
238
239         if (ap->event_sub_url == NULL) {
240                 wpa_printf(MSG_DEBUG, "WPS ER: No eventSubURL - cannot "
241                            "subscribe");
242                 return;
243         }
244         if (ap->http) {
245                 wpa_printf(MSG_DEBUG, "WPS ER: Pending HTTP request - cannot "
246                            "send subscribe request");
247                 return;
248         }
249
250         url = http_client_url_parse(ap->event_sub_url, &dst, &path);
251         if (url == NULL) {
252                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse eventSubURL");
253                 return;
254         }
255
256         req = wpabuf_alloc(os_strlen(ap->event_sub_url) + 1000);
257         if (req == NULL) {
258                 os_free(url);
259                 return;
260         }
261         wpabuf_printf(req,
262                       "SUBSCRIBE %s HTTP/1.1\r\n"
263                       "HOST: %s:%d\r\n"
264                       "CALLBACK: <http://%s:%d/event/%d>\r\n"
265                       "NT: upnp:event\r\n"
266                       "TIMEOUT: Second-%d\r\n"
267                       "\r\n",
268                       path, inet_ntoa(dst.sin_addr), ntohs(dst.sin_port),
269                       ap->er->ip_addr_text, ap->er->http_port, ap->id, 1800);
270         os_free(url);
271         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Subscription request",
272                           wpabuf_head(req), wpabuf_len(req));
273
274         ap->http = http_client_addr(&dst, req, 1000, wps_er_http_subscribe_cb,
275                                     ap);
276         if (ap->http == NULL)
277                 wpabuf_free(req);
278 }
279
280
281 static void wps_er_parse_device_description(struct wps_er_ap *ap,
282                                             struct wpabuf *reply)
283 {
284         /* Note: reply includes null termination after the buffer data */
285         const char *data = wpabuf_head(reply);
286
287         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Device info",
288                           wpabuf_head(reply), wpabuf_len(reply));
289
290         ap->friendly_name = xml_get_first_item(data, "friendlyName");
291         wpa_printf(MSG_DEBUG, "WPS ER: friendlyName='%s'", ap->friendly_name);
292
293         ap->manufacturer = xml_get_first_item(data, "manufacturer");
294         wpa_printf(MSG_DEBUG, "WPS ER: manufacturer='%s'", ap->manufacturer);
295
296         ap->manufacturer_url = xml_get_first_item(data, "manufacturerURL");
297         wpa_printf(MSG_DEBUG, "WPS ER: manufacturerURL='%s'",
298                    ap->manufacturer_url);
299
300         ap->model_description = xml_get_first_item(data, "modelDescription");
301         wpa_printf(MSG_DEBUG, "WPS ER: modelDescription='%s'",
302                    ap->model_description);
303
304         ap->model_name = xml_get_first_item(data, "modelName");
305         wpa_printf(MSG_DEBUG, "WPS ER: modelName='%s'", ap->model_name);
306
307         ap->model_number = xml_get_first_item(data, "modelNumber");
308         wpa_printf(MSG_DEBUG, "WPS ER: modelNumber='%s'", ap->model_number);
309
310         ap->model_url = xml_get_first_item(data, "modelURL");
311         wpa_printf(MSG_DEBUG, "WPS ER: modelURL='%s'", ap->model_url);
312
313         ap->serial_number = xml_get_first_item(data, "serialNumber");
314         wpa_printf(MSG_DEBUG, "WPS ER: serialNumber='%s'", ap->serial_number);
315
316         ap->udn = xml_get_first_item(data, "UDN");
317         wpa_printf(MSG_DEBUG, "WPS ER: UDN='%s'", ap->udn);
318
319         ap->upc = xml_get_first_item(data, "UPC");
320         wpa_printf(MSG_DEBUG, "WPS ER: UPC='%s'", ap->upc);
321
322         ap->scpd_url = http_link_update(
323                 xml_get_first_item(data, "SCPDURL"), ap->location);
324         wpa_printf(MSG_DEBUG, "WPS ER: SCPDURL='%s'", ap->scpd_url);
325
326         ap->control_url = http_link_update(
327                 xml_get_first_item(data, "controlURL"), ap->location);
328         wpa_printf(MSG_DEBUG, "WPS ER: controlURL='%s'", ap->control_url);
329
330         ap->event_sub_url = http_link_update(
331                 xml_get_first_item(data, "eventSubURL"), ap->location);
332         wpa_printf(MSG_DEBUG, "WPS ER: eventSubURL='%s'", ap->event_sub_url);
333 }
334
335
336 static void wps_er_http_dev_desc_cb(void *ctx, struct http_client *c,
337                                     enum http_client_event event)
338 {
339         struct wps_er_ap *ap = ctx;
340         struct wpabuf *reply;
341         int subscribe = 0;
342
343         switch (event) {
344         case HTTP_CLIENT_OK:
345                 reply = http_client_get_body(c);
346                 if (reply == NULL)
347                         break;
348                 wps_er_parse_device_description(ap, reply);
349                 subscribe = 1;
350                 break;
351         case HTTP_CLIENT_FAILED:
352         case HTTP_CLIENT_INVALID_REPLY:
353         case HTTP_CLIENT_TIMEOUT:
354                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to fetch device info");
355                 break;
356         }
357         http_client_free(ap->http);
358         ap->http = NULL;
359         if (subscribe)
360                 wps_er_subscribe(ap);
361 }
362
363
364 static void wps_er_ap_add(struct wps_er *er, struct in_addr *addr,
365                           const char *location, int max_age)
366 {
367         struct wps_er_ap *ap;
368
369         ap = wps_er_ap_get(er, addr);
370         if (ap) {
371                 /* Update advertisement timeout */
372                 eloop_cancel_timeout(wps_er_ap_timeout, er, ap);
373                 eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap);
374                 return;
375         }
376
377         ap = os_zalloc(sizeof(*ap));
378         if (ap == NULL)
379                 return;
380         ap->er = er;
381         ap->id = ++er->next_ap_id;
382         ap->location = os_strdup(location);
383         if (ap->location == NULL) {
384                 os_free(ap);
385                 return;
386         }
387         ap->next = er->ap;
388         er->ap = ap;
389
390         ap->addr.s_addr = addr->s_addr;
391         eloop_register_timeout(max_age, 0, wps_er_ap_timeout, er, ap);
392
393         wpa_printf(MSG_DEBUG, "WPS ER: Added AP entry for %s (%s)",
394                    inet_ntoa(ap->addr), ap->location);
395
396         /* Fetch device description */
397         ap->http = http_client_url(ap->location, NULL, 10000,
398                                    wps_er_http_dev_desc_cb, ap);
399 }
400
401
402 static void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr)
403 {
404         struct wps_er_ap *prev = NULL, *ap = er->ap;
405
406         while (ap) {
407                 if (ap->addr.s_addr == addr->s_addr) {
408                         if (prev)
409                                 prev->next = ap->next;
410                         else
411                                 er->ap = ap->next;
412                         wps_er_ap_free(er, ap);
413                         return;
414                 }
415                 prev = ap;
416                 ap = ap->next;
417         }
418 }
419
420
421 static void wps_er_ap_remove_all(struct wps_er *er)
422 {
423         struct wps_er_ap *prev, *ap;
424
425         ap = er->ap;
426         er->ap = NULL;
427
428         while (ap) {
429                 prev = ap;
430                 ap = ap->next;
431                 wps_er_ap_free(er, prev);
432         }
433 }
434
435
436 static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
437 {
438         struct wps_er *er = eloop_ctx;
439         struct sockaddr_in addr; /* client address */
440         socklen_t addr_len;
441         int nread;
442         char buf[MULTICAST_MAX_READ], *pos, *pos2, *start;
443         int wfa = 0, byebye = 0;
444         int max_age = -1;
445         char *location = NULL;
446
447         addr_len = sizeof(addr);
448         nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
449                          (struct sockaddr *) &addr, &addr_len);
450         if (nread <= 0)
451                 return;
452         buf[nread] = '\0';
453
454         wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
455                    inet_ntoa(addr.sin_addr));
456         wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
457                           (u8 *) buf, nread);
458
459         if (sd == er->multicast_sd) {
460                 /* Reply to M-SEARCH */
461                 if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
462                         return; /* unexpected response header */
463         } else {
464                 /* Unsolicited message (likely NOTIFY or M-SEARCH) */
465                 if (os_strncmp(buf, "NOTIFY ", 7) != 0)
466                         return; /* only process notifications */
467         }
468
469         for (start = buf; start && *start; start = pos) {
470                 pos = os_strchr(start, '\n');
471                 if (pos) {
472                         if (pos[-1] == '\r')
473                                 pos[-1] = '\0';
474                         *pos++ = '\0';
475                 }
476                 if (os_strstr(start, "schemas-wifialliance-org:device:"
477                               "WFADevice:1"))
478                         wfa = 1;
479                 if (os_strstr(start, "schemas-wifialliance-org:service:"
480                               "WFAWLANConfig:1"))
481                         wfa = 1;
482                 if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
483                         start += 9;
484                         while (*start == ' ')
485                                 start++;
486                         location = start;
487                 } else if (os_strncasecmp(start, "NTS:", 4) == 0) {
488                         if (os_strstr(start, "ssdp:byebye"))
489                                 byebye = 1;
490                 } else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
491                         start += 9;
492                         while (*start == ' ')
493                                 start++;
494                         pos2 = os_strstr(start, "max-age=");
495                         if (pos2 == NULL)
496                                 continue;
497                         pos2 += 8;
498                         max_age = atoi(pos2);
499                 }
500         }
501
502         if (!wfa)
503                 return; /* Not WPS advertisement/reply */
504
505         if (byebye) {
506                 wps_er_ap_remove(er, &addr.sin_addr);
507                 return;
508         }
509
510         if (!location)
511                 return; /* Unknown location */
512
513         if (max_age < 1)
514                 return; /* No max-age reported */
515
516         wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
517                    "(packet source: %s  max-age: %d)",
518                    location, inet_ntoa(addr.sin_addr), max_age);
519
520         wps_er_ap_add(er, &addr.sin_addr, location, max_age);
521 }
522
523
524 static void wps_er_send_ssdp_msearch(struct wps_er *er)
525 {
526         struct wpabuf *msg;
527         struct sockaddr_in dest;
528
529         msg = wpabuf_alloc(500);
530         if (msg == NULL)
531                 return;
532
533         wpabuf_put_str(msg,
534                        "M-SEARCH * HTTP/1.1\r\n"
535                        "HOST: 239.255.255.250:1900\r\n"
536                        "MAN: \"ssdp:discover\"\r\n"
537                        "MX: 3\r\n"
538                        "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
539                        "\r\n"
540                        "\r\n");
541
542         os_memset(&dest, 0, sizeof(dest));
543         dest.sin_family = AF_INET;
544         dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
545         dest.sin_port = htons(UPNP_MULTICAST_PORT);
546
547         if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
548                    (struct sockaddr *) &dest, sizeof(dest)) < 0)
549                 wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
550                            "%d (%s)", errno, strerror(errno));
551
552         wpabuf_free(msg);
553 }
554
555
556 static void http_put_date(struct wpabuf *buf)
557 {
558         wpabuf_put_str(buf, "Date: ");
559         format_date(buf);
560         wpabuf_put_str(buf, "\r\n");
561 }
562
563
564 static void wps_er_http_resp_not_found(struct http_request *req)
565 {
566         struct wpabuf *buf;
567         buf = wpabuf_alloc(200);
568         if (buf == NULL) {
569                 http_request_deinit(req);
570                 return;
571         }
572
573         wpabuf_put_str(buf,
574                        "HTTP/1.1 404 Not Found\r\n"
575                        "Server: unspecified, UPnP/1.0, unspecified\r\n"
576                        "Connection: close\r\n");
577         http_put_date(buf);
578         wpabuf_put_str(buf, "\r\n");
579         http_request_send_and_deinit(req, buf);
580 }
581
582
583 static void wps_er_http_resp_ok(struct http_request *req)
584 {
585         struct wpabuf *buf;
586         buf = wpabuf_alloc(200);
587         if (buf == NULL) {
588                 http_request_deinit(req);
589                 return;
590         }
591
592         wpabuf_put_str(buf,
593                        "HTTP/1.1 200 OK\r\n"
594                        "Server: unspecified, UPnP/1.0, unspecified\r\n"
595                        "Connection: close\r\n"
596                        "Content-Length: 0\r\n");
597         http_put_date(buf);
598         wpabuf_put_str(buf, "\r\n");
599         http_request_send_and_deinit(req, buf);
600 }
601
602
603 static void wps_er_sta_timeout(void *eloop_data, void *user_ctx)
604 {
605         struct wps_er_sta *sta = eloop_data;
606         wpa_printf(MSG_DEBUG, "WPS ER: STA entry timed out");
607         wps_er_sta_free(sta);
608 }
609
610
611 static struct wps_er_sta * wps_er_add_sta_data(struct wps_er_ap *ap,
612                                                const u8 *addr,
613                                                struct wps_parse_attr *attr,
614                                                int probe_req)
615 {
616         struct wps_er_sta *sta = wps_er_sta_get(ap, addr);
617
618         if (sta == NULL) {
619                 sta = os_zalloc(sizeof(*sta));
620                 if (sta == NULL)
621                         return NULL;
622                 os_memcpy(sta->addr, addr, ETH_ALEN);
623                 sta->ap = ap;
624                 sta->next = ap->sta;
625                 ap->sta = sta;
626         }
627
628         if (!probe_req)
629                 sta->m1_received = 1;
630
631         if (attr->config_methods && (!probe_req || !sta->m1_received))
632                 sta->config_methods = WPA_GET_BE16(attr->config_methods);
633         if (attr->uuid_e && (!probe_req || !sta->m1_received))
634                 os_memcpy(sta->uuid, attr->uuid_e, WPS_UUID_LEN);
635         if (attr->primary_dev_type && (!probe_req || !sta->m1_received))
636                 os_memcpy(sta->pri_dev_type, attr->primary_dev_type, 8);
637         if (attr->dev_password_id && (!probe_req || !sta->m1_received))
638                 sta->dev_passwd_id = WPA_GET_BE16(attr->dev_password_id);
639
640         if (attr->manufacturer) {
641                 os_free(sta->manufacturer);
642                 sta->manufacturer = os_malloc(attr->manufacturer_len + 1);
643                 if (sta->manufacturer) {
644                         os_memcpy(sta->manufacturer, attr->manufacturer,
645                                   attr->manufacturer_len);
646                         sta->manufacturer[attr->manufacturer_len] = '\0';
647                 }
648         }
649
650         if (attr->model_name) {
651                 os_free(sta->model_name);
652                 sta->model_name = os_malloc(attr->model_name_len + 1);
653                 if (sta->model_name) {
654                         os_memcpy(sta->model_name, attr->model_name,
655                                   attr->model_name_len);
656                         sta->model_name[attr->model_name_len] = '\0';
657                 }
658         }
659
660         if (attr->model_number) {
661                 os_free(sta->model_number);
662                 sta->model_number = os_malloc(attr->model_number_len + 1);
663                 if (sta->model_number) {
664                         os_memcpy(sta->model_number, attr->model_number,
665                                   attr->model_number_len);
666                         sta->model_number[attr->model_number_len] = '\0';
667                 }
668         }
669
670         if (attr->serial_number) {
671                 os_free(sta->serial_number);
672                 sta->serial_number = os_malloc(attr->serial_number_len + 1);
673                 if (sta->serial_number) {
674                         os_memcpy(sta->serial_number, attr->serial_number,
675                                   attr->serial_number_len);
676                         sta->serial_number[attr->serial_number_len] = '\0';
677                 }
678         }
679
680         if (attr->dev_name) {
681                 os_free(sta->dev_name);
682                 sta->dev_name = os_malloc(attr->dev_name_len + 1);
683                 if (sta->dev_name) {
684                         os_memcpy(sta->dev_name, attr->dev_name,
685                                   attr->dev_name_len);
686                         sta->dev_name[attr->dev_name_len] = '\0';
687                 }
688         }
689
690         eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL);
691         eloop_register_timeout(300, 0, wps_er_sta_timeout, sta, NULL);
692
693         /* TODO: wpa_msg indication if new STA */
694
695         return sta;
696 }
697
698
699 static void wps_er_process_wlanevent_probe_req(struct wps_er_ap *ap,
700                                                const u8 *addr,
701                                                struct wpabuf *msg)
702 {
703         struct wps_parse_attr attr;
704
705         wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - Probe Request - from "
706                    MACSTR, MAC2STR(addr));
707         wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message "
708                         "(TLVs from Probe Request)", msg);
709
710         if (wps_parse_msg(msg, &attr) < 0) {
711                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
712                            "WLANEvent message");
713                 return;
714         }
715
716         wps_er_add_sta_data(ap, addr, &attr, 1);
717 }
718
719
720 static void wps_er_sta_send_msg(struct wps_er_sta *sta, struct wpabuf *msg)
721 {
722         /* TODO: send msg as UPnP POST: PutWLANResponse(NewMessage,
723          * NewWLANEventType, NewWLANEventMAC) */
724
725         wpabuf_free(msg);
726 }
727
728
729 static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg)
730 {
731         enum wps_process_res res;
732
733         res = wps_process_msg(sta->wps, WSC_MSG, msg);
734         if (res == WPS_CONTINUE) {
735                 enum wsc_op_code op_code;
736                 struct wpabuf *next = wps_get_msg(sta->wps, &op_code);
737                 if (next)
738                         wps_er_sta_send_msg(sta, next);
739         }
740 }
741
742
743 static void wps_er_sta_start(struct wps_er_sta *sta, struct wpabuf *msg)
744 {
745         struct wps_config cfg;
746
747         if (sta->wps)
748                 wps_deinit(sta->wps);
749
750         os_memset(&cfg, 0, sizeof(cfg));
751         cfg.wps = sta->ap->er->wps;
752         cfg.registrar = 1;
753         cfg.peer_addr = sta->addr;
754
755         sta->wps = wps_init(&cfg);
756         if (sta->wps == NULL)
757                 return;
758
759         wps_er_sta_process(sta, msg);
760 }
761
762
763 static void wps_er_process_wlanevent_eap(struct wps_er_ap *ap, const u8 *addr,
764                                          struct wpabuf *msg)
765 {
766         struct wps_parse_attr attr;
767         struct wps_er_sta *sta;
768
769         wpa_printf(MSG_DEBUG, "WPS ER: WLANEvent - EAP - from " MACSTR,
770                    MAC2STR(addr));
771         wpa_hexdump_buf(MSG_MSGDUMP, "WPS ER: WLANEvent - Enrollee's message "
772                         "(TLVs from EAP-WSC)", msg);
773
774         if (wps_parse_msg(msg, &attr) < 0) {
775                 wpa_printf(MSG_DEBUG, "WPS ER: Failed to parse TLVs in "
776                            "WLANEvent message");
777                 return;
778         }
779
780         sta = wps_er_add_sta_data(ap, addr, &attr, 0);
781
782         if (attr.msg_type && *attr.msg_type == WPS_M1)
783                 wps_er_sta_start(sta, msg);
784         else if (sta->wps)
785                 wps_er_sta_process(sta, msg);
786 }
787
788
789 static void wps_er_process_wlanevent(struct wps_er_ap *ap,
790                                      struct wpabuf *event)
791 {
792         u8 *data;
793         u8 wlan_event_type;
794         u8 wlan_event_mac[ETH_ALEN];
795         struct wpabuf msg;
796
797         wpa_hexdump(MSG_MSGDUMP, "WPS ER: Received WLANEvent",
798                     wpabuf_head(event), wpabuf_len(event));
799         if (wpabuf_len(event) < 1 + 17) {
800                 wpa_printf(MSG_DEBUG, "WPS ER: Too short WLANEvent");
801                 return;
802         }
803
804         data = wpabuf_mhead(event);
805         wlan_event_type = data[0];
806         if (hwaddr_aton((char *) data + 1, wlan_event_mac) < 0) {
807                 wpa_printf(MSG_DEBUG, "WPS ER: Invalid WLANEventMAC in "
808                            "WLANEvent");
809                 return;
810         }
811
812         wpabuf_set(&msg, data + 1 + 17, wpabuf_len(event) - (1 + 17));
813
814         switch (wlan_event_type) {
815         case 1:
816                 wps_er_process_wlanevent_probe_req(ap, wlan_event_mac, &msg);
817                 break;
818         case 2:
819                 wps_er_process_wlanevent_eap(ap, wlan_event_mac, &msg);
820                 break;
821         default:
822                 wpa_printf(MSG_DEBUG, "WPS ER: Unknown WLANEventType %d",
823                            wlan_event_type);
824                 break;
825         }
826 }
827
828
829 static void wps_er_http_event(struct wps_er *er, struct http_request *req,
830                               unsigned int ap_id)
831 {
832         struct wps_er_ap *ap = wps_er_ap_get_id(er, ap_id);
833         struct wpabuf *event;
834         enum http_reply_code ret;
835
836         if (ap == NULL) {
837                 wpa_printf(MSG_DEBUG, "WPS ER: HTTP event from unknown AP id "
838                            "%u", ap_id);
839                 wps_er_http_resp_not_found(req);
840                 return;
841         }
842         wpa_printf(MSG_MSGDUMP, "WPS ER: HTTP event from AP id %u: %s",
843                    ap_id, http_request_get_data(req));
844
845         event = xml_get_base64_item(http_request_get_data(req), "WLANEvent",
846                                     &ret);
847         if (event == NULL) {
848                 wpa_printf(MSG_DEBUG, "WPS ER: Could not extract WLANEvent "
849                            "from the event notification");
850                 /*
851                  * Reply with OK anyway to avoid getting unregistered from
852                  * events.
853                  */
854                 wps_er_http_resp_ok(req);
855                 return;
856         }
857
858         wps_er_process_wlanevent(ap, event);
859
860         wpabuf_free(event);
861         wps_er_http_resp_ok(req);
862 }
863
864
865 static void wps_er_http_notify(struct wps_er *er, struct http_request *req)
866 {
867         char *uri = http_request_get_uri(req);
868
869         if (os_strncmp(uri, "/event/", 7) == 0) {
870                 wps_er_http_event(er, req, atoi(uri + 7));
871         } else {
872                 wpa_printf(MSG_DEBUG, "WPS ER: Unknown HTTP NOTIFY for '%s'",
873                            uri);
874                 wps_er_http_resp_not_found(req);
875         }
876 }
877
878
879 static void wps_er_http_req(void *ctx, struct http_request *req)
880 {
881         struct wps_er *er = ctx;
882         struct sockaddr_in *cli = http_request_get_cli_addr(req);
883         enum httpread_hdr_type type = http_request_get_type(req);
884         struct wpabuf *buf;
885
886         wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from "
887                    "%s:%d",
888                    http_request_get_uri(req), type,
889                    inet_ntoa(cli->sin_addr), ntohs(cli->sin_port));
890
891         switch (type) {
892         case HTTPREAD_HDR_TYPE_NOTIFY:
893                 wps_er_http_notify(er, req);
894                 break;
895         default:
896                 wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type "
897                            "%d", type);
898                 buf = wpabuf_alloc(200);
899                 if (buf == NULL) {
900                         http_request_deinit(req);
901                         return;
902                 }
903                 wpabuf_put_str(buf,
904                                "HTTP/1.1 501 Unimplemented\r\n"
905                                "Connection: close\r\n");
906                 http_put_date(buf);
907                 wpabuf_put_str(buf, "\r\n");
908                 http_request_send_and_deinit(req, buf);
909                 break;
910         }
911 }
912
913
914 struct wps_er *
915 wps_er_init(struct wps_context *wps, const char *ifname)
916 {
917         struct wps_er *er;
918         struct wps_registrar_config rcfg;
919         struct in_addr addr;
920
921         er = os_zalloc(sizeof(*er));
922         if (er == NULL)
923                 return NULL;
924
925         er->multicast_sd = -1;
926         er->ssdp_sd = -1;
927
928         os_strlcpy(er->ifname, ifname, sizeof(er->ifname));
929         er->wps = wps;
930         os_memset(&rcfg, 0, sizeof(rcfg));
931         rcfg.pin_needed_cb = wps_er_pin_needed_cb;
932         rcfg.cb_ctx = er;
933
934         if (get_netif_info(ifname,
935                            &er->ip_addr, &er->ip_addr_text,
936                            er->mac_addr, &er->mac_addr_text)) {
937                 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
938                            "for %s. Does it have IP address?", ifname);
939                 wps_er_deinit(er);
940                 return NULL;
941         }
942
943         if (add_ssdp_network(ifname)) {
944                 wps_er_deinit(er);
945                 return NULL;
946         }
947
948         er->multicast_sd = ssdp_open_multicast_sock(er->ip_addr);
949         if (er->multicast_sd < 0) {
950                 wps_er_deinit(er);
951                 return NULL;
952         }
953
954         er->ssdp_sd = ssdp_listener_open();
955         if (er->ssdp_sd < 0) {
956                 wps_er_deinit(er);
957                 return NULL;
958         }
959         if (eloop_register_sock(er->multicast_sd, EVENT_TYPE_READ,
960                                 wps_er_ssdp_rx, er, NULL) ||
961             eloop_register_sock(er->ssdp_sd, EVENT_TYPE_READ,
962                                 wps_er_ssdp_rx, er, NULL)) {
963                 wps_er_deinit(er);
964                 return NULL;
965         }
966
967         addr.s_addr = er->ip_addr;
968         er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er);
969         if (er->http_srv == NULL) {
970                 wps_er_deinit(er);
971                 return NULL;
972         }
973         er->http_port = http_server_get_port(er->http_srv);
974
975         wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s "
976                    "mac_addr=%s)",
977                    er->ifname, er->ip_addr_text, er->mac_addr_text);
978
979         wps_er_send_ssdp_msearch(er);
980
981         return er;
982 }
983
984
985 void wps_er_deinit(struct wps_er *er)
986 {
987         if (er == NULL)
988                 return;
989         http_server_deinit(er->http_srv);
990         wps_er_ap_remove_all(er);
991         if (er->multicast_sd >= 0) {
992                 eloop_unregister_sock(er->multicast_sd, EVENT_TYPE_READ);
993                 close(er->multicast_sd);
994         }
995         if (er->ssdp_sd >= 0) {
996                 eloop_unregister_sock(er->ssdp_sd, EVENT_TYPE_READ);
997                 close(er->ssdp_sd);
998         }
999         os_free(er->ip_addr_text);
1000         os_free(er->mac_addr_text);
1001         os_free(er);
1002 }