1.. _bsd_sockets_interface:
2
3BSD Sockets
4###########
5
6.. contents::
7    :local:
8    :depth: 2
9
10Overview
11********
12
13Zephyr offers an implementation of a subset of the BSD Sockets API (a part
14of the POSIX standard). This API allows to reuse existing programming experience
15and port existing simple networking applications to Zephyr.
16
17Here are the key requirements and concepts which governed BSD Sockets
18compatible API implementation for Zephyr:
19
20* Has minimal overhead, similar to the requirement for other
21  Zephyr subsystems.
22* Is namespaced by default, to avoid name conflicts with well-known
23  names like ``close()``, which may be part of libc or other POSIX
24  compatibility libraries.
25  If enabled by :kconfig:option:`CONFIG_POSIX_API`, it will also
26  expose native POSIX names.
27
28BSD Sockets compatible API is enabled using :kconfig:option:`CONFIG_NET_SOCKETS`
29config option and implements the following operations: ``socket()``, ``close()``,
30``recv()``, ``recvfrom()``, ``send()``, ``sendto()``, ``connect()``, ``bind()``,
31``listen()``, ``accept()``, ``fcntl()`` (to set non-blocking mode),
32``getsockopt()``, ``setsockopt()``, ``poll()``, ``select()``,
33``getaddrinfo()``, ``getnameinfo()``.
34
35Based on the namespacing requirements above, these operations are by
36default exposed as functions with ``zsock_`` prefix, e.g.
37:c:func:`zsock_socket` and :c:func:`zsock_close`. If the config option
38:kconfig:option:`CONFIG_POSIX_API` is defined, all the functions
39will be also exposed as aliases without the prefix. This includes the
40functions like ``close()`` and ``fcntl()`` (which may conflict with
41functions in libc or other libraries, for example, with the filesystem
42libraries).
43
44Another entailment of the design requirements above is that the Zephyr
45API aggressively employs the short-read/short-write property of the POSIX API
46whenever possible (to minimize complexity and overheads). POSIX allows
47for calls like ``recv()`` and ``send()`` to actually process (receive
48or send) less data than requested by the user (on ``SOCK_STREAM`` type
49sockets). For example, a call ``recv(sock, 1000, 0)`` may return 100,
50meaning that only 100 bytes were read (short read), and the application
51needs to retry call(s) to receive the remaining 900 bytes.
52
53The BSD Sockets API uses file descriptors to represent sockets. File
54descriptors are small integers, consecutively assigned from zero, shared
55among sockets, files, special devices (like stdin/stdout), etc. Internally,
56there is a table mapping file descriptors to internal object pointers.
57The file descriptor table is used by the BSD Sockets API even if the rest
58of the POSIX subsystem (filesystem, stdin/stdout) is not enabled.
59
60See :zephyr:code-sample:`sockets-echo-server` and :zephyr:code-sample:`sockets-echo-client`
61sample applications to learn how to create a simple server or client BSD socket based
62application.
63
64.. _secure_sockets_interface:
65
66Secure Sockets
67**************
68
69Zephyr provides an extension of standard POSIX socket API, allowing to create
70and configure sockets with TLS protocol types, facilitating secure
71communication. Secure functions for the implementation are provided by
72mbedTLS library. Secure sockets implementation allows use of both TLS and DTLS
73protocols with standard socket calls. See :c:enum:`net_ip_protocol_secure` type
74for supported secure protocol versions.
75
76To enable secure sockets, set the :kconfig:option:`CONFIG_NET_SOCKETS_SOCKOPT_TLS`
77option. To enable DTLS support, use :kconfig:option:`CONFIG_NET_SOCKETS_ENABLE_DTLS`
78option.
79
80.. _sockets_tls_credentials_subsys:
81
82TLS credentials subsystem
83=========================
84
85TLS credentials must be registered in the system before they can be used with
86secure sockets. See :c:func:`tls_credential_add` for more information.
87
88When a specific TLS credential is registered in the system, it is assigned with
89numeric value of type :c:type:`sec_tag_t`, called a tag. This value can be used
90later on to reference the credential during secure socket configuration with
91socket options.
92
93The following TLS credential types can be registered in the system:
94
95- ``TLS_CREDENTIAL_CA_CERTIFICATE``
96- ``TLS_CREDENTIAL_SERVER_CERTIFICATE``
97- ``TLS_CREDENTIAL_PRIVATE_KEY``
98- ``TLS_CREDENTIAL_PSK``
99- ``TLS_CREDENTIAL_PSK_ID``
100
101An example registration of CA certificate (provided in ``ca_certificate``
102array) looks like this:
103
104.. code-block:: c
105
106   ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
107                            ca_certificate, sizeof(ca_certificate));
108
109By default certificates in DER format are supported. PEM support can be enabled
110in mbedTLS settings.
111
112Secure Socket Creation
113======================
114
115A secure socket can be created by specifying secure protocol type, for instance:
116
117.. code-block:: c
118
119   sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
120
121Once created, it can be configured with socket options. For instance, the
122CA certificate and hostname can be set:
123
124.. code-block:: c
125
126   sec_tag_t sec_tag_opt[] = {
127           CA_CERTIFICATE_TAG,
128   };
129
130   ret = setsockopt(sock, SOL_TLS, TLS_SEC_TAG_LIST,
131                    sec_tag_opt, sizeof(sec_tag_opt));
132
133.. code-block:: c
134
135   char host[] = "google.com";
136
137   ret = setsockopt(sock, SOL_TLS, TLS_HOSTNAME, host, sizeof(host));
138
139Once configured, socket can be used just like a regular TCP socket.
140
141Several samples in Zephyr use secure sockets for communication. For a sample use
142see e.g. :zephyr:code-sample:`echo-server sample application <sockets-echo-server>` or
143:zephyr:code-sample:`HTTP GET sample application <sockets-http-get>`.
144
145Secure Sockets options
146======================
147
148Secure sockets offer the following options for socket management:
149
150.. doxygengroup:: secure_sockets_options
151
152Socket offloading
153*****************
154
155Zephyr allows to register custom socket implementations (called offloaded
156sockets). This allows for seamless integration for devices which provide an
157external IP stack and expose socket-like API.
158
159Socket offloading can be enabled with :kconfig:option:`CONFIG_NET_SOCKETS_OFFLOAD`
160option. A network driver that wants to register a new socket implementation
161should use :c:macro:`NET_SOCKET_OFFLOAD_REGISTER` macro. The macro accepts the
162following parameters:
163
164 * ``socket_name``
165     An arbitrary name for the socket implementation.
166
167 * ``prio``
168     Socket implementation's priority. The higher the priority, the earlier this
169     particular implementation will be processed when creating a new socket.
170     Lower numeric value indicates higher priority.
171
172 * ``_family``
173     Socket family implemented by the offloaded socket. ``AF_UNSPEC`` indicates
174     any family.
175
176 * ``_is_supported``
177     A filtering function, used to verify whether a particular socket family,
178     type and protocol are supported by the offloaded socket implementation.
179
180 * ``_handler``
181     A function compatible with :c:func:`socket` API, used to create an
182     offloaded socket.
183
184Every offloaded socket implementation should also implement a set of socket
185APIs, specified in :c:struct:`socket_op_vtable` struct.
186
187The function registered for socket creation should allocate a new file
188descriptor using :c:func:`zvfs_reserve_fd` function. Any additional actions,
189specific to the creation of a particular offloaded socket implementation,
190should take place after the file descriptor is allocated. As a final step,
191if the offloaded socket was created successfully, the file descriptor should
192be finalized with :c:func:`zvfs_finalize_typed_fd`, or :c:func:`zvfs_finalize_fd`
193functions. The finalize function allows to register a
194:c:struct:`socket_op_vtable` structure implementing socket APIs for an
195offloaded socket along with an optional socket context data pointer.
196
197Finally, when an offloaded network interface is initialized, it should indicate
198that the interface is offloaded with :c:func:`net_if_socket_offload_set`
199function. The function registers the function used to create an offloaded socket
200(the same as the one provided in :c:macro:`NET_SOCKET_OFFLOAD_REGISTER`) at the
201network interface.
202
203Offloaded socket creation
204=========================
205
206When application creates a new socket with :c:func:`socket` function, the
207network stack iterates over all registered socket implementations (native and
208offloaded). Higher priority socket implementations are processed first.
209For each registered socket implementation, an address family is verified, and if
210it matches (or the socket was registered as ``AF_UNSPEC``), the corresponding
211``_is_supported`` function is called to verify the remaining socket parameters.
212The first implementation that fulfills the socket requirements (i. e.
213``_is_supported`` returns true) will create a new socket with its ``_handler``
214function.
215
216The above indicates the importance of the socket priority. If multiple socket
217implementations support the same set of socket family/type/protocol, the first
218implementation processed by the system will create a socket. Therefore it's
219important to give the highest priority to the implementation that should be the
220system default.
221
222The socket priority for native socket implementation is configured with Kconfig.
223Use :kconfig:option:`CONFIG_NET_SOCKETS_TLS_PRIORITY` to set the priority for
224the native TLS sockets.
225Use :kconfig:option:`CONFIG_NET_SOCKETS_PRIORITY_DEFAULT` to set the priority
226for the remaining native sockets.
227
228Dealing with multiple offloaded interfaces
229==========================================
230
231As the :c:func:`socket` function does not allow to specify which network
232interface should be used by a socket, it's not possible to choose a specific
233implementation in case multiple offloaded socket implementations, supporting the
234same type of sockets, are available. The same problem arises when both native
235and offloaded sockets are available in the system.
236
237To address this problem, a special socket implementation (called socket
238dispatcher) was introduced. The sole reason for this module is to postpone the
239socket creation for until the first operation on a socket is performed. This
240leaves an opening to use ``SO_BINDTODEVICE`` socket option, to bind a socket to
241a particular network interface (and thus offloaded socket implementation).
242The socket dispatcher can be enabled with :kconfig:option:`CONFIG_NET_SOCKETS_OFFLOAD_DISPATCHER`
243Kconfig option.
244
245When enabled, the application can specify the network interface to use with
246:c:func:`setsockopt` function:
247
248.. code-block:: c
249
250   /* A "dispatcher" socket is created */
251   sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
252
253   struct ifreq ifreq = {
254      .ifr_name = "SimpleLink"
255   };
256
257   /* The socket is "dispatched" to a particular network interface
258    * (offloaded or not).
259    */
260   setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq));
261
262Similarly, if TLS is supported by both native and offloaded sockets,
263``TLS_NATIVE`` socket option can be used to indicate that a native TLS socket
264should be created. The underlying socket can then be bound to a particular
265network interface:
266
267.. code-block:: c
268
269   /* A "dispatcher" socket is created */
270   sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
271
272   int tls_native = 1;
273
274   /* The socket is "dispatched" to a native TLS socket implmeentation.
275    * The underlying socket is a "dispatcher" socket now.
276    */
277   setsockopt(sock, SOL_TLS, TLS_NATIVE, &tls_native, sizeof(tls_native));
278
279   struct ifreq ifreq = {
280      .ifr_name = "SimpleLink"
281   };
282
283   /* The underlying socket is "dispatched" to a particular network interface
284    * (offloaded or not).
285    */
286   setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq));
287
288In case no ``SO_BINDTODEVICE`` socket option is used on a socket, the socket
289will be dispatched according to the default priority and filtering rules on a
290first socket API call.
291
292API Reference
293*************
294
295BSD Sockets
296===========
297
298.. doxygengroup:: bsd_sockets
299
300TLS Credentials
301===============
302
303.. doxygengroup:: tls_credentials
304