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