1 /*
2 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "eapol.h"
10 #include "securec.h"
11 #include "osal_time.h"
12 #include "osal_mem.h"
13 #include "hdf_log.h"
14
15 #define HDF_LOG_TAG HDF_WIFI_CORE
16
17 #define RETURN_IF_INPUT_VALID(netDevice, buff) do { \
18 if ((netDevice) == NULL || (buff) == NULL) { \
19 HDF_LOGE("%s, netdevice = null or buf = null.", __func__); \
20 return HDF_ERR_INVALID_PARAM; \
21 } \
22 if ((netDevice)->specialProcPriv == NULL) { \
23 HDF_LOGE("%s : specialProcPriv = null", __func__); \
24 return HDF_ERR_INVALID_PARAM; \
25 } \
26 } while (0) \
27
EnableEapol(const struct NetDevice * netDevice,struct EapolEnable * buff)28 static int32_t EnableEapol(const struct NetDevice *netDevice, struct EapolEnable *buff)
29 {
30 struct EapolData *eapol = NULL;
31
32 RETURN_IF_INPUT_VALID(netDevice, buff);
33 eapol = (struct EapolData *)netDevice->specialProcPriv;
34 eapol->regFlag = true;
35 eapol->context = buff->context;
36 eapol->notify = buff->notify;
37 return HDF_SUCCESS;
38 }
39
DisableEapol(const struct NetDevice * netDevice)40 static int32_t DisableEapol(const struct NetDevice *netDevice)
41 {
42 struct EapolData *eapol = NULL;
43
44 if (netDevice == NULL || netDevice->specialProcPriv == NULL) {
45 HDF_LOGE("%s: netDevice = null or specialProcPriv = null!", __func__);
46 return HDF_ERR_INVALID_PARAM;
47 }
48 eapol = (struct EapolData *)netDevice->specialProcPriv;
49 eapol->regFlag = false;
50 eapol->context = NULL;
51 eapol->notify = NULL;
52 return HDF_SUCCESS;
53 }
54
GetEapol(const struct NetDevice * netDevice,struct EapolRx * buff)55 static int32_t GetEapol(const struct NetDevice *netDevice, struct EapolRx *buff)
56 {
57 struct EapolData *eapol = NULL;
58 struct EapolRx *eapolRx = buff;
59 NetBuf *netBuff = NULL;
60 uint8_t *p = NULL;
61 uint32_t len;
62
63 RETURN_IF_INPUT_VALID(netDevice, buff);
64 eapol = (struct EapolData *)netDevice->specialProcPriv;
65 if (NetBufQueueIsEmpty(&eapol->eapolQueue)) {
66 HDF_LOGE("%s fail : eapolQueue empty!", __func__);
67 return HDF_FAILURE;
68 }
69 netBuff = NetBufQueueDequeue(&eapol->eapolQueue);
70 if (netBuff == NULL) {
71 HDF_LOGE("%s fail : dequeue netBuff = null!", __func__);
72 return HDF_FAILURE;
73 }
74
75 p = NetBufGetAddress(netBuff, E_DATA_BUF);
76 len = NetBufGetDataLen(netBuff);
77 if (len > eapolRx->len) {
78 HDF_LOGE("%s fail : eapolRx->len too small! netBuff->len(%u) > eapolRx->len(%u).",
79 __func__, netBuff->len, eapolRx->len);
80 NetBufFree(netBuff);
81 return HDF_FAILURE;
82 }
83 if (p != NULL) {
84 if (memcpy_s(eapolRx->buff, eapolRx->len, p, len) != EOK) {
85 HDF_LOGE("%s::mem safe function err!", __func__);
86 NetBufFree(netBuff);
87 return HDF_FAILURE;
88 }
89 }
90 eapolRx->len = len;
91 NetBufFree(netBuff);
92 return HDF_SUCCESS;
93 }
94
SendEapol(struct NetDevice * netDevice,struct EapolTx * buff)95 static int32_t SendEapol(struct NetDevice *netDevice, struct EapolTx *buff)
96 {
97 struct EapolTx *eapolTx = buff;
98 NetBuf *netBuff = NULL;
99
100 if (netDevice == NULL || buff == NULL) {
101 HDF_LOGE("%s : netdevice = null or buff = null.", __func__);
102 return HDF_ERR_INVALID_PARAM;
103 }
104 if ((netDevice->netDeviceIf == NULL) || (netDevice->netDeviceIf->xmit == NULL)) {
105 HDF_LOGE("%s : netDeviceIf NULL.", __func__);
106 return HDF_FAILURE;
107 }
108
109 if (eapolTx->buff == NULL) {
110 HDF_LOGE("%s::eapolTx->buff = null!", __func__);
111 return HDF_ERR_INVALID_PARAM;
112 }
113 netBuff = NetBufDevAlloc(netDevice, eapolTx->len);
114 if (netBuff == NULL) {
115 HDF_LOGE("%s : netBuff alloc fail!", __func__);
116 return HDF_FAILURE;
117 }
118 NetBufPush(netBuff, E_DATA_BUF, eapolTx->len);
119 if (memcpy_s(NetBufGetAddress(netBuff, E_DATA_BUF), eapolTx->len,
120 eapolTx->buff, eapolTx->len) != EOK) {
121 NetBufFree(netBuff);
122 HDF_LOGE("%s::mem safe function err!", __func__);
123 return HDF_FAILURE;
124 }
125 return netDevice->netDeviceIf->xmit(netDevice, netBuff);
126 }
127
HandleEapolQueue(struct EapolData * eapol)128 static void HandleEapolQueue(struct EapolData *eapol)
129 {
130 int64_t currentTime = 0;
131 int64_t intervalTime = 0;
132 uint16_t maxCount;
133 OsalTimespec timeSpec;
134 NetBuf *netBuf = NULL;
135
136 if (eapol == NULL) {
137 return;
138 }
139
140 if (OsalGetTime(&timeSpec) == HDF_SUCCESS) {
141 currentTime = timeSpec.sec;
142 }
143 maxCount = (eapol->maxCount != 0) ? eapol->maxCount : EAPOL_MAX_COUNT;
144 /* The queue is empty to update enqueueTime and count */
145 if (NetBufQueueIsEmpty(&eapol->eapolQueue)) {
146 eapol->enqueueTime = currentTime;
147 eapol->count = 0;
148 return;
149 }
150
151 /* prevent a large amount of netbuff resources being used when WPA is abnormal */
152 if (currentTime > eapol->enqueueTime) {
153 intervalTime = currentTime - eapol->enqueueTime;
154 }
155 if (intervalTime > EAPOL_MAX_ENQUEUE_TIME || eapol->count >= maxCount) {
156 /* output log to solve problem */
157 if (intervalTime > EAPOL_MAX_ENQUEUE_TIME) {
158 HDF_LOGE("%s discard pre netbuf : intervalTime(%lld) > EAPOL_MAX_ENQUEUE_TIME.", __func__,
159 intervalTime);
160 } else {
161 HDF_LOGE("%s discard pre netbuf : eapol->count(%u) = maxCount(%hu).", __func__, eapol->count, maxCount);
162 }
163 eapol->count--;
164 eapol->enqueueTime = currentTime;
165 netBuf = NetBufQueueDequeue(&eapol->eapolQueue);
166 if (netBuf == NULL) {
167 HDF_LOGE("%s error : netbuff = null!", __func__);
168 return;
169 }
170 NetBufFree(netBuf);
171 }
172 return;
173 }
174
WriteEapolToQueue(const struct NetDevice * netDevice,NetBuf * buff)175 static int32_t WriteEapolToQueue(const struct NetDevice *netDevice, NetBuf *buff)
176 {
177 struct EapolData *eapol = NULL;
178
179 RETURN_IF_INPUT_VALID(netDevice, buff);
180 eapol = (struct EapolData *)netDevice->specialProcPriv;
181 if (eapol->regFlag && (eapol->notify != NULL)) {
182 HandleEapolQueue(eapol);
183 /* eapol data enqueue and notify wap processing */
184 eapol->count++;
185 NetBufQueueEnqueue(&eapol->eapolQueue, buff);
186 eapol->notify(netDevice->name, eapol->context);
187 return HDF_SUCCESS;
188 } else {
189 /* free netbuff when not register notify. */
190 NetBufFree(buff);
191 HDF_LOGE("%s fail : eapol process is not register.", __func__);
192 return HDF_SUCCESS;
193 }
194 }
195
196 static struct EapolInterface g_eapolInterface = {
197 .enableEapol = EnableEapol,
198 .disableEapol = DisableEapol,
199 .getEapol = GetEapol,
200 .sendEapol = SendEapol,
201 .writeEapolToQueue = WriteEapolToQueue,
202 };
203
204 struct Eapol g_eapol = {
205 .eapolOp = &g_eapolInterface,
206 };
207
CreateEapolData(struct NetDevice * netDevice)208 int32_t CreateEapolData(struct NetDevice *netDevice)
209 {
210 struct EapolData *eapolData = NULL;
211
212 if (netDevice == NULL) {
213 HDF_LOGE("%s Fail : netdev = null!", __func__);
214 return HDF_ERR_INVALID_PARAM;
215 }
216 if (netDevice->specialProcPriv != NULL) {
217 HDF_LOGI("%s: CreateEapolData already create!", __func__);
218 return HDF_SUCCESS;
219 }
220 eapolData = (struct EapolData *)OsalMemCalloc(sizeof(struct EapolData));
221 if (eapolData == NULL) {
222 HDF_LOGE("%s Fail : malloc fail!", __func__);
223 return HDF_FAILURE;
224 }
225 (void)memset_s(eapolData, sizeof(struct EapolData), 0, sizeof(struct EapolData));
226 NetBufQueueInit(&eapolData->eapolQueue);
227 netDevice->specialProcPriv = eapolData;
228 HDF_LOGI("%s: CreateEapolData success!", __func__);
229 return HDF_SUCCESS;
230 }
231
DestroyEapolData(struct NetDevice * netDevice)232 void DestroyEapolData(struct NetDevice *netDevice)
233 {
234 struct EapolData *eapolData = NULL;
235
236 if (netDevice == NULL || netDevice->specialProcPriv == NULL) {
237 HDF_LOGE("%s already free!", __func__);
238 return;
239 }
240 eapolData = (struct EapolData *)netDevice->specialProcPriv;
241 NetBufQueueClear(&eapolData->eapolQueue);
242 OsalMemFree(eapolData);
243 netDevice->specialProcPriv = NULL;
244 HDF_LOGI("%s: DestroyEapolData success!", __func__);
245 return;
246 }
247
EapolGetInstance(void)248 const struct Eapol *EapolGetInstance(void)
249 {
250 return &g_eapol;
251 }
252