00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 #include "includes.h"
00174
00175 #include <assert.h>
00176 #include <net/if.h>
00177 #include <netdb.h>
00178 #include <sys/ioctl.h>
00179
00180 #include "common.h"
00181 #include "uuid.h"
00182 #include "base64.h"
00183 #include "wps.h"
00184 #include "wps_i.h"
00185 #include "wps_upnp.h"
00186 #include "wps_upnp_i.h"
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 #define NO_DOMAIN_NAME_RESOLUTION 1
00201
00202
00203
00204
00205
00206
00207
00208
00209 #define MAX_SUBSCRIPTIONS 4
00210 #define MAX_ADDR_PER_SUBSCRIPTION 8
00211
00212
00213
00214 void format_date(struct wpabuf *buf)
00215 {
00216 const char *weekday_str = "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat";
00217 const char *month_str = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0"
00218 "Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
00219 struct tm *date;
00220 time_t t;
00221
00222 t = time(NULL);
00223 date = gmtime(&t);
00224 wpabuf_printf(buf, "%s, %02d %s %d %02d:%02d:%02d GMT",
00225 &weekday_str[date->tm_wday * 4], date->tm_mday,
00226 &month_str[date->tm_mon * 4], date->tm_year + 1900,
00227 date->tm_hour, date->tm_min, date->tm_sec);
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 static void uuid_make(u8 uuid[UUID_LEN])
00247 {
00248 os_get_random(uuid, UUID_LEN);
00249
00250
00251 uuid[6] &= 0x0f; uuid[6] |= (4 << 4);
00252 uuid[8] &= 0x3f; uuid[8] |= 0x80;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 static void subscr_addr_delete(struct subscr_addr *a)
00274 {
00275
00276
00277
00278
00279 os_free(a);
00280 }
00281
00282
00283
00284 static void subscr_addr_free_all(struct subscription *s)
00285 {
00286 struct subscr_addr *a, *tmp;
00287 dl_list_for_each_safe(a, tmp, &s->addr_list, struct subscr_addr, list)
00288 {
00289 dl_list_del(&a->list);
00290 subscr_addr_delete(a);
00291 }
00292 }
00293
00294
00295
00296 static void subscr_addr_add_url(struct subscription *s, const char *url)
00297 {
00298 int alloc_len;
00299 char *scratch_mem = NULL;
00300 char *mem;
00301 char *domain_and_port;
00302 char *delim;
00303 char *path;
00304 char *domain;
00305 int port = 80;
00306 struct addrinfo hints;
00307 struct addrinfo *result = NULL;
00308 struct addrinfo *rp;
00309 int rerr;
00310 struct subscr_addr *a = NULL;
00311
00312
00313 if (os_strncasecmp(url, "http://", 7))
00314 goto fail;
00315 url += 7;
00316
00317
00318 alloc_len = (2 * (os_strlen(url) + 1));
00319 scratch_mem = os_zalloc(alloc_len);
00320 if (scratch_mem == NULL)
00321 goto fail;
00322 mem = scratch_mem;
00323 strcpy(mem, url);
00324 domain_and_port = mem;
00325 mem += 1 + os_strlen(mem);
00326 delim = os_strchr(domain_and_port, '/');
00327 if (delim) {
00328 *delim++ = 0;
00329 path = delim;
00330 } else {
00331 path = domain_and_port + os_strlen(domain_and_port);
00332 }
00333 domain = mem;
00334 strcpy(domain, domain_and_port);
00335 delim = strchr(domain, ':');
00336 if (delim) {
00337 *delim++ = 0;
00338 if (isdigit(*delim))
00339 port = atol(delim);
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349 os_memset(&hints, 0, sizeof(struct addrinfo));
00350 hints.ai_family = AF_INET;
00351 hints.ai_socktype = SOCK_STREAM;
00352 #if NO_DOMAIN_NAME_RESOLUTION
00353
00354
00355
00356 hints.ai_flags = AI_NUMERICHOST;
00357 #else
00358
00359 hints.ai_flags = 0;
00360 #endif
00361 hints.ai_protocol = 0;
00362 rerr = getaddrinfo(domain, NULL ,
00363 &hints, &result);
00364 if (rerr) {
00365 wpa_printf(MSG_INFO, "WPS UPnP: Resolve error %d (%s) on: %s",
00366 rerr, gai_strerror(rerr), domain);
00367 goto fail;
00368 }
00369 for (rp = result; rp; rp = rp->ai_next) {
00370
00371 if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) {
00372 wpa_printf(MSG_INFO, "WPS UPnP: subscr_addr_add_url: "
00373 "Ignoring excessive addresses");
00374 break;
00375 }
00376
00377 a = os_zalloc(sizeof(*a) + alloc_len);
00378 if (a == NULL)
00379 continue;
00380 mem = (void *) (a + 1);
00381 a->domain_and_port = mem;
00382 strcpy(mem, domain_and_port);
00383 mem += 1 + strlen(mem);
00384 a->path = mem;
00385 if (path[0] != '/')
00386 *mem++ = '/';
00387 strcpy(mem, path);
00388 mem += 1 + strlen(mem);
00389 os_memcpy(&a->saddr, rp->ai_addr, sizeof(a->saddr));
00390 a->saddr.sin_port = htons(port);
00391
00392 dl_list_add(&s->addr_list, &a->list);
00393 a = NULL;
00394 }
00395
00396 fail:
00397 if (result)
00398 freeaddrinfo(result);
00399 os_free(scratch_mem);
00400 os_free(a);
00401 }
00402
00403
00404
00405
00406
00407 static void subscr_addr_list_create(struct subscription *s,
00408 const char *url_list)
00409 {
00410 char *end;
00411 for (;;) {
00412 while (*url_list == ' ' || *url_list == '\t')
00413 url_list++;
00414 if (*url_list != '<')
00415 break;
00416 url_list++;
00417 end = os_strchr(url_list, '>');
00418 if (end == NULL)
00419 break;
00420 *end++ = 0;
00421 subscr_addr_add_url(s, url_list);
00422 url_list = end;
00423 }
00424 }
00425
00426
00427 int send_wpabuf(int fd, struct wpabuf *buf)
00428 {
00429 wpa_printf(MSG_DEBUG, "WPS UPnP: Send %lu byte message",
00430 (unsigned long) wpabuf_len(buf));
00431 errno = 0;
00432 if (write(fd, wpabuf_head(buf), wpabuf_len(buf)) !=
00433 (int) wpabuf_len(buf)) {
00434 wpa_printf(MSG_ERROR, "WPS UPnP: Failed to send buffer: "
00435 "errno=%d (%s)",
00436 errno, strerror(errno));
00437 return -1;
00438 }
00439
00440 return 0;
00441 }
00442
00443
00444 static void wpabuf_put_property(struct wpabuf *buf, const char *name,
00445 const char *value)
00446 {
00447 wpabuf_put_str(buf, "<e:property>");
00448 wpabuf_printf(buf, "<%s>", name);
00449 if (value)
00450 wpabuf_put_str(buf, value);
00451 wpabuf_printf(buf, "</%s>", name);
00452 wpabuf_put_str(buf, "</e:property>\n");
00453 }
00454
00455
00464 static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
00465 {
00466
00467 struct wpabuf *buf;
00468 int buf_size = 0;
00469 struct subscription *s, *tmp;
00470
00471 const char *format_head =
00472 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
00473 "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
00474 const char *format_tail = "</e:propertyset>\n";
00475
00476 if (dl_list_empty(&sm->subscriptions)) {
00477
00478 return;
00479 }
00480
00481
00482 buf_size += os_strlen(format_head);
00483 buf_size += 50 + 2 * os_strlen("WLANEvent");
00484 if (sm->wlanevent)
00485 buf_size += os_strlen(sm->wlanevent);
00486 buf_size += os_strlen(format_tail);
00487
00488 buf = wpabuf_alloc(buf_size);
00489 if (buf == NULL)
00490 return;
00491 wpabuf_put_str(buf, format_head);
00492 wpabuf_put_property(buf, "WLANEvent", sm->wlanevent);
00493 wpabuf_put_str(buf, format_tail);
00494
00495 wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s",
00496 (char *) wpabuf_head(buf));
00497
00498 dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
00499 list) {
00500 if (event_add(s, buf)) {
00501 wpa_printf(MSG_INFO, "WPS UPnP: Dropping "
00502 "subscriber due to event backlog");
00503 dl_list_del(&s->list);
00504 subscription_destroy(s);
00505 }
00506 }
00507
00508 wpabuf_free(buf);
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 void subscription_destroy(struct subscription *s)
00522 {
00523 wpa_printf(MSG_DEBUG, "WPS UPnP: Destroy subscription %p", s);
00524 subscr_addr_free_all(s);
00525 event_delete_all(s);
00526 upnp_er_remove_notification(s);
00527 os_free(s);
00528 }
00529
00530
00531
00532 static void subscription_list_age(struct upnp_wps_device_sm *sm, time_t now)
00533 {
00534 struct subscription *s, *tmp;
00535 dl_list_for_each_safe(s, tmp, &sm->subscriptions,
00536 struct subscription, list) {
00537 if (s->timeout_time > now)
00538 break;
00539 wpa_printf(MSG_DEBUG, "WPS UPnP: Removing aged subscription");
00540 dl_list_del(&s->list);
00541 subscription_destroy(s);
00542 }
00543 }
00544
00545
00546
00547
00548
00549 struct subscription * subscription_find(struct upnp_wps_device_sm *sm,
00550 const u8 uuid[UUID_LEN])
00551 {
00552 struct subscription *s;
00553 dl_list_for_each(s, &sm->subscriptions, struct subscription, list) {
00554 if (os_memcmp(s->uuid, uuid, UUID_LEN) == 0)
00555 return s;
00556 }
00557 return NULL;
00558 }
00559
00560
00561 static struct wpabuf * build_fake_wsc_ack(void)
00562 {
00563 struct wpabuf *msg = wpabuf_alloc(100);
00564 if (msg == NULL)
00565 return NULL;
00566 wpabuf_put_u8(msg, UPNP_WPS_WLANEVENT_TYPE_EAP);
00567 wpabuf_put_str(msg, "00:00:00:00:00:00");
00568 if (wps_build_version(msg) ||
00569 wps_build_msg_type(msg, WPS_WSC_ACK)) {
00570 wpabuf_free(msg);
00571 return NULL;
00572 }
00573
00574 wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
00575 wpabuf_put_be16(msg, WPS_NONCE_LEN);
00576 wpabuf_put(msg, WPS_NONCE_LEN);
00577
00578 wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
00579 wpabuf_put_be16(msg, WPS_NONCE_LEN);
00580 wpabuf_put(msg, WPS_NONCE_LEN);
00581 return msg;
00582 }
00583
00584
00585
00586
00587
00588 static int subscription_first_event(struct subscription *s)
00589 {
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 char *wlan_event;
00601 struct wpabuf *buf;
00602 int ap_status = 1;
00603 const char *head =
00604 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
00605 "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
00606 const char *tail = "</e:propertyset>\n";
00607 char txt[10];
00608
00609 if (s->sm->wlanevent == NULL) {
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 struct wpabuf *msg;
00620 wpa_printf(MSG_DEBUG, "WPS UPnP: Use a fake WSC_ACK as the "
00621 "initial WLANEvent");
00622 msg = build_fake_wsc_ack();
00623 if (msg) {
00624 s->sm->wlanevent = (char *)
00625 base64_encode(wpabuf_head(msg),
00626 wpabuf_len(msg), NULL);
00627 wpabuf_free(msg);
00628 }
00629 }
00630
00631 wlan_event = s->sm->wlanevent;
00632 if (wlan_event == NULL || *wlan_event == '\0') {
00633 wpa_printf(MSG_DEBUG, "WPS UPnP: WLANEvent not known for "
00634 "initial event message");
00635 wlan_event = "";
00636 }
00637 buf = wpabuf_alloc(500 + os_strlen(wlan_event));
00638 if (buf == NULL)
00639 return 1;
00640
00641 wpabuf_put_str(buf, head);
00642 wpabuf_put_property(buf, "STAStatus", "1");
00643 os_snprintf(txt, sizeof(txt), "%d", ap_status);
00644 wpabuf_put_property(buf, "APStatus", txt);
00645 if (*wlan_event)
00646 wpabuf_put_property(buf, "WLANEvent", wlan_event);
00647 wpabuf_put_str(buf, tail);
00648
00649 if (event_add(s, buf)) {
00650 wpabuf_free(buf);
00651 return 1;
00652 }
00653 wpabuf_free(buf);
00654
00655 return 0;
00656 }
00657
00658
00665 struct subscription * subscription_start(struct upnp_wps_device_sm *sm,
00666 const char *callback_urls)
00667 {
00668 struct subscription *s;
00669 time_t now = time(NULL);
00670 time_t expire = now + UPNP_SUBSCRIBE_SEC;
00671
00672
00673 subscription_list_age(sm, now);
00674
00675
00676 if (dl_list_len(&sm->subscriptions) >= MAX_SUBSCRIPTIONS) {
00677 s = dl_list_first(&sm->subscriptions, struct subscription,
00678 list);
00679 wpa_printf(MSG_INFO, "WPS UPnP: Too many subscriptions, "
00680 "trashing oldest");
00681 dl_list_del(&s->list);
00682 subscription_destroy(s);
00683 }
00684
00685 s = os_zalloc(sizeof(*s));
00686 if (s == NULL)
00687 return NULL;
00688 dl_list_init(&s->addr_list);
00689 dl_list_init(&s->event_queue);
00690
00691 s->sm = sm;
00692 s->timeout_time = expire;
00693 uuid_make(s->uuid);
00694 subscr_addr_list_create(s, callback_urls);
00695
00696 dl_list_add_tail(&sm->subscriptions, &s->list);
00697
00698
00699
00700 if (subscription_first_event(s)) {
00701 wpa_printf(MSG_INFO, "WPS UPnP: Dropping subscriber due to "
00702 "event backlog");
00703 dl_list_del(&s->list);
00704 subscription_destroy(s);
00705 return NULL;
00706 }
00707 wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription %p started with %s",
00708 s, callback_urls);
00709
00710 event_send_all_later(sm);
00711 return s;
00712 }
00713
00714
00715
00716 struct subscription * subscription_renew(struct upnp_wps_device_sm *sm,
00717 const u8 uuid[UUID_LEN])
00718 {
00719 time_t now = time(NULL);
00720 time_t expire = now + UPNP_SUBSCRIBE_SEC;
00721 struct subscription *s = subscription_find(sm, uuid);
00722 if (s == NULL)
00723 return NULL;
00724 wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewed");
00725 dl_list_del(&s->list);
00726 s->timeout_time = expire;
00727
00728 dl_list_add_tail(&sm->subscriptions, &s->list);
00729 return s;
00730 }
00731
00732
00745 int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm,
00746 const u8 from_mac_addr[ETH_ALEN],
00747 enum upnp_wps_wlanevent_type ev_type,
00748 const struct wpabuf *msg)
00749 {
00750 int ret = -1;
00751 char type[2];
00752 const u8 *mac = from_mac_addr;
00753 char mac_text[18];
00754 u8 *raw = NULL;
00755 size_t raw_len;
00756 char *val;
00757 size_t val_len;
00758 int pos = 0;
00759
00760 if (!sm)
00761 goto fail;
00762
00763 os_snprintf(type, sizeof(type), "%1u", ev_type);
00764
00765 raw_len = 1 + 17 + (msg ? wpabuf_len(msg) : 0);
00766 raw = os_zalloc(raw_len);
00767 if (!raw)
00768 goto fail;
00769
00770 *(raw + pos) = (u8) ev_type;
00771 pos += 1;
00772 os_snprintf(mac_text, sizeof(mac_text), MACSTR, MAC2STR(mac));
00773 wpa_printf(MSG_DEBUG, "WPS UPnP: Proxying WLANEvent from %s",
00774 mac_text);
00775 os_memcpy(raw + pos, mac_text, 17);
00776 pos += 17;
00777 if (msg) {
00778 os_memcpy(raw + pos, wpabuf_head(msg), wpabuf_len(msg));
00779 pos += wpabuf_len(msg);
00780 }
00781 raw_len = pos;
00782
00783 val = (char *) base64_encode(raw, raw_len, &val_len);
00784 if (val == NULL)
00785 goto fail;
00786
00787 os_free(sm->wlanevent);
00788 sm->wlanevent = val;
00789 upnp_wps_device_send_event(sm);
00790
00791 ret = 0;
00792
00793 fail:
00794 os_free(raw);
00795
00796 return ret;
00797 }
00798
00799
00800 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
00801 #include <sys/sysctl.h>
00802 #include <net/route.h>
00803 #include <net/if_dl.h>
00804
00805 static int eth_get(const char *device, u8 ea[ETH_ALEN])
00806 {
00807 struct if_msghdr *ifm;
00808 struct sockaddr_dl *sdl;
00809 u_char *p, *buf;
00810 size_t len;
00811 int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
00812
00813 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
00814 return -1;
00815 if ((buf = os_malloc(len)) == NULL)
00816 return -1;
00817 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
00818 os_free(buf);
00819 return -1;
00820 }
00821 for (p = buf; p < buf + len; p += ifm->ifm_msglen) {
00822 ifm = (struct if_msghdr *)p;
00823 sdl = (struct sockaddr_dl *)(ifm + 1);
00824 if (ifm->ifm_type != RTM_IFINFO ||
00825 (ifm->ifm_addrs & RTA_IFP) == 0)
00826 continue;
00827 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
00828 os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0)
00829 continue;
00830 os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen);
00831 break;
00832 }
00833 os_free(buf);
00834
00835 if (p >= buf + len) {
00836 errno = ESRCH;
00837 return -1;
00838 }
00839 return 0;
00840 }
00841 #endif
00842
00843
00852 int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text,
00853 u8 mac[ETH_ALEN])
00854 {
00855 struct ifreq req;
00856 int sock = -1;
00857 struct sockaddr_in *addr;
00858 struct in_addr in_addr;
00859
00860 *ip_addr_text = os_zalloc(16);
00861 if (*ip_addr_text == NULL)
00862 goto fail;
00863
00864 sock = socket(AF_INET, SOCK_DGRAM, 0);
00865 if (sock < 0)
00866 goto fail;
00867
00868 os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name));
00869 if (ioctl(sock, SIOCGIFADDR, &req) < 0) {
00870 wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFADDR failed: %d (%s)",
00871 errno, strerror(errno));
00872 goto fail;
00873 }
00874 addr = (void *) &req.ifr_addr;
00875 *ip_addr = addr->sin_addr.s_addr;
00876 in_addr.s_addr = *ip_addr;
00877 os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr));
00878
00879 #ifdef __linux__
00880 os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name));
00881 if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) {
00882 wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFHWADDR failed: "
00883 "%d (%s)", errno, strerror(errno));
00884 goto fail;
00885 }
00886 os_memcpy(mac, req.ifr_addr.sa_data, 6);
00887 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
00888 if (eth_get(net_if, mac) < 0) {
00889 wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address");
00890 goto fail;
00891 }
00892 #else
00893 #error MAC address fetch not implemented
00894 #endif
00895
00896 close(sock);
00897 return 0;
00898
00899 fail:
00900 if (sock >= 0)
00901 close(sock);
00902 os_free(*ip_addr_text);
00903 *ip_addr_text = NULL;
00904 return -1;
00905 }
00906
00907
00908 static void upnp_wps_free_msearchreply(struct dl_list *head)
00909 {
00910 struct advertisement_state_machine *a, *tmp;
00911 dl_list_for_each_safe(a, tmp, head, struct advertisement_state_machine,
00912 list)
00913 msearchreply_state_machine_stop(a);
00914 }
00915
00916
00917 static void upnp_wps_free_subscriptions(struct dl_list *head)
00918 {
00919 struct subscription *s, *tmp;
00920 dl_list_for_each_safe(s, tmp, head, struct subscription, list) {
00921 dl_list_del(&s->list);
00922 subscription_destroy(s);
00923 }
00924 }
00925
00926
00931 void upnp_wps_device_stop(struct upnp_wps_device_sm *sm)
00932 {
00933 if (!sm || !sm->started)
00934 return;
00935
00936 wpa_printf(MSG_DEBUG, "WPS UPnP: Stop device");
00937 web_listener_stop(sm);
00938 upnp_wps_free_msearchreply(&sm->msearch_replies);
00939 upnp_wps_free_subscriptions(&sm->subscriptions);
00940
00941 advertisement_state_machine_stop(sm, 1);
00942
00943 event_send_stop_all(sm);
00944 os_free(sm->wlanevent);
00945 sm->wlanevent = NULL;
00946 os_free(sm->ip_addr_text);
00947 sm->ip_addr_text = NULL;
00948 if (sm->multicast_sd >= 0)
00949 close(sm->multicast_sd);
00950 sm->multicast_sd = -1;
00951 ssdp_listener_stop(sm);
00952
00953 sm->started = 0;
00954 }
00955
00956
00963 int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if)
00964 {
00965 if (!sm || !net_if)
00966 return -1;
00967
00968 if (sm->started)
00969 upnp_wps_device_stop(sm);
00970
00971 sm->multicast_sd = -1;
00972 sm->ssdp_sd = -1;
00973 sm->started = 1;
00974 sm->advertise_count = 0;
00975
00976
00977 if (add_ssdp_network(net_if))
00978 goto fail;
00979
00980
00981 if (get_netif_info(net_if, &sm->ip_addr, &sm->ip_addr_text,
00982 sm->mac_addr)) {
00983 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
00984 "for %s. Does it have IP address?", net_if);
00985 goto fail;
00986 }
00987
00988
00989
00990
00991 if (web_listener_start(sm))
00992 goto fail;
00993
00994
00995 if (ssdp_listener_start(sm))
00996 goto fail;
00997
00998
00999 if (ssdp_open_multicast(sm) < 0)
01000 goto fail;
01001
01002
01003
01004
01005
01006
01007 if (advertisement_state_machine_start(sm))
01008 goto fail;
01009
01010 return 0;
01011
01012 fail:
01013 upnp_wps_device_stop(sm);
01014 return -1;
01015 }
01016
01017
01022 void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm)
01023 {
01024 if (!sm)
01025 return;
01026
01027 upnp_wps_device_stop(sm);
01028
01029 if (sm->peer.wps)
01030 wps_deinit(sm->peer.wps);
01031 os_free(sm->root_dir);
01032 os_free(sm->desc_url);
01033 os_free(sm->ctx->ap_pin);
01034 os_free(sm->ctx);
01035 os_free(sm);
01036 }
01037
01038
01046 struct upnp_wps_device_sm *
01047 upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps,
01048 void *priv)
01049 {
01050 struct upnp_wps_device_sm *sm;
01051
01052 sm = os_zalloc(sizeof(*sm));
01053 if (!sm) {
01054 wpa_printf(MSG_ERROR, "WPS UPnP: upnp_wps_device_init failed");
01055 return NULL;
01056 }
01057
01058 sm->ctx = ctx;
01059 sm->wps = wps;
01060 sm->priv = priv;
01061 dl_list_init(&sm->msearch_replies);
01062 dl_list_init(&sm->subscriptions);
01063
01064 return sm;
01065 }
01066
01067
01073 int upnp_wps_subscribers(struct upnp_wps_device_sm *sm)
01074 {
01075 return !dl_list_empty(&sm->subscriptions);
01076 }