1COAP_ENDPOINT_SERVER(3)         libcoap Manual         COAP_ENDPOINT_SERVER(3)
2
3
4

NAME

6       coap_endpoint_server, coap_context_set_pki,
7       coap_context_set_pki_root_cas, coap_context_set_psk2,
8       coap_new_endpoint, coap_free_endpoint, coap_endpoint_set_default_mtu,
9       coap_join_mcast_group_intf, coap_mcast_per_resource - Work with CoAP
10       server endpoints
11

SYNOPSIS

13       #include <coap3/coap.h>
14
15       int coap_context_set_pki(coap_context_t *context, const coap_dtls_pki_t
16       *setup_data);
17
18       int coap_context_set_pki_root_cas(coap_context_t *context, const char
19       *ca_file, const char *ca_dir);
20
21       int coap_context_set_psk2(coap_context_t *context, coap_dtls_spsk_t
22       *setup_data);
23
24       coap_endpoint_t *coap_new_endpoint(coap_context_t *context, const
25       coap_address_t *listen_addr, coap_proto_t proto);
26
27       void coap_free_endpoint(coap_endpoint_t *endpoint);
28
29       void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned
30       mtu);
31
32       int coap_join_mcast_group_intf(coap_context_t *context, const char
33       *groupname, const char *ifname);
34
35       void coap_mcast_per_resource(coap_context_t *context);
36
37       For specific (D)TLS library support, link with -lcoap-3-notls,
38       -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls or
39       -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default
40       (D)TLS library support.
41

DESCRIPTION

43       This man page focuses on the setting up of a CoAP server endpoint. For
44       a CoAP client endpoint, see coap_endpoint_client(3).
45
46       The CoAP stack’s global state is stored in a coap_context_t context
47       object. Resources, Endpoints and Sessions are associated with this
48       context object. There can be more than one coap_context_t object per
49       application, it is up to the application to manage each one
50       accordingly.
51
52       A CoAP session maintains the state of an ongoing connection between a
53       Client and Server which is stored in a coap_session_t session object. A
54       CoAP session is tracked by local port, CoAP protocol, remote IP address
55       and remote port, or in the case of Unix Domain sockets, the local path
56       and the remote path.
57
58       The session network traffic can be encrypted or un-encrypted if there
59       is an underlying TLS library.
60
61       If (D)TLS is going to be used for encrypting the network traffic, then
62       the (D)TLS information for Pre-Shared Keys (PSK) or Public Key
63       Infrastructure (PKI) needs to be configured before any network traffic
64       starts to flow. For Servers, this has to be done before the Endpoint is
65       created.
66
67       For Servers, all the encryption information is held internally by the
68       (D)TLS context level and the CoAP context level as the Server is
69       listening for new incoming traffic based on the Endpoint definition.
70       The (D)TLS and CoAP session will not get built until the new traffic
71       starts, which is done by the libcoap library.
72
73       In principle the set-up sequence for CoAP Servers looks like
74
75           coap_new_context()
76           coap_context_set_pki_root_cas() - if the root CAs need to be updated and using PKI
77           coap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required
78           coap_new_endpoint()
79
80       Multiple endpoints can be set up per context, each listening for a new
81       traffic flow with different TCP/UDP protocols, (D)TLS protocols, port
82       numbers, Unix pathnames etc. When a new traffic flow is started, then
83       the CoAP library will create and start a new server session.
84

FUNCTIONS

86       Function: coap_context_set_pki()
87
88       The coap_context_set_pki() function, for a specific context, is used to
89       configure the (D)TLS context using the setup_data PKI variables as
90       defined in the coap_dtls_pki_t structure - see coap_encryption(3).
91
92       Function: coap_context_set_pki_root_cas()
93
94       The coap_context_set_pki_root_cas() function is used to define a set of
95       root CAs to be used instead of the default set of root CAs provided as
96       a part of the TLS library. ca_file points to a PEM encoded file
97       containing the list of CAs. ca_file can be NULL. ca_dir points to a
98       directory containing a set of PEM encoded files containing rootCAs.
99       ca_dir can be NULL. One or both of ca_file and ca_dir must be set.
100       NOTE: Some TLS libraries send the full list of CAs added by this
101       function during the (D)TLS session setup handshakes. To stop this,
102       either provide a single CA using the ca_file definition in pki_key in
103       setup_data variable when calling coap_context_set_pki(), or set
104       check_common_ca to 0 in setup_data variable. See coap_encryption(3).
105
106       Function: coap_context_set_psk2()
107
108       The coap_context_set_psk2() function is used to configure the (D)TLS
109       context using the setup_data PSK variables as defined in the
110       coap_dtls_spsk_t structure - see coap_encryption(3). This function can
111       only be used for servers as setup_data provides a hint, not an
112       identity.
113
114       Function: coap_new_endpoint()
115
116       The coap_new_endpoint() function creates a new endpoint for context
117       that is listening for new traffic as defined in listen_addr (see
118       coap_address_t(3)). If the address family is AF_INET or AF_INET6, then
119       it listens on the IP address and port number defined by listen_addr. If
120       the port number is 0, then the default CoAP port is used. If the
121       address family is AF_UNIX, then it listens on the defined unix domain
122       path which has to be unique per endpoint. This unique unix domain path
123       will get deleted on clean application exit.
124
125       Different CoAP protocols can be defined for proto - the current
126       supported list is:
127
128           COAP_PROTO_UDP
129           COAP_PROTO_DTLS
130           COAP_PROTO_TCP
131           COAP_PROTO_TLS
132           COAP_PROTO_WS
133           COAP_PROTO_WSS
134
135       coap_tcp_is_supported(3), coap_dtls_is_supported(3),
136       coap_tls_is_supported(3), coap_ws_is_supported(3) and
137       coap_wss_is_supported(3) can be used for checking whether the
138       underlying TCP, (D)TLS or WebSocket protocol support is available. See
139       coap_tls_library(3) for further information on the types of (D)TLS
140       sessions supported.
141
142       When traffic starts to come in from a client, a server CoAP session is
143       created associated with this endpoint. This CoAP session is created
144       with a reference count of 0. This means that if the server session is
145       not used for 5 minutes, then it will get completely freed off. See
146       coap_session_reference(3) and coap_session_release(3) for further
147       information.
148
149       Function: coap_free_endpoint()
150
151       The coap_free_endpoint() function must be used to free off the
152       endpoint. It clears out all the sessions associated with this endpoint
153       along with any data associated with the sessions as well as deleting
154       the unix domain path if the address family is AF_UNIX.
155
156       Function: coap_endpoint_set_default_mtu()
157
158       The coap_endpoint_set_default_mtu() function is used to set the MTU
159       size (the maximum message size) of the data in a packet, excluding any
160       IP or TCP/UDP overhead to mtu for the endpoint. A sensible default is
161       1280.
162
163       Function: coap_join_mcast_group_intf()
164
165       The coap_join_mcast_group_intf() function is used to join the currently
166       defined endpoints that are UDP, associated with context, to the defined
167       multicast group groupname. If ifname is not NULL, then the multicast
168       group is associated with this interface, otherwise the underlying O/S
169       will choose the first appropriate interface. When the endpoint is freed
170       off, the associated multicast group will be removed. The registered
171       multicast addresses for CoAP are 224.0.1.187, ff0x::fd (Variable-Scope)
172       - i.e. ff02::fd (Link-Local) and ff05::fd (Site-Local).
173
174       NOTE: multicast is not supported for address family type AF_UNIX.
175
176       Function: coap_mcast_per_resource()
177
178       The coap_mcast_per_resource() function enables mcast to be controlled
179       on a per resource basis giving the server application flexibility in
180       how to respond to mcast requests. With this enabled, this is done
181       through additional flag definitions when setting up each resource. See
182       coap_resource(3).
183

RETURN VALUES

185       coap_context_set_pki(), coap_context_set_pki_root_cas() and
186       coap_context_set_psk2() return 1 on success, 0 on failure.
187
188       coap_new_endpoint() returns a newly created endpoint or NULL if there
189       is a creation failure.
190
191       coap_join_mcast_group_intf() returns 0 on success, -1 on failure.
192

EXAMPLES

194       CoAP Server Non-Encrypted Setup
195
196           #include <coap3/coap.h>
197
198           static coap_context_t *
199           setup_server_context (void) {
200             coap_endpoint_t *endpoint;
201             coap_address_t listen_addr;
202             coap_context_t *context = coap_new_context(NULL);
203
204             if (!context)
205               return NULL;
206             /* See coap_block(3) */
207             coap_context_set_block_mode(context,
208                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
209
210
211             /* See coap_address(3) */
212             coap_address_init(&listen_addr);
213             listen_addr.addr.sa.sa_family = AF_INET;
214             listen_addr.addr.sin.sin_port = htons (5683);
215
216             endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP);
217             if (!endpoint) {
218               coap_free_context(context);
219               return NULL;
220             }
221
222             /* Initialize resources - See coap_resource(3) init_resources() example */
223
224             return context;
225           }
226
227       CoAP Server Non-Encrypted Unix Domain Setup
228
229           #include <coap3/coap.h>
230
231           #include <stdio.h>
232           #include <unistd.h>
233
234           /* This need to be unique per endpoint */
235           #define UNIX_DOMAIN_LISTEN_DGRAM "/tmp/server.dgram"
236
237           static coap_context_t *
238           setup_server_context (void) {
239             coap_endpoint_t *endpoint;
240             coap_address_t listen_addr;
241             coap_context_t *context = coap_new_context(NULL);
242
243             if (!context)
244               return NULL;
245             /* See coap_block(3) */
246             coap_context_set_block_mode(context,
247                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
248
249
250             /* See coap_address(3) */
251             coap_address_set_unix_domain(&listen_addr,
252                                   (const uint8_t *)UNIX_DOMAIN_LISTEN_DGRAM,
253                                    strlen(UNIX_DOMAIN_LISTEN_DGRAM));
254             /* Only do this if you know it is safe to do so */
255             unlink(listen_addr.addr.cun.sun_path);
256
257             endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP);
258             if (!endpoint) {
259               coap_free_context(context);
260               return NULL;
261             }
262
263             /* Initialize resources - See coap_resource(3) init_resources() example */
264
265             return context;
266           }
267
268       CoAP Server DTLS PKI Setup
269
270           #include <coap3/coap.h>
271
272           typedef struct valid_cns_t {
273             size_t count;
274             char **cn_list;
275           } valid_cns_t;
276
277           /*
278            * Common Name (CN) Callback verifier
279            */
280           static int
281           verify_cn_callback(const char *cn,
282                              const uint8_t *asn1_public_cert,
283                              size_t asn1_length,
284                              coap_session_t *c_session,
285                              unsigned depth,
286                              int validated,
287                              void *arg
288           ) {
289             valid_cns_t *valid_cn_list = (valid_cns_t*)arg;
290             size_t i;
291             /* Remove (void) definition if variable is used */
292             (void)asn1_public_cert;
293             (void)asn1_length;
294             (void)c_session;
295             (void)depth;
296             (void)validated;
297
298             /* Check that the CN is valid */
299             for (i = 0; i < valid_cn_list->count; i++) {
300               if (!strcasecmp(cn, valid_cn_list->cn_list[i])) {
301                 return 1;
302               }
303             }
304             return 0;
305           }
306
307           typedef struct sni_def_t {
308             char* sni;
309             coap_dtls_key_t key;
310           } sni_def_t;
311
312           typedef struct valid_snis_t {
313             size_t count;
314             sni_def_t *sni_list;
315           } valid_snis_t;
316
317           /*
318            * Subject Name Identifier (SNI) callback verifier
319            */
320           static coap_dtls_key_t *
321           verify_pki_sni_callback(const char *sni,
322                                   void *arg
323           ) {
324             valid_snis_t *valid_sni_list = (valid_snis_t *)arg;
325             size_t i;
326
327             /* Check that the SNI is valid */
328             for (i = 0; i < valid_sni_list->count; i++) {
329               if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
330                 return &valid_sni_list->sni_list[i].key;
331               }
332             }
333             return NULL;
334           }
335
336           /*
337            * Set up PKI encryption information
338            */
339           static coap_context_t *
340           setup_server_context_pki (const char *public_cert_file,
341                                     const char *private_key_file,
342                                     const char *ca_file,
343                                     valid_cns_t *valid_cn_list,
344                                     valid_snis_t *valid_sni_list
345           ) {
346             coap_endpoint_t *endpoint;
347             coap_address_t listen_addr;
348             coap_dtls_pki_t dtls_pki;
349             coap_context_t *context;
350
351             /* See coap_tls_library(3) */
352             if (!coap_dtls_is_supported())
353               return NULL;
354
355             context = coap_new_context(NULL);
356             if (!context)
357               return NULL;
358             /* See coap_block(3) */
359             coap_context_set_block_mode(context,
360                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
361
362
363             memset (&dtls_pki, 0, sizeof (dtls_pki));
364
365             /* see coap_encryption(3) */
366             dtls_pki.version                 = COAP_DTLS_PKI_SETUP_VERSION;
367             dtls_pki.verify_peer_cert        = 1;
368             dtls_pki.check_common_ca         = 1;
369             dtls_pki.allow_self_signed       = 1;
370             dtls_pki.allow_expired_certs     = 1;
371             dtls_pki.cert_chain_validation   = 1;
372             dtls_pki.cert_chain_verify_depth = 1;
373             dtls_pki.check_cert_revocation   = 1;
374             dtls_pki.allow_no_crl            = 1;
375             dtls_pki.allow_expired_crl       = 1;
376             dtls_pki.allow_bad_md_hash       = 0;
377             dtls_pki.allow_short_rsa_length  = 0;
378             dtls_pki.is_rpk_not_cert         = 0; /* Set to 1 if RPK */
379             dtls_pki.validate_cn_call_back   = verify_cn_callback;
380             dtls_pki.cn_call_back_arg        = valid_cn_list;
381             dtls_pki.validate_sni_call_back  = verify_pki_sni_callback;
382             dtls_pki.sni_call_back_arg       = valid_sni_list;
383             dtls_pki.additional_tls_setup_call_back = NULL;
384             dtls_pki.client_sni              = NULL;
385             dtls_pki.pki_key.key_type        = COAP_PKI_KEY_PEM;
386             dtls_pki.pki_key.key.pem.ca_file = ca_file;
387             dtls_pki.pki_key.key.pem.public_cert = public_cert_file;
388             dtls_pki.pki_key.key.pem.private_key = private_key_file;
389
390             if (coap_context_set_pki(context, &dtls_pki)) {
391               coap_free_context(context);
392               return NULL;
393             }
394
395             /* See coap_address(3) */
396             coap_address_init(&listen_addr);
397             listen_addr.addr.sa.sa_family = AF_INET;
398             listen_addr.addr.sin.sin_port = htons (5684);
399
400             endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
401             if (!endpoint) {
402               coap_free_context(context);
403               return NULL;
404             }
405
406             /* Initialize resources - See coap_resource(3) init_resources() example */
407
408             return context;
409           }
410
411       CoAP Server DTLS PSK Setup
412
413           #include <coap3/coap.h>
414
415           typedef struct id_def_t {
416             char* id;
417             coap_bin_const_t key;
418           } id_def_t;
419
420           typedef struct valid_ids_t {
421             int count;
422             id_def_t *id_list;
423           } valid_ids_t;
424
425           /*
426            * PSK Identity Pre-Shared Key selection Callback function
427            */
428           static const coap_bin_const_t *
429           verify_id_callback(coap_bin_const_t *identity,
430                              coap_session_t *c_session,
431                              void *arg
432           ) {
433             valid_ids_t *valid_id_list = (valid_ids_t*)arg;
434             int i;
435             /* Remove (void) definition if variable is used */
436             (void)c_session;
437
438             /* Check that the Identity is valid */
439             for (i = 0; i < valid_id_list->count; i++) {
440               if (!strcasecmp((const char*)identity->s, valid_id_list->id_list[i].id)) {
441                 return &valid_id_list->id_list[i].key;
442               }
443             }
444             return NULL;
445           }
446
447           typedef struct sni_psk_def_t {
448             char* sni;
449             coap_dtls_spsk_info_t psk_info;
450           } sni_psk_def_t;
451
452           typedef struct valid_psk_snis_t {
453             int count;
454             sni_psk_def_t *sni_list;
455           } valid_psk_snis_t;
456
457           /*
458            * PSK Subject Name Identifier (SNI) callback verifier
459            */
460           static const coap_dtls_spsk_info_t *
461           verify_psk_sni_callback(const char *sni,
462                                   coap_session_t *c_session,
463                                   void *arg
464           ) {
465             valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg;
466             int i;
467             /* Remove (void) definition if variable is used */
468             (void)c_session;
469
470             /* Check that the SNI is valid */
471             for (i = 0; i < valid_sni_list->count; i++) {
472               if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) {
473                 return &valid_sni_list->sni_list[i].psk_info;
474               }
475             }
476             return NULL;
477           }
478
479           static coap_context_t *
480           setup_server_context_psk (const char *hint,
481                                     const uint8_t *key,
482                                     unsigned int key_len,
483                                     valid_ids_t *valid_id_list,
484                                     valid_psk_snis_t *valid_sni_list
485           ) {
486             coap_endpoint_t *endpoint;
487             coap_address_t listen_addr;
488             coap_context_t *context;
489             coap_dtls_spsk_t dtls_psk;
490
491             /* See coap_tls_library(3) */
492             if (!coap_dtls_is_supported())
493               return NULL;
494
495             context = coap_new_context(NULL);
496             if (!context)
497               return NULL;
498             /* See coap_block(3) */
499             coap_context_set_block_mode(context,
500                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
501
502
503             memset (&dtls_psk, 0, sizeof (dtls_psk));
504
505             /* see coap_encryption(3) */
506             dtls_psk.version                 = COAP_DTLS_SPSK_SETUP_VERSION;
507             dtls_psk.validate_id_call_back   = verify_id_callback;
508             dtls_psk.id_call_back_arg        = valid_id_list;
509             dtls_psk.validate_sni_call_back  = verify_psk_sni_callback;
510             dtls_psk.sni_call_back_arg       = valid_sni_list;
511             dtls_psk.psk_info.hint.s         = (const uint8_t*)hint;
512             dtls_psk.psk_info.hint.length    = hint ? strlen(hint) : 0;
513             dtls_psk.psk_info.key.s          = key;
514             dtls_psk.psk_info.key.length     = key_len;
515
516             if (coap_context_set_psk2(context, &dtls_psk)) {
517               coap_free_context(context);
518               return NULL;
519             }
520
521             /* See coap_address(3) */
522             coap_address_init(&listen_addr);
523             listen_addr.addr.sa.sa_family = AF_INET;
524             listen_addr.addr.sin.sin_port = htons (5684);
525
526             endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS);
527             if (!endpoint) {
528               coap_free_context(context);
529               return NULL;
530             }
531
532             /* Initialize resources - See coap_resource(3) init_resources() example */
533
534             return context;
535           }
536

SEE ALSO

538       coap_address(3), coap_block(3), coap_context(3), coap_encryption(3),
539       coap_endpoint_client(3), coap_resource(3), coap_session(3) and
540       coap_tls_library(3)
541

FURTHER INFORMATION

543       See
544
545       "RFC7252: The Constrained Application Protocol (CoAP)"
546
547       "RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and
548       WebSockets"
549
550       for further information.
551

BUGS

553       Please report bugs on the mailing list for libcoap:
554       libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
555       https://github.com/obgm/libcoap/issues
556

AUTHORS

558       The libcoap project <libcoap-developers@lists.sourceforge.net>
559
560
561
562coap_endpoint_server 4.3.4        10/09/2023           COAP_ENDPOINT_SERVER(3)
Impressum