1COAP_ENDPOINT_SERVER(3) libcoap Manual COAP_ENDPOINT_SERVER(3)
2
3
4
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
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
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
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
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
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
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
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
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
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)