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