18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and IEEE has withdrawn it. In other words, it is likely better to look at 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * using some other mechanism for AP-to-AP communication than extending the 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * implementation here. 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Level 1: no administrative or security support 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (e.g., static BSSID to IP address mapping in each AP) 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Level 2: support for dynamic mapping of BSSID to IP address 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Level 3: support for encryption and authentication of IAPP messages 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - add support for MOVE-notify and MOVE-response (this requires support for 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * finding out IP address for previous AP using RADIUS) 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * reassociation to another AP 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - implement counters etc. for IAPP MIB 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - verify endianness of fields in IAPP messages; are they big-endian as 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * used here? 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - RADIUS connection for AP registration and BSSID to IP address mapping 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - TCP connection for IAPP MOVE, CACHE 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - broadcast ESP for IAPP ADD-notify 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - ESP for IAPP MOVE messages 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - security block sending/processing 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * - IEEE 802.11 context transfer 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <net/if.h> 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <sys/ioctl.h> 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef USE_KERNEL_HEADERS 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <linux/if_packet.h> 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* USE_KERNEL_HEADERS */ 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <netpacket/packet.h> 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* USE_KERNEL_HEADERS */ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h" 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h" 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h" 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "iapp.h" 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IAPP_MULTICAST "224.0.1.178" 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IAPP_UDP_PORT 3517 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IAPP_TCP_PORT 3517 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_hdr { 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 version; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 command; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be16 identifier; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be16 length; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by length-6 octets of data */ 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define IAPP_VERSION 0 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtenum IAPP_COMMAND { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CMD_ADD_notify = 0, 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CMD_MOVE_notify = 1, 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CMD_MOVE_response = 2, 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CMD_Send_Security_Block = 3, 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CMD_ACK_Security_Block = 4, 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CMD_CACHE_notify = 5, 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CMD_CACHE_response = 6, 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* ADD-notify - multicast UDP on the local LAN */ 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_add_notify { 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr_len; /* ETH_ALEN */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 reserved; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac_addr[ETH_ALEN]; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be16 seq_num; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_layer2_update { 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 da[ETH_ALEN]; /* broadcast */ 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 sa[ETH_ALEN]; /* STA addr */ 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be16 len; /* 6 */ 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dsap; /* null DSAP address */ 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ssap; /* null SSAP address, CR=Response */ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 control; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 xid_info[3]; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* MOVE-notify - unicast TCP */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_move_notify { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr_len; /* ETH_ALEN */ 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 reserved; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac_addr[ETH_ALEN]; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 seq_num; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ctx_block_len; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by ctx_block_len bytes */ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* MOVE-response - unicast TCP */ 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_move_response { 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr_len; /* ETH_ALEN */ 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 status; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac_addr[ETH_ALEN]; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 seq_num; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ctx_block_len; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by ctx_block_len bytes */ 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtenum { 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_MOVE_SUCCESSFUL = 0, 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_MOVE_DENIED = 1, 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_MOVE_STALE_MOVE = 2, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* CACHE-notify */ 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_cache_notify { 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr_len; /* ETH_ALEN */ 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 reserved; 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac_addr[ETH_ALEN]; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 seq_num; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 current_ap[ETH_ALEN]; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ctx_block_len; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ctx_block_len bytes of context block followed by 16-bit context 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * timeout */ 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* CACHE-response - unicast TCP */ 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_cache_response { 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr_len; /* ETH_ALEN */ 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 status; 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac_addr[ETH_ALEN]; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 seq_num; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtenum { 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CACHE_SUCCESSFUL = 0, 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt IAPP_CACHE_STALE_CACHE = 1, 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Send-Security-Block - unicast TCP */ 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_send_security_block { 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 iv[8]; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 sec_block_len; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by sec_block_len bytes of security block */ 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* ACK-Security-Block - unicast TCP */ 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_ack_security_block { 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 iv[8]; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 new_ap_ack_authenticator[48]; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} __attribute__ ((packed)); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_data { 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 identifier; /* next IAPP identifier */ 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct in_addr own, multicast; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int udp_sock; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int packet_sock; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num) 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[128]; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_hdr *hdr; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_add_notify *add; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in addr; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send IAPP ADD-notify to remove possible association from other APs 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct iapp_hdr *) buf; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version = IAPP_VERSION; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->command = IAPP_CMD_ADD_notify; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->identifier = host_to_be16(iapp->identifier++); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add)); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add = (struct iapp_add_notify *) (hdr + 1); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add->addr_len = ETH_ALEN; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add->reserved = 0; 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(add->mac_addr, mac_addr, ETH_ALEN); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt add->seq_num = host_to_be16(seq_num); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_family = AF_INET; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_addr.s_addr = iapp->multicast.s_addr; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sin_port = htons(IAPP_UDP_PORT); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0, 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &addr, sizeof(addr)) < 0) 207cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "sendto[IAPP-ADD]: %s", strerror(errno)); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr) 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_layer2_update msg; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Send Level 2 Update Frame to update forwarding tables in layer 2 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * bridge devices */ 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(msg.da, 0xff, ETH_ALEN); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(msg.sa, addr, ETH_ALEN); 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.len = host_to_be16(6); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.dsap = 0; /* NULL DSAP address */ 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */ 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.control = 0xaf; /* XID response lsb.1111F101. 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * F=0 (no poll command; unsolicited frame) */ 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.xid_info[0] = 0x81; /* XID format identifier */ 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FIX: what is correct RW with 802.11? */ 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0) 234cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "send[L2 Update]: %s", strerror(errno)); 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iapp_new_station - IAPP processing for a new STA 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @iapp: IAPP data 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sta: The associated station 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid iapp_new_station(struct iapp_data *iapp, struct sta_info *sta) 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 245b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt u16 seq = 0; /* TODO */ 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iapp == NULL) 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq); 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_send_layer2_update(iapp, sta->addr); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_send_add(iapp, sta->addr, seq); 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 256b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt /* TODO: If this was reassociation: 257b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt * IAPP-MOVE.request(MAC Address, Sequence Number, Old AP, 258b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt * Context Block, Timeout) 259b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt * TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to 260b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt * IP address */ 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void iapp_process_add_notify(struct iapp_data *iapp, 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *from, 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_hdr *hdr, int len) 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sta_info *sta; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len != sizeof(*add)) { 272cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Invalid IAPP-ADD packet length %d (expected %lu)", 273cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt len, (unsigned long) sizeof(*add)); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta = ap_get_sta(iapp->hapd, add->mac_addr); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IAPP-ADD.indication(MAC Address, Sequence Number) */ 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_INFO, 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Received IAPP ADD-notify (seq# %d) from %s:%d%s", 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(add->seq_num), 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_ntoa(from->sin_addr), ntohs(from->sin_port), 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sta ? "" : " (STA not found)"); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sta) 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: could use seq_num to try to determine whether last association 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to this AP is newer than the one advertised in IAPP-ADD. Although, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this is not really a reliable verification. */ 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Removing STA due to IAPP ADD-notify"); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ap_sta_disconnect(iapp->hapd, sta, NULL, 0); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iapp_receive_udp - Process IAPP UDP frames 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sock: File descriptor for the socket 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @eloop_ctx: IAPP data (struct iapp_data *) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sock_ctx: Not used 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx) 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_data *iapp = eloop_ctx; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len, hlen; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned char buf[128]; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in from; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt socklen_t fromlen; 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_hdr *hdr; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Handle incoming IAPP frames (over UDP/IP) */ 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt fromlen = sizeof(from); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0, 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (struct sockaddr *) &from, &fromlen); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 0) { 322cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_receive_udp - recvfrom: %s", 323cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (from.sin_addr.s_addr == iapp->own.s_addr) 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; /* ignore own IAPP messages */ 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP, 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Received %d byte IAPP frame from %s%s\n", 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len, inet_ntoa(from.sin_addr), 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len < (int) sizeof(*hdr) ? " (too short)" : ""); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < (int) sizeof(*hdr)) 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct iapp_hdr *) buf; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlen = be_to_host16(hdr->length); 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP, 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "RX: version=%d command=%d id=%d len=%d\n", 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->version, hdr->command, 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt be_to_host16(hdr->identifier), hlen); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr->version != IAPP_VERSION) { 347cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Dropping IAPP frame with unknown version %d", 348cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hdr->version); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hlen > len) { 352cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Underflow IAPP frame (hlen=%d len=%d)", 353cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hlen, len); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hlen < len) { 357cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Ignoring %d extra bytes from IAPP frame", 358cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt len - hlen); 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = hlen; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr->command) { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IAPP_CMD_ADD_notify: 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_process_add_notify(iapp, &from, hdr, hlen - sizeof(*hdr)); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case IAPP_CMD_MOVE_notify: 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: MOVE is using TCP; so move this to TCP handler once it 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is implemented.. */ 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IAPP-MOVE.indication(MAC Address, New BSSID, 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Sequence Number, AP Address, Context Block) */ 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: process */ 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 374cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Unknown IAPP command %d", hdr->command); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface) 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ifreq ifr; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_ll addr; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ifindex; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct sockaddr_in *paddr, uaddr; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct iapp_data *iapp; 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ip_mreqn mreq; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp = os_zalloc(sizeof(*iapp)); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iapp == NULL) 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp->hapd = hapd; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp->udp_sock = iapp->packet_sock = -1; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * open socket for sending and receiving IAPP frames over TCP 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0); 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iapp->udp_sock < 0) { 401cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - socket[PF_INET,SOCK_DGRAM]: %s", 402cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&ifr, 0, sizeof(ifr)); 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) { 410cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFINDEX): %s", 411cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ifindex = ifr.ifr_ifindex; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) { 418cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFADDR): %s", 419cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt paddr = (struct sockaddr_in *) &ifr.ifr_addr; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (paddr->sin_family != AF_INET) { 425cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "IAPP: Invalid address family %i (SIOCGIFADDR)", 426cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt paddr->sin_family); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp->own.s_addr = paddr->sin_addr.s_addr; 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) { 433cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFBRDADDR): %s", 434cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt paddr = (struct sockaddr_in *) &ifr.ifr_addr; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (paddr->sin_family != AF_INET) { 440cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Invalid address family %i (SIOCGIFBRDADDR)", 441cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt paddr->sin_family); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt inet_aton(IAPP_MULTICAST, &iapp->multicast); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&uaddr, 0, sizeof(uaddr)); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uaddr.sin_family = AF_INET; 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt uaddr.sin_port = htons(IAPP_UDP_PORT); 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr, 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(uaddr)) < 0) { 452cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s", 453cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&mreq, 0, sizeof(mreq)); 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mreq.imr_multiaddr = iapp->multicast; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mreq.imr_address.s_addr = INADDR_ANY; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mreq.imr_ifindex = 0; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(mreq)) < 0) { 464cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - setsockopt[UDP,IP_ADD_MEMBERSHIP]: %s", 465cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iapp->packet_sock < 0) { 472cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - socket[PF_PACKET,SOCK_RAW]: %s", 473cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&addr, 0, sizeof(addr)); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sll_family = AF_PACKET; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt addr.sll_ifindex = ifindex; 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bind(iapp->packet_sock, (struct sockaddr *) &addr, 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(addr)) < 0) { 483cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_init - bind[PACKET]: %s", 484cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp, 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp, NULL)) { 491cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "Could not register read socket for IAPP"); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iapp_deinit(iapp); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 496cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "IEEE 802.11F (IAPP) using interface %s", iface); 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * be openned only after receiving Initiate-Accept. If Initiate-Reject 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * is received, IAPP is not started. */ 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return iapp; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid iapp_deinit(struct iapp_data *iapp) 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ip_mreqn mreq; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iapp == NULL) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iapp->udp_sock >= 0) { 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&mreq, 0, sizeof(mreq)); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mreq.imr_multiaddr = iapp->multicast; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mreq.imr_address.s_addr = INADDR_ANY; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mreq.imr_ifindex = 0; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP, 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &mreq, sizeof(mreq)) < 0) { 521cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_INFO, "iapp_deinit - setsockopt[UDP,IP_DEL_MEMBERSHIP]: %s", 522cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt strerror(errno)); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(iapp->udp_sock); 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(iapp->udp_sock); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iapp->packet_sock >= 0) { 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_unregister_read_sock(iapp->packet_sock); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt close(iapp->packet_sock); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(iapp); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 534