]>
Commit | Line | Data |
---|---|---|
6fc6879b JM |
1 | /* |
2 | * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) | |
3 | * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> | |
4 | * | |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
6fc6879b JM |
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 | |
1c6e69cc | 10 | * using some other mechanism for AP-to-AP communication than extending the |
6fc6879b JM |
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 | ||
1057d78e | 34 | #include "utils/includes.h" |
6fc6879b JM |
35 | #include <net/if.h> |
36 | #include <sys/ioctl.h> | |
6fc6879b | 37 | #include <netpacket/packet.h> |
6fc6879b | 38 | |
1057d78e JM |
39 | #include "utils/common.h" |
40 | #include "utils/eloop.h" | |
81f4f619 | 41 | #include "common/ieee802_11_defs.h" |
6226e38d JM |
42 | #include "hostapd.h" |
43 | #include "ap_config.h" | |
44 | #include "ieee802_11.h" | |
45 | #include "sta_info.h" | |
6fc6879b | 46 | #include "iapp.h" |
6fc6879b JM |
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 | 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 | hdr = (struct iapp_hdr *) buf; | |
185 | hdr->version = IAPP_VERSION; | |
186 | hdr->command = IAPP_CMD_ADD_notify; | |
187 | hdr->identifier = host_to_be16(iapp->identifier++); | |
188 | hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add)); | |
189 | ||
190 | add = (struct iapp_add_notify *) (hdr + 1); | |
191 | add->addr_len = ETH_ALEN; | |
192 | add->reserved = 0; | |
193 | os_memcpy(add->mac_addr, mac_addr, ETH_ALEN); | |
194 | ||
195 | add->seq_num = host_to_be16(seq_num); | |
196 | ||
197 | os_memset(&addr, 0, sizeof(addr)); | |
198 | addr.sin_family = AF_INET; | |
199 | addr.sin_addr.s_addr = iapp->multicast.s_addr; | |
200 | addr.sin_port = htons(IAPP_UDP_PORT); | |
201 | if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0, | |
202 | (struct sockaddr *) &addr, sizeof(addr)) < 0) | |
61323e70 | 203 | wpa_printf(MSG_INFO, "sendto[IAPP-ADD]: %s", strerror(errno)); |
6fc6879b JM |
204 | } |
205 | ||
206 | ||
207 | 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 | os_memset(msg.da, 0xff, ETH_ALEN); | |
218 | os_memcpy(msg.sa, addr, ETH_ALEN); | |
219 | msg.len = host_to_be16(6); | |
220 | msg.dsap = 0; /* NULL DSAP address */ | |
221 | msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */ | |
222 | msg.control = 0xaf; /* XID response lsb.1111F101. | |
223 | * F=0 (no poll command; unsolicited frame) */ | |
224 | msg.xid_info[0] = 0x81; /* XID format identifier */ | |
225 | msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ | |
226 | msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW) | |
227 | * FIX: what is correct RW with 802.11? */ | |
228 | ||
229 | if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0) | |
61323e70 | 230 | wpa_printf(MSG_INFO, "send[L2 Update]: %s", strerror(errno)); |
6fc6879b JM |
231 | } |
232 | ||
233 | ||
1c6e69cc JM |
234 | /** |
235 | * iapp_new_station - IAPP processing for a new STA | |
236 | * @iapp: IAPP data | |
237 | * @sta: The associated station | |
238 | */ | |
6fc6879b JM |
239 | void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta) |
240 | { | |
5bdac4ab | 241 | u16 seq = 0; /* TODO */ |
6fc6879b JM |
242 | |
243 | if (iapp == NULL) | |
244 | return; | |
245 | ||
6fc6879b JM |
246 | /* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */ |
247 | hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP, | |
248 | HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq); | |
249 | iapp_send_layer2_update(iapp, sta->addr); | |
250 | iapp_send_add(iapp, sta->addr, seq); | |
251 | ||
5bdac4ab JM |
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 */ | |
6fc6879b JM |
257 | } |
258 | ||
259 | ||
260 | static void iapp_process_add_notify(struct iapp_data *iapp, | |
261 | struct sockaddr_in *from, | |
262 | struct iapp_hdr *hdr, int len) | |
263 | { | |
264 | struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1); | |
265 | struct sta_info *sta; | |
266 | ||
267 | if (len != sizeof(*add)) { | |
61323e70 JM |
268 | wpa_printf(MSG_INFO, "Invalid IAPP-ADD packet length %d (expected %lu)", |
269 | len, (unsigned long) sizeof(*add)); | |
6fc6879b JM |
270 | return; |
271 | } | |
272 | ||
273 | sta = ap_get_sta(iapp->hapd, add->mac_addr); | |
274 | ||
275 | /* IAPP-ADD.indication(MAC Address, Sequence Number) */ | |
276 | 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 | be_to_host16(add->seq_num), | |
280 | inet_ntoa(from->sin_addr), ntohs(from->sin_port), | |
281 | sta ? "" : " (STA not found)"); | |
282 | ||
283 | if (!sta) | |
284 | 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 | hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, | |
291 | HOSTAPD_LEVEL_DEBUG, | |
292 | "Removing STA due to IAPP ADD-notify"); | |
45cefa0b | 293 | ap_sta_disconnect(iapp->hapd, sta, NULL, 0); |
6fc6879b JM |
294 | } |
295 | ||
296 | ||
1c6e69cc JM |
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 | */ | |
6fc6879b JM |
303 | static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx) |
304 | { | |
305 | 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 | fromlen = sizeof(from); | |
315 | len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0, | |
316 | (struct sockaddr *) &from, &fromlen); | |
317 | if (len < 0) { | |
61323e70 JM |
318 | wpa_printf(MSG_INFO, "iapp_receive_udp - recvfrom: %s", |
319 | strerror(errno)); | |
6fc6879b JM |
320 | return; |
321 | } | |
322 | ||
323 | if (from.sin_addr.s_addr == iapp->own.s_addr) | |
324 | return; /* ignore own IAPP messages */ | |
325 | ||
326 | 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 | if (len < (int) sizeof(*hdr)) | |
333 | return; | |
334 | ||
335 | hdr = (struct iapp_hdr *) buf; | |
336 | hlen = be_to_host16(hdr->length); | |
337 | hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP, | |
338 | HOSTAPD_LEVEL_DEBUG, | |
339 | "RX: version=%d command=%d id=%d len=%d\n", | |
340 | hdr->version, hdr->command, | |
341 | be_to_host16(hdr->identifier), hlen); | |
342 | if (hdr->version != IAPP_VERSION) { | |
61323e70 JM |
343 | wpa_printf(MSG_INFO, "Dropping IAPP frame with unknown version %d", |
344 | hdr->version); | |
6fc6879b JM |
345 | return; |
346 | } | |
347 | if (hlen > len) { | |
61323e70 JM |
348 | wpa_printf(MSG_INFO, "Underflow IAPP frame (hlen=%d len=%d)", |
349 | hlen, len); | |
6fc6879b JM |
350 | return; |
351 | } | |
352 | if (hlen < len) { | |
61323e70 JM |
353 | wpa_printf(MSG_INFO, "Ignoring %d extra bytes from IAPP frame", |
354 | len - hlen); | |
6fc6879b JM |
355 | len = hlen; |
356 | } | |
357 | ||
358 | switch (hdr->command) { | |
359 | case IAPP_CMD_ADD_notify: | |
4aa01d38 | 360 | iapp_process_add_notify(iapp, &from, hdr, len - sizeof(*hdr)); |
6fc6879b JM |
361 | 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 | break; | |
369 | default: | |
61323e70 | 370 | wpa_printf(MSG_INFO, "Unknown IAPP command %d", hdr->command); |
6fc6879b JM |
371 | break; |
372 | } | |
373 | } | |
374 | ||
375 | ||
376 | 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 | ||
385 | iapp = os_zalloc(sizeof(*iapp)); | |
386 | if (iapp == NULL) | |
387 | return NULL; | |
388 | iapp->hapd = hapd; | |
389 | iapp->udp_sock = iapp->packet_sock = -1; | |
390 | ||
391 | /* TODO: | |
392 | * open socket for sending and receiving IAPP frames over TCP | |
393 | */ | |
394 | ||
395 | iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0); | |
396 | if (iapp->udp_sock < 0) { | |
61323e70 JM |
397 | wpa_printf(MSG_INFO, "iapp_init - socket[PF_INET,SOCK_DGRAM]: %s", |
398 | strerror(errno)); | |
6fc6879b JM |
399 | iapp_deinit(iapp); |
400 | return NULL; | |
401 | } | |
402 | ||
403 | os_memset(&ifr, 0, sizeof(ifr)); | |
404 | os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name)); | |
405 | if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) { | |
61323e70 JM |
406 | wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFINDEX): %s", |
407 | strerror(errno)); | |
6fc6879b JM |
408 | iapp_deinit(iapp); |
409 | return NULL; | |
410 | } | |
411 | ifindex = ifr.ifr_ifindex; | |
412 | ||
413 | if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) { | |
61323e70 JM |
414 | wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFADDR): %s", |
415 | strerror(errno)); | |
6fc6879b JM |
416 | iapp_deinit(iapp); |
417 | return NULL; | |
418 | } | |
419 | paddr = (struct sockaddr_in *) &ifr.ifr_addr; | |
420 | if (paddr->sin_family != AF_INET) { | |
61323e70 JM |
421 | wpa_printf(MSG_INFO, "IAPP: Invalid address family %i (SIOCGIFADDR)", |
422 | paddr->sin_family); | |
6fc6879b JM |
423 | iapp_deinit(iapp); |
424 | return NULL; | |
425 | } | |
426 | iapp->own.s_addr = paddr->sin_addr.s_addr; | |
427 | ||
428 | if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) { | |
61323e70 JM |
429 | wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFBRDADDR): %s", |
430 | strerror(errno)); | |
6fc6879b JM |
431 | iapp_deinit(iapp); |
432 | return NULL; | |
433 | } | |
434 | paddr = (struct sockaddr_in *) &ifr.ifr_addr; | |
435 | if (paddr->sin_family != AF_INET) { | |
61323e70 JM |
436 | wpa_printf(MSG_INFO, "Invalid address family %i (SIOCGIFBRDADDR)", |
437 | paddr->sin_family); | |
6fc6879b JM |
438 | iapp_deinit(iapp); |
439 | return NULL; | |
440 | } | |
441 | inet_aton(IAPP_MULTICAST, &iapp->multicast); | |
442 | ||
443 | os_memset(&uaddr, 0, sizeof(uaddr)); | |
444 | uaddr.sin_family = AF_INET; | |
445 | uaddr.sin_port = htons(IAPP_UDP_PORT); | |
446 | if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr, | |
447 | sizeof(uaddr)) < 0) { | |
61323e70 JM |
448 | wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s", |
449 | strerror(errno)); | |
6fc6879b JM |
450 | iapp_deinit(iapp); |
451 | return NULL; | |
452 | } | |
453 | ||
454 | os_memset(&mreq, 0, sizeof(mreq)); | |
455 | mreq.imr_multiaddr = iapp->multicast; | |
456 | mreq.imr_address.s_addr = INADDR_ANY; | |
457 | mreq.imr_ifindex = 0; | |
458 | if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, | |
459 | sizeof(mreq)) < 0) { | |
61323e70 JM |
460 | wpa_printf(MSG_INFO, "iapp_init - setsockopt[UDP,IP_ADD_MEMBERSHIP]: %s", |
461 | strerror(errno)); | |
6fc6879b JM |
462 | iapp_deinit(iapp); |
463 | return NULL; | |
464 | } | |
465 | ||
466 | iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); | |
467 | if (iapp->packet_sock < 0) { | |
61323e70 JM |
468 | wpa_printf(MSG_INFO, "iapp_init - socket[PF_PACKET,SOCK_RAW]: %s", |
469 | strerror(errno)); | |
6fc6879b JM |
470 | iapp_deinit(iapp); |
471 | return NULL; | |
472 | } | |
473 | ||
474 | os_memset(&addr, 0, sizeof(addr)); | |
475 | addr.sll_family = AF_PACKET; | |
476 | addr.sll_ifindex = ifindex; | |
477 | if (bind(iapp->packet_sock, (struct sockaddr *) &addr, | |
478 | sizeof(addr)) < 0) { | |
61323e70 JM |
479 | wpa_printf(MSG_INFO, "iapp_init - bind[PACKET]: %s", |
480 | strerror(errno)); | |
6fc6879b JM |
481 | iapp_deinit(iapp); |
482 | return NULL; | |
483 | } | |
484 | ||
485 | if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp, | |
486 | iapp, NULL)) { | |
61323e70 | 487 | wpa_printf(MSG_INFO, "Could not register read socket for IAPP"); |
6fc6879b JM |
488 | iapp_deinit(iapp); |
489 | return NULL; | |
490 | } | |
491 | ||
61323e70 | 492 | wpa_printf(MSG_INFO, "IEEE 802.11F (IAPP) using interface %s", iface); |
6fc6879b JM |
493 | |
494 | /* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive | |
495 | * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually | |
496 | * be openned only after receiving Initiate-Accept. If Initiate-Reject | |
497 | * is received, IAPP is not started. */ | |
498 | ||
499 | return iapp; | |
500 | } | |
501 | ||
502 | ||
503 | void iapp_deinit(struct iapp_data *iapp) | |
504 | { | |
505 | struct ip_mreqn mreq; | |
506 | ||
507 | if (iapp == NULL) | |
508 | return; | |
509 | ||
510 | if (iapp->udp_sock >= 0) { | |
511 | os_memset(&mreq, 0, sizeof(mreq)); | |
512 | mreq.imr_multiaddr = iapp->multicast; | |
513 | mreq.imr_address.s_addr = INADDR_ANY; | |
514 | mreq.imr_ifindex = 0; | |
515 | if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP, | |
516 | &mreq, sizeof(mreq)) < 0) { | |
61323e70 JM |
517 | wpa_printf(MSG_INFO, "iapp_deinit - setsockopt[UDP,IP_DEL_MEMBERSHIP]: %s", |
518 | strerror(errno)); | |
6fc6879b JM |
519 | } |
520 | ||
521 | eloop_unregister_read_sock(iapp->udp_sock); | |
522 | close(iapp->udp_sock); | |
523 | } | |
524 | if (iapp->packet_sock >= 0) { | |
525 | eloop_unregister_read_sock(iapp->packet_sock); | |
526 | close(iapp->packet_sock); | |
527 | } | |
528 | os_free(iapp); | |
529 | } |