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 return -1;
117 }
118
119 if ((optName == SO_ERROR) && (level == SOL_SOCKET)) {
120 if (*optLen < (FILLP_INT)sizeof(int)) {
121 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
122 SET_ERRNO(FILLP_EINVAL);
123 return -1;
124 }
125
126 if (sock->err == FILLP_EINPROGRESS) {
127 int errToErrno = FillpErrToErrno(sock->netconn->lastErr);
128 FILLP_SOCK_SET_ERR(sock, errToErrno);
129 }
130
131 *(int *)optVal = sock->err;
132 sock->err = ERR_OK;
133 } else if (level == IPPROTO_FILLP) {
134 err = SockGetSockOptFillp(sock, optName, optVal, optLen);
135 } else {
136 osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
137 if (!OS_SOCK_OPS_FUNC_VALID(osSock, getsockopt)) {
138 SET_ERRNO(FILLP_EINVAL);
139 err = -1;
140 } else {
141 err = osSock->ioSock->ops->getsockopt(osSock->ioSock, level, optName, optVal, optLen);
142 }
143 }
144
145 (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
146 FILLP_LOGINF("SockGetSockOpt: return fillp_sock_id:%d, err:%d", sockIndex, err);
147
148 if (err != ERR_OK) {
149 err = -1;
150 }
151
152 return err;
153 }
154
SockSetOptTimestamp(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)155 static FILLP_INT SockSetOptTimestamp(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
156 {
157 FILLP_INT err;
158
159 if (optLen < (FILLP_INT)sizeof(FILLP_INT)) {
160 SET_ERRNO(FILLP_EINVAL);
161 return ERR_PARAM;
162 }
163
164 if (*(FILLP_CONST FILLP_INT *)optVal) {
165 err = SockUpdatePktDataOpt(sock, (FILLP_UINT16)FILLP_OPT_FLAG_TIMESTAMP, 0);
166 } else {
167 err = SockUpdatePktDataOpt(sock, 0, (FILLP_UINT16)FILLP_OPT_FLAG_TIMESTAMP);
168 }
169 if (err != ERR_OK) {
170 SET_ERRNO(FILLP_EINVAL);
171 }
172
173 return err;
174 }
175
SockSetOptLinger(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)176 static FILLP_INT SockSetOptLinger(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
177 {
178 FILLP_INT err = ERR_PARAM;
179 if (optLen < (FILLP_INT)sizeof(struct linger)) {
180 SET_ERRNO(FILLP_EINVAL);
181 } else {
182 err = memcpy_s((void *)&sock->fillpLinger, sizeof(struct linger), optVal, (FILLP_UINT32)optLen);
183 if (err != EOK) {
184 FILLP_LOGERR("memcpy_s failed with errcode %d", err);
185 SET_ERRNO(FILLP_EINVAL);
186 err = ERR_PARAM;
187 }
188 }
189
190 return err;
191 }
192
SockSetFcAlg(struct FtSocket * sock,FILLP_UINT32 alg)193 static FILLP_INT SockSetFcAlg(struct FtSocket *sock, FILLP_UINT32 alg)
194 {
195 FILLP_UINT8 connState;
196
197 if (sock->netconn == FILLP_NULL_PTR) {
198 FILLP_LOGERR("netconn is NULL, fillp_sock_id:%d", sock->index);
199 return FILLP_EINVAL;
200 }
201
202 connState = NETCONN_GET_STATE(sock->netconn);
203 if (connState != CONN_STATE_IDLE) {
204 FILLP_LOGERR("Netconn state is not idle fillp_sock_id:%d,state:%u", sock->index, connState);
205 return FILLP_EINVAL;
206 }
207
208 if (sock->netconn->pcb == FILLP_NULL_PTR) {
209 FILLP_LOGERR("pcb is NULL, fillp_sock_id:%d", sock->index);
210 return FILLP_EINVAL;
211 }
212
213 if (alg != FILLP_ALG_ONE && alg != FILLP_ALG_TWO && alg != FILLP_ALG_THREE &&
214 alg != FILLP_ALG_MSG && alg != FILLP_ALG_BASE) {
215 FILLP_LOGERR("alg %u is not supported", alg);
216 return FILLP_EINVAL;
217 }
218
219 if (alg != FILLP_ALG_BASE) {
220 sock->netconn->pcb->fpcb.fcAlg = (FILLP_UINT8)FILLP_SUPPORT_ALG_N(alg);
221 } else {
222 sock->netconn->pcb->fpcb.fcAlg = FILLP_SUPPORT_ALG_BASE;
223 }
224 if (alg == FILLP_ALG_MSG) {
225 sock->resConf.common.recvCache = FILLP_DEFAULT_MSG_RECV_CACHE;
226 sock->resConf.common.sendCache = FILLP_DEFAULT_MSG_SEND_CACHE;
227 NetconnSetRecvCacheSize(sock->netconn, sock->resConf.common.recvCache);
228 NetconnSetSendCacheSize(sock->netconn, sock->resConf.common.sendCache);
229 }
230 return FILLP_OK;
231 }
232
SockSetOptFcAlg(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)233 static FILLP_INT SockSetOptFcAlg(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
234 {
235 FILLP_INT err = ERR_PARAM;
236
237 if (optLen < (FILLP_INT)sizeof(FILLP_UINT32)) {
238 SET_ERRNO(FILLP_EINVAL);
239 return err;
240 }
241
242 if (SockSetFcAlg(sock, *(FILLP_UINT32 *)optVal) != ERR_OK) {
243 SET_ERRNO(FILLP_EINVAL);
244 } else {
245 err = 0;
246 }
247
248 return err;
249 }
250
SockSetOptDirectlySend(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)251 static FILLP_INT SockSetOptDirectlySend(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
252 {
253 if (optLen < (FILLP_INT)sizeof(FILLP_INT)) {
254 SET_ERRNO(FILLP_EINVAL);
255 return ERR_PARAM;
256 }
257
258 sock->directlySend = *(FILLP_INT *)optVal;
259 FILLP_LOGBUTT("fillp sock id: %d, set directlySend to %d", sock->index, sock->directlySend);
260 return ERR_OK;
261 }
262
SockSetSockOptFillp(struct FtSocket * sock,FILLP_INT optName,FILLP_CONST void * optVal,socklen_t optLen)263 static FILLP_INT SockSetSockOptFillp(struct FtSocket *sock,
264 FILLP_INT optName, FILLP_CONST void *optVal, socklen_t optLen)
265 {
266 FILLP_INT err = -1;
267 switch (optName) {
268 case FILLP_PKT_DATA_OPTS_TIMESTAMP:
269 err = SockSetOptTimestamp(sock, optVal, optLen);
270 break;
271 case SO_LINGER:
272 err = SockSetOptLinger(sock, optVal, optLen);
273 break;
274 case FILLP_SOCK_FC_ALG:
275 err = SockSetOptFcAlg(sock, optVal, optLen);
276 break;
277 case FILLP_SOCK_DIRECTLY_SEND:
278 err = SockSetOptDirectlySend(sock, optVal, optLen);
279 break;
280 default:
281 SET_ERRNO(FILLP_EINVAL);
282 break;
283 }
284 return err;
285 }
286
SockSetSockOpt(FILLP_INT sockIndex,FILLP_INT level,FILLP_INT optName,FILLP_CONST void * optVal,socklen_t optLen)287 FILLP_INT SockSetSockOpt(
288 FILLP_INT sockIndex,
289 FILLP_INT level,
290 FILLP_INT optName,
291 FILLP_CONST void *optVal,
292 socklen_t optLen)
293 {
294 struct FtSocket *sock = FILLP_NULL_PTR;
295 struct SockOsSocket *osSock = FILLP_NULL_PTR;
296 FillpErrorType err;
297
298 FILLP_LOGINF("SockSetSockOpt: sock = %d", sockIndex);
299
300 if (optVal == FILLP_NULL_PTR) {
301 SET_ERRNO(FILLP_EFAULT);
302 return -1;
303 }
304
305 if ((level == SOL_SOCKET) && ((optName == SO_SNDBUF) || (optName == SO_RCVBUF))) {
306 FILLP_LOGERR("SockSetSockOpt: sock = %d invalid param optName=%d", sockIndex, optName);
307 SET_ERRNO(FILLP_EOPNOTSUPP);
308 return -1;
309 }
310
311 sock = SockApiGetAndCheck(sockIndex);
312 if (sock == FILLP_NULL_PTR) {
313 return -1;
314 }
315
316 if (level == IPPROTO_FILLP) {
317 err = SockSetSockOptFillp(sock, optName, optVal, optLen);
318 } else {
319 osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
320 if (OS_SOCK_OPS_FUNC_VALID(osSock, setsockopt)) {
321 err = osSock->ioSock->ops->setsockopt(osSock->ioSock, level, optName, optVal, optLen);
322 } else {
323 SET_ERRNO(FILLP_EINVAL);
324 err = -1;
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