1/* 2 * UPnP WPS Device - Event processing 3 * Copyright (c) 2000-2003 Intel Corporation 4 * Copyright (c) 2006-2007 Sony Corporation 5 * Copyright (c) 2008-2009 Atheros Communications 6 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 7 * 8 * See wps_upnp.c for more details on licensing and code history. 9 */ 10 11#include "includes.h" 12#include <assert.h> 13#include <fcntl.h> 14 15#include "common.h" 16#include "eloop.h" 17#include "uuid.h" 18#include "httpread.h" 19#include "wps_defs.h" 20#include "wps_upnp.h" 21#include "wps_upnp_i.h" 22 23/* 24 * Event message generation (to subscribers) 25 * 26 * We make a separate copy for each message for each subscriber. This memory 27 * wasted could be limited (adding code complexity) by sharing copies, keeping 28 * a usage count and freeing when zero. 29 * 30 * Sending a message requires using a HTTP over TCP NOTIFY 31 * (like a PUT) which requires a number of states.. 32 */ 33 34#define MAX_EVENTS_QUEUED 20 /* How far behind queued events */ 35#define EVENT_TIMEOUT_SEC 30 /* Drop sending event after timeout */ 36 37/* How long to wait before sending event */ 38#define EVENT_DELAY_SECONDS 0 39#define EVENT_DELAY_MSEC 0 40 41/* 42 * Event information that we send to each subscriber is remembered in this 43 * struct. The event cannot be sent by simple UDP; it has to be sent by a HTTP 44 * over TCP transaction which requires various states.. It may also need to be 45 * retried at a different address (if more than one is available). 46 * 47 * TODO: As an optimization we could share data between subscribers. 48 */ 49struct wps_event_ { 50 struct wps_event_ *next; 51 struct wps_event_ *prev; /* double linked list */ 52 struct subscription *s; /* parent */ 53 unsigned subscriber_sequence; /* which event for this subscription*/ 54 int retry; /* which retry */ 55 struct subscr_addr *addr; /* address to connect to */ 56 struct wpabuf *data; /* event data to send */ 57 /* The following apply while we are sending an event message. */ 58 int sd; /* -1 or socket descriptor for open connection */ 59 int sd_registered; /* nonzero if we must cancel registration */ 60 struct httpread *hread; /* NULL or open connection for event msg */ 61}; 62 63 64static void event_timeout_handler(void *eloop_data, void *user_ctx); 65 66/* event_clean -- clean sockets etc. of event 67 * Leaves data, retry count etc. alone. 68 */ 69static void event_clean(struct wps_event_ *e) 70{ 71 if (e->s->current_event == e) { 72 eloop_cancel_timeout(event_timeout_handler, NULL, e); 73 e->s->current_event = NULL; 74 } 75 if (e->sd_registered) { 76 eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE); 77 e->sd_registered = 0; 78 } 79 if (e->sd != -1) { 80 close(e->sd); 81 e->sd = -1; 82 } 83 if (e->hread) 84 httpread_destroy(e->hread); 85 e->hread = NULL; 86} 87 88 89/* event_delete -- delete single unqueued event 90 * (be sure to dequeue first if need be) 91 */ 92static void event_delete(struct wps_event_ *e) 93{ 94 event_clean(e); 95 wpabuf_free(e->data); 96 os_free(e); 97} 98 99 100/* event_dequeue -- get next event from the queue 101 * Returns NULL if empty. 102 */ 103static struct wps_event_ *event_dequeue(struct subscription *s) 104{ 105 struct wps_event_ **event_head = &s->event_queue; 106 struct wps_event_ *e = *event_head; 107 if (e == NULL) 108 return NULL; 109 e->next->prev = e->prev; 110 e->prev->next = e->next; 111 if (*event_head == e) { 112 if (e == e->next) { 113 /* last in queue */ 114 *event_head = NULL; 115 } else { 116 *event_head = e->next; 117 } 118 } 119 s->n_queue--; 120 e->next = e->prev = NULL; 121 /* but parent "s" is still valid */ 122 return e; 123} 124 125 126/* event_enqueue_at_end -- add event to end of queue */ 127static void event_enqueue_at_end(struct subscription *s, struct wps_event_ *e) 128{ 129 struct wps_event_ **event_head = &s->event_queue; 130 if (*event_head == NULL) { 131 *event_head = e->next = e->prev = e; 132 } else { 133 e->next = *event_head; 134 e->prev = e->next->prev; 135 e->prev->next = e; 136 e->next->prev = e; 137 } 138 s->n_queue++; 139} 140 141 142/* event_enqueue_at_begin -- add event to begin of queue 143 * (appropriate for retrying event only) 144 */ 145static void event_enqueue_at_begin(struct subscription *s, 146 struct wps_event_ *e) 147{ 148 struct wps_event_ **event_head = &s->event_queue; 149 if (*event_head == NULL) { 150 *event_head = e->next = e->prev = e; 151 } else { 152 e->prev = *event_head; 153 e->next = e->prev->next; 154 e->prev->next = e; 155 e->next->prev = e; 156 *event_head = e; 157 } 158 s->n_queue++; 159} 160 161 162/* event_delete_all -- delete entire event queue and current event */ 163void event_delete_all(struct subscription *s) 164{ 165 struct wps_event_ *e; 166 while ((e = event_dequeue(s)) != NULL) 167 event_delete(e); 168 if (s->current_event) { 169 event_delete(s->current_event); 170 /* will set: s->current_event = NULL; */ 171 } 172} 173 174 175/** 176 * event_retry - Called when we had a failure delivering event msg 177 * @e: Event 178 * @do_next_address: skip address e.g. on connect fail 179 */ 180static void event_retry(struct wps_event_ *e, int do_next_address) 181{ 182 struct subscription *s = e->s; 183 struct upnp_wps_device_sm *sm = s->sm; 184 185 event_clean(e); 186 /* will set: s->current_event = NULL; */ 187 188 if (do_next_address) 189 e->retry++; 190 if (e->retry >= s->n_addr) { 191 wpa_printf(MSG_DEBUG, "WPS UPnP: Giving up on sending event " 192 "for %s", e->addr->domain_and_port); 193 return; 194 } 195 event_enqueue_at_begin(s, e); 196 event_send_all_later(sm); 197} 198 199 200/* called if the overall event-sending process takes too long */ 201static void event_timeout_handler(void *eloop_data, void *user_ctx) 202{ 203 struct wps_event_ *e = user_ctx; 204 struct subscription *s = e->s; 205 206 assert(e == s->current_event); 207 208 wpa_printf(MSG_DEBUG, "WPS UPnP: Event send timeout"); 209 event_retry(e, 1); 210} 211 212 213/* event_got_response_handler -- called back when http response is received. */ 214static void event_got_response_handler(struct httpread *handle, void *cookie, 215 enum httpread_event en) 216{ 217 struct wps_event_ *e = cookie; 218 struct subscription *s = e->s; 219 struct upnp_wps_device_sm *sm = s->sm; 220 struct httpread *hread = e->hread; 221 int reply_code = 0; 222 223 assert(e == s->current_event); 224 eloop_cancel_timeout(event_timeout_handler, NULL, e); 225 226 if (en == HTTPREAD_EVENT_FILE_READY) { 227 if (httpread_hdr_type_get(hread) == HTTPREAD_HDR_TYPE_REPLY) { 228 reply_code = httpread_reply_code_get(hread); 229 if (reply_code == HTTP_OK) { 230 wpa_printf(MSG_DEBUG, 231 "WPS UPnP: Got event reply OK from " 232 "%s", e->addr->domain_and_port); 233 event_delete(e); 234 goto send_more; 235 } else { 236 wpa_printf(MSG_DEBUG, "WPS UPnP: Got event " 237 "error reply code %d from %s", 238 reply_code, 239 e->addr->domain_and_port); 240 goto bad; 241 } 242 } else { 243 wpa_printf(MSG_DEBUG, "WPS UPnP: Got bogus event " 244 "response %d from %s", en, 245 e->addr->domain_and_port); 246 } 247 } else { 248 wpa_printf(MSG_DEBUG, "WPS UPnP: Event response timeout/fail " 249 "for %s", e->addr->domain_and_port); 250 goto bad; 251 } 252 event_retry(e, 1); 253 goto send_more; 254 255send_more: 256 /* Schedule sending more if there is more to send */ 257 if (s->event_queue) 258 event_send_all_later(sm); 259 return; 260 261bad: 262 /* 263 * If other side doesn't like what we say, forget about them. 264 * (There is no way to tell other side that we are dropping 265 * them...). 266 * Alternately, we could just do event_delete(e) 267 */ 268 wpa_printf(MSG_DEBUG, "WPS UPnP: Deleting subscription due to errors"); 269 subscription_unlink(s); 270 subscription_destroy(s); 271} 272 273 274/* event_send_tx_ready -- actually write event message 275 * 276 * Prequisite: subscription socket descriptor has become ready to 277 * write (because connection to subscriber has been made). 278 * 279 * It is also possible that we are called because the connect has failed; 280 * it is possible to test for this, or we can just go ahead and then 281 * the write will fail. 282 */ 283static void event_send_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) 284{ 285 struct wps_event_ *e = sock_ctx; 286 struct subscription *s = e->s; 287 struct wpabuf *buf; 288 char *b; 289 290 assert(e == s->current_event); 291 assert(e->sd == sock); 292 293 buf = wpabuf_alloc(1000 + wpabuf_len(e->data)); 294 if (buf == NULL) { 295 event_retry(e, 0); 296 goto bad; 297 } 298 wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path); 299 wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n"); 300 wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port); 301 wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n" 302 "NT: upnp:event\r\n" 303 "NTS: upnp:propchange\r\n"); 304 wpabuf_put_str(buf, "SID: uuid:"); 305 b = wpabuf_put(buf, 0); 306 uuid_bin2str(s->uuid, b, 80); 307 wpabuf_put(buf, os_strlen(b)); 308 wpabuf_put_str(buf, "\r\n"); 309 wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence); 310 wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n", 311 (int) wpabuf_len(e->data)); 312 wpabuf_put_str(buf, "\r\n"); /* terminating empty line */ 313 wpabuf_put_buf(buf, e->data); 314 315 /* Since the message size is pretty small, we should be 316 * able to get the operating system to buffer what we give it 317 * and not have to come back again later to write more... 318 */ 319#if 0 320 /* we could: Turn blocking back on? */ 321 fcntl(e->sd, F_SETFL, 0); 322#endif 323 wpa_printf(MSG_DEBUG, "WPS UPnP: Sending event to %s", 324 e->addr->domain_and_port); 325 if (send_wpabuf(e->sd, buf) < 0) { 326 event_retry(e, 1); 327 goto bad; 328 } 329 wpabuf_free(buf); 330 buf = NULL; 331 332 if (e->sd_registered) { 333 e->sd_registered = 0; 334 eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE); 335 } 336 /* Set up to read the reply */ 337 e->hread = httpread_create(e->sd, event_got_response_handler, 338 e /* cookie */, 339 0 /* no data expected */, 340 EVENT_TIMEOUT_SEC); 341 if (e->hread == NULL) { 342 wpa_printf(MSG_ERROR, "WPS UPnP: httpread_create failed"); 343 event_retry(e, 0); 344 goto bad; 345 } 346 return; 347 348bad: 349 /* Schedule sending more if there is more to send */ 350 if (s->event_queue) 351 event_send_all_later(s->sm); 352 wpabuf_free(buf); 353} 354 355 356/* event_send_start -- prepare to send a event message to subscriber 357 * 358 * This gets complicated because: 359 * -- The message is sent via TCP and we have to keep the stream open 360 * for 30 seconds to get a response... then close it. 361 * -- But we might have other event happen in the meantime... 362 * we have to queue them, if we lose them then the subscriber will 363 * be forced to unsubscribe and subscribe again. 364 * -- If multiple URLs are provided then we are supposed to try successive 365 * ones after 30 second timeout. 366 * -- The URLs might use domain names instead of dotted decimal addresses, 367 * and resolution of those may cause unwanted sleeping. 368 * -- Doing the initial TCP connect can take a while, so we have to come 369 * back after connection and then send the data. 370 * 371 * Returns nonzero on error; 372 * 373 * Prerequisite: No current event send (s->current_event == NULL) 374 * and non-empty queue. 375 */ 376static int event_send_start(struct subscription *s) 377{ 378 struct wps_event_ *e; 379 int itry; 380 381 /* 382 * Assume we are called ONLY with no current event and ONLY with 383 * nonempty event queue and ONLY with at least one address to send to. 384 */ 385 assert(s->addr_list != NULL); 386 assert(s->current_event == NULL); 387 assert(s->event_queue != NULL); 388 389 s->current_event = e = event_dequeue(s); 390 391 /* Use address acc. to no. of retries */ 392 e->addr = s->addr_list; 393 for (itry = 0; itry < e->retry; itry++) 394 e->addr = e->addr->next; 395 396 e->sd = socket(AF_INET, SOCK_STREAM, 0); 397 if (e->sd < 0) { 398 event_retry(e, 0); 399 return -1; 400 } 401 /* set non-blocking so we don't sleep waiting for connection */ 402 if (fcntl(e->sd, F_SETFL, O_NONBLOCK) != 0) { 403 event_retry(e, 0); 404 return -1; 405 } 406 /* 407 * Start the connect. It might succeed immediately but more likely will 408 * return errno EINPROGRESS. 409 */ 410 if (connect(e->sd, (struct sockaddr *) &e->addr->saddr, 411 sizeof(e->addr->saddr))) { 412 if (errno != EINPROGRESS) { 413 event_retry(e, 1); 414 return -1; 415 } 416 } 417 /* Call back when ready for writing (or on failure...). */ 418 if (eloop_register_sock(e->sd, EVENT_TYPE_WRITE, event_send_tx_ready, 419 NULL, e)) { 420 event_retry(e, 0); 421 return -1; 422 } 423 e->sd_registered = 1; 424 /* Don't wait forever! */ 425 if (eloop_register_timeout(EVENT_TIMEOUT_SEC, 0, event_timeout_handler, 426 NULL, e)) { 427 event_retry(e, 0); 428 return -1; 429 } 430 return 0; 431} 432 433 434/* event_send_all_later_handler -- actually send events as needed */ 435static void event_send_all_later_handler(void *eloop_data, void *user_ctx) 436{ 437 struct upnp_wps_device_sm *sm = user_ctx; 438 struct subscription *s; 439 struct subscription *s_old; 440 int nerrors = 0; 441 442 sm->event_send_all_queued = 0; 443 s = sm->subscriptions; 444 if (s == NULL) 445 return; 446 do { 447 if (s->addr_list == NULL) { 448 /* if we've given up on all addresses */ 449 wpa_printf(MSG_DEBUG, "WPS UPnP: Removing " 450 "subscription with no addresses"); 451 s_old = s; 452 s = s_old->next; 453 subscription_unlink(s_old); 454 subscription_destroy(s_old); 455 } else { 456 if (s->current_event == NULL /* not busy */ && 457 s->event_queue != NULL /* more to do */) { 458 if (event_send_start(s)) 459 nerrors++; 460 } 461 s = s->next; 462 } 463 } while (sm->subscriptions != NULL && s != sm->subscriptions); 464 465 if (nerrors) { 466 /* Try again later */ 467 event_send_all_later(sm); 468 } 469} 470 471 472/* event_send_all_later -- schedule sending events to all subscribers 473 * that need it. 474 * This avoids two problems: 475 * -- After getting a subscription, we should not send the first event 476 * until after our reply is fully queued to be sent back, 477 * -- Possible stack depth or infinite recursion issues. 478 */ 479void event_send_all_later(struct upnp_wps_device_sm *sm) 480{ 481 /* 482 * The exact time in the future isn't too important. Waiting a bit 483 * might let us do several together. 484 */ 485 if (sm->event_send_all_queued) 486 return; 487 sm->event_send_all_queued = 1; 488 eloop_register_timeout(EVENT_DELAY_SECONDS, EVENT_DELAY_MSEC, 489 event_send_all_later_handler, NULL, sm); 490} 491 492 493/* event_send_stop_all -- cleanup */ 494void event_send_stop_all(struct upnp_wps_device_sm *sm) 495{ 496 if (sm->event_send_all_queued) 497 eloop_cancel_timeout(event_send_all_later_handler, NULL, sm); 498 sm->event_send_all_queued = 0; 499} 500 501 502/** 503 * event_add - Add a new event to a queue 504 * @s: Subscription 505 * @data: Event data (is copied; caller retains ownership) 506 * Returns: 0 on success, 1 on error 507 */ 508int event_add(struct subscription *s, const struct wpabuf *data) 509{ 510 struct wps_event_ *e; 511 512 if (s->n_queue >= MAX_EVENTS_QUEUED) { 513 wpa_printf(MSG_DEBUG, "WPS UPnP: Too many events queued for " 514 "subscriber"); 515 return 1; 516 } 517 518 e = os_zalloc(sizeof(*e)); 519 if (e == NULL) 520 return 1; 521 e->s = s; 522 e->sd = -1; 523 e->data = wpabuf_dup(data); 524 if (e->data == NULL) { 525 os_free(e); 526 return 1; 527 } 528 e->subscriber_sequence = s->next_subscriber_sequence++; 529 if (s->next_subscriber_sequence == 0) 530 s->next_subscriber_sequence++; 531 event_enqueue_at_end(s, e); 532 event_send_all_later(s->sm); 533 return 0; 534} 535