00001
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
00174 #include "includes.h"
00175
00176 #include <assert.h>
00177 #include <net/if.h>
00178 #include <netdb.h>
00179 #include <sys/ioctl.h>
00180
00181 #include "common.h"
00182 #include "uuid.h"
00183 #include "base64.h"
00184 #include "wps.h"
00185 #include "wps_i.h"
00186 #include "wps_upnp.h"
00187 #include "wps_upnp_i.h"
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 #define NO_DOMAIN_NAME_RESOLUTION 1
00202
00203
00204
00205
00206
00207
00208
00209
00210 #define MAX_SUBSCRIPTIONS 4
00211 #define MAX_ADDR_PER_SUBSCRIPTION 8
00212
00213
00214
00215 void format_date(struct wpabuf *buf)
00216 {
00217 const char *weekday_str = "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat";
00218 const char *month_str = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0"
00219 "Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
00220 struct tm *date;
00221 time_t t;
00222
00223 t = time(NULL);
00224 date = gmtime(&t);
00225 wpabuf_printf(buf, "%s, %02d %s %d %02d:%02d:%02d GMT",
00226 &weekday_str[date->tm_wday * 4], date->tm_mday,
00227 &month_str[date->tm_mon * 4], date->tm_year + 1900,
00228 date->tm_hour, date->tm_min, date->tm_sec);
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 static void uuid_make(u8 uuid[UUID_LEN])
00248 {
00249 os_get_random(uuid, UUID_LEN);
00250
00251
00252 uuid[6] &= 0x0f; uuid[6] |= (4 << 4);
00253 uuid[8] &= 0x3f; uuid[8] |= 0x80;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 static void subscr_addr_delete(struct subscr_addr *a)
00275 {
00276
00277
00278
00279
00280 os_free(a);
00281 }
00282
00283
00284
00285 static void subscr_addr_unlink(struct subscription *s, struct subscr_addr *a)
00286 {
00287 struct subscr_addr **listp = &s->addr_list;
00288 s->n_addr--;
00289 a->next->prev = a->prev;
00290 a->prev->next = a->next;
00291 if (*listp == a) {
00292 if (a == a->next) {
00293
00294 *listp = NULL;
00295 assert(s->n_addr == 0);
00296 } else {
00297 *listp = a->next;
00298 }
00299 }
00300 }
00301
00302
00303
00304 static void subscr_addr_free_all(struct subscription *s)
00305 {
00306 struct subscr_addr **listp = &s->addr_list;
00307 struct subscr_addr *a;
00308 while ((a = *listp) != NULL) {
00309 subscr_addr_unlink(s, a);
00310 subscr_addr_delete(a);
00311 }
00312 }
00313
00314
00315
00316 static void subscr_addr_link(struct subscription *s, struct subscr_addr *a)
00317 {
00318 struct subscr_addr **listp = &s->addr_list;
00319 s->n_addr++;
00320 if (*listp == NULL) {
00321 *listp = a->next = a->prev = a;
00322 } else {
00323 a->next = *listp;
00324 a->prev = (*listp)->prev;
00325 a->prev->next = a;
00326 a->next->prev = a;
00327 }
00328 }
00329
00330
00331
00332 static void subscr_addr_add_url(struct subscription *s, const char *url)
00333 {
00334 int alloc_len;
00335 char *scratch_mem = NULL;
00336 char *mem;
00337 char *domain_and_port;
00338 char *delim;
00339 char *path;
00340 char *domain;
00341 int port = 80;
00342 struct addrinfo hints;
00343 struct addrinfo *result = NULL;
00344 struct addrinfo *rp;
00345 int rerr;
00346 struct subscr_addr *a = NULL;
00347
00348
00349 if (os_strncasecmp(url, "http://", 7))
00350 goto fail;
00351 url += 7;
00352
00353
00354 alloc_len = (2 * (os_strlen(url) + 1));
00355 scratch_mem = os_zalloc(alloc_len);
00356 if (scratch_mem == NULL)
00357 goto fail;
00358 mem = scratch_mem;
00359 strcpy(mem, url);
00360 domain_and_port = mem;
00361 mem += 1 + os_strlen(mem);
00362 delim = os_strchr(domain_and_port, '/');
00363 if (delim) {
00364 *delim++ = 0;
00365 path = delim;
00366 } else {
00367 path = domain_and_port + os_strlen(domain_and_port);
00368 }
00369 domain = mem;
00370 strcpy(domain, domain_and_port);
00371 delim = strchr(domain, ':');
00372 if (delim) {
00373 *delim++ = 0;
00374 if (isdigit(*delim))
00375 port = atol(delim);
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385 os_memset(&hints, 0, sizeof(struct addrinfo));
00386 hints.ai_family = AF_INET;
00387 hints.ai_socktype = SOCK_STREAM;
00388 #if NO_DOMAIN_NAME_RESOLUTION
00389
00390
00391
00392 hints.ai_flags = AI_NUMERICHOST;
00393 #else
00394
00395 hints.ai_flags = 0;
00396 #endif
00397 hints.ai_protocol = 0;
00398 rerr = getaddrinfo(domain, NULL ,
00399 &hints, &result);
00400 if (rerr) {
00401 wpa_printf(MSG_INFO, "WPS UPnP: Resolve error %d (%s) on: %s",
00402 rerr, gai_strerror(rerr), domain);
00403 goto fail;
00404 }
00405 for (rp = result; rp; rp = rp->ai_next) {
00406
00407 if (s->n_addr >= MAX_ADDR_PER_SUBSCRIPTION) {
00408 wpa_printf(MSG_INFO, "WPS UPnP: subscr_addr_add_url: "
00409 "Ignoring excessive addresses");
00410 break;
00411 }
00412
00413 a = os_zalloc(sizeof(*a) + alloc_len);
00414 if (a == NULL)
00415 continue;
00416 a->s = s;
00417 mem = (void *) (a + 1);
00418 a->domain_and_port = mem;
00419 strcpy(mem, domain_and_port);
00420 mem += 1 + strlen(mem);
00421 a->path = mem;
00422 if (path[0] != '/')
00423 *mem++ = '/';
00424 strcpy(mem, path);
00425 mem += 1 + strlen(mem);
00426 os_memcpy(&a->saddr, rp->ai_addr, sizeof(a->saddr));
00427 a->saddr.sin_port = htons(port);
00428
00429 subscr_addr_link(s, a);
00430 a = NULL;
00431 }
00432
00433 fail:
00434 if (result)
00435 freeaddrinfo(result);
00436 os_free(scratch_mem);
00437 os_free(a);
00438 }
00439
00440
00441
00442
00443
00444 static void subscr_addr_list_create(struct subscription *s,
00445 const char *url_list)
00446 {
00447 char *end;
00448 for (;;) {
00449 while (*url_list == ' ' || *url_list == '\t')
00450 url_list++;
00451 if (*url_list != '<')
00452 break;
00453 url_list++;
00454 end = os_strchr(url_list, '>');
00455 if (end == NULL)
00456 break;
00457 *end++ = 0;
00458 subscr_addr_add_url(s, url_list);
00459 url_list = end;
00460 }
00461 }
00462
00463
00464 int send_wpabuf(int fd, struct wpabuf *buf)
00465 {
00466 wpa_printf(MSG_DEBUG, "WPS UPnP: Send %lu byte message",
00467 (unsigned long) wpabuf_len(buf));
00468 errno = 0;
00469 if (write(fd, wpabuf_head(buf), wpabuf_len(buf)) !=
00470 (int) wpabuf_len(buf)) {
00471 wpa_printf(MSG_ERROR, "WPS UPnP: Failed to send buffer: "
00472 "errno=%d (%s)",
00473 errno, strerror(errno));
00474 return -1;
00475 }
00476
00477 return 0;
00478 }
00479
00480
00481 static void wpabuf_put_property(struct wpabuf *buf, const char *name,
00482 const char *value)
00483 {
00484 wpabuf_put_str(buf, "<e:property>");
00485 wpabuf_printf(buf, "<%s>", name);
00486 if (value)
00487 wpabuf_put_str(buf, value);
00488 wpabuf_printf(buf, "</%s>", name);
00489 wpabuf_put_str(buf, "</e:property>\n");
00490 }
00491
00492
00502 static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
00503 {
00504
00505 struct wpabuf *buf;
00506 int buf_size = 0;
00507 struct subscription *s;
00508
00509 const char *format_head =
00510 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
00511 "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
00512 const char *format_tail = "</e:propertyset>\n";
00513
00514 if (sm->subscriptions == NULL) {
00515
00516 return;
00517 }
00518
00519
00520 buf_size += os_strlen(format_head);
00521 buf_size += 50 + 2 * os_strlen("WLANEvent");
00522 if (sm->wlanevent)
00523 buf_size += os_strlen(sm->wlanevent);
00524 buf_size += os_strlen(format_tail);
00525
00526 buf = wpabuf_alloc(buf_size);
00527 if (buf == NULL)
00528 return;
00529 wpabuf_put_str(buf, format_head);
00530 wpabuf_put_property(buf, "WLANEvent", sm->wlanevent);
00531 wpabuf_put_str(buf, format_tail);
00532
00533 wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s",
00534 (char *) wpabuf_head(buf));
00535
00536 s = sm->subscriptions;
00537 do {
00538 if (event_add(s, buf)) {
00539 struct subscription *s_old = s;
00540 wpa_printf(MSG_INFO, "WPS UPnP: Dropping "
00541 "subscriber due to event backlog");
00542 s = s_old->next;
00543 subscription_unlink(s_old);
00544 subscription_destroy(s_old);
00545 } else {
00546 s = s->next;
00547 }
00548 } while (s != sm->subscriptions);
00549
00550 wpabuf_free(buf);
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 void subscription_unlink(struct subscription *s)
00562 {
00563 struct upnp_wps_device_sm *sm = s->sm;
00564
00565 if (s->next == s) {
00566
00567 sm->subscriptions = NULL;
00568 } else {
00569 if (sm->subscriptions == s)
00570 sm->subscriptions = s->next;
00571 s->next->prev = s->prev;
00572 s->prev->next = s->next;
00573 }
00574 sm->n_subscriptions--;
00575 }
00576
00577
00578
00579
00580
00581 static void subscription_link_to_end(struct subscription *s)
00582 {
00583 struct upnp_wps_device_sm *sm = s->sm;
00584
00585 if (sm->subscriptions) {
00586 s->next = sm->subscriptions;
00587 s->prev = s->next->prev;
00588 s->prev->next = s;
00589 s->next->prev = s;
00590 } else {
00591 sm->subscriptions = s->next = s->prev = s;
00592 }
00593 sm->n_subscriptions++;
00594 }
00595
00596
00597
00598
00599
00600 void subscription_destroy(struct subscription *s)
00601 {
00602 wpa_printf(MSG_DEBUG, "WPS UPnP: Destroy subscription %p", s);
00603 if (s->addr_list)
00604 subscr_addr_free_all(s);
00605 event_delete_all(s);
00606 os_free(s);
00607 }
00608
00609
00610
00611 static void subscription_list_age(struct upnp_wps_device_sm *sm, time_t now)
00612 {
00613 struct subscription *s;
00614 while ((s = sm->subscriptions) != NULL && s->timeout_time < now) {
00615 wpa_printf(MSG_DEBUG, "WPS UPnP: Removing aged subscription");
00616 subscription_unlink(s);
00617 subscription_destroy(s);
00618 }
00619 }
00620
00621
00622
00623
00624
00625 struct subscription * subscription_find(struct upnp_wps_device_sm *sm,
00626 const u8 uuid[UUID_LEN])
00627 {
00628 struct subscription *s0 = sm->subscriptions;
00629 struct subscription *s = s0;
00630
00631 if (s0 == NULL)
00632 return NULL;
00633 do {
00634 if (os_memcmp(s->uuid, uuid, UUID_LEN) == 0)
00635 return s;
00636 s = s->next;
00637 } while (s != s0);
00638
00639 return NULL;
00640 }
00641
00642
00643 static struct wpabuf * build_fake_wsc_ack(void)
00644 {
00645 struct wpabuf *msg = wpabuf_alloc(100);
00646 if (msg == NULL)
00647 return NULL;
00648 wpabuf_put_u8(msg, UPNP_WPS_WLANEVENT_TYPE_EAP);
00649 wpabuf_put_str(msg, "00:00:00:00:00:00");
00650 wps_build_version(msg);
00651 wps_build_msg_type(msg, WPS_WSC_ACK);
00652
00653 wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
00654 wpabuf_put_be16(msg, WPS_NONCE_LEN);
00655 wpabuf_put(msg, WPS_NONCE_LEN);
00656
00657 wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
00658 wpabuf_put_be16(msg, WPS_NONCE_LEN);
00659 wpabuf_put(msg, WPS_NONCE_LEN);
00660 return msg;
00661 }
00662
00663
00664
00665
00666
00667 static int subscription_first_event(struct subscription *s)
00668 {
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 char *wlan_event;
00680 struct wpabuf *buf;
00681 int ap_status = 1;
00682 const char *head =
00683 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
00684 "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
00685 const char *tail = "</e:propertyset>\n";
00686 char txt[10];
00687
00688 if (s->sm->wlanevent == NULL) {
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698 struct wpabuf *msg;
00699 wpa_printf(MSG_DEBUG, "WPS UPnP: Use a fake WSC_ACK as the "
00700 "initial WLANEvent");
00701 msg = build_fake_wsc_ack();
00702 if (msg) {
00703 s->sm->wlanevent = (char *)
00704 base64_encode(wpabuf_head(msg),
00705 wpabuf_len(msg), NULL);
00706 wpabuf_free(msg);
00707 }
00708 }
00709
00710 wlan_event = s->sm->wlanevent;
00711 if (wlan_event == NULL || *wlan_event == '\0') {
00712 wpa_printf(MSG_DEBUG, "WPS UPnP: WLANEvent not known for "
00713 "initial event message");
00714 wlan_event = "";
00715 }
00716 buf = wpabuf_alloc(500 + os_strlen(wlan_event));
00717 if (buf == NULL)
00718 return 1;
00719
00720 wpabuf_put_str(buf, head);
00721 wpabuf_put_property(buf, "STAStatus", "1");
00722 os_snprintf(txt, sizeof(txt), "%d", ap_status);
00723 wpabuf_put_property(buf, "APStatus", txt);
00724 if (*wlan_event)
00725 wpabuf_put_property(buf, "WLANEvent", wlan_event);
00726 wpabuf_put_str(buf, tail);
00727
00728 if (event_add(s, buf)) {
00729 wpabuf_free(buf);
00730 return 1;
00731 }
00732 wpabuf_free(buf);
00733
00734 return 0;
00735 }
00736
00737
00745 struct subscription * subscription_start(struct upnp_wps_device_sm *sm,
00746 const char *callback_urls)
00747 {
00748 struct subscription *s;
00749 time_t now = time(NULL);
00750 time_t expire = now + UPNP_SUBSCRIBE_SEC;
00751
00752
00753 subscription_list_age(sm, now);
00754
00755
00756 if (sm->n_subscriptions >= MAX_SUBSCRIPTIONS) {
00757 s = sm->subscriptions;
00758 wpa_printf(MSG_INFO, "WPS UPnP: Too many subscriptions, "
00759 "trashing oldest");
00760 subscription_unlink(s);
00761 subscription_destroy(s);
00762 }
00763
00764 s = os_zalloc(sizeof(*s));
00765 if (s == NULL)
00766 return NULL;
00767
00768 s->sm = sm;
00769 s->timeout_time = expire;
00770 uuid_make(s->uuid);
00771 subscr_addr_list_create(s, callback_urls);
00772
00773 subscription_link_to_end(s);
00774
00775
00776
00777 if (subscription_first_event(s)) {
00778 wpa_printf(MSG_INFO, "WPS UPnP: Dropping subscriber due to "
00779 "event backlog");
00780 subscription_unlink(s);
00781 subscription_destroy(s);
00782 return NULL;
00783 }
00784 wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription %p started with %s",
00785 s, callback_urls);
00786
00787 event_send_all_later(sm);
00788 return s;
00789 }
00790
00791
00792
00793 struct subscription * subscription_renew(struct upnp_wps_device_sm *sm,
00794 const u8 uuid[UUID_LEN])
00795 {
00796 time_t now = time(NULL);
00797 time_t expire = now + UPNP_SUBSCRIBE_SEC;
00798 struct subscription *s = subscription_find(sm, uuid);
00799 if (s == NULL)
00800 return NULL;
00801 wpa_printf(MSG_DEBUG, "WPS UPnP: Subscription renewed");
00802 subscription_unlink(s);
00803 s->timeout_time = expire;
00804
00805 subscription_link_to_end(s);
00806 return s;
00807 }
00808
00809
00823 int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm,
00824 const u8 from_mac_addr[ETH_ALEN],
00825 enum upnp_wps_wlanevent_type ev_type,
00826 const struct wpabuf *msg)
00827 {
00828 int ret = -1;
00829 char type[2];
00830 const u8 *mac = from_mac_addr;
00831 char mac_text[18];
00832 u8 *raw = NULL;
00833 size_t raw_len;
00834 char *val;
00835 size_t val_len;
00836 int pos = 0;
00837
00838 if (!sm)
00839 goto fail;
00840
00841 os_snprintf(type, sizeof(type), "%1u", ev_type);
00842
00843 raw_len = 1 + 17 + (msg ? wpabuf_len(msg) : 0);
00844 raw = os_zalloc(raw_len);
00845 if (!raw)
00846 goto fail;
00847
00848 *(raw + pos) = (u8) ev_type;
00849 pos += 1;
00850 os_snprintf(mac_text, sizeof(mac_text), MACSTR, MAC2STR(mac));
00851 wpa_printf(MSG_DEBUG, "WPS UPnP: Proxying WLANEvent from %s",
00852 mac_text);
00853 os_memcpy(raw + pos, mac_text, 17);
00854 pos += 17;
00855 if (msg) {
00856 os_memcpy(raw + pos, wpabuf_head(msg), wpabuf_len(msg));
00857 pos += wpabuf_len(msg);
00858 }
00859 raw_len = pos;
00860
00861 val = (char *) base64_encode(raw, raw_len, &val_len);
00862 if (val == NULL)
00863 goto fail;
00864
00865 os_free(sm->wlanevent);
00866 sm->wlanevent = val;
00867 upnp_wps_device_send_event(sm);
00868
00869 ret = 0;
00870
00871 fail:
00872 os_free(raw);
00873
00874 return ret;
00875 }
00876
00877
00878 #ifdef __FreeBSD__
00879 #include <sys/sysctl.h>
00880 #include <net/route.h>
00881 #include <net/if_dl.h>
00882
00883 static int eth_get(const char *device, u8 ea[ETH_ALEN])
00884 {
00885 struct if_msghdr *ifm;
00886 struct sockaddr_dl *sdl;
00887 u_char *p, *buf;
00888 size_t len;
00889 int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
00890
00891 if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
00892 return -1;
00893 if ((buf = os_malloc(len)) == NULL)
00894 return -1;
00895 if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
00896 os_free(buf);
00897 return -1;
00898 }
00899 for (p = buf; p < buf + len; p += ifm->ifm_msglen) {
00900 ifm = (struct if_msghdr *)p;
00901 sdl = (struct sockaddr_dl *)(ifm + 1);
00902 if (ifm->ifm_type != RTM_IFINFO ||
00903 (ifm->ifm_addrs & RTA_IFP) == 0)
00904 continue;
00905 if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
00906 os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0)
00907 continue;
00908 os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen);
00909 break;
00910 }
00911 os_free(buf);
00912
00913 if (p >= buf + len) {
00914 errno = ESRCH;
00915 return -1;
00916 }
00917 return 0;
00918 }
00919 #endif
00920
00921
00932 int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text,
00933 u8 mac[ETH_ALEN], char **mac_addr_text)
00934 {
00935 struct ifreq req;
00936 int sock = -1;
00937 struct sockaddr_in *addr;
00938 struct in_addr in_addr;
00939
00940 *ip_addr_text = os_zalloc(16);
00941 *mac_addr_text = os_zalloc(18);
00942 if (*ip_addr_text == NULL || *mac_addr_text == NULL)
00943 goto fail;
00944
00945 sock = socket(AF_INET, SOCK_DGRAM, 0);
00946 if (sock < 0)
00947 goto fail;
00948
00949 os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name));
00950 if (ioctl(sock, SIOCGIFADDR, &req) < 0) {
00951 wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFADDR failed: %d (%s)",
00952 errno, strerror(errno));
00953 goto fail;
00954 }
00955 addr = (void *) &req.ifr_addr;
00956 *ip_addr = addr->sin_addr.s_addr;
00957 in_addr.s_addr = *ip_addr;
00958 os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr));
00959
00960 #ifdef __linux__
00961 os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name));
00962 if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) {
00963 wpa_printf(MSG_ERROR, "WPS UPnP: SIOCGIFHWADDR failed: "
00964 "%d (%s)", errno, strerror(errno));
00965 goto fail;
00966 }
00967 os_memcpy(mac, req.ifr_addr.sa_data, 6);
00968 #elif defined(__FreeBSD__)
00969 if (eth_get(net_if, mac) < 0) {
00970 wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address");
00971 goto fail;
00972 }
00973 #else
00974 #error MAC address fetch not implemented
00975 #endif
00976 os_snprintf(*mac_addr_text, 18, MACSTR, MAC2STR(mac));
00977
00978 close(sock);
00979 return 0;
00980
00981 fail:
00982 if (sock >= 0)
00983 close(sock);
00984 os_free(*ip_addr_text);
00985 *ip_addr_text = NULL;
00986 os_free(*mac_addr_text);
00987 *mac_addr_text = NULL;
00988 return -1;
00989 }
00990
00991
00997 void upnp_wps_device_stop(struct upnp_wps_device_sm *sm)
00998 {
00999 if (!sm || !sm->started)
01000 return;
01001
01002 wpa_printf(MSG_DEBUG, "WPS UPnP: Stop device");
01003 web_listener_stop(sm);
01004 while (sm->msearch_replies)
01005 msearchreply_state_machine_stop(sm->msearch_replies);
01006 while (sm->subscriptions) {
01007 struct subscription *s = sm->subscriptions;
01008 subscription_unlink(s);
01009 subscription_destroy(s);
01010 }
01011
01012 advertisement_state_machine_stop(sm, 1);
01013
01014 event_send_stop_all(sm);
01015 os_free(sm->wlanevent);
01016 sm->wlanevent = NULL;
01017 os_free(sm->net_if);
01018 sm->net_if = NULL;
01019 os_free(sm->mac_addr_text);
01020 sm->mac_addr_text = NULL;
01021 os_free(sm->ip_addr_text);
01022 sm->ip_addr_text = NULL;
01023 if (sm->multicast_sd >= 0)
01024 close(sm->multicast_sd);
01025 sm->multicast_sd = -1;
01026 ssdp_listener_stop(sm);
01027
01028 sm->started = 0;
01029 }
01030
01031
01039 int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if)
01040 {
01041 if (!sm || !net_if)
01042 return -1;
01043
01044 if (sm->started)
01045 upnp_wps_device_stop(sm);
01046
01047 sm->net_if = strdup(net_if);
01048 sm->multicast_sd = -1;
01049 sm->ssdp_sd = -1;
01050 sm->started = 1;
01051 sm->advertise_count = 0;
01052
01053
01054 if (add_ssdp_network(net_if))
01055 goto fail;
01056
01057
01058 if (get_netif_info(net_if,
01059 &sm->ip_addr, &sm->ip_addr_text,
01060 sm->mac_addr, &sm->mac_addr_text)) {
01061 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
01062 "for %s. Does it have IP address?", net_if);
01063 goto fail;
01064 }
01065
01066
01067
01068
01069 if (web_listener_start(sm))
01070 goto fail;
01071
01072
01073 if (ssdp_listener_start(sm))
01074 goto fail;
01075
01076
01077 if (ssdp_open_multicast(sm) < 0)
01078 goto fail;
01079
01080
01081
01082
01083
01084
01085 if (advertisement_state_machine_start(sm))
01086 goto fail;
01087
01088 return 0;
01089
01090 fail:
01091 upnp_wps_device_stop(sm);
01092 return -1;
01093 }
01094
01095
01101 void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm)
01102 {
01103 if (!sm)
01104 return;
01105
01106 upnp_wps_device_stop(sm);
01107
01108 if (sm->peer.wps)
01109 wps_deinit(sm->peer.wps);
01110 os_free(sm->root_dir);
01111 os_free(sm->desc_url);
01112 os_free(sm->ctx);
01113 os_free(sm);
01114 }
01115
01116
01125 struct upnp_wps_device_sm *
01126 upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps,
01127 void *priv)
01128 {
01129 struct upnp_wps_device_sm *sm;
01130
01131 sm = os_zalloc(sizeof(*sm));
01132 if (!sm) {
01133 wpa_printf(MSG_ERROR, "WPS UPnP: upnp_wps_device_init failed");
01134 return NULL;
01135 }
01136
01137 sm->ctx = ctx;
01138 sm->wps = wps;
01139 sm->priv = priv;
01140
01141 return sm;
01142 }
01143
01144
01151 int upnp_wps_subscribers(struct upnp_wps_device_sm *sm)
01152 {
01153 return sm->subscriptions != NULL;
01154 }
01155