1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "socket_opt.h"
17 #include "sockets.h"
18 #include "socket_common.h"
19 #include "spunge.h"
20 #include "spunge_message.h"
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
SockGetOptSendCache(struct FtSocket * sock,void * optVal,FILLP_INT * optLen)26 static FILLP_INT SockGetOptSendCache(struct FtSocket *sock, void *optVal, FILLP_INT *optLen)
27 {
28 struct FillpCurrentSendCacheInf *currentSendCacheInfo = FILLP_NULL_PTR;
29 struct FillpSendPcb *sendPcb = FILLP_NULL_PTR;
30 if ((*optLen < (FILLP_INT)sizeof(struct FillpCurrentSendCacheInf)) || (sock->netconn == FILLP_NULL_PTR)) {
31 SET_ERRNO(FILLP_EINVAL);
32 return -1;
33 }
34 if ((sock->netconn == FILLP_NULL_PTR) || (sock->netconn->state != CONN_STATE_CONNECTED)) {
35 FILLP_LOGERR("SockGetSockOpt: sock state must be connected Invalid sock = %d", sock->index);
36 SET_ERRNO(FILLP_EBADF);
37 return -1;
38 }
39
40 currentSendCacheInfo = (struct FillpCurrentSendCacheInf *)optVal;
41 sendPcb = &(sock->netconn->pcb->fpcb.send);
42 currentSendCacheInfo->currentSendCacheSize = sendPcb->curItemCount;
43 currentSendCacheInfo->currentDataSizeInCache = (FILLP_UINT32)(sendPcb->unSendList.size +
44 sendPcb->unackList.count + sendPcb->redunList.nodeNum + sendPcb->unrecvList.nodeNum +
45 sendPcb->itemWaitTokenLists.nodeNum);
46
47 return ERR_OK;
48 }
49
SockGetSockOptFillp(struct FtSocket * sock,FILLP_INT optName,void * optVal,FILLP_INT * optLen)50 static FILLP_INT SockGetSockOptFillp(struct FtSocket *sock, FILLP_INT optName, void *optVal, FILLP_INT *optLen)
51 {
52 FILLP_INT err;
53 switch (optName) {
54 case FILLP_PKT_DATA_OPTS_TIMESTAMP:
55 if (*optLen < (FILLP_INT)sizeof(FILLP_INT)) {
56 SET_ERRNO(FILLP_EINVAL);
57 err = -1;
58 break;
59 }
60 if (sock->dataOptionFlag & FILLP_OPT_FLAG_TIMESTAMP) {
61 *(FILLP_INT *)optVal = 1;
62 *optLen = (FILLP_INT)sizeof(FILLP_INT);
63 } else {
64 *(FILLP_INT *)optVal = 0;
65 *optLen = (FILLP_INT)sizeof(FILLP_INT);
66 }
67 err = ERR_OK;
68 break;
69 case FILLP_SOCK_SEND_CACHE_INFO:
70 err = SockGetOptSendCache(sock, optVal, optLen);
71 break;
72 case SO_LINGER:
73 if (*optLen < (FILLP_INT)sizeof(struct linger)) {
74 SET_ERRNO(FILLP_EINVAL);
75 err = -1;
76 } else {
77 err = memcpy_s(optVal, (FILLP_UINT32)(*optLen), (void *)&sock->fillpLinger, sizeof(struct linger));
78 if (err != EOK) {
79 FILLP_LOGERR("memcpy_s failed with errcode %d", err);
80 SET_ERRNO(FILLP_EINVAL);
81 err = -1;
82 } else {
83 *optLen = (FILLP_INT)sizeof(struct linger);
84 err = ERR_OK;
85 }
86 }
87 break;
88 default:
89 SET_ERRNO(FILLP_EINVAL);
90 err = -1;
91 break;
92 }
93 return err;
94 }
95
SockGetSockOpt(FILLP_INT sockIndex,FILLP_INT level,FILLP_INT optName,void * optVal,FILLP_INT * optLen)96 FILLP_INT SockGetSockOpt(
97 FILLP_INT sockIndex,
98 FILLP_INT level,
99 FILLP_INT optName,
100 void *optVal,
101 FILLP_INT *optLen)
102 {
103 struct FtSocket *sock = SockApiGetAndCheck(sockIndex);
104 struct SockOsSocket *osSock = FILLP_NULL_PTR;
105 FillpErrorType err = ERR_OK;
106
107 FILLP_LOGINF("SockGetSockOpt: sock = %d", sockIndex);
108
109 if (sock == FILLP_NULL_PTR) {
110 return -1;
111 }
112
113 if ((optLen == FILLP_NULL_PTR) || (optVal == FILLP_NULL_PTR)) {
114 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
115 SET_ERRNO(FILLP_EFAULT);
116 FILLP_LOGERR("SockGetSockOpt: optLen or optVal NULL");
117 return -1;
118 }
119
120 if ((optName == SO_ERROR) && (level == SOL_SOCKET)) {
121 if (*optLen < (FILLP_INT)sizeof(int)) {
122 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
123 SET_ERRNO(FILLP_EINVAL);
124 return -1;
125 }
126
127 if (sock->err == FILLP_EINPROGRESS) {
128 int errToErrno = FillpErrToErrno(sock->netconn->lastErr);
129 FILLP_SOCK_SET_ERR(sock, errToErrno);
130 }
131
132 *(int *)optVal = sock->err;
133 sock->err = ERR_OK;
134 } else if (level == IPPROTO_FILLP) {
135 err = SockGetSockOptFillp(sock, optName, optVal, optLen);
136 } else {
137 osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
138 if (!OS_SOCK_OPS_FUNC_VALID(osSock, getsockopt)) {
139 SET_ERRNO(FILLP_EINVAL);
140 err = -1;
141 } else {
142 err = osSock->ioSock->ops->getsockopt(osSock->ioSock, level, optName, optVal, optLen);
143 }
144 }
145
146 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
147 FILLP_LOGINF("SockGetSockOpt: return fillp_sock_id:%d, err:%d", sockIndex, err);
148
149 if (err != ERR_OK) {
150 err = -1;
151 }
152
153 return err;
154 }
155
SockSetOptTimestamp(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)156 static FILLP_INT SockSetOptTimestamp(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
157 {
158 FILLP_INT err;
159
160 if (optLen < (FILLP_INT)sizeof(FILLP_INT)) {
161 SET_ERRNO(FILLP_EINVAL);
162 return ERR_PARAM;
163 }
164
165 if (*(FILLP_CONST FILLP_INT *)optVal) {
166 err = SockUpdatePktDataOpt(sock, (FILLP_UINT16)FILLP_OPT_FLAG_TIMESTAMP, 0);
167 } else {
168 err = SockUpdatePktDataOpt(sock, 0, (FILLP_UINT16)FILLP_OPT_FLAG_TIMESTAMP);
169 }
170 if (err != ERR_OK) {
171 SET_ERRNO(FILLP_EINVAL);
172 }
173
174 return err;
175 }
176
SockSetOptLinger(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)177 static FILLP_INT SockSetOptLinger(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
178 {
179 FILLP_INT err = ERR_PARAM;
180 if (optLen < (FILLP_INT)sizeof(struct linger)) {
181 SET_ERRNO(FILLP_EINVAL);
182 } else {
183 err = memcpy_s((void *)&sock->fillpLinger, sizeof(struct linger), optVal, (FILLP_UINT32)optLen);
184 if (err != EOK) {
185 FILLP_LOGERR("memcpy_s failed with errcode %d", err);
186 SET_ERRNO(FILLP_EINVAL);
187 err = ERR_PARAM;
188 }
189 }
190
191 return err;
192 }
193
SockSetFcAlg(struct FtSocket * sock,FILLP_UINT32 alg)194 static FILLP_INT SockSetFcAlg(struct FtSocket *sock, FILLP_UINT32 alg)
195 {
196 FILLP_UINT8 connState;
197
198 if (sock->netconn == FILLP_NULL_PTR) {
199 FILLP_LOGERR("netconn is NULL, fillp_sock_id:%d", sock->index);
200 return FILLP_EINVAL;
201 }
202
203 connState = NETCONN_GET_STATE(sock->netconn);
204 if (connState != CONN_STATE_IDLE) {
205 FILLP_LOGERR("Netconn state is not idle fillp_sock_id:%d,state:%u", sock->index, connState);
206 return FILLP_EINVAL;
207 }
208
209 if (sock->netconn->pcb == FILLP_NULL_PTR) {
210 FILLP_LOGERR("pcb is NULL, fillp_sock_id:%d", sock->index);
211 return FILLP_EINVAL;
212 }
213
214 if (alg != FILLP_ALG_ONE && alg != FILLP_ALG_TWO && alg != FILLP_ALG_THREE &&
215 alg != FILLP_ALG_MSG && alg != FILLP_ALG_BASE) {
216 FILLP_LOGERR("alg %u is not supported", alg);
217 return FILLP_EINVAL;
218 }
219
220 if (alg != FILLP_ALG_BASE) {
221 sock->netconn->pcb->fpcb.fcAlg = (FILLP_UINT8)FILLP_SUPPORT_ALG_N(alg);
222 } else {
223 sock->netconn->pcb->fpcb.fcAlg = FILLP_SUPPORT_ALG_BASE;
224 }
225 if (alg == FILLP_ALG_MSG) {
226 sock->resConf.common.recvCache = FILLP_DEFAULT_MSG_RECV_CACHE;
227 sock->resConf.common.sendCache = FILLP_DEFAULT_MSG_SEND_CACHE;
228 NetconnSetRecvCacheSize(sock->netconn, sock->resConf.common.recvCache);
229 NetconnSetSendCacheSize(sock->netconn, sock->resConf.common.sendCache);
230 }
231 return FILLP_OK;
232 }
233
SockSetOptFcAlg(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)234 static FILLP_INT SockSetOptFcAlg(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
235 {
236 FILLP_INT err = ERR_PARAM;
237
238 if (optLen < (FILLP_INT)sizeof(FILLP_UINT32)) {
239 SET_ERRNO(FILLP_EINVAL);
240 return err;
241 }
242
243 if (SockSetFcAlg(sock, *(FILLP_UINT32 *)optVal) != ERR_OK) {
244 SET_ERRNO(FILLP_EINVAL);
245 } else {
246 err = 0;
247 }
248
249 return err;
250 }
251
SockSetOptDirectlySend(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)252 static FILLP_INT SockSetOptDirectlySend(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
253 {
254 if (optLen < (FILLP_INT)sizeof(FILLP_INT)) {
255 SET_ERRNO(FILLP_EINVAL);
256 return ERR_PARAM;
257 }
258
259 sock->directlySend = *(FILLP_INT *)optVal;
260 FILLP_LOGBUTT("fillp sock id: %d, set directlySend to %d", sock->index, sock->directlySend);
261 return ERR_OK;
262 }
263
SockSetSockOptFillp(struct FtSocket * sock,FILLP_INT optName,FILLP_CONST void * optVal,socklen_t optLen)264 static FILLP_INT SockSetSockOptFillp(struct FtSocket *sock,
265 FILLP_INT optName, FILLP_CONST void *optVal, socklen_t optLen)
266 {
267 FILLP_INT err = -1;
268 switch (optName) {
269 case FILLP_PKT_DATA_OPTS_TIMESTAMP:
270 err = SockSetOptTimestamp(sock, optVal, optLen);
271 break;
272 case SO_LINGER:
273 err = SockSetOptLinger(sock, optVal, optLen);
274 break;
275 case FILLP_SOCK_FC_ALG:
276 err = SockSetOptFcAlg(sock, optVal, optLen);
277 break;
278 case FILLP_SOCK_DIRECTLY_SEND:
279 err = SockSetOptDirectlySend(sock, optVal, optLen);
280 break;
281 default:
282 SET_ERRNO(FILLP_EINVAL);
283 break;
284 }
285 return err;
286 }
287
SockSetSockOpt(FILLP_INT sockIndex,FILLP_INT level,FILLP_INT optName,FILLP_CONST void * optVal,socklen_t optLen)288 FILLP_INT SockSetSockOpt(
289 FILLP_INT sockIndex,
290 FILLP_INT level,
291 FILLP_INT optName,
292 FILLP_CONST void *optVal,
293 socklen_t optLen)
294 {
295 struct FtSocket *sock = FILLP_NULL_PTR;
296 struct SockOsSocket *osSock = FILLP_NULL_PTR;
297 FillpErrorType err = -1;
298
299 FILLP_LOGINF("SockSetSockOpt: sock = %d", sockIndex);
300
301 if (optVal == FILLP_NULL_PTR) {
302 SET_ERRNO(FILLP_EFAULT);
303 return err;
304 }
305
306 if ((level == SOL_SOCKET) && ((optName == SO_SNDBUF) || (optName == SO_RCVBUF))) {
307 FILLP_LOGERR("SockSetSockOpt: sock = %d invalid param optName=%d", sockIndex, optName);
308 SET_ERRNO(FILLP_EOPNOTSUPP);
309 return err;
310 }
311
312 sock = SockApiGetAndCheck(sockIndex);
313 if (sock == FILLP_NULL_PTR) {
314 return err;
315 }
316
317 if (level == IPPROTO_FILLP) {
318 err = SockSetSockOptFillp(sock, optName, optVal, optLen);
319 } else {
320 osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
321 if (OS_SOCK_OPS_FUNC_VALID(osSock, setsockopt)) {
322 err = osSock->ioSock->ops->setsockopt(osSock->ioSock, level, optName, optVal, optLen);
323 } else {
324 SET_ERRNO(FILLP_EINVAL);
325 }
326 }
327
328 if (err != ERR_OK) {
329 err = -1;
330 }
331
332 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
333 FILLP_LOGINF("SockSetSockOpt: return fillp_sock_id:%d, err:%d", sockIndex, err);
334
335 return err;
336 }
337
338 #ifdef __cplusplus
339 }
340 #endif
341