1 /* 2 * FILS HLP request processing 3 * Copyright (c) 2017, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "utils/includes.h" 10 11 #include "utils/common.h" 12 #include "utils/eloop.h" 13 #include "common/dhcp.h" 14 #include "hostapd.h" 15 #include "sta_info.h" 16 #include "ieee802_11.h" 17 #include "fils_hlp.h" 18 19 20 static be16 ip_checksum(const void *buf, size_t len) 21 { 22 u32 sum = 0; 23 const u16 *pos; 24 25 for (pos = buf; len >= 2; len -= 2) 26 sum += ntohs(*pos++); 27 if (len) 28 sum += ntohs(*pos << 8); 29 30 sum = (sum >> 16) + (sum & 0xffff); 31 sum += sum >> 16; 32 return htons(~sum); 33 } 34 35 36 static int fils_dhcp_request(struct hostapd_data *hapd, struct sta_info *sta, 37 struct dhcp_data *dhcpoffer, u8 *dhcpofferend) 38 { 39 u8 *pos, *end; 40 struct dhcp_data *dhcp; 41 struct sockaddr_in addr; 42 ssize_t res; 43 const u8 *server_id = NULL; 44 45 if (!sta->hlp_dhcp_discover) { 46 wpa_printf(MSG_DEBUG, 47 "FILS: No pending HLP DHCPDISCOVER available"); 48 return -1; 49 } 50 51 /* Convert to DHCPREQUEST, remove rapid commit option, replace requested 52 * IP address option with yiaddr. */ 53 pos = wpabuf_mhead(sta->hlp_dhcp_discover); 54 end = pos + wpabuf_len(sta->hlp_dhcp_discover); 55 dhcp = (struct dhcp_data *) pos; 56 pos = (u8 *) (dhcp + 1); 57 pos += 4; /* skip magic */ 58 while (pos < end && *pos != DHCP_OPT_END) { 59 u8 opt, olen; 60 61 opt = *pos++; 62 if (opt == DHCP_OPT_PAD) 63 continue; 64 if (pos >= end) 65 break; 66 olen = *pos++; 67 if (olen > end - pos) 68 break; 69 70 switch (opt) { 71 case DHCP_OPT_MSG_TYPE: 72 if (olen > 0) 73 *pos = DHCPREQUEST; 74 break; 75 case DHCP_OPT_RAPID_COMMIT: 76 case DHCP_OPT_REQUESTED_IP_ADDRESS: 77 case DHCP_OPT_SERVER_ID: 78 /* Remove option */ 79 pos -= 2; 80 os_memmove(pos, pos + 2 + olen, end - pos - 2 - olen); 81 end -= 2 + olen; 82 olen = 0; 83 break; 84 } 85 pos += olen; 86 } 87 if (pos >= end || *pos != DHCP_OPT_END) { 88 wpa_printf(MSG_DEBUG, "FILS: Could not update DHCPDISCOVER"); 89 return -1; 90 } 91 sta->hlp_dhcp_discover->used = pos - (u8 *) dhcp; 92 93 /* Copy Server ID option from DHCPOFFER to DHCPREQUEST */ 94 pos = (u8 *) (dhcpoffer + 1); 95 end = dhcpofferend; 96 pos += 4; /* skip magic */ 97 while (pos < end && *pos != DHCP_OPT_END) { 98 u8 opt, olen; 99 100 opt = *pos++; 101 if (opt == DHCP_OPT_PAD) 102 continue; 103 if (pos >= end) 104 break; 105 olen = *pos++; 106 if (olen > end - pos) 107 break; 108 109 switch (opt) { 110 case DHCP_OPT_SERVER_ID: 111 server_id = pos - 2; 112 break; 113 } 114 pos += olen; 115 } 116 117 if (wpabuf_resize(&sta->hlp_dhcp_discover, 118 6 + 1 + (server_id ? 2 + server_id[1] : 0))) 119 return -1; 120 if (server_id) 121 wpabuf_put_data(sta->hlp_dhcp_discover, server_id, 122 2 + server_id[1]); 123 wpabuf_put_u8(sta->hlp_dhcp_discover, DHCP_OPT_REQUESTED_IP_ADDRESS); 124 wpabuf_put_u8(sta->hlp_dhcp_discover, 4); 125 wpabuf_put_data(sta->hlp_dhcp_discover, &dhcpoffer->your_ip, 4); 126 wpabuf_put_u8(sta->hlp_dhcp_discover, DHCP_OPT_END); 127 128 os_memset(&addr, 0, sizeof(addr)); 129 addr.sin_family = AF_INET; 130 addr.sin_addr.s_addr = hapd->conf->dhcp_server.u.v4.s_addr; 131 addr.sin_port = htons(hapd->conf->dhcp_server_port); 132 res = sendto(hapd->dhcp_sock, wpabuf_head(sta->hlp_dhcp_discover), 133 wpabuf_len(sta->hlp_dhcp_discover), 0, 134 (const struct sockaddr *) &addr, sizeof(addr)); 135 if (res < 0) { 136 wpa_printf(MSG_ERROR, "FILS: DHCP sendto failed: %s", 137 strerror(errno)); 138 return -1; 139 } 140 wpa_printf(MSG_DEBUG, 141 "FILS: Acting as DHCP rapid commit proxy for %s:%d", 142 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); 143 wpabuf_free(sta->hlp_dhcp_discover); 144 sta->hlp_dhcp_discover = NULL; 145 sta->fils_dhcp_rapid_commit_proxy = 1; 146 return 0; 147 } 148 149 150 static void fils_dhcp_handler(int sd, void *eloop_ctx, void *sock_ctx) 151 { 152 struct hostapd_data *hapd = sock_ctx; 153 struct sta_info *sta; 154 u8 buf[1500], *pos, *end, *end_opt = NULL; 155 struct dhcp_data *dhcp; 156 struct sockaddr_in addr; 157 socklen_t addr_len; 158 ssize_t res; 159 u8 msgtype = 0; 160 int rapid_commit = 0; 161 struct iphdr *iph; 162 struct udphdr *udph; 163 struct wpabuf *resp; 164 const u8 *rpos; 165 size_t left, len; 166 167 addr_len = sizeof(addr); 168 res = recvfrom(sd, buf, sizeof(buf), 0, 169 (struct sockaddr *) &addr, &addr_len); 170 if (res < 0) { 171 wpa_printf(MSG_DEBUG, "FILS: DHCP read failed: %s", 172 strerror(errno)); 173 return; 174 } 175 wpa_printf(MSG_DEBUG, "FILS: DHCP response from server %s:%d (len=%d)", 176 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), (int) res); 177 wpa_hexdump(MSG_MSGDUMP, "FILS: HLP - DHCP server response", buf, res); 178 if ((size_t) res < sizeof(*dhcp)) 179 return; 180 dhcp = (struct dhcp_data *) buf; 181 if (dhcp->op != 2) 182 return; /* Not a BOOTREPLY */ 183 if (dhcp->relay_ip != hapd->conf->own_ip_addr.u.v4.s_addr) { 184 wpa_printf(MSG_DEBUG, 185 "FILS: HLP - DHCP response to unknown relay address 0x%x", 186 dhcp->relay_ip); 187 return; 188 } 189 dhcp->relay_ip = 0; 190 pos = (u8 *) (dhcp + 1); 191 end = &buf[res]; 192 193 if (end - pos < 4 || WPA_GET_BE32(pos) != DHCP_MAGIC) { 194 wpa_printf(MSG_DEBUG, "FILS: HLP - no DHCP magic in response"); 195 return; 196 } 197 pos += 4; 198 199 wpa_hexdump(MSG_DEBUG, "FILS: HLP - DHCP options in response", 200 pos, end - pos); 201 while (pos < end && *pos != DHCP_OPT_END) { 202 u8 opt, olen; 203 204 opt = *pos++; 205 if (opt == DHCP_OPT_PAD) 206 continue; 207 if (pos >= end) 208 break; 209 olen = *pos++; 210 if (olen > end - pos) 211 break; 212 213 switch (opt) { 214 case DHCP_OPT_MSG_TYPE: 215 if (olen > 0) 216 msgtype = pos[0]; 217 break; 218 case DHCP_OPT_RAPID_COMMIT: 219 rapid_commit = 1; 220 break; 221 } 222 pos += olen; 223 } 224 if (pos < end && *pos == DHCP_OPT_END) 225 end_opt = pos; 226 227 wpa_printf(MSG_DEBUG, 228 "FILS: HLP - DHCP message type %u (rapid_commit=%d hw_addr=" 229 MACSTR ")", 230 msgtype, rapid_commit, MAC2STR(dhcp->hw_addr)); 231 232 sta = ap_get_sta(hapd, dhcp->hw_addr); 233 if (!sta || !sta->fils_pending_assoc_req) { 234 wpa_printf(MSG_DEBUG, 235 "FILS: No pending HLP DHCP exchange with hw_addr" 236 MACSTR, MAC2STR(dhcp->hw_addr)); 237 return; 238 } 239 240 if (hapd->conf->dhcp_rapid_commit_proxy && msgtype == DHCPOFFER && 241 !rapid_commit) { 242 /* Use hostapd to take care of 4-message exchange and convert 243 * the final DHCPACK to rapid commit version. */ 244 if (fils_dhcp_request(hapd, sta, dhcp, end) == 0) 245 return; 246 /* failed, so send the server response as-is */ 247 } else if (msgtype != DHCPACK) { 248 wpa_printf(MSG_DEBUG, 249 "FILS: No DHCPACK available from the server and cannot do rapid commit proxying"); 250 } 251 252 pos = buf; 253 resp = wpabuf_alloc(2 * ETH_ALEN + 6 + 2 + 254 sizeof(*iph) + sizeof(*udph) + (end - pos) + 2); 255 if (!resp) 256 return; 257 wpabuf_put_data(resp, sta->addr, ETH_ALEN); 258 wpabuf_put_data(resp, hapd->own_addr, ETH_ALEN); 259 wpabuf_put_data(resp, "\xaa\xaa\x03\x00\x00\x00", 6); 260 wpabuf_put_be16(resp, ETH_P_IP); 261 iph = wpabuf_put(resp, sizeof(*iph)); 262 iph->version = 4; 263 iph->ihl = sizeof(*iph) / 4; 264 iph->tot_len = htons(sizeof(*iph) + sizeof(*udph) + (end - pos)); 265 iph->ttl = 1; 266 iph->saddr = hapd->conf->dhcp_server.u.v4.s_addr; 267 iph->daddr = dhcp->client_ip; 268 iph->check = ip_checksum(iph, sizeof(*iph)); 269 udph = wpabuf_put(resp, sizeof(*udph)); 270 udph->uh_sport = htons(DHCP_SERVER_PORT); 271 udph->uh_dport = htons(DHCP_CLIENT_PORT); 272 udph->len = htons(sizeof(*udph) + (end - pos)); 273 udph->check = htons(0x0000); /* TODO: calculate checksum */ 274 if (hapd->conf->dhcp_rapid_commit_proxy && msgtype == DHCPACK && 275 !rapid_commit && sta->fils_dhcp_rapid_commit_proxy && end_opt) { 276 /* Add rapid commit option */ 277 wpabuf_put_data(resp, pos, end_opt - pos); 278 wpabuf_put_u8(resp, DHCP_OPT_RAPID_COMMIT); 279 wpabuf_put_u8(resp, 0); 280 wpabuf_put_data(resp, end_opt, end - end_opt); 281 } else { 282 wpabuf_put_data(resp, pos, end - pos); 283 } 284 if (wpabuf_resize(&sta->fils_hlp_resp, wpabuf_len(resp) + 285 2 * wpabuf_len(resp) / 255 + 100)) { 286 wpabuf_free(resp); 287 return; 288 } 289 290 rpos = wpabuf_head(resp); 291 left = wpabuf_len(resp); 292 293 wpabuf_put_u8(sta->fils_hlp_resp, WLAN_EID_EXTENSION); /* Element ID */ 294 if (left <= 254) 295 len = 1 + left; 296 else 297 len = 255; 298 wpabuf_put_u8(sta->fils_hlp_resp, len); /* Length */ 299 /* Element ID Extension */ 300 wpabuf_put_u8(sta->fils_hlp_resp, WLAN_EID_EXT_FILS_HLP_CONTAINER); 301 /* Destination MAC Address, Source MAC Address, HLP Packet. 302 * HLP Packet is in MSDU format (i.e., including the LLC/SNAP header 303 * when LPD is used). */ 304 wpabuf_put_data(sta->fils_hlp_resp, rpos, len - 1); 305 rpos += len - 1; 306 left -= len - 1; 307 while (left) { 308 wpabuf_put_u8(sta->fils_hlp_resp, WLAN_EID_FRAGMENT); 309 len = left > 255 ? 255 : left; 310 wpabuf_put_u8(sta->fils_hlp_resp, len); 311 wpabuf_put_data(sta->fils_hlp_resp, rpos, len); 312 rpos += len; 313 left -= len; 314 } 315 wpabuf_free(resp); 316 fils_hlp_finish_assoc(hapd, sta); 317 } 318 319 320 static int fils_process_hlp_dhcp(struct hostapd_data *hapd, 321 struct sta_info *sta, 322 const u8 *msg, size_t len) 323 { 324 const struct dhcp_data *dhcp; 325 struct wpabuf *dhcp_buf; 326 struct dhcp_data *dhcp_msg; 327 u8 msgtype = 0; 328 int rapid_commit = 0; 329 const u8 *pos = msg, *end; 330 struct sockaddr_in addr; 331 ssize_t res; 332 333 if (len < sizeof(*dhcp)) 334 return 0; 335 dhcp = (const struct dhcp_data *) pos; 336 end = pos + len; 337 wpa_printf(MSG_DEBUG, 338 "FILS: HLP request DHCP: op=%u htype=%u hlen=%u hops=%u xid=0x%x", 339 dhcp->op, dhcp->htype, dhcp->hlen, dhcp->hops, 340 ntohl(dhcp->xid)); 341 pos += sizeof(*dhcp); 342 if (dhcp->op != 1) 343 return 0; /* Not a BOOTREQUEST */ 344 345 if (end - pos < 4) 346 return 0; 347 if (WPA_GET_BE32(pos) != DHCP_MAGIC) { 348 wpa_printf(MSG_DEBUG, "FILS: HLP - no DHCP magic"); 349 return 0; 350 } 351 pos += 4; 352 353 wpa_hexdump(MSG_DEBUG, "FILS: HLP - DHCP options", pos, end - pos); 354 while (pos < end && *pos != DHCP_OPT_END) { 355 u8 opt, olen; 356 357 opt = *pos++; 358 if (opt == DHCP_OPT_PAD) 359 continue; 360 if (pos >= end) 361 break; 362 olen = *pos++; 363 if (olen > end - pos) 364 break; 365 366 switch (opt) { 367 case DHCP_OPT_MSG_TYPE: 368 if (olen > 0) 369 msgtype = pos[0]; 370 break; 371 case DHCP_OPT_RAPID_COMMIT: 372 rapid_commit = 1; 373 break; 374 } 375 pos += olen; 376 } 377 378 wpa_printf(MSG_DEBUG, "FILS: HLP - DHCP message type %u", msgtype); 379 if (msgtype != DHCPDISCOVER) 380 return 0; 381 382 if (hapd->conf->dhcp_server.af != AF_INET || 383 hapd->conf->dhcp_server.u.v4.s_addr == 0) { 384 wpa_printf(MSG_DEBUG, 385 "FILS: HLP - no DHCPv4 server configured - drop request"); 386 return 0; 387 } 388 389 if (hapd->conf->own_ip_addr.af != AF_INET || 390 hapd->conf->own_ip_addr.u.v4.s_addr == 0) { 391 wpa_printf(MSG_DEBUG, 392 "FILS: HLP - no IPv4 own_ip_addr configured - drop request"); 393 return 0; 394 } 395 396 if (hapd->dhcp_sock < 0) { 397 int s; 398 399 s = socket(AF_INET, SOCK_DGRAM, 0); 400 if (s < 0) { 401 wpa_printf(MSG_ERROR, 402 "FILS: Failed to open DHCP socket: %s", 403 strerror(errno)); 404 return 0; 405 } 406 407 if (hapd->conf->dhcp_relay_port) { 408 os_memset(&addr, 0, sizeof(addr)); 409 addr.sin_family = AF_INET; 410 addr.sin_addr.s_addr = 411 hapd->conf->own_ip_addr.u.v4.s_addr; 412 addr.sin_port = htons(hapd->conf->dhcp_relay_port); 413 if (bind(s, (struct sockaddr *) &addr, sizeof(addr))) { 414 wpa_printf(MSG_ERROR, 415 "FILS: Failed to bind DHCP socket: %s", 416 strerror(errno)); 417 close(s); 418 return 0; 419 } 420 } 421 if (eloop_register_sock(s, EVENT_TYPE_READ, 422 fils_dhcp_handler, NULL, hapd)) { 423 close(s); 424 return 0; 425 } 426 427 hapd->dhcp_sock = s; 428 } 429 430 dhcp_buf = wpabuf_alloc(len); 431 if (!dhcp_buf) 432 return 0; 433 dhcp_msg = wpabuf_put(dhcp_buf, len); 434 os_memcpy(dhcp_msg, msg, len); 435 dhcp_msg->relay_ip = hapd->conf->own_ip_addr.u.v4.s_addr; 436 os_memset(&addr, 0, sizeof(addr)); 437 addr.sin_family = AF_INET; 438 addr.sin_addr.s_addr = hapd->conf->dhcp_server.u.v4.s_addr; 439 addr.sin_port = htons(hapd->conf->dhcp_server_port); 440 res = sendto(hapd->dhcp_sock, dhcp_msg, len, 0, 441 (const struct sockaddr *) &addr, sizeof(addr)); 442 if (res < 0) { 443 wpa_printf(MSG_ERROR, "FILS: DHCP sendto failed: %s", 444 strerror(errno)); 445 wpabuf_free(dhcp_buf); 446 /* Close the socket to try to recover from error */ 447 eloop_unregister_read_sock(hapd->dhcp_sock); 448 close(hapd->dhcp_sock); 449 hapd->dhcp_sock = -1; 450 return 0; 451 } 452 453 wpa_printf(MSG_DEBUG, 454 "FILS: HLP relayed DHCP request to server %s:%d (rapid_commit=%d)", 455 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), 456 rapid_commit); 457 if (hapd->conf->dhcp_rapid_commit_proxy && rapid_commit) { 458 /* Store a copy of the DHCPDISCOVER for rapid commit proxying 459 * purposes if the server does not support the rapid commit 460 * option. */ 461 wpa_printf(MSG_DEBUG, 462 "FILS: Store DHCPDISCOVER for rapid commit proxy"); 463 wpabuf_free(sta->hlp_dhcp_discover); 464 sta->hlp_dhcp_discover = dhcp_buf; 465 } else { 466 wpabuf_free(dhcp_buf); 467 } 468 469 return 1; 470 } 471 472 473 static int fils_process_hlp_udp(struct hostapd_data *hapd, 474 struct sta_info *sta, const u8 *dst, 475 const u8 *pos, size_t len) 476 { 477 const struct iphdr *iph; 478 const struct udphdr *udph; 479 u16 sport, dport, ulen; 480 481 if (len < sizeof(*iph) + sizeof(*udph)) 482 return 0; 483 iph = (const struct iphdr *) pos; 484 udph = (const struct udphdr *) (iph + 1); 485 sport = ntohs(udph->uh_sport); 486 dport = ntohs(udph->uh_dport); 487 ulen = ntohs(udph->uh_ulen); 488 wpa_printf(MSG_DEBUG, 489 "FILS: HLP request UDP: sport=%u dport=%u ulen=%u sum=0x%x", 490 sport, dport, ulen, ntohs(udph->uh_sum)); 491 /* TODO: Check UDP checksum */ 492 if (ulen < sizeof(*udph) || ulen > len - sizeof(*iph)) 493 return 0; 494 495 if (dport == DHCP_SERVER_PORT && sport == DHCP_CLIENT_PORT) { 496 return fils_process_hlp_dhcp(hapd, sta, (const u8 *) (udph + 1), 497 ulen - sizeof(*udph)); 498 } 499 500 return 0; 501 } 502 503 504 static int fils_process_hlp_ip(struct hostapd_data *hapd, 505 struct sta_info *sta, const u8 *dst, 506 const u8 *pos, size_t len) 507 { 508 const struct iphdr *iph; 509 u16 tot_len; 510 511 if (len < sizeof(*iph)) 512 return 0; 513 iph = (const struct iphdr *) pos; 514 if (ip_checksum(iph, sizeof(*iph)) != 0) { 515 wpa_printf(MSG_DEBUG, 516 "FILS: HLP request IPv4 packet had invalid header checksum - dropped"); 517 return 0; 518 } 519 tot_len = ntohs(iph->tot_len); 520 if (tot_len > len) 521 return 0; 522 wpa_printf(MSG_DEBUG, 523 "FILS: HLP request IPv4: saddr=%08x daddr=%08x protocol=%u", 524 iph->saddr, iph->daddr, iph->protocol); 525 switch (iph->protocol) { 526 case 17: 527 return fils_process_hlp_udp(hapd, sta, dst, pos, len); 528 } 529 530 return 0; 531 } 532 533 534 static int fils_process_hlp_req(struct hostapd_data *hapd, 535 struct sta_info *sta, 536 const u8 *pos, size_t len) 537 { 538 const u8 *pkt, *end; 539 540 wpa_printf(MSG_DEBUG, "FILS: HLP request from " MACSTR " (dst=" MACSTR 541 " src=" MACSTR " len=%u)", 542 MAC2STR(sta->addr), MAC2STR(pos), MAC2STR(pos + ETH_ALEN), 543 (unsigned int) len); 544 if (os_memcmp(sta->addr, pos + ETH_ALEN, ETH_ALEN) != 0) { 545 wpa_printf(MSG_DEBUG, 546 "FILS: Ignore HLP request with unexpected source address" 547 MACSTR, MAC2STR(pos + ETH_ALEN)); 548 return 0; 549 } 550 551 end = pos + len; 552 pkt = pos + 2 * ETH_ALEN; 553 if (end - pkt >= 6 && 554 os_memcmp(pkt, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) 555 pkt += 6; /* Remove SNAP/LLC header */ 556 wpa_hexdump(MSG_MSGDUMP, "FILS: HLP request packet", pkt, end - pkt); 557 558 if (end - pkt < 2) 559 return 0; 560 561 switch (WPA_GET_BE16(pkt)) { 562 case ETH_P_IP: 563 return fils_process_hlp_ip(hapd, sta, pos, pkt + 2, 564 end - pkt - 2); 565 } 566 567 return 0; 568 } 569 570 571 int fils_process_hlp(struct hostapd_data *hapd, struct sta_info *sta, 572 const u8 *pos, int left) 573 { 574 const u8 *end = pos + left; 575 u8 *tmp, *tmp_pos; 576 int ret = 0; 577 578 /* Old DHCPDISCOVER is not needed anymore, if it was still pending */ 579 wpabuf_free(sta->hlp_dhcp_discover); 580 sta->hlp_dhcp_discover = NULL; 581 sta->fils_dhcp_rapid_commit_proxy = 0; 582 583 /* Check if there are any FILS HLP Container elements */ 584 while (end - pos >= 2) { 585 if (2 + pos[1] > end - pos) 586 return 0; 587 if (pos[0] == WLAN_EID_EXTENSION && 588 pos[1] >= 1 + 2 * ETH_ALEN && 589 pos[2] == WLAN_EID_EXT_FILS_HLP_CONTAINER) 590 break; 591 pos += 2 + pos[1]; 592 } 593 if (end - pos < 2) 594 return 0; /* No FILS HLP Container elements */ 595 596 tmp = os_malloc(end - pos); 597 if (!tmp) 598 return 0; 599 600 while (end - pos >= 2) { 601 if (2 + pos[1] > end - pos || 602 pos[0] != WLAN_EID_EXTENSION || 603 pos[1] < 1 + 2 * ETH_ALEN || 604 pos[2] != WLAN_EID_EXT_FILS_HLP_CONTAINER) 605 break; 606 tmp_pos = tmp; 607 os_memcpy(tmp_pos, pos + 3, pos[1] - 1); 608 tmp_pos += pos[1] - 1; 609 pos += 2 + pos[1]; 610 611 /* Add possible fragments */ 612 while (end - pos >= 2 && pos[0] == WLAN_EID_FRAGMENT && 613 2 + pos[1] <= end - pos) { 614 os_memcpy(tmp_pos, pos + 2, pos[1]); 615 tmp_pos += pos[1]; 616 pos += 2 + pos[1]; 617 } 618 619 if (fils_process_hlp_req(hapd, sta, tmp, tmp_pos - tmp) > 0) 620 ret = 1; 621 } 622 623 os_free(tmp); 624 625 return ret; 626 } 627 628 629 void fils_hlp_deinit(struct hostapd_data *hapd) 630 { 631 if (hapd->dhcp_sock >= 0) { 632 eloop_unregister_read_sock(hapd->dhcp_sock); 633 close(hapd->dhcp_sock); 634 hapd->dhcp_sock = -1; 635 } 636 } 637