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