$search
00001 /* 00002 * EAP common peer/server definitions 00003 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "eap_defs.h" 00019 #include "eap_common.h" 00020 00037 const u8 * eap_hdr_validate(int vendor, EapType eap_type, 00038 const struct wpabuf *msg, size_t *plen) 00039 { 00040 const struct eap_hdr *hdr; 00041 const u8 *pos; 00042 size_t len; 00043 00044 hdr = wpabuf_head(msg); 00045 00046 if (wpabuf_len(msg) < sizeof(*hdr)) { 00047 wpa_printf(MSG_INFO, "EAP: Too short EAP frame"); 00048 return NULL; 00049 } 00050 00051 len = be_to_host16(hdr->length); 00052 if (len < sizeof(*hdr) + 1 || len > wpabuf_len(msg)) { 00053 wpa_printf(MSG_INFO, "EAP: Invalid EAP length"); 00054 return NULL; 00055 } 00056 00057 pos = (const u8 *) (hdr + 1); 00058 00059 if (*pos == EAP_TYPE_EXPANDED) { 00060 int exp_vendor; 00061 u32 exp_type; 00062 if (len < sizeof(*hdr) + 8) { 00063 wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP " 00064 "length"); 00065 return NULL; 00066 } 00067 pos++; 00068 exp_vendor = WPA_GET_BE24(pos); 00069 pos += 3; 00070 exp_type = WPA_GET_BE32(pos); 00071 pos += 4; 00072 if (exp_vendor != vendor || exp_type != (u32) eap_type) { 00073 wpa_printf(MSG_INFO, "EAP: Invalid expanded frame " 00074 "type"); 00075 return NULL; 00076 } 00077 00078 *plen = len - sizeof(*hdr) - 8; 00079 return pos; 00080 } else { 00081 if (vendor != EAP_VENDOR_IETF || *pos != eap_type) { 00082 wpa_printf(MSG_INFO, "EAP: Invalid frame type"); 00083 return NULL; 00084 } 00085 *plen = len - sizeof(*hdr) - 1; 00086 return pos + 1; 00087 } 00088 } 00089 00090 00107 struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len, 00108 u8 code, u8 identifier) 00109 { 00110 struct wpabuf *buf; 00111 struct eap_hdr *hdr; 00112 size_t len; 00113 00114 len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + 00115 payload_len; 00116 buf = wpabuf_alloc(len); 00117 if (buf == NULL) 00118 return NULL; 00119 00120 hdr = wpabuf_put(buf, sizeof(*hdr)); 00121 hdr->code = code; 00122 hdr->identifier = identifier; 00123 hdr->length = host_to_be16(len); 00124 00125 if (vendor == EAP_VENDOR_IETF) { 00126 wpabuf_put_u8(buf, type); 00127 } else { 00128 wpabuf_put_u8(buf, EAP_TYPE_EXPANDED); 00129 wpabuf_put_be24(buf, vendor); 00130 wpabuf_put_be32(buf, type); 00131 } 00132 00133 return buf; 00134 } 00135 00136 00146 void eap_update_len(struct wpabuf *msg) 00147 { 00148 struct eap_hdr *hdr; 00149 hdr = wpabuf_mhead(msg); 00150 if (wpabuf_len(msg) < sizeof(*hdr)) 00151 return; 00152 hdr->length = host_to_be16(wpabuf_len(msg)); 00153 } 00154 00155 00161 u8 eap_get_id(const struct wpabuf *msg) 00162 { 00163 const struct eap_hdr *eap; 00164 00165 if (wpabuf_len(msg) < sizeof(*eap)) 00166 return 0; 00167 00168 eap = wpabuf_head(msg); 00169 return eap->identifier; 00170 } 00171 00172 00178 EapType eap_get_type(const struct wpabuf *msg) 00179 { 00180 if (wpabuf_len(msg) < sizeof(struct eap_hdr) + 1) 00181 return EAP_TYPE_NONE; 00182 00183 return ((const u8 *) wpabuf_head(msg))[sizeof(struct eap_hdr)]; 00184 }