Deleted Added
full compact
iapp.c (252726) iapp.c (281806)
1/*
2 * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
3 * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 *
8 * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired

--- 190 unchanged lines hidden (view full) ---

199 add->seq_num = host_to_be16(seq_num);
200
201 os_memset(&addr, 0, sizeof(addr));
202 addr.sin_family = AF_INET;
203 addr.sin_addr.s_addr = iapp->multicast.s_addr;
204 addr.sin_port = htons(IAPP_UDP_PORT);
205 if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0,
206 (struct sockaddr *) &addr, sizeof(addr)) < 0)
1/*
2 * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
3 * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 *
8 * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired

--- 190 unchanged lines hidden (view full) ---

199 add->seq_num = host_to_be16(seq_num);
200
201 os_memset(&addr, 0, sizeof(addr));
202 addr.sin_family = AF_INET;
203 addr.sin_addr.s_addr = iapp->multicast.s_addr;
204 addr.sin_port = htons(IAPP_UDP_PORT);
205 if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0,
206 (struct sockaddr *) &addr, sizeof(addr)) < 0)
207 perror("sendto[IAPP-ADD]");
207 wpa_printf(MSG_INFO, "sendto[IAPP-ADD]: %s", strerror(errno));
208}
209
210
211static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
212{
213 struct iapp_layer2_update msg;
214
215 /* Send Level 2 Update Frame to update forwarding tables in layer 2

--- 10 unchanged lines hidden (view full) ---

226 msg.control = 0xaf; /* XID response lsb.1111F101.
227 * F=0 (no poll command; unsolicited frame) */
228 msg.xid_info[0] = 0x81; /* XID format identifier */
229 msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
230 msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW)
231 * FIX: what is correct RW with 802.11? */
232
233 if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0)
208}
209
210
211static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
212{
213 struct iapp_layer2_update msg;
214
215 /* Send Level 2 Update Frame to update forwarding tables in layer 2

--- 10 unchanged lines hidden (view full) ---

226 msg.control = 0xaf; /* XID response lsb.1111F101.
227 * F=0 (no poll command; unsolicited frame) */
228 msg.xid_info[0] = 0x81; /* XID format identifier */
229 msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
230 msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW)
231 * FIX: what is correct RW with 802.11? */
232
233 if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0)
234 perror("send[L2 Update]");
234 wpa_printf(MSG_INFO, "send[L2 Update]: %s", strerror(errno));
235}
236
237
238/**
239 * iapp_new_station - IAPP processing for a new STA
240 * @iapp: IAPP data
241 * @sta: The associated station
242 */
243void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
244{
235}
236
237
238/**
239 * iapp_new_station - IAPP processing for a new STA
240 * @iapp: IAPP data
241 * @sta: The associated station
242 */
243void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
244{
245 struct ieee80211_mgmt *assoc;
246 u16 seq;
245 u16 seq = 0; /* TODO */
247
248 if (iapp == NULL)
249 return;
250
246
247 if (iapp == NULL)
248 return;
249
251 assoc = sta->last_assoc_req;
252 seq = assoc ? WLAN_GET_SEQ_SEQ(le_to_host16(assoc->seq_ctrl)) : 0;
253
254 /* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
255 hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
256 HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
257 iapp_send_layer2_update(iapp, sta->addr);
258 iapp_send_add(iapp, sta->addr, seq);
259
250 /* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
251 hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
252 HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
253 iapp_send_layer2_update(iapp, sta->addr);
254 iapp_send_add(iapp, sta->addr, seq);
255
260 if (assoc && WLAN_FC_GET_STYPE(le_to_host16(assoc->frame_control)) ==
261 WLAN_FC_STYPE_REASSOC_REQ) {
262 /* IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
263 * Context Block, Timeout)
264 */
265 /* TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
266 * IP address */
267 }
256 /* TODO: If this was reassociation:
257 * IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
258 * Context Block, Timeout)
259 * TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
260 * IP address */
268}
269
270
271static void iapp_process_add_notify(struct iapp_data *iapp,
272 struct sockaddr_in *from,
273 struct iapp_hdr *hdr, int len)
274{
275 struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1);
276 struct sta_info *sta;
277
278 if (len != sizeof(*add)) {
261}
262
263
264static void iapp_process_add_notify(struct iapp_data *iapp,
265 struct sockaddr_in *from,
266 struct iapp_hdr *hdr, int len)
267{
268 struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1);
269 struct sta_info *sta;
270
271 if (len != sizeof(*add)) {
279 printf("Invalid IAPP-ADD packet length %d (expected %lu)\n",
280 len, (unsigned long) sizeof(*add));
272 wpa_printf(MSG_INFO, "Invalid IAPP-ADD packet length %d (expected %lu)",
273 len, (unsigned long) sizeof(*add));
281 return;
282 }
283
284 sta = ap_get_sta(iapp->hapd, add->mac_addr);
285
286 /* IAPP-ADD.indication(MAC Address, Sequence Number) */
287 hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
288 HOSTAPD_LEVEL_INFO,

--- 32 unchanged lines hidden (view full) ---

321 struct iapp_hdr *hdr;
322
323 /* Handle incoming IAPP frames (over UDP/IP) */
324
325 fromlen = sizeof(from);
326 len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0,
327 (struct sockaddr *) &from, &fromlen);
328 if (len < 0) {
274 return;
275 }
276
277 sta = ap_get_sta(iapp->hapd, add->mac_addr);
278
279 /* IAPP-ADD.indication(MAC Address, Sequence Number) */
280 hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
281 HOSTAPD_LEVEL_INFO,

--- 32 unchanged lines hidden (view full) ---

314 struct iapp_hdr *hdr;
315
316 /* Handle incoming IAPP frames (over UDP/IP) */
317
318 fromlen = sizeof(from);
319 len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0,
320 (struct sockaddr *) &from, &fromlen);
321 if (len < 0) {
329 perror("recvfrom");
322 wpa_printf(MSG_INFO, "iapp_receive_udp - recvfrom: %s",
323 strerror(errno));
330 return;
331 }
332
333 if (from.sin_addr.s_addr == iapp->own.s_addr)
334 return; /* ignore own IAPP messages */
335
336 hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
337 HOSTAPD_LEVEL_DEBUG,

--- 7 unchanged lines hidden (view full) ---

345 hdr = (struct iapp_hdr *) buf;
346 hlen = be_to_host16(hdr->length);
347 hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
348 HOSTAPD_LEVEL_DEBUG,
349 "RX: version=%d command=%d id=%d len=%d\n",
350 hdr->version, hdr->command,
351 be_to_host16(hdr->identifier), hlen);
352 if (hdr->version != IAPP_VERSION) {
324 return;
325 }
326
327 if (from.sin_addr.s_addr == iapp->own.s_addr)
328 return; /* ignore own IAPP messages */
329
330 hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
331 HOSTAPD_LEVEL_DEBUG,

--- 7 unchanged lines hidden (view full) ---

339 hdr = (struct iapp_hdr *) buf;
340 hlen = be_to_host16(hdr->length);
341 hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
342 HOSTAPD_LEVEL_DEBUG,
343 "RX: version=%d command=%d id=%d len=%d\n",
344 hdr->version, hdr->command,
345 be_to_host16(hdr->identifier), hlen);
346 if (hdr->version != IAPP_VERSION) {
353 printf("Dropping IAPP frame with unknown version %d\n",
354 hdr->version);
347 wpa_printf(MSG_INFO, "Dropping IAPP frame with unknown version %d",
348 hdr->version);
355 return;
356 }
357 if (hlen > len) {
349 return;
350 }
351 if (hlen > len) {
358 printf("Underflow IAPP frame (hlen=%d len=%d)\n", hlen, len);
352 wpa_printf(MSG_INFO, "Underflow IAPP frame (hlen=%d len=%d)",
353 hlen, len);
359 return;
360 }
361 if (hlen < len) {
354 return;
355 }
356 if (hlen < len) {
362 printf("Ignoring %d extra bytes from IAPP frame\n",
363 len - hlen);
357 wpa_printf(MSG_INFO, "Ignoring %d extra bytes from IAPP frame",
358 len - hlen);
364 len = hlen;
365 }
366
367 switch (hdr->command) {
368 case IAPP_CMD_ADD_notify:
359 len = hlen;
360 }
361
362 switch (hdr->command) {
363 case IAPP_CMD_ADD_notify:
369 iapp_process_add_notify(iapp, &from, hdr, hlen - sizeof(*hdr));
364 iapp_process_add_notify(iapp, &from, hdr, len - sizeof(*hdr));
370 break;
371 case IAPP_CMD_MOVE_notify:
372 /* TODO: MOVE is using TCP; so move this to TCP handler once it
373 * is implemented.. */
374 /* IAPP-MOVE.indication(MAC Address, New BSSID,
375 * Sequence Number, AP Address, Context Block) */
376 /* TODO: process */
377 break;
378 default:
365 break;
366 case IAPP_CMD_MOVE_notify:
367 /* TODO: MOVE is using TCP; so move this to TCP handler once it
368 * is implemented.. */
369 /* IAPP-MOVE.indication(MAC Address, New BSSID,
370 * Sequence Number, AP Address, Context Block) */
371 /* TODO: process */
372 break;
373 default:
379 printf("Unknown IAPP command %d\n", hdr->command);
374 wpa_printf(MSG_INFO, "Unknown IAPP command %d", hdr->command);
380 break;
381 }
382}
383
384
385struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
386{
387 struct ifreq ifr;

--- 10 unchanged lines hidden (view full) ---

398 iapp->udp_sock = iapp->packet_sock = -1;
399
400 /* TODO:
401 * open socket for sending and receiving IAPP frames over TCP
402 */
403
404 iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
405 if (iapp->udp_sock < 0) {
375 break;
376 }
377}
378
379
380struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
381{
382 struct ifreq ifr;

--- 10 unchanged lines hidden (view full) ---

393 iapp->udp_sock = iapp->packet_sock = -1;
394
395 /* TODO:
396 * open socket for sending and receiving IAPP frames over TCP
397 */
398
399 iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
400 if (iapp->udp_sock < 0) {
406 perror("socket[PF_INET,SOCK_DGRAM]");
401 wpa_printf(MSG_INFO, "iapp_init - socket[PF_INET,SOCK_DGRAM]: %s",
402 strerror(errno));
407 iapp_deinit(iapp);
408 return NULL;
409 }
410
411 os_memset(&ifr, 0, sizeof(ifr));
412 os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
413 if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) {
403 iapp_deinit(iapp);
404 return NULL;
405 }
406
407 os_memset(&ifr, 0, sizeof(ifr));
408 os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
409 if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) {
414 perror("ioctl(SIOCGIFINDEX)");
410 wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFINDEX): %s",
411 strerror(errno));
415 iapp_deinit(iapp);
416 return NULL;
417 }
418 ifindex = ifr.ifr_ifindex;
419
420 if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
412 iapp_deinit(iapp);
413 return NULL;
414 }
415 ifindex = ifr.ifr_ifindex;
416
417 if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
421 perror("ioctl(SIOCGIFADDR)");
418 wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFADDR): %s",
419 strerror(errno));
422 iapp_deinit(iapp);
423 return NULL;
424 }
425 paddr = (struct sockaddr_in *) &ifr.ifr_addr;
426 if (paddr->sin_family != AF_INET) {
420 iapp_deinit(iapp);
421 return NULL;
422 }
423 paddr = (struct sockaddr_in *) &ifr.ifr_addr;
424 if (paddr->sin_family != AF_INET) {
427 printf("Invalid address family %i (SIOCGIFADDR)\n",
428 paddr->sin_family);
425 wpa_printf(MSG_INFO, "IAPP: Invalid address family %i (SIOCGIFADDR)",
426 paddr->sin_family);
429 iapp_deinit(iapp);
430 return NULL;
431 }
432 iapp->own.s_addr = paddr->sin_addr.s_addr;
433
434 if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) {
427 iapp_deinit(iapp);
428 return NULL;
429 }
430 iapp->own.s_addr = paddr->sin_addr.s_addr;
431
432 if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) {
435 perror("ioctl(SIOCGIFBRDADDR)");
433 wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFBRDADDR): %s",
434 strerror(errno));
436 iapp_deinit(iapp);
437 return NULL;
438 }
439 paddr = (struct sockaddr_in *) &ifr.ifr_addr;
440 if (paddr->sin_family != AF_INET) {
435 iapp_deinit(iapp);
436 return NULL;
437 }
438 paddr = (struct sockaddr_in *) &ifr.ifr_addr;
439 if (paddr->sin_family != AF_INET) {
441 printf("Invalid address family %i (SIOCGIFBRDADDR)\n",
442 paddr->sin_family);
440 wpa_printf(MSG_INFO, "Invalid address family %i (SIOCGIFBRDADDR)",
441 paddr->sin_family);
443 iapp_deinit(iapp);
444 return NULL;
445 }
446 inet_aton(IAPP_MULTICAST, &iapp->multicast);
447
448 os_memset(&uaddr, 0, sizeof(uaddr));
449 uaddr.sin_family = AF_INET;
450 uaddr.sin_port = htons(IAPP_UDP_PORT);
451 if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
452 sizeof(uaddr)) < 0) {
442 iapp_deinit(iapp);
443 return NULL;
444 }
445 inet_aton(IAPP_MULTICAST, &iapp->multicast);
446
447 os_memset(&uaddr, 0, sizeof(uaddr));
448 uaddr.sin_family = AF_INET;
449 uaddr.sin_port = htons(IAPP_UDP_PORT);
450 if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
451 sizeof(uaddr)) < 0) {
453 perror("bind[UDP]");
452 wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s",
453 strerror(errno));
454 iapp_deinit(iapp);
455 return NULL;
456 }
457
458 os_memset(&mreq, 0, sizeof(mreq));
459 mreq.imr_multiaddr = iapp->multicast;
460 mreq.imr_address.s_addr = INADDR_ANY;
461 mreq.imr_ifindex = 0;
462 if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
463 sizeof(mreq)) < 0) {
454 iapp_deinit(iapp);
455 return NULL;
456 }
457
458 os_memset(&mreq, 0, sizeof(mreq));
459 mreq.imr_multiaddr = iapp->multicast;
460 mreq.imr_address.s_addr = INADDR_ANY;
461 mreq.imr_ifindex = 0;
462 if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
463 sizeof(mreq)) < 0) {
464 perror("setsockopt[UDP,IP_ADD_MEMBERSHIP]");
464 wpa_printf(MSG_INFO, "iapp_init - setsockopt[UDP,IP_ADD_MEMBERSHIP]: %s",
465 strerror(errno));
465 iapp_deinit(iapp);
466 return NULL;
467 }
468
469 iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
470 if (iapp->packet_sock < 0) {
466 iapp_deinit(iapp);
467 return NULL;
468 }
469
470 iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
471 if (iapp->packet_sock < 0) {
471 perror("socket[PF_PACKET,SOCK_RAW]");
472 wpa_printf(MSG_INFO, "iapp_init - socket[PF_PACKET,SOCK_RAW]: %s",
473 strerror(errno));
472 iapp_deinit(iapp);
473 return NULL;
474 }
475
476 os_memset(&addr, 0, sizeof(addr));
477 addr.sll_family = AF_PACKET;
478 addr.sll_ifindex = ifindex;
479 if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
480 sizeof(addr)) < 0) {
474 iapp_deinit(iapp);
475 return NULL;
476 }
477
478 os_memset(&addr, 0, sizeof(addr));
479 addr.sll_family = AF_PACKET;
480 addr.sll_ifindex = ifindex;
481 if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
482 sizeof(addr)) < 0) {
481 perror("bind[PACKET]");
483 wpa_printf(MSG_INFO, "iapp_init - bind[PACKET]: %s",
484 strerror(errno));
482 iapp_deinit(iapp);
483 return NULL;
484 }
485
486 if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp,
487 iapp, NULL)) {
485 iapp_deinit(iapp);
486 return NULL;
487 }
488
489 if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp,
490 iapp, NULL)) {
488 printf("Could not register read socket for IAPP.\n");
491 wpa_printf(MSG_INFO, "Could not register read socket for IAPP");
489 iapp_deinit(iapp);
490 return NULL;
491 }
492
492 iapp_deinit(iapp);
493 return NULL;
494 }
495
493 printf("IEEE 802.11F (IAPP) using interface %s\n", iface);
496 wpa_printf(MSG_INFO, "IEEE 802.11F (IAPP) using interface %s", iface);
494
495 /* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive
496 * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually
497 * be openned only after receiving Initiate-Accept. If Initiate-Reject
498 * is received, IAPP is not started. */
499
500 return iapp;
501}

--- 8 unchanged lines hidden (view full) ---

510
511 if (iapp->udp_sock >= 0) {
512 os_memset(&mreq, 0, sizeof(mreq));
513 mreq.imr_multiaddr = iapp->multicast;
514 mreq.imr_address.s_addr = INADDR_ANY;
515 mreq.imr_ifindex = 0;
516 if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP,
517 &mreq, sizeof(mreq)) < 0) {
497
498 /* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive
499 * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually
500 * be openned only after receiving Initiate-Accept. If Initiate-Reject
501 * is received, IAPP is not started. */
502
503 return iapp;
504}

--- 8 unchanged lines hidden (view full) ---

513
514 if (iapp->udp_sock >= 0) {
515 os_memset(&mreq, 0, sizeof(mreq));
516 mreq.imr_multiaddr = iapp->multicast;
517 mreq.imr_address.s_addr = INADDR_ANY;
518 mreq.imr_ifindex = 0;
519 if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP,
520 &mreq, sizeof(mreq)) < 0) {
518 perror("setsockopt[UDP,IP_DEL_MEMBERSHIP]");
521 wpa_printf(MSG_INFO, "iapp_deinit - setsockopt[UDP,IP_DEL_MEMBERSHIP]: %s",
522 strerror(errno));
519 }
520
521 eloop_unregister_read_sock(iapp->udp_sock);
522 close(iapp->udp_sock);
523 }
524 if (iapp->packet_sock >= 0) {
525 eloop_unregister_read_sock(iapp->packet_sock);
526 close(iapp->packet_sock);
527 }
528 os_free(iapp);
529}
523 }
524
525 eloop_unregister_read_sock(iapp->udp_sock);
526 close(iapp->udp_sock);
527 }
528 if (iapp->packet_sock >= 0) {
529 eloop_unregister_read_sock(iapp->packet_sock);
530 close(iapp->packet_sock);
531 }
532 os_free(iapp);
533}