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