LCOV - code coverage report
Current view: top level - src/ap - iapp.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 97 187 51.9 %
Date: 2016-10-02 Functions: 6 7 85.7 %

          Line data    Source code
       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
       9             :  * and IEEE has withdrawn it. In other words, it is likely better to look at
      10             :  * using some other mechanism for AP-to-AP communication than extending the
      11             :  * implementation here.
      12             :  */
      13             : 
      14             : /* TODO:
      15             :  * Level 1: no administrative or security support
      16             :  *      (e.g., static BSSID to IP address mapping in each AP)
      17             :  * Level 2: support for dynamic mapping of BSSID to IP address
      18             :  * Level 3: support for encryption and authentication of IAPP messages
      19             :  * - add support for MOVE-notify and MOVE-response (this requires support for
      20             :  *   finding out IP address for previous AP using RADIUS)
      21             :  * - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during
      22             :  *   reassociation to another AP
      23             :  * - implement counters etc. for IAPP MIB
      24             :  * - verify endianness of fields in IAPP messages; are they big-endian as
      25             :  *   used here?
      26             :  * - RADIUS connection for AP registration and BSSID to IP address mapping
      27             :  * - TCP connection for IAPP MOVE, CACHE
      28             :  * - broadcast ESP for IAPP ADD-notify
      29             :  * - ESP for IAPP MOVE messages
      30             :  * - security block sending/processing
      31             :  * - IEEE 802.11 context transfer
      32             :  */
      33             : 
      34             : #include "utils/includes.h"
      35             : #include <net/if.h>
      36             : #include <sys/ioctl.h>
      37             : #include <netpacket/packet.h>
      38             : 
      39             : #include "utils/common.h"
      40             : #include "utils/eloop.h"
      41             : #include "common/ieee802_11_defs.h"
      42             : #include "hostapd.h"
      43             : #include "ap_config.h"
      44             : #include "ieee802_11.h"
      45             : #include "sta_info.h"
      46             : #include "iapp.h"
      47             : 
      48             : 
      49             : #define IAPP_MULTICAST "224.0.1.178"
      50             : #define IAPP_UDP_PORT 3517
      51             : #define IAPP_TCP_PORT 3517
      52             : 
      53             : struct iapp_hdr {
      54             :         u8 version;
      55             :         u8 command;
      56             :         be16 identifier;
      57             :         be16 length;
      58             :         /* followed by length-6 octets of data */
      59             : } __attribute__ ((packed));
      60             : 
      61             : #define IAPP_VERSION 0
      62             : 
      63             : enum IAPP_COMMAND {
      64             :         IAPP_CMD_ADD_notify = 0,
      65             :         IAPP_CMD_MOVE_notify = 1,
      66             :         IAPP_CMD_MOVE_response = 2,
      67             :         IAPP_CMD_Send_Security_Block = 3,
      68             :         IAPP_CMD_ACK_Security_Block = 4,
      69             :         IAPP_CMD_CACHE_notify = 5,
      70             :         IAPP_CMD_CACHE_response = 6,
      71             : };
      72             : 
      73             : 
      74             : /* ADD-notify - multicast UDP on the local LAN */
      75             : struct iapp_add_notify {
      76             :         u8 addr_len; /* ETH_ALEN */
      77             :         u8 reserved;
      78             :         u8 mac_addr[ETH_ALEN];
      79             :         be16 seq_num;
      80             : } __attribute__ ((packed));
      81             : 
      82             : 
      83             : /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
      84             : struct iapp_layer2_update {
      85             :         u8 da[ETH_ALEN]; /* broadcast */
      86             :         u8 sa[ETH_ALEN]; /* STA addr */
      87             :         be16 len; /* 6 */
      88             :         u8 dsap; /* null DSAP address */
      89             :         u8 ssap; /* null SSAP address, CR=Response */
      90             :         u8 control;
      91             :         u8 xid_info[3];
      92             : } __attribute__ ((packed));
      93             : 
      94             : 
      95             : /* MOVE-notify - unicast TCP */
      96             : struct iapp_move_notify {
      97             :         u8 addr_len; /* ETH_ALEN */
      98             :         u8 reserved;
      99             :         u8 mac_addr[ETH_ALEN];
     100             :         u16 seq_num;
     101             :         u16 ctx_block_len;
     102             :         /* followed by ctx_block_len bytes */
     103             : } __attribute__ ((packed));
     104             : 
     105             : 
     106             : /* MOVE-response - unicast TCP */
     107             : struct iapp_move_response {
     108             :         u8 addr_len; /* ETH_ALEN */
     109             :         u8 status;
     110             :         u8 mac_addr[ETH_ALEN];
     111             :         u16 seq_num;
     112             :         u16 ctx_block_len;
     113             :         /* followed by ctx_block_len bytes */
     114             : } __attribute__ ((packed));
     115             : 
     116             : enum {
     117             :         IAPP_MOVE_SUCCESSFUL = 0,
     118             :         IAPP_MOVE_DENIED = 1,
     119             :         IAPP_MOVE_STALE_MOVE = 2,
     120             : };
     121             : 
     122             : 
     123             : /* CACHE-notify */
     124             : struct iapp_cache_notify {
     125             :         u8 addr_len; /* ETH_ALEN */
     126             :         u8 reserved;
     127             :         u8 mac_addr[ETH_ALEN];
     128             :         u16 seq_num;
     129             :         u8 current_ap[ETH_ALEN];
     130             :         u16 ctx_block_len;
     131             :         /* ctx_block_len bytes of context block followed by 16-bit context
     132             :          * timeout */
     133             : } __attribute__ ((packed));
     134             : 
     135             : 
     136             : /* CACHE-response - unicast TCP */
     137             : struct iapp_cache_response {
     138             :         u8 addr_len; /* ETH_ALEN */
     139             :         u8 status;
     140             :         u8 mac_addr[ETH_ALEN];
     141             :         u16 seq_num;
     142             : } __attribute__ ((packed));
     143             : 
     144             : enum {
     145             :         IAPP_CACHE_SUCCESSFUL = 0,
     146             :         IAPP_CACHE_STALE_CACHE = 1,
     147             : };
     148             : 
     149             : 
     150             : /* Send-Security-Block - unicast TCP */
     151             : struct iapp_send_security_block {
     152             :         u8 iv[8];
     153             :         u16 sec_block_len;
     154             :         /* followed by sec_block_len bytes of security block */
     155             : } __attribute__ ((packed));
     156             : 
     157             : 
     158             : /* ACK-Security-Block - unicast TCP */
     159             : struct iapp_ack_security_block {
     160             :         u8 iv[8];
     161             :         u8 new_ap_ack_authenticator[48];
     162             : } __attribute__ ((packed));
     163             : 
     164             : 
     165             : struct iapp_data {
     166             :         struct hostapd_data *hapd;
     167             :         u16 identifier; /* next IAPP identifier */
     168             :         struct in_addr own, multicast;
     169             :         int udp_sock;
     170             :         int packet_sock;
     171             : };
     172             : 
     173             : 
     174           4 : static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num)
     175             : {
     176             :         char buf[128];
     177             :         struct iapp_hdr *hdr;
     178             :         struct iapp_add_notify *add;
     179             :         struct sockaddr_in addr;
     180             : 
     181             :         /* Send IAPP ADD-notify to remove possible association from other APs
     182             :          */
     183             : 
     184           4 :         hdr = (struct iapp_hdr *) buf;
     185           4 :         hdr->version = IAPP_VERSION;
     186           4 :         hdr->command = IAPP_CMD_ADD_notify;
     187           4 :         hdr->identifier = host_to_be16(iapp->identifier++);
     188           4 :         hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add));
     189             : 
     190           4 :         add = (struct iapp_add_notify *) (hdr + 1);
     191           4 :         add->addr_len = ETH_ALEN;
     192           4 :         add->reserved = 0;
     193           4 :         os_memcpy(add->mac_addr, mac_addr, ETH_ALEN);
     194             : 
     195           4 :         add->seq_num = host_to_be16(seq_num);
     196             :         
     197           4 :         os_memset(&addr, 0, sizeof(addr));
     198           4 :         addr.sin_family = AF_INET;
     199           4 :         addr.sin_addr.s_addr = iapp->multicast.s_addr;
     200           4 :         addr.sin_port = htons(IAPP_UDP_PORT);
     201           4 :         if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0,
     202             :                    (struct sockaddr *) &addr, sizeof(addr)) < 0)
     203           0 :                 wpa_printf(MSG_INFO, "sendto[IAPP-ADD]: %s", strerror(errno));
     204           4 : }
     205             : 
     206             : 
     207           4 : static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
     208             : {
     209             :         struct iapp_layer2_update msg;
     210             : 
     211             :         /* Send Level 2 Update Frame to update forwarding tables in layer 2
     212             :          * bridge devices */
     213             : 
     214             :         /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
     215             :          * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
     216             : 
     217           4 :         os_memset(msg.da, 0xff, ETH_ALEN);
     218           4 :         os_memcpy(msg.sa, addr, ETH_ALEN);
     219           4 :         msg.len = host_to_be16(6);
     220           4 :         msg.dsap = 0; /* NULL DSAP address */
     221           4 :         msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */
     222           4 :         msg.control = 0xaf; /* XID response lsb.1111F101.
     223             :                              * F=0 (no poll command; unsolicited frame) */
     224           4 :         msg.xid_info[0] = 0x81; /* XID format identifier */
     225           4 :         msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
     226           4 :         msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW)
     227             :                                    * FIX: what is correct RW with 802.11? */
     228             : 
     229           4 :         if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0)
     230           0 :                 wpa_printf(MSG_INFO, "send[L2 Update]: %s", strerror(errno));
     231           4 : }
     232             : 
     233             : 
     234             : /**
     235             :  * iapp_new_station - IAPP processing for a new STA
     236             :  * @iapp: IAPP data
     237             :  * @sta: The associated station
     238             :  */
     239           4 : void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
     240             : {
     241           4 :         u16 seq = 0; /* TODO */
     242             : 
     243           4 :         if (iapp == NULL)
     244           4 :                 return;
     245             : 
     246             :         /* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
     247           4 :         hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
     248             :                        HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
     249           4 :         iapp_send_layer2_update(iapp, sta->addr);
     250           4 :         iapp_send_add(iapp, sta->addr, seq);
     251             : 
     252             :         /* TODO: If this was reassociation:
     253             :          * IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
     254             :          *                   Context Block, Timeout)
     255             :          * TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
     256             :          * IP address */
     257             : }
     258             : 
     259             : 
     260           0 : static void iapp_process_add_notify(struct iapp_data *iapp,
     261             :                                     struct sockaddr_in *from,
     262             :                                     struct iapp_hdr *hdr, int len)
     263             : {
     264           0 :         struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1);
     265             :         struct sta_info *sta;
     266             : 
     267           0 :         if (len != sizeof(*add)) {
     268           0 :                 wpa_printf(MSG_INFO, "Invalid IAPP-ADD packet length %d (expected %lu)",
     269             :                            len, (unsigned long) sizeof(*add));
     270           0 :                 return;
     271             :         }
     272             : 
     273           0 :         sta = ap_get_sta(iapp->hapd, add->mac_addr);
     274             : 
     275             :         /* IAPP-ADD.indication(MAC Address, Sequence Number) */
     276           0 :         hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
     277             :                        HOSTAPD_LEVEL_INFO,
     278             :                        "Received IAPP ADD-notify (seq# %d) from %s:%d%s",
     279           0 :                        be_to_host16(add->seq_num),
     280           0 :                        inet_ntoa(from->sin_addr), ntohs(from->sin_port),
     281             :                        sta ? "" : " (STA not found)");
     282             : 
     283           0 :         if (!sta)
     284           0 :                 return;
     285             : 
     286             :         /* TODO: could use seq_num to try to determine whether last association
     287             :          * to this AP is newer than the one advertised in IAPP-ADD. Although,
     288             :          * this is not really a reliable verification. */
     289             : 
     290           0 :         hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
     291             :                        HOSTAPD_LEVEL_DEBUG,
     292             :                        "Removing STA due to IAPP ADD-notify");
     293           0 :         ap_sta_disconnect(iapp->hapd, sta, NULL, 0);
     294             : }
     295             : 
     296             : 
     297             : /**
     298             :  * iapp_receive_udp - Process IAPP UDP frames
     299             :  * @sock: File descriptor for the socket
     300             :  * @eloop_ctx: IAPP data (struct iapp_data *)
     301             :  * @sock_ctx: Not used
     302             :  */
     303           6 : static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx)
     304             : {
     305           6 :         struct iapp_data *iapp = eloop_ctx;
     306             :         int len, hlen;
     307             :         unsigned char buf[128];
     308             :         struct sockaddr_in from;
     309             :         socklen_t fromlen;
     310             :         struct iapp_hdr *hdr;
     311             : 
     312             :         /* Handle incoming IAPP frames (over UDP/IP) */
     313             : 
     314           6 :         fromlen = sizeof(from);
     315           6 :         len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0,
     316             :                        (struct sockaddr *) &from, &fromlen);
     317           6 :         if (len < 0) {
     318           0 :                 wpa_printf(MSG_INFO, "iapp_receive_udp - recvfrom: %s",
     319           0 :                            strerror(errno));
     320           0 :                 return;
     321             :         }
     322             : 
     323           6 :         if (from.sin_addr.s_addr == iapp->own.s_addr)
     324           6 :                 return; /* ignore own IAPP messages */
     325             : 
     326           0 :         hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
     327             :                        HOSTAPD_LEVEL_DEBUG,
     328             :                        "Received %d byte IAPP frame from %s%s\n",
     329             :                        len, inet_ntoa(from.sin_addr),
     330             :                        len < (int) sizeof(*hdr) ? " (too short)" : "");
     331             : 
     332           0 :         if (len < (int) sizeof(*hdr))
     333           0 :                 return;
     334             : 
     335           0 :         hdr = (struct iapp_hdr *) buf;
     336           0 :         hlen = be_to_host16(hdr->length);
     337           0 :         hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
     338             :                        HOSTAPD_LEVEL_DEBUG,
     339             :                        "RX: version=%d command=%d id=%d len=%d\n",
     340           0 :                        hdr->version, hdr->command,
     341           0 :                        be_to_host16(hdr->identifier), hlen);
     342           0 :         if (hdr->version != IAPP_VERSION) {
     343           0 :                 wpa_printf(MSG_INFO, "Dropping IAPP frame with unknown version %d",
     344           0 :                            hdr->version);
     345           0 :                 return;
     346             :         }
     347           0 :         if (hlen > len) {
     348           0 :                 wpa_printf(MSG_INFO, "Underflow IAPP frame (hlen=%d len=%d)",
     349             :                            hlen, len);
     350           0 :                 return;
     351             :         }
     352           0 :         if (hlen < len) {
     353           0 :                 wpa_printf(MSG_INFO, "Ignoring %d extra bytes from IAPP frame",
     354             :                            len - hlen);
     355           0 :                 len = hlen;
     356             :         }
     357             : 
     358           0 :         switch (hdr->command) {
     359             :         case IAPP_CMD_ADD_notify:
     360           0 :                 iapp_process_add_notify(iapp, &from, hdr, len - sizeof(*hdr));
     361           0 :                 break;
     362             :         case IAPP_CMD_MOVE_notify:
     363             :                 /* TODO: MOVE is using TCP; so move this to TCP handler once it
     364             :                  * is implemented.. */
     365             :                 /* IAPP-MOVE.indication(MAC Address, New BSSID,
     366             :                  * Sequence Number, AP Address, Context Block) */
     367             :                 /* TODO: process */
     368           0 :                 break;
     369             :         default:
     370           0 :                 wpa_printf(MSG_INFO, "Unknown IAPP command %d", hdr->command);
     371           0 :                 break;
     372             :         }
     373             : }
     374             : 
     375             : 
     376           2 : struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
     377             : {
     378             :         struct ifreq ifr;
     379             :         struct sockaddr_ll addr;
     380             :         int ifindex;
     381             :         struct sockaddr_in *paddr, uaddr;
     382             :         struct iapp_data *iapp;
     383             :         struct ip_mreqn mreq;
     384           2 :         int reuseaddr = 1;
     385             : 
     386           2 :         iapp = os_zalloc(sizeof(*iapp));
     387           2 :         if (iapp == NULL)
     388           0 :                 return NULL;
     389           2 :         iapp->hapd = hapd;
     390           2 :         iapp->udp_sock = iapp->packet_sock = -1;
     391             : 
     392             :         /* TODO:
     393             :          * open socket for sending and receiving IAPP frames over TCP
     394             :          */
     395             : 
     396           2 :         iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
     397           2 :         if (iapp->udp_sock < 0) {
     398           0 :                 wpa_printf(MSG_INFO, "iapp_init - socket[PF_INET,SOCK_DGRAM]: %s",
     399           0 :                            strerror(errno));
     400           0 :                 iapp_deinit(iapp);
     401           0 :                 return NULL;
     402             :         }
     403             : 
     404           2 :         os_memset(&ifr, 0, sizeof(ifr));
     405           2 :         os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
     406           2 :         if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) {
     407           0 :                 wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFINDEX): %s",
     408           0 :                            strerror(errno));
     409           0 :                 iapp_deinit(iapp);
     410           0 :                 return NULL;
     411             :         }
     412           2 :         ifindex = ifr.ifr_ifindex;
     413             : 
     414           2 :         if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
     415           0 :                 wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFADDR): %s",
     416           0 :                            strerror(errno));
     417           0 :                 iapp_deinit(iapp);
     418           0 :                 return NULL;
     419             :         }
     420           2 :         paddr = (struct sockaddr_in *) &ifr.ifr_addr;
     421           2 :         if (paddr->sin_family != AF_INET) {
     422           0 :                 wpa_printf(MSG_INFO, "IAPP: Invalid address family %i (SIOCGIFADDR)",
     423           0 :                            paddr->sin_family);
     424           0 :                 iapp_deinit(iapp);
     425           0 :                 return NULL;
     426             :         }
     427           2 :         iapp->own.s_addr = paddr->sin_addr.s_addr;
     428             : 
     429           2 :         if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) {
     430           0 :                 wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFBRDADDR): %s",
     431           0 :                            strerror(errno));
     432           0 :                 iapp_deinit(iapp);
     433           0 :                 return NULL;
     434             :         }
     435           2 :         paddr = (struct sockaddr_in *) &ifr.ifr_addr;
     436           2 :         if (paddr->sin_family != AF_INET) {
     437           0 :                 wpa_printf(MSG_INFO, "Invalid address family %i (SIOCGIFBRDADDR)",
     438           0 :                            paddr->sin_family);
     439           0 :                 iapp_deinit(iapp);
     440           0 :                 return NULL;
     441             :         }
     442           2 :         inet_aton(IAPP_MULTICAST, &iapp->multicast);
     443             : 
     444           2 :         os_memset(&uaddr, 0, sizeof(uaddr));
     445           2 :         uaddr.sin_family = AF_INET;
     446           2 :         uaddr.sin_port = htons(IAPP_UDP_PORT);
     447             : 
     448           2 :         if (setsockopt(iapp->udp_sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
     449             :                        sizeof(reuseaddr)) < 0) {
     450           0 :                 wpa_printf(MSG_INFO,
     451             :                            "iapp_init - setsockopt[UDP,SO_REUSEADDR]: %s",
     452           0 :                            strerror(errno));
     453             :                 /*
     454             :                  * Ignore this and try to continue. This is fine for single
     455             :                  * BSS cases, but may fail if multiple BSSes enable IAPP.
     456             :                  */
     457             :         }
     458             : 
     459           2 :         if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
     460             :                  sizeof(uaddr)) < 0) {
     461           0 :                 wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s",
     462           0 :                            strerror(errno));
     463           0 :                 iapp_deinit(iapp);
     464           0 :                 return NULL;
     465             :         }
     466             : 
     467           2 :         os_memset(&mreq, 0, sizeof(mreq));
     468           2 :         mreq.imr_multiaddr = iapp->multicast;
     469           2 :         mreq.imr_address.s_addr = INADDR_ANY;
     470           2 :         mreq.imr_ifindex = 0;
     471           2 :         if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
     472             :                        sizeof(mreq)) < 0) {
     473           0 :                 wpa_printf(MSG_INFO, "iapp_init - setsockopt[UDP,IP_ADD_MEMBERSHIP]: %s",
     474           0 :                            strerror(errno));
     475           0 :                 iapp_deinit(iapp);
     476           0 :                 return NULL;
     477             :         }
     478             : 
     479           2 :         iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
     480           2 :         if (iapp->packet_sock < 0) {
     481           0 :                 wpa_printf(MSG_INFO, "iapp_init - socket[PF_PACKET,SOCK_RAW]: %s",
     482           0 :                            strerror(errno));
     483           0 :                 iapp_deinit(iapp);
     484           0 :                 return NULL;
     485             :         }
     486             : 
     487           2 :         os_memset(&addr, 0, sizeof(addr));
     488           2 :         addr.sll_family = AF_PACKET;
     489           2 :         addr.sll_ifindex = ifindex;
     490           2 :         if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
     491             :                  sizeof(addr)) < 0) {
     492           0 :                 wpa_printf(MSG_INFO, "iapp_init - bind[PACKET]: %s",
     493           0 :                            strerror(errno));
     494           0 :                 iapp_deinit(iapp);
     495           0 :                 return NULL;
     496             :         }
     497             : 
     498           2 :         if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp,
     499             :                                      iapp, NULL)) {
     500           0 :                 wpa_printf(MSG_INFO, "Could not register read socket for IAPP");
     501           0 :                 iapp_deinit(iapp);
     502           0 :                 return NULL;
     503             :         }
     504             : 
     505           2 :         wpa_printf(MSG_INFO, "IEEE 802.11F (IAPP) using interface %s", iface);
     506             : 
     507             :         /* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive
     508             :          * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually
     509             :          * be openned only after receiving Initiate-Accept. If Initiate-Reject
     510             :          * is received, IAPP is not started. */
     511             : 
     512           2 :         return iapp;
     513             : }
     514             : 
     515             : 
     516        2046 : void iapp_deinit(struct iapp_data *iapp)
     517             : {
     518             :         struct ip_mreqn mreq;
     519             : 
     520        2046 :         if (iapp == NULL)
     521        4090 :                 return;
     522             : 
     523           2 :         if (iapp->udp_sock >= 0) {
     524           2 :                 os_memset(&mreq, 0, sizeof(mreq));
     525           2 :                 mreq.imr_multiaddr = iapp->multicast;
     526           2 :                 mreq.imr_address.s_addr = INADDR_ANY;
     527           2 :                 mreq.imr_ifindex = 0;
     528           2 :                 if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP,
     529             :                                &mreq, sizeof(mreq)) < 0) {
     530           0 :                         wpa_printf(MSG_INFO, "iapp_deinit - setsockopt[UDP,IP_DEL_MEMBERSHIP]: %s",
     531           0 :                                    strerror(errno));
     532             :                 }
     533             : 
     534           2 :                 eloop_unregister_read_sock(iapp->udp_sock);
     535           2 :                 close(iapp->udp_sock);
     536             :         }
     537           2 :         if (iapp->packet_sock >= 0) {
     538           2 :                 eloop_unregister_read_sock(iapp->packet_sock);
     539           2 :                 close(iapp->packet_sock);
     540             :         }
     541           2 :         os_free(iapp);
     542             : }

Generated by: LCOV version 1.10