1 /**
2  * Copyright (c) 2018 Linaro Limited.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "simplelink_log.h"
8 LOG_MODULE_DECLARE(LOG_MODULE_NAME);
9 
10 #include <stdlib.h>
11 #include <limits.h>
12 #include <zephyr/posix/fcntl.h>
13 
14 #include <zephyr/kernel.h>
15 /* Define sockaddr, etc, before simplelink.h */
16 #include <zephyr/net/socket_offload.h>
17 
18 #include <errno.h>
19 #include <ti/drivers/net/wifi/simplelink.h>
20 #include <ti/drivers/net/wifi/source/driver.h>
21 #include <ti/net/slnetutils.h>
22 #include <ti/net/slnetif.h>
23 #include "simplelink_support.h"
24 
25 #include "sockets_internal.h"
26 #include "tls_internal.h"
27 
28 #define FAILED (-1)
29 
30 /* Increment by 1 to make sure we do not store the value of 0, which has
31  * a special meaning in the fdtable subsys.
32  */
33 #define SD_TO_OBJ(sd) ((void *)(sd + 1))
34 #define OBJ_TO_SD(obj) (((int)obj) - 1)
35 
36 static int simplelink_socket_accept(void *obj, struct sockaddr *addr,
37 			     socklen_t *addrlen);
38 
39 /*
40  * Convert SL error codes into BSD errno values
41  * note that we are handling the same set of values as in TI SlNetSock
42  * minus the ones that are not defined in ti/drivers/net/wifi/errors.h.
43  */
getErrno(_i32 error)44 static int getErrno(_i32 error)
45 {
46 	if (error >= 0) {
47 		return error;
48 	}
49 	/* This switch case block is necessary for translating the NWP error
50 	 * code to BSD ones. The #ifdef in each case are made in order to
51 	 * reduce code footprint: These cases are compiled if and only if
52 	 * there's a discrepancy between the BSD error number and the error
53 	 * code returned by the NWP.
54 	 */
55 	switch (error) {
56 #if EBADF != SL_ERROR_BSD_EBADF
57 	case SL_ERROR_BSD_EBADF:
58 		error = EBADF;
59 		break;
60 #endif
61 #if ENSOCK !=  SL_ERROR_BSD_ENSOCK
62 	case SL_ERROR_BSD_ENSOCK:
63 		/* The limit on total # of open sockets has been reached */
64 		error = ENSOCK;
65 		break;
66 #endif
67 #if EAGAIN != SL_ERROR_BSD_EAGAIN
68 	case SL_ERROR_BSD_EAGAIN:
69 		error = EAGAIN;
70 		break;
71 #endif
72 #if ENOMEM != SL_ERROR_BSD_ENOMEM
73 	case SL_ERROR_BSD_ENOMEM:
74 		error = ENOMEM;
75 		break;
76 #endif
77 #if EACCES != SL_ERROR_BSD_EACCES
78 	case SL_ERROR_BSD_EACCES:
79 		error = EACCES;
80 		break;
81 #endif
82 #if EFAULT != SL_ERROR_BSD_EFAULT
83 	case SL_ERROR_BSD_EFAULT:
84 		error = EFAULT;
85 		break;
86 #endif
87 #if EINVAL != SL_ERROR_BSD_EINVAL
88 	case SL_ERROR_BSD_EINVAL:
89 		error = EINVAL;
90 		break;
91 #endif
92 #if EDESTADDRREQ != SL_ERROR_BSD_EDESTADDRREQ
93 	case SL_ERROR_BSD_EDESTADDRREQ:
94 		error = EDESTADDRREQ;
95 		break;
96 #endif
97 #if EPROTOTYPE != SL_ERROR_BSD_EPROTOTYPE
98 	case SL_ERROR_BSD_EPROTOTYPE:
99 		error = EPROTOTYPE;
100 		break;
101 #endif
102 #if ENOPROTOOPT != SL_ERROR_BSD_ENOPROTOOPT
103 	case SL_ERROR_BSD_ENOPROTOOPT:
104 		error = ENOPROTOOPT;
105 		break;
106 #endif
107 #if EPROTONOSUPPORT != SL_ERROR_BSD_EPROTONOSUPPORT
108 	case SL_ERROR_BSD_EPROTONOSUPPORT:
109 		error = EPROTONOSUPPORT;
110 		break;
111 #endif
112 #if EOPNOTSUPP != SL_ERROR_BSD_EOPNOTSUPP
113 	case SL_ERROR_BSD_EOPNOTSUPP:
114 		error = EOPNOTSUPP;
115 		break;
116 #endif
117 #if EAFNOSUPPORT != SL_ERROR_BSD_EAFNOSUPPORT
118 	case SL_ERROR_BSD_EAFNOSUPPORT:
119 		error = EAFNOSUPPORT;
120 		break;
121 #endif
122 #if EADDRINUSE != SL_ERROR_BSD_EADDRINUSE
123 	case SL_ERROR_BSD_EADDRINUSE:
124 		error = EADDRINUSE;
125 		break;
126 #endif
127 #if EADDRNOTAVAIL != SL_ERROR_BSD_EADDRNOTAVAIL
128 	case SL_ERROR_BSD_EADDRNOTAVAIL:
129 		error = EADDRNOTAVAIL;
130 		break;
131 #endif
132 #if ENETUNREACH != SL_ERROR_BSD_ENETUNREACH
133 	case SL_ERROR_BSD_ENETUNREACH:
134 		error = ENETUNREACH;
135 		break;
136 #endif
137 #if ENOBUFS != SL_ERROR_BSD_ENOBUFS
138 	case SL_ERROR_BSD_ENOBUFS:
139 		error = ENOBUFS;
140 		break;
141 #endif
142 #if EISCONN != SL_ERROR_BSD_EISCONN
143 	case SL_ERROR_BSD_EISCONN:
144 		error = EISCONN;
145 		break;
146 #endif
147 #if ENOTCONN != SL_ERROR_BSD_ENOTCONN
148 	case SL_ERROR_BSD_ENOTCONN:
149 		error = ENOTCONN;
150 		break;
151 #endif
152 #if ETIMEDOUT != SL_ERROR_BSD_ETIMEDOUT
153 	case SL_ERROR_BSD_ETIMEDOUT:
154 		error = ETIMEDOUT;
155 		break;
156 #endif
157 #if ECONNREFUSED != SL_ERROR_BSD_ECONNREFUSED
158 	case SL_ERROR_BSD_ECONNREFUSED:
159 		error = ECONNREFUSED;
160 		break;
161 #endif
162 	/* The cases below are proprietary driver errors, which can
163 	 * be returned by the SimpleLink Driver, in various cases of failure.
164 	 * Each is mapped to the corresponding BSD error.
165 	 */
166 	case SL_POOL_IS_EMPTY:
167 	case SL_RET_CODE_NO_FREE_ASYNC_BUFFERS_ERROR:
168 	case SL_RET_CODE_MALLOC_ERROR:
169 		error = ENOMEM;
170 		break;
171 	case SL_RET_CODE_INVALID_INPUT:
172 	case SL_EZEROLEN:
173 	case SL_ESMALLBUF:
174 	case SL_INVALPARAM:
175 		error = EINVAL;
176 		break;
177 	default:
178 	/* Do nothing ..
179 	 * If no case is true, that means that the BSD error
180 	 * code and the code returned by the NWP are either identical,
181 	 * or no proprietary error has occurred.
182 	 */
183 		break;
184 	}
185 
186 	return error;
187 }
188 
simplelink_socket_family_from_posix(int family,int * family_sl)189 static int simplelink_socket_family_from_posix(int family, int *family_sl)
190 {
191 	switch (family) {
192 	case AF_INET:
193 		*family_sl = SL_AF_INET;
194 		break;
195 	case AF_INET6:
196 		*family_sl = SL_AF_INET6;
197 		break;
198 	default:
199 		return -EAFNOSUPPORT;
200 	}
201 
202 	return 0;
203 }
204 
simplelink_socket_type_from_posix(int type,int * type_sl)205 static int simplelink_socket_type_from_posix(int type, int *type_sl)
206 {
207 	switch (type) {
208 	case SOCK_STREAM:
209 		*type_sl = SL_SOCK_STREAM;
210 		break;
211 	case SOCK_DGRAM:
212 		*type_sl = SL_SOCK_DGRAM;
213 		break;
214 	case SOCK_RAW:
215 		*type_sl = SL_SOCK_RAW;
216 		break;
217 	default:
218 		return -ESOCKTNOSUPPORT;
219 	}
220 
221 	return 0;
222 }
223 
simplelink_socket_proto_from_zephyr(int proto,int * proto_sl)224 static int simplelink_socket_proto_from_zephyr(int proto, int *proto_sl)
225 {
226 	if (proto >= IPPROTO_TLS_1_0 && proto <= IPPROTO_TLS_1_2) {
227 		*proto_sl = SL_SEC_SOCKET;
228 	} else if (proto >= IPPROTO_DTLS_1_0 && proto <= IPPROTO_DTLS_1_2) {
229 		/* SimpleLink doesn't handle DTLS yet! */
230 		return -EPROTONOSUPPORT;
231 	} else {
232 		switch (proto) {
233 		case IPPROTO_TCP:
234 			*proto_sl = SL_IPPROTO_TCP;
235 			break;
236 		case IPPROTO_UDP:
237 			*proto_sl = SL_IPPROTO_UDP;
238 			break;
239 		default:
240 			return -EPROTONOSUPPORT;
241 		}
242 	}
243 
244 	return 0;
245 }
246 
simplelink_socket(int family,int type,int proto)247 static int simplelink_socket(int family, int type, int proto)
248 {
249 	uint8_t sec_method = SL_SO_SEC_METHOD_SSLv3_TLSV1_2;
250 	int sd;
251 	int retval = 0;
252 	int sl_proto = proto;
253 	int err;
254 
255 	/* Map Zephyr socket.h family to SimpleLink's: */
256 	err = simplelink_socket_family_from_posix(family, &family);
257 	if (err) {
258 		LOG_ERR("unsupported family: %d", family);
259 		retval = slcb_SetErrno(-err);
260 		goto exit;
261 	}
262 
263 	/* Map Zephyr socket.h type to SimpleLink's: */
264 	err = simplelink_socket_type_from_posix(type, &type);
265 	if (err) {
266 		LOG_ERR("unsupported type: %d", type);
267 		retval = slcb_SetErrno(-err);
268 		goto exit;
269 	}
270 
271 	/* Map Zephyr protocols to TI's values: */
272 	err = simplelink_socket_proto_from_zephyr(proto, &sl_proto);
273 	if (err) {
274 		LOG_ERR("unsupported proto: %d", proto);
275 		retval = slcb_SetErrno(-err);
276 		goto exit;
277 	}
278 
279 	sd = sl_Socket(family, type, sl_proto);
280 	if (sd >= 0) {
281 		if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
282 		    && sl_proto == SL_SEC_SOCKET) {
283 			/* Now, set specific TLS version via setsockopt(): */
284 			sec_method = (proto - IPPROTO_TLS_1_0) +
285 				SL_SO_SEC_METHOD_TLSV1;
286 			retval = sl_SetSockOpt(sd, SL_SOL_SOCKET,
287 				SL_SO_SECMETHOD,
288 				&sec_method, sizeof(sec_method));
289 			if (retval < 0) {
290 				retval = slcb_SetErrno(EPROTONOSUPPORT);
291 				(void)sl_Close(sd);
292 				goto exit;
293 			}
294 		}
295 	}
296 
297 	retval = sd;
298 
299 	if (retval < 0) {
300 		retval = slcb_SetErrno(getErrno(retval));
301 	}
302 
303 exit:
304 	return retval;
305 }
306 
simplelink_close(void * obj)307 static int simplelink_close(void *obj)
308 {
309 	int sd = OBJ_TO_SD(obj);
310 	int retval;
311 
312 	retval = sl_Close(sd);
313 
314 	if (retval < 0) {
315 		retval = slcb_SetErrno(getErrno(retval));
316 	}
317 
318 	return retval;
319 }
320 
translate_z_to_sl_addrlen(socklen_t addrlen,SlSockAddrIn_t * sl_addr_in,SlSockAddrIn6_t * sl_addr_in6,SlSocklen_t * sl_addrlen)321 static SlSockAddr_t *translate_z_to_sl_addrlen(socklen_t addrlen,
322 					       SlSockAddrIn_t *sl_addr_in,
323 					       SlSockAddrIn6_t *sl_addr_in6,
324 					       SlSocklen_t *sl_addrlen)
325 {
326 	SlSockAddr_t *sl_addr = NULL;
327 
328 	if (addrlen == sizeof(struct sockaddr_in)) {
329 		*sl_addrlen = sizeof(SlSockAddrIn_t);
330 		sl_addr = (SlSockAddr_t *)sl_addr_in;
331 	} else if (addrlen == sizeof(struct sockaddr_in6)) {
332 		*sl_addrlen = sizeof(SlSockAddrIn6_t);
333 		sl_addr = (SlSockAddr_t *)sl_addr_in6;
334 	}
335 
336 	return sl_addr;
337 }
338 
translate_z_to_sl_addrs(const struct sockaddr * addr,socklen_t addrlen,SlSockAddrIn_t * sl_addr_in,SlSockAddrIn6_t * sl_addr_in6,SlSocklen_t * sl_addrlen)339 static SlSockAddr_t *translate_z_to_sl_addrs(const struct sockaddr *addr,
340 					     socklen_t addrlen,
341 					     SlSockAddrIn_t *sl_addr_in,
342 					     SlSockAddrIn6_t *sl_addr_in6,
343 					     SlSocklen_t *sl_addrlen)
344 {
345 	SlSockAddr_t *sl_addr = NULL;
346 
347 	if (addrlen == sizeof(struct sockaddr_in)) {
348 		struct sockaddr_in *z_sockaddr_in = (struct sockaddr_in *)addr;
349 
350 		*sl_addrlen = sizeof(SlSockAddrIn_t);
351 		sl_addr_in->sin_family = SL_AF_INET;
352 		sl_addr_in->sin_port = z_sockaddr_in->sin_port;
353 		sl_addr_in->sin_addr.s_addr =
354 			z_sockaddr_in->sin_addr.s_addr;
355 
356 		sl_addr = (SlSockAddr_t *)sl_addr_in;
357 	} else if (addrlen == sizeof(struct sockaddr_in6)) {
358 		struct sockaddr_in6 *z_sockaddr_in6 =
359 			(struct sockaddr_in6 *)addr;
360 
361 		*sl_addrlen = sizeof(SlSockAddrIn6_t);
362 		sl_addr_in6->sin6_family = SL_AF_INET6;
363 		sl_addr_in6->sin6_port = z_sockaddr_in6->sin6_port;
364 		memcpy(sl_addr_in6->sin6_addr._S6_un._S6_u32,
365 		       z_sockaddr_in6->sin6_addr.s6_addr,
366 		       sizeof(sl_addr_in6->sin6_addr._S6_un._S6_u32));
367 
368 		sl_addr = (SlSockAddr_t *)sl_addr_in6;
369 	}
370 
371 	return sl_addr;
372 }
373 
translate_sl_to_z_addr(SlSockAddr_t * sl_addr,SlSocklen_t sl_addrlen,struct sockaddr * addr,socklen_t * addrlen)374 static void translate_sl_to_z_addr(SlSockAddr_t *sl_addr,
375 				   SlSocklen_t sl_addrlen,
376 				   struct sockaddr *addr,
377 				   socklen_t *addrlen)
378 {
379 	SlSockAddrIn_t *sl_addr_in;
380 	SlSockAddrIn6_t *sl_addr_in6;
381 
382 	if (sl_addr->sa_family == SL_AF_INET) {
383 		if (sl_addrlen == (SlSocklen_t)sizeof(SlSockAddrIn_t)) {
384 			struct sockaddr_in *z_sockaddr_in =
385 				(struct sockaddr_in *)addr;
386 
387 			sl_addr_in = (SlSockAddrIn_t *)sl_addr;
388 			z_sockaddr_in->sin_family = AF_INET;
389 			z_sockaddr_in->sin_port = sl_addr_in->sin_port;
390 			z_sockaddr_in->sin_addr.s_addr =
391 				sl_addr_in->sin_addr.s_addr;
392 			*addrlen = sizeof(struct sockaddr_in);
393 		} else {
394 			*addrlen = sl_addrlen;
395 		}
396 	} else if (sl_addr->sa_family == SL_AF_INET6) {
397 		if (sl_addrlen == sizeof(SlSockAddrIn6_t)) {
398 			struct sockaddr_in6 *z_sockaddr_in6 =
399 				(struct sockaddr_in6 *)addr;
400 			sl_addr_in6 = (SlSockAddrIn6_t *)sl_addr;
401 
402 			z_sockaddr_in6->sin6_family = AF_INET6;
403 			z_sockaddr_in6->sin6_port = sl_addr_in6->sin6_port;
404 			z_sockaddr_in6->sin6_scope_id =
405 				(uint8_t)sl_addr_in6->sin6_scope_id;
406 			memcpy(z_sockaddr_in6->sin6_addr.s6_addr,
407 			       sl_addr_in6->sin6_addr._S6_un._S6_u32,
408 			       sizeof(z_sockaddr_in6->sin6_addr.s6_addr));
409 			*addrlen = sizeof(struct sockaddr_in6);
410 		} else {
411 			*addrlen = sl_addrlen;
412 		}
413 	}
414 }
415 
simplelink_accept(void * obj,struct sockaddr * addr,socklen_t * addrlen)416 static int simplelink_accept(void *obj, struct sockaddr *addr,
417 			     socklen_t *addrlen)
418 {
419 	int sd = OBJ_TO_SD(obj);
420 	int retval;
421 	SlSockAddr_t *sl_addr;
422 	SlSockAddrIn_t sl_addr_in;
423 	SlSockAddrIn6_t sl_addr_in6;
424 	SlSocklen_t sl_addrlen;
425 
426 	if ((addrlen == NULL) || (addr == NULL)) {
427 		retval = SL_RET_CODE_INVALID_INPUT;
428 		goto exit;
429 	}
430 
431 	/* Translate between Zephyr's and SimpleLink's sockaddr's: */
432 	sl_addr = translate_z_to_sl_addrlen(*addrlen, &sl_addr_in, &sl_addr_in6,
433 				  &sl_addrlen);
434 	if (sl_addr == NULL) {
435 		retval = SL_RET_CODE_INVALID_INPUT;
436 		goto exit;
437 	}
438 
439 	retval = sl_Accept(sd, sl_addr, &sl_addrlen);
440 	if (retval < 0) {
441 		goto exit;
442 	}
443 
444 	/* Translate returned sl_addr into *addr and set *addrlen: */
445 	translate_sl_to_z_addr(sl_addr, sl_addrlen, addr, addrlen);
446 
447 exit:
448 	if (retval < 0) {
449 		retval = slcb_SetErrno(getErrno(retval));
450 	}
451 
452 	return retval;
453 }
454 
simplelink_bind(void * obj,const struct sockaddr * addr,socklen_t addrlen)455 static int simplelink_bind(void *obj, const struct sockaddr *addr,
456 			   socklen_t addrlen)
457 {
458 	int sd = OBJ_TO_SD(obj);
459 	int retval;
460 	SlSockAddr_t *sl_addr;
461 	SlSockAddrIn_t sl_addr_in;
462 	SlSockAddrIn6_t sl_addr_in6;
463 	SlSocklen_t sl_addrlen;
464 
465 	if (addr == NULL) {
466 		retval = slcb_SetErrno(EISDIR);
467 		return retval;
468 	}
469 
470 	/* Translate to sl_Bind() parameters: */
471 	sl_addr = translate_z_to_sl_addrs(addr, addrlen, &sl_addr_in,
472 					  &sl_addr_in6, &sl_addrlen);
473 
474 	if (sl_addr == NULL) {
475 		retval = SL_RET_CODE_INVALID_INPUT;
476 		goto exit;
477 	}
478 
479 	retval = sl_Bind(sd, sl_addr, sl_addrlen);
480 
481 exit:
482 	if (retval < 0) {
483 		retval = slcb_SetErrno(getErrno(retval));
484 	}
485 
486 	return retval;
487 }
488 
simplelink_listen(void * obj,int backlog)489 static int simplelink_listen(void *obj, int backlog)
490 {
491 	int sd = OBJ_TO_SD(obj);
492 	int retval;
493 
494 	retval = (int)sl_Listen(sd, backlog);
495 
496 	if (retval < 0) {
497 		retval = slcb_SetErrno(getErrno(retval));
498 	}
499 
500 	return retval;
501 }
502 
simplelink_connect(void * obj,const struct sockaddr * addr,socklen_t addrlen)503 static int simplelink_connect(void *obj, const struct sockaddr *addr,
504 			      socklen_t addrlen)
505 {
506 	int sd = OBJ_TO_SD(obj);
507 	int retval;
508 	SlSockAddr_t *sl_addr;
509 	SlSockAddrIn_t sl_addr_in;
510 	SlSockAddrIn6_t sl_addr_in6;
511 	SlSocklen_t sl_addrlen;
512 
513 	__ASSERT_NO_MSG(addr);
514 
515 	/* Translate to sl_Connect() parameters: */
516 	sl_addr = translate_z_to_sl_addrs(addr, addrlen, &sl_addr_in,
517 					  &sl_addr_in6, &sl_addrlen);
518 
519 	if (sl_addr == NULL) {
520 		retval = SL_RET_CODE_INVALID_INPUT;
521 		goto exit;
522 	}
523 
524 	retval = sl_Connect(sd, sl_addr, sl_addrlen);
525 
526 	/* TBD: Until we have a good way to get correct date from Zephyr,
527 	 * log a date validation error as a warning, but continue connection:
528 	 */
529 	if (retval == SL_ERROR_BSD_ESECDATEERROR) {
530 		LOG_WRN("Failed certificate date validation: %d", retval);
531 		retval = 0;
532 	}
533 
534 	/* Warn users when root CA is not in the certificate catalog.
535 	 * For enhanced security, users should update the catalog with the
536 	 * certificates for sites the device is expected to connect to. Note
537 	 * the connection is established successfully even when the root CA
538 	 * is not part of the catalog.
539 	 */
540 	if (retval == SL_ERROR_BSD_ESECUNKNOWNROOTCA) {
541 		LOG_WRN("Unknown root CA used. For proper security, please "
542 			"use a root CA that is part of the certificate "
543 			"catalog in production systems.");
544 		retval = 0;
545 	}
546 
547 exit:
548 	if (retval < 0) {
549 		retval = slcb_SetErrno(getErrno(retval));
550 	}
551 
552 	return retval;
553 }
554 
555 #define ONE_THOUSAND 1000
556 
557 static const struct socket_op_vtable simplelink_socket_fd_op_vtable;
558 
simplelink_poll(struct zsock_pollfd * fds,int nfds,int msecs)559 static int simplelink_poll(struct zsock_pollfd *fds, int nfds, int msecs)
560 {
561 	int max_sd = 0;
562 	struct SlTimeval_t tv, *ptv;
563 	SlFdSet_t rfds;	 /* Set of read file descriptors */
564 	SlFdSet_t wfds;	 /* Set of write file descriptors */
565 	int i, retval, sd;
566 	void *obj;
567 
568 	if (nfds > SL_FD_SETSIZE) {
569 		retval = slcb_SetErrno(EINVAL);
570 		goto exit;
571 	}
572 
573 	/* Convert time to SlTimeval struct values: */
574 	if (msecs == SYS_FOREVER_MS) {
575 		ptv = NULL;
576 	} else {
577 		tv.tv_sec = msecs / ONE_THOUSAND;
578 		tv.tv_usec = (msecs % ONE_THOUSAND) * ONE_THOUSAND;
579 		ptv = &tv;
580 	}
581 
582 	/* Setup read and write fds for select, based on pollfd fields: */
583 	SL_SOCKET_FD_ZERO(&rfds);
584 	SL_SOCKET_FD_ZERO(&wfds);
585 
586 	for (i = 0; i < nfds; i++) {
587 		fds[i].revents = 0;
588 		if (fds[i].fd < 0) {
589 			continue;
590 		} else {
591 			obj = z_get_fd_obj(fds[i].fd,
592 					   (const struct fd_op_vtable *)
593 						&simplelink_socket_fd_op_vtable,
594 					   ENOTSUP);
595 			if (obj != NULL) {
596 				/* Offloaded socket found. */
597 				sd = OBJ_TO_SD(obj);
598 			} else {
599 				/* Non-offloaded socket, return an error. */
600 				retval = slcb_SetErrno(EINVAL);
601 				goto exit;
602 			}
603 		}
604 		if (fds[i].events & ZSOCK_POLLIN) {
605 			SL_SOCKET_FD_SET(sd, &rfds);
606 		}
607 		if (fds[i].events & ZSOCK_POLLOUT) {
608 			SL_SOCKET_FD_SET(sd, &wfds);
609 		}
610 		if (sd > max_sd) {
611 			max_sd = sd;
612 		}
613 	}
614 
615 	/* Wait for requested read and write fds to be ready: */
616 	retval = sl_Select(max_sd + 1, &rfds, &wfds, NULL, ptv);
617 	if (retval > 0) {
618 		for (i = 0; i < nfds; i++) {
619 			if (fds[i].fd >= 0) {
620 				obj = z_get_fd_obj(
621 					fds[i].fd,
622 					(const struct fd_op_vtable *)
623 						&simplelink_socket_fd_op_vtable,
624 					ENOTSUP);
625 				sd = OBJ_TO_SD(obj);
626 				if (SL_SOCKET_FD_ISSET(sd, &rfds)) {
627 					fds[i].revents |= ZSOCK_POLLIN;
628 				}
629 				if (SL_SOCKET_FD_ISSET(sd, &wfds)) {
630 					fds[i].revents |= ZSOCK_POLLOUT;
631 				}
632 			}
633 		}
634 	}
635 
636 	if (retval < 0) {
637 		retval = slcb_SetErrno(getErrno(retval));
638 	}
639 
640 exit:
641 	return retval;
642 }
643 
644 #ifdef CONFIG_NET_SOCKETS_SOCKOPT_TLS
645 
646 /* Iterate through the list of Zephyr's credential types, and
647  * map to SimpleLink values, then set stored filenames
648  * via SimpleLink's sl_SetSockOpt()
649  */
map_credentials(int sd,const void * optval,socklen_t optlen)650 static int map_credentials(int sd, const void *optval, socklen_t optlen)
651 {
652 	sec_tag_t *sec_tags = (sec_tag_t *)optval;
653 	int retval = 0;
654 	int sec_tags_len;
655 	sec_tag_t tag;
656 	int opt;
657 	int i;
658 	struct tls_credential *cert;
659 
660 	if ((optlen % sizeof(sec_tag_t)) != 0 || (optlen == 0)) {
661 		retval = EINVAL;
662 		goto exit;
663 	} else {
664 		sec_tags_len = optlen / sizeof(sec_tag_t);
665 	}
666 
667 	/* For each tag, retrieve the credentials value and type: */
668 	for (i = 0; i < sec_tags_len; i++) {
669 		tag = sec_tags[i];
670 		cert = credential_next_get(tag, NULL);
671 		while (cert != NULL) {
672 			/* Map Zephyr cert types to Simplelink cert options: */
673 			switch (cert->type) {
674 			case TLS_CREDENTIAL_CA_CERTIFICATE:
675 				opt = SL_SO_SECURE_FILES_CA_FILE_NAME;
676 				break;
677 			case TLS_CREDENTIAL_SERVER_CERTIFICATE:
678 				opt = SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME;
679 				break;
680 			case TLS_CREDENTIAL_PRIVATE_KEY:
681 				opt = SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME;
682 				break;
683 			case TLS_CREDENTIAL_NONE:
684 			case TLS_CREDENTIAL_PSK:
685 			case TLS_CREDENTIAL_PSK_ID:
686 			default:
687 				/* Not handled by SimpleLink: */
688 				retval = EINVAL;
689 				goto exit;
690 			}
691 			retval = sl_SetSockOpt(sd, SL_SOL_SOCKET, opt,
692 					       cert->buf,
693 					       (SlSocklen_t)cert->len);
694 			if (retval < 0) {
695 				retval = getErrno(retval);
696 				break;
697 			}
698 			cert = credential_next_get(tag, cert);
699 		}
700 	}
701 
702 exit:
703 	return retval;
704 }
705 #else
map_credentials(int sd,const void * optval,socklen_t optlen)706 static int map_credentials(int sd, const void *optval, socklen_t optlen)
707 {
708 	return 0;
709 }
710 #endif  /* CONFIG_NET_SOCKETS_SOCKOPT_TLS */
711 
712 /* Needed to keep line lengths < 80: */
713 #define _SEC_DOMAIN_VERIF SL_SO_SECURE_DOMAIN_NAME_VERIFICATION
714 
simplelink_setsockopt(void * obj,int level,int optname,const void * optval,socklen_t optlen)715 static int simplelink_setsockopt(void *obj, int level, int optname,
716 				 const void *optval, socklen_t optlen)
717 {
718 	int sd = OBJ_TO_SD(obj);
719 	int retval;
720 
721 	if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS) && level == SOL_TLS) {
722 		/* Handle Zephyr's SOL_TLS secure socket options: */
723 		switch (optname) {
724 		case TLS_SEC_TAG_LIST:
725 			/* Bind credential filenames to this socket: */
726 			retval = map_credentials(sd, optval, optlen);
727 			if (retval != 0) {
728 				retval = slcb_SetErrno(retval);
729 				goto exit;
730 			}
731 			break;
732 		case TLS_HOSTNAME:
733 			retval = sl_SetSockOpt(sd, SL_SOL_SOCKET,
734 					       _SEC_DOMAIN_VERIF,
735 					       (const char *)optval, optlen);
736 			break;
737 		case TLS_PEER_VERIFY:
738 			if (optval) {
739 				/*
740 				 * Not currently supported. Verification
741 				 * is automatically performed if a CA
742 				 * certificate is set. We are returning
743 				 * success here to allow
744 				 * mqtt_client_tls_connect()
745 				 * to proceed, given it requires
746 				 * verification and it is indeed
747 				 * performed when the cert is set.
748 				 */
749 				if (*(uint32_t *)optval != 2U) {
750 					retval = slcb_SetErrno(ENOTSUP);
751 					goto exit;
752 				} else {
753 					retval = 0;
754 				}
755 			} else {
756 				retval = slcb_SetErrno(EINVAL);
757 				goto exit;
758 			}
759 			break;
760 		case TLS_CIPHERSUITE_LIST:
761 		case TLS_DTLS_ROLE:
762 			/* Not yet supported: */
763 			retval = slcb_SetErrno(ENOTSUP);
764 			goto exit;
765 		default:
766 			retval = slcb_SetErrno(EINVAL);
767 			goto exit;
768 		}
769 	} else {
770 		/* Can be SOL_SOCKET or TI specific: */
771 
772 		/* Note: this logic should match SimpleLink SDK's socket.c: */
773 		switch (optname) {
774 		case TCP_NODELAY:
775 			if (optval) {
776 				/* if user wishes to have TCP_NODELAY = FALSE,
777 				 * we return EINVAL and fail in the cases below.
778 				 */
779 				if (*(uint32_t *)optval) {
780 					retval = 0;
781 					goto exit;
782 				}
783 			}
784 			/* These sock opts aren't supported by the cc32xx
785 			 * network stack, so we ignore them and set errno to
786 			 * EINVAL in order to not break "off-the-shelf" BSD
787 			 * code.
788 			 */
789 		case SO_BROADCAST:
790 		case SO_REUSEADDR:
791 		case SO_SNDBUF:
792 			retval = slcb_SetErrno(EINVAL);
793 			goto exit;
794 		default:
795 			break;
796 		}
797 		retval = sl_SetSockOpt(sd, SL_SOL_SOCKET, optname, optval,
798 				       (SlSocklen_t)optlen);
799 	}
800 
801 	if (retval < 0) {
802 		retval = slcb_SetErrno(getErrno(retval));
803 	}
804 
805 exit:
806 	return retval;
807 }
808 
simplelink_getsockopt(void * obj,int level,int optname,void * optval,socklen_t * optlen)809 static int simplelink_getsockopt(void *obj, int level, int optname,
810 				 void *optval, socklen_t *optlen)
811 {
812 	int sd = OBJ_TO_SD(obj);
813 	int retval;
814 
815 	if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS) && level == SOL_TLS) {
816 		/* Handle Zephyr's SOL_TLS secure socket options: */
817 		switch (optname) {
818 		case TLS_SEC_TAG_LIST:
819 		case TLS_CIPHERSUITE_LIST:
820 		case TLS_CIPHERSUITE_USED:
821 			/* Not yet supported: */
822 			retval = slcb_SetErrno(ENOTSUP);
823 			goto exit;
824 		default:
825 			retval = slcb_SetErrno(EINVAL);
826 			goto exit;
827 		}
828 	} else {
829 		/* Can be SOL_SOCKET or TI specific: */
830 
831 		/* Note: this logic should match SimpleLink SDK's socket.c: */
832 		switch (optname) {
833 			/* TCP_NODELAY always set by the NWP, so return True */
834 		case TCP_NODELAY:
835 			if (optval) {
836 				(*(_u32 *)optval) = TRUE;
837 				retval = 0;
838 				goto exit;
839 			}
840 			/* These sock opts aren't supported by the cc32xx
841 			 * network stack, so we silently ignore them and set
842 			 * errno to EINVAL in order to not break "off-the-shelf"
843 			 * BSD code.
844 			 */
845 		case SO_BROADCAST:
846 		case SO_REUSEADDR:
847 		case SO_SNDBUF:
848 			retval = slcb_SetErrno(EINVAL);
849 			goto exit;
850 		default:
851 			break;
852 		}
853 		retval = sl_GetSockOpt(sd, SL_SOL_SOCKET, optname, optval,
854 				       (SlSocklen_t *)optlen);
855 	}
856 
857 	if (retval < 0) {
858 		retval = slcb_SetErrno(getErrno(retval));
859 	}
860 
861 exit:
862 	return retval;
863 }
864 
865 /* SimpleLink does not support flags in recv.
866  * However, to enable more Zephyr apps to use this socket_offload, rather than
867  * failing with ENOTSUP, we can closely emulate the MSG_DONTWAIT feature using
868  * SimpleLink socket options.
869  */
handle_recv_flags(int sd,int flags,bool set,int * nb_enabled)870 static int handle_recv_flags(int sd, int flags, bool set, int *nb_enabled)
871 {
872 	ssize_t retval = 0;
873 	SlSocklen_t optlen = sizeof(SlSockNonblocking_t);
874 	SlSockNonblocking_t enableOption;
875 
876 	if (flags & ZSOCK_MSG_PEEK) {
877 		retval = ENOTSUP;
878 	} else if (flags & ZSOCK_MSG_DONTWAIT) {
879 		if (set) {
880 			/* Get previous state, to restore later: */
881 			sl_GetSockOpt(sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING,
882 				      (_u8 *)&enableOption, &optlen);
883 			*nb_enabled = enableOption.NonBlockingEnabled;
884 
885 			/* Now, set to non_blocking if not already set: */
886 			if (!*nb_enabled) {
887 				enableOption.NonBlockingEnabled = 1;
888 				sl_SetSockOpt(sd, SL_SOL_SOCKET,
889 					      SL_SO_NONBLOCKING,
890 					      (_u8 *)&enableOption,
891 					      sizeof(enableOption));
892 			}
893 		} else {
894 			/* Restore socket to previous state: */
895 			enableOption.NonBlockingEnabled = *nb_enabled;
896 			sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING,
897 				      (_u8 *)&enableOption,
898 				      sizeof(enableOption));
899 		}
900 	}
901 
902 	return retval;
903 }
904 
simplelink_recvfrom(void * obj,void * buf,size_t len,int flags,struct sockaddr * from,socklen_t * fromlen)905 static ssize_t simplelink_recvfrom(void *obj, void *buf, size_t len, int flags,
906 				   struct sockaddr *from, socklen_t *fromlen)
907 {
908 	int sd = OBJ_TO_SD(obj);
909 	ssize_t retval;
910 	SlSockAddr_t *sl_addr;
911 	SlSockAddrIn_t sl_addr_in;
912 	SlSockAddrIn6_t sl_addr_in6;
913 	SlSocklen_t sl_addrlen;
914 	int nb_enabled;
915 
916 	retval = handle_recv_flags(sd, flags, TRUE, &nb_enabled);
917 
918 	if (!retval) {
919 		/* Translate to sl_RecvFrom() parameters: */
920 		if (fromlen != NULL) {
921 			sl_addr = translate_z_to_sl_addrlen(*fromlen,
922 							    &sl_addr_in,
923 							    &sl_addr_in6,
924 							    &sl_addrlen);
925 			retval = (ssize_t)sl_RecvFrom(sd, buf, len, 0, sl_addr,
926 						      &sl_addrlen);
927 		} else {
928 			retval = (ssize_t)sl_Recv(sd, buf, len, 0);
929 		}
930 
931 		handle_recv_flags(sd, flags, FALSE, &nb_enabled);
932 		if (retval >= 0) {
933 			if (fromlen != NULL) {
934 				/*
935 				 * Translate sl_addr into *addr and set
936 				 * *addrlen
937 				 */
938 				translate_sl_to_z_addr(sl_addr, sl_addrlen,
939 						       from, fromlen);
940 			}
941 		} else {
942 			retval = slcb_SetErrno(getErrno(retval));
943 		}
944 	} else {
945 		retval = slcb_SetErrno(retval);
946 	}
947 
948 	return retval;
949 }
950 
simplelink_sendto(void * obj,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)951 static ssize_t simplelink_sendto(void *obj, const void *buf, size_t len,
952 				 int flags, const struct sockaddr *to,
953 				 socklen_t tolen)
954 {
955 	int sd = OBJ_TO_SD(obj);
956 	ssize_t retval;
957 	SlSockAddr_t *sl_addr;
958 	SlSockAddrIn_t sl_addr_in;
959 	SlSockAddrIn6_t sl_addr_in6;
960 	SlSocklen_t sl_addrlen;
961 
962 	if (to != NULL) {
963 		/* Translate to sl_SendTo() parameters: */
964 		sl_addr = translate_z_to_sl_addrs(to, tolen, &sl_addr_in,
965 						  &sl_addr_in6, &sl_addrlen);
966 
967 		if (sl_addr == NULL) {
968 			retval = SL_RET_CODE_INVALID_INPUT;
969 			goto exit;
970 		}
971 
972 		retval = sl_SendTo(sd, buf, (uint16_t)len, flags,
973 				   sl_addr, sl_addrlen);
974 	} else {
975 		retval = (ssize_t)sl_Send(sd, buf, len, flags);
976 	}
977 
978 exit:
979 	if (retval < 0) {
980 		retval = slcb_SetErrno(getErrno(retval));
981 	}
982 
983 	return retval;
984 }
985 
simplelink_sendmsg(void * obj,const struct msghdr * msg,int flags)986 static ssize_t simplelink_sendmsg(void *obj, const struct msghdr *msg,
987 				  int flags)
988 {
989 	errno = -ENOTSUP;
990 	return -1;
991 }
992 
993 /* Adds address info entry to a list */
set_addr_info(const struct SlNetUtil_addrInfo_t * sl_ai,struct zsock_addrinfo ** res)994 static int set_addr_info(const struct SlNetUtil_addrInfo_t *sl_ai,
995 			 struct zsock_addrinfo **res)
996 {
997 	struct zsock_addrinfo *ai;
998 	struct sockaddr *ai_addr;
999 	int retval = 0;
1000 
1001 	ai = calloc(1, sizeof(struct zsock_addrinfo));
1002 	if (!ai) {
1003 		retval = DNS_EAI_MEMORY;
1004 		goto exit;
1005 	} else {
1006 		/* Now, alloc the embedded sockaddr struct: */
1007 		ai_addr = calloc(1, sizeof(struct sockaddr));
1008 		if (!ai_addr) {
1009 			retval = DNS_EAI_MEMORY;
1010 			free(ai);
1011 			goto exit;
1012 		}
1013 	}
1014 
1015 	/* Now, fill in the fields of res (addrinfo struct): */
1016 	ai->ai_family = (sl_ai->ai_family == SL_AF_INET6 ? AF_INET6 : AF_INET);
1017 	ai->ai_socktype = (sl_ai->ai_socktype == SLNETSOCK_SOCK_DGRAM ?
1018 		SOCK_DGRAM : SOCK_STREAM);
1019 	ai->ai_protocol = (sl_ai->ai_protocol == SLNETSOCK_PROTO_UDP ?
1020 		IPPROTO_UDP : IPPROTO_TCP);
1021 
1022 	/* Fill sockaddr struct fields based on family: */
1023 	if (ai->ai_family == AF_INET) {
1024 		SlNetSock_AddrIn_t *sl_addr =
1025 			(SlNetSock_AddrIn_t *)sl_ai->ai_addr;
1026 
1027 		net_sin(ai_addr)->sin_family = ai->ai_family;
1028 		net_sin(ai_addr)->sin_addr.s_addr = sl_addr->sin_addr.s_addr;
1029 		net_sin(ai_addr)->sin_port = sl_addr->sin_port;
1030 		ai->ai_addrlen = sizeof(struct sockaddr_in);
1031 	} else {
1032 		SlNetSock_AddrIn6_t *sl_addr =
1033 			(SlNetSock_AddrIn6_t *)sl_ai->ai_addr;
1034 
1035 		net_sin6(ai_addr)->sin6_family = ai->ai_family;
1036 		net_sin6(ai_addr)->sin6_addr.s6_addr32[0] =
1037 			sl_addr->sin6_addr._S6_un._S6_u32[0];
1038 		net_sin6(ai_addr)->sin6_addr.s6_addr32[1] =
1039 			sl_addr->sin6_addr._S6_un._S6_u32[1];
1040 		net_sin6(ai_addr)->sin6_addr.s6_addr32[2] =
1041 			sl_addr->sin6_addr._S6_un._S6_u32[2];
1042 		net_sin6(ai_addr)->sin6_addr.s6_addr32[3] =
1043 			sl_addr->sin6_addr._S6_un._S6_u32[3];
1044 		net_sin6(ai_addr)->sin6_port = sl_addr->sin6_port;
1045 		ai->ai_addrlen = sizeof(struct sockaddr_in6);
1046 	}
1047 	ai->ai_addr = ai_addr;
1048 	ai->ai_next = *res;
1049 	*res = ai;
1050 
1051 exit:
1052 	return retval;
1053 }
1054 
simplelink_getaddrinfo(const char * node,const char * service,const struct zsock_addrinfo * hints,struct zsock_addrinfo ** res)1055 static int simplelink_getaddrinfo(const char *node, const char *service,
1056 				  const struct zsock_addrinfo *hints,
1057 				  struct zsock_addrinfo **res)
1058 {
1059 	int32_t retval;
1060 	struct SlNetUtil_addrInfo_t sl_hints;
1061 	struct SlNetUtil_addrInfo_t *sl_res, *sl_ai;
1062 
1063 	/* Initialize sl_hints to the defaults */
1064 	memset(&sl_hints, 0, sizeof(sl_hints));
1065 
1066 	/* Check args: */
1067 	if (!res) {
1068 		retval = DNS_EAI_NONAME;
1069 		goto exit;
1070 	}
1071 
1072 	if (hints) {
1073 		/*
1074 		 * SlNetUtil only supports AI_NUMERICHOST and AI_PASSIVE, so
1075 		 * the rest are ignored.
1076 		 */
1077 		sl_hints.ai_flags |= ((hints->ai_flags & AI_PASSIVE) ?
1078 			SLNETUTIL_AI_PASSIVE : 0);
1079 		sl_hints.ai_flags |= ((hints->ai_flags & AI_NUMERICHOST) ?
1080 			SLNETUTIL_AI_NUMERICHOST : 0);
1081 		if (hints->ai_family == AF_UNSPEC) {
1082 			sl_hints.ai_family = SLNETSOCK_AF_UNSPEC;
1083 		} else {
1084 			sl_hints.ai_family = (hints->ai_family == AF_INET6 ?
1085 				SLNETSOCK_AF_INET6 : SLNETSOCK_AF_INET);
1086 		}
1087 		if (hints->ai_socktype == 0) {
1088 			sl_hints.ai_socktype = 0;
1089 		} else {
1090 			sl_hints.ai_socktype =
1091 				(hints->ai_socktype == SOCK_DGRAM ?
1092 				SLNETSOCK_SOCK_DGRAM : SLNETSOCK_SOCK_STREAM);
1093 		}
1094 		if (hints->ai_protocol == 0) {
1095 			sl_hints.ai_protocol = 0;
1096 		} else {
1097 			sl_hints.ai_protocol =
1098 				(hints->ai_protocol == IPPROTO_UDP ?
1099 				SLNETSOCK_PROTO_UDP : SLNETSOCK_PROTO_TCP);
1100 		}
1101 
1102 	}
1103 
1104 	/* Now, try to resolve host name: */
1105 	retval = SlNetUtil_getAddrInfo(SLNETIF_ID_1, node,
1106 		service, &sl_hints, &sl_res);
1107 
1108 	if (retval < 0) {
1109 		LOG_ERR("Could not resolve name: %s, retval: %d",
1110 			    node, retval);
1111 		retval = DNS_EAI_NONAME;
1112 		goto exit;
1113 	}
1114 
1115 	sl_ai = sl_res;
1116 	*res = NULL;
1117 	while (sl_ai != NULL) {
1118 		retval = set_addr_info(sl_ai, res);
1119 		if (retval < 0) {
1120 			LOG_ERR("Unable to set address info, retval: %d",
1121 				retval);
1122 			goto exit;
1123 		}
1124 		sl_ai = sl_ai->ai_next;
1125 	}
1126 	SlNetUtil_freeAddrInfo(sl_res);
1127 exit:
1128 	return retval;
1129 }
1130 
simplelink_freeaddrinfo(struct zsock_addrinfo * res)1131 static void simplelink_freeaddrinfo(struct zsock_addrinfo *res)
1132 {
1133 	__ASSERT_NO_MSG(res);
1134 
1135 	free(res->ai_addr);
1136 	free(res);
1137 }
1138 
simplelink_fcntl(int sd,int cmd,va_list args)1139 static int simplelink_fcntl(int sd, int cmd, va_list args)
1140 {
1141 	int retval = 0;
1142 	SlSockNonblocking_t enableOption;
1143 	SlSocklen_t optlen = sizeof(SlSockNonblocking_t);
1144 
1145 	switch (cmd) {
1146 	case F_GETFL:
1147 		retval = sl_GetSockOpt(sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING,
1148 			(_u8 *)&enableOption, &optlen);
1149 		if (retval == 0) {
1150 			if (enableOption.NonBlockingEnabled) {
1151 				retval |= O_NONBLOCK;
1152 			}
1153 		}
1154 		break;
1155 	case F_SETFL:
1156 		if ((va_arg(args, int) & O_NONBLOCK) != 0) {
1157 			enableOption.NonBlockingEnabled = 1;
1158 		} else {
1159 			enableOption.NonBlockingEnabled = 0;
1160 		}
1161 		retval = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING,
1162 			&enableOption, optlen);
1163 		break;
1164 	default:
1165 		LOG_ERR("Invalid command: %d", cmd);
1166 		retval = slcb_SetErrno(EINVAL);
1167 		goto exit;
1168 	}
1169 
1170 	if (retval < 0) {
1171 		retval = slcb_SetErrno(getErrno(retval));
1172 	}
1173 
1174 exit:
1175 	return retval;
1176 }
1177 
simplelink_ioctl(void * obj,unsigned int request,va_list args)1178 static int simplelink_ioctl(void *obj, unsigned int request, va_list args)
1179 {
1180 	int sd = OBJ_TO_SD(obj);
1181 
1182 	switch (request) {
1183 	case ZFD_IOCTL_POLL_PREPARE:
1184 		return -EXDEV;
1185 
1186 	case ZFD_IOCTL_POLL_UPDATE:
1187 		return -EOPNOTSUPP;
1188 
1189 	case ZFD_IOCTL_POLL_OFFLOAD: {
1190 		struct zsock_pollfd *fds;
1191 		int nfds;
1192 		int timeout;
1193 
1194 		fds = va_arg(args, struct zsock_pollfd *);
1195 		nfds = va_arg(args, int);
1196 		timeout = va_arg(args, int);
1197 
1198 		return simplelink_poll(fds, nfds, timeout);
1199 	}
1200 
1201 	/* Otherwise, just forward to offloaded fcntl()
1202 	 * In Zephyr, fcntl() is just an alias of ioctl().
1203 	 */
1204 	default:
1205 		return simplelink_fcntl(sd, request, args);
1206 	}
1207 }
1208 
simplelink_read(void * obj,void * buffer,size_t count)1209 static ssize_t simplelink_read(void *obj, void *buffer, size_t count)
1210 {
1211 	return simplelink_recvfrom(obj, buffer, count, 0, NULL, 0);
1212 }
1213 
simplelink_write(void * obj,const void * buffer,size_t count)1214 static ssize_t simplelink_write(void *obj, const void *buffer,
1215 					  size_t count)
1216 {
1217 	return simplelink_sendto(obj, buffer, count, 0, NULL, 0);
1218 }
1219 
1220 static const struct socket_op_vtable simplelink_socket_fd_op_vtable = {
1221 	.fd_vtable = {
1222 		.read = simplelink_read,
1223 		.write = simplelink_write,
1224 		.close = simplelink_close,
1225 		.ioctl = simplelink_ioctl,
1226 	},
1227 	.bind = simplelink_bind,
1228 	.connect = simplelink_connect,
1229 	.listen = simplelink_listen,
1230 	.accept = simplelink_socket_accept,
1231 	.sendto = simplelink_sendto,
1232 	.sendmsg = simplelink_sendmsg,
1233 	.recvfrom = simplelink_recvfrom,
1234 	.getsockopt = simplelink_getsockopt,
1235 	.setsockopt = simplelink_setsockopt,
1236 };
1237 
simplelink_is_supported(int family,int type,int proto)1238 static bool simplelink_is_supported(int family, int type, int proto)
1239 {
1240 	int dummy;
1241 	int err;
1242 
1243 	err = simplelink_socket_family_from_posix(family, &dummy);
1244 	if (err) {
1245 		return false;
1246 	}
1247 
1248 	err = simplelink_socket_type_from_posix(type, &dummy);
1249 	if (err) {
1250 		return false;
1251 	}
1252 
1253 	err = simplelink_socket_proto_from_zephyr(proto, &dummy);
1254 	if (err) {
1255 		return false;
1256 	}
1257 
1258 	return true;
1259 }
1260 
simplelink_socket_create(int family,int type,int proto)1261 int simplelink_socket_create(int family, int type, int proto)
1262 {
1263 	int fd = z_reserve_fd();
1264 	int sock;
1265 
1266 	if (fd < 0) {
1267 		return -1;
1268 	}
1269 
1270 	sock = simplelink_socket(family, type, proto);
1271 	if (sock < 0) {
1272 		z_free_fd(fd);
1273 		return -1;
1274 	}
1275 
1276 	z_finalize_fd(fd, SD_TO_OBJ(sock),
1277 		      (const struct fd_op_vtable *)
1278 					&simplelink_socket_fd_op_vtable);
1279 
1280 	return fd;
1281 }
1282 
simplelink_socket_accept(void * obj,struct sockaddr * addr,socklen_t * addrlen)1283 static int simplelink_socket_accept(void *obj, struct sockaddr *addr,
1284 			     socklen_t *addrlen)
1285 {
1286 	int fd = z_reserve_fd();
1287 	int sock;
1288 
1289 	if (fd < 0) {
1290 		return -1;
1291 	}
1292 
1293 	sock = simplelink_accept(obj, addr, addrlen);
1294 	if (sock < 0) {
1295 		z_free_fd(fd);
1296 		return -1;
1297 	}
1298 
1299 	z_finalize_fd(fd, SD_TO_OBJ(sock),
1300 		      (const struct fd_op_vtable *)
1301 					&simplelink_socket_fd_op_vtable);
1302 
1303 	return fd;
1304 }
1305 
1306 #ifdef CONFIG_NET_SOCKETS_OFFLOAD
1307 NET_SOCKET_OFFLOAD_REGISTER(simplelink, CONFIG_NET_SOCKETS_OFFLOAD_PRIORITY, AF_UNSPEC,
1308 			    simplelink_is_supported, simplelink_socket_create);
1309 #endif
1310 
simplelink_sockets_init(void)1311 void simplelink_sockets_init(void)
1312 {
1313 }
1314 
1315 const struct socket_dns_offload simplelink_dns_ops = {
1316 	.getaddrinfo = simplelink_getaddrinfo,
1317 	.freeaddrinfo = simplelink_freeaddrinfo,
1318 };
1319