eap_tlv.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "eap_i.h"
00020 #include "eap_tlv.h"
00021 
00022 
00034 u8 * eap_tlv_build_nak(int id, u16 nak_type, size_t *resp_len)
00035 {
00036         struct eap_hdr *hdr;
00037         u8 *pos;
00038 
00039         hdr = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, resp_len,
00040                             10, EAP_CODE_RESPONSE, id, &pos);
00041         if (hdr == NULL)
00042                 return NULL;
00043 
00044         *pos++ = 0x80; /* Mandatory */
00045         *pos++ = EAP_TLV_NAK_TLV;
00046         /* Length */
00047         *pos++ = 0;
00048         *pos++ = 6;
00049         /* Vendor-Id */
00050         *pos++ = 0;
00051         *pos++ = 0;
00052         *pos++ = 0;
00053         *pos++ = 0;
00054         /* NAK-Type */
00055         WPA_PUT_BE16(pos, nak_type);
00056 
00057         return (u8 *) hdr;
00058 }
00059 
00060 
00072 u8 * eap_tlv_build_result(int id, u16 status, size_t *resp_len)
00073 {
00074         struct eap_hdr *hdr;
00075         u8 *pos;
00076 
00077         hdr = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, resp_len,
00078                             6, EAP_CODE_RESPONSE, id, &pos);
00079         if (hdr == NULL)
00080                 return NULL;
00081 
00082         *pos++ = 0x80; /* Mandatory */
00083         *pos++ = EAP_TLV_RESULT_TLV;
00084         /* Length */
00085         *pos++ = 0;
00086         *pos++ = 2;
00087         /* Status */
00088         WPA_PUT_BE16(pos, status);
00089 
00090         return (u8 *) hdr;
00091 }
00092 
00093 
00109 int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret,
00110                     const struct eap_hdr *hdr, u8 **resp, size_t *resp_len)
00111 {
00112         size_t left, tlv_len;
00113         const u8 *pos;
00114         const u8 *result_tlv = NULL;
00115         size_t result_tlv_len = 0;
00116         int tlv_type, mandatory;
00117 
00118         /* Parse TLVs */
00119         left = be_to_host16(hdr->length) - sizeof(struct eap_hdr) - 1;
00120         pos = (const u8 *) (hdr + 1);
00121         pos++;
00122         wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
00123         while (left >= 4) {
00124                 mandatory = !!(pos[0] & 0x80);
00125                 tlv_type = WPA_GET_BE16(pos) & 0x3fff;
00126                 pos += 2;
00127                 tlv_len = WPA_GET_BE16(pos);
00128                 pos += 2;
00129                 left -= 4;
00130                 if (tlv_len > left) {
00131                         wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
00132                                    "(tlv_len=%lu left=%lu)",
00133                                    (unsigned long) tlv_len,
00134                                    (unsigned long) left);
00135                         return -1;
00136                 }
00137                 switch (tlv_type) {
00138                 case EAP_TLV_RESULT_TLV:
00139                         result_tlv = pos;
00140                         result_tlv_len = tlv_len;
00141                         break;
00142                 default:
00143                         wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
00144                                    "%d%s", tlv_type,
00145                                    mandatory ? " (mandatory)" : "");
00146                         if (mandatory) {
00147                                 /* NAK TLV and ignore all TLVs in this packet.
00148                                  */
00149                                 *resp = eap_tlv_build_nak(hdr->identifier,
00150                                                           tlv_type, resp_len);
00151                                 return *resp == NULL ? -1 : 0;
00152                         }
00153                         /* Ignore this TLV, but process other TLVs */
00154                         break;
00155                 }
00156 
00157                 pos += tlv_len;
00158                 left -= tlv_len;
00159         }
00160         if (left) {
00161                 wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
00162                            "Request (left=%lu)", (unsigned long) left);
00163                 return -1;
00164         }
00165 
00166         /* Process supported TLVs */
00167         if (result_tlv) {
00168                 int status, resp_status;
00169                 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
00170                             result_tlv, result_tlv_len);
00171                 if (result_tlv_len < 2) {
00172                         wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
00173                                    "(len=%lu)",
00174                                    (unsigned long) result_tlv_len);
00175                         return -1;
00176                 }
00177                 status = WPA_GET_BE16(result_tlv);
00178                 if (status == EAP_TLV_RESULT_SUCCESS) {
00179                         wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
00180                                    "- EAP-TLV/Phase2 Completed");
00181                         resp_status = EAP_TLV_RESULT_SUCCESS;
00182                         ret->decision = DECISION_UNCOND_SUCC;
00183                 } else if (status == EAP_TLV_RESULT_FAILURE) {
00184                         wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
00185                         resp_status = EAP_TLV_RESULT_FAILURE;
00186                         ret->decision = DECISION_FAIL;
00187                 } else {
00188                         wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
00189                                    "Status %d", status);
00190                         resp_status = EAP_TLV_RESULT_FAILURE;
00191                         ret->decision = DECISION_FAIL;
00192                 }
00193                 ret->methodState = METHOD_DONE;
00194 
00195                 *resp = eap_tlv_build_result(hdr->identifier, resp_status,
00196                                              resp_len);
00197         }
00198 
00199         return 0;
00200 }
00201 

Generated on Sun Dec 31 13:48:54 2006 for wpa_supplicant by  doxygen 1.4.2