2 * hostapd / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include "eap_common/eap_tlv_common.h"
23 enum { CONTINUE, SUCCESS, FAILURE } state;
27 static void * eap_tlv_init(struct eap_sm *sm)
29 struct eap_tlv_data *data;
31 data = os_zalloc(sizeof(*data));
34 data->state = CONTINUE;
40 static void eap_tlv_reset(struct eap_sm *sm, void *priv)
42 struct eap_tlv_data *data = priv;
47 static struct wpabuf * eap_tlv_buildReq(struct eap_sm *sm, void *priv, u8 id)
52 if (sm->tlv_request == TLV_REQ_SUCCESS) {
53 status = EAP_TLV_RESULT_SUCCESS;
55 status = EAP_TLV_RESULT_FAILURE;
58 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 6,
59 EAP_CODE_REQUEST, id);
63 wpabuf_put_u8(req, 0x80); /* Mandatory */
64 wpabuf_put_u8(req, EAP_TLV_RESULT_TLV);
66 wpabuf_put_be16(req, 2);
68 wpabuf_put_be16(req, status);
74 static Boolean eap_tlv_check(struct eap_sm *sm, void *priv,
75 struct wpabuf *respData)
80 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, respData, &len);
82 wpa_printf(MSG_INFO, "EAP-TLV: Invalid frame");
90 static void eap_tlv_process(struct eap_sm *sm, void *priv,
91 struct wpabuf *respData)
93 struct eap_tlv_data *data = priv;
96 const u8 *result_tlv = NULL;
97 size_t result_tlv_len = 0;
98 int tlv_type, mandatory, tlv_len;
100 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, respData, &left);
105 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
107 mandatory = !!(pos[0] & 0x80);
108 tlv_type = pos[0] & 0x3f;
109 tlv_type = (tlv_type << 8) | pos[1];
110 tlv_len = ((int) pos[2] << 8) | pos[3];
113 if ((size_t) tlv_len > left) {
114 wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
115 "(tlv_len=%d left=%lu)", tlv_len,
116 (unsigned long) left);
117 data->state = FAILURE;
121 case EAP_TLV_RESULT_TLV:
123 result_tlv_len = tlv_len;
126 wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
128 mandatory ? " (mandatory)" : "");
130 data->state = FAILURE;
133 /* Ignore this TLV, but process other TLVs */
141 wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
142 "Request (left=%lu)", (unsigned long) left);
143 data->state = FAILURE;
147 /* Process supported TLVs */
150 const char *requested;
152 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
153 result_tlv, result_tlv_len);
154 if (result_tlv_len < 2) {
155 wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
157 (unsigned long) result_tlv_len);
158 data->state = FAILURE;
161 requested = sm->tlv_request == TLV_REQ_SUCCESS ? "Success" :
163 status = WPA_GET_BE16(result_tlv);
164 if (status == EAP_TLV_RESULT_SUCCESS) {
165 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
166 "- requested %s", requested);
167 if (sm->tlv_request == TLV_REQ_SUCCESS)
168 data->state = SUCCESS;
170 data->state = FAILURE;
172 } else if (status == EAP_TLV_RESULT_FAILURE) {
173 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure - "
174 "requested %s", requested);
175 if (sm->tlv_request == TLV_REQ_FAILURE)
176 data->state = SUCCESS;
178 data->state = FAILURE;
180 wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
181 "Status %d", status);
182 data->state = FAILURE;
188 static Boolean eap_tlv_isDone(struct eap_sm *sm, void *priv)
190 struct eap_tlv_data *data = priv;
191 return data->state != CONTINUE;
195 static Boolean eap_tlv_isSuccess(struct eap_sm *sm, void *priv)
197 struct eap_tlv_data *data = priv;
198 return data->state == SUCCESS;
202 int eap_server_tlv_register(void)
204 struct eap_method *eap;
207 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
208 EAP_VENDOR_IETF, EAP_TYPE_TLV, "TLV");
212 eap->init = eap_tlv_init;
213 eap->reset = eap_tlv_reset;
214 eap->buildReq = eap_tlv_buildReq;
215 eap->check = eap_tlv_check;
216 eap->process = eap_tlv_process;
217 eap->isDone = eap_tlv_isDone;
218 eap->isSuccess = eap_tlv_isSuccess;
220 ret = eap_server_method_register(eap);
222 eap_server_method_free(eap);