1// -*- mode:doc; -*- 2// vim: set syntax=asciidoc tw=0 3 4coap_endpoint_server(3) 5======================= 6:doctype: manpage 7:man source: coap_endpoint_server 8:man version: @PACKAGE_VERSION@ 9:man manual: libcoap Manual 10 11NAME 12---- 13coap_endpoint_server, 14coap_context_set_pki, 15coap_context_set_pki_root_cas, 16coap_context_set_psk2, 17coap_new_endpoint, 18coap_free_endpoint, 19coap_endpoint_set_default_mtu, 20coap_join_mcast_group_intf, 21coap_mcast_per_resource 22- Work with CoAP server endpoints 23 24SYNOPSIS 25-------- 26*#include <coap@LIBCOAP_API_VERSION@/coap.h>* 27 28*int coap_context_set_pki(coap_context_t *_context_, 29const coap_dtls_pki_t *_setup_data_);* 30 31*int coap_context_set_pki_root_cas(coap_context_t *_context_, 32const char *_ca_file_, const char *_ca_dir_);* 33 34*int coap_context_set_psk2(coap_context_t *_context_, 35coap_dtls_spsk_t *setup_data);* 36 37*coap_endpoint_t *coap_new_endpoint(coap_context_t *_context_, 38const coap_address_t *_listen_addr_, coap_proto_t _proto_);* 39 40*void coap_free_endpoint(coap_endpoint_t *_endpoint_);* 41 42*void coap_endpoint_set_default_mtu(coap_endpoint_t *_endpoint_, 43unsigned _mtu_);* 44 45*int coap_join_mcast_group_intf(coap_context_t *_context_, 46const char *_groupname_, const char *_ifname_);* 47 48*void coap_mcast_per_resource(coap_context_t *_context_);* 49 50For specific (D)TLS library support, link with 51*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, 52*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* 53or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with 54*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. 55 56DESCRIPTION 57----------- 58This man page focuses on the setting up of a CoAP server endpoint. For a CoAP 59client endpoint, see *coap_endpoint_client*(3). 60 61The CoAP stack's global state is stored in a coap_context_t _context_ object. 62Resources, Endpoints and Sessions are associated with this _context_ object. 63There can be more than one coap_context_t object per application, it is up to 64the application to manage each one accordingly. 65 66A CoAP _session_ maintains the state of an ongoing connection between a Client 67and Server which is stored in a coap_session_t _session_ object. A CoAP 68_session_ is tracked by local port, CoAP protocol, remote IP address and 69remote port, or in the case of Unix Domain sockets, the local path and the 70remote path. 71 72The _session_ network traffic can be encrypted or un-encrypted if there is an 73underlying TLS library. 74 75If (D)TLS is going to be used for encrypting the network traffic, then the 76(D)TLS 77information for Pre-Shared Keys (PSK) or Public Key Infrastructure (PKI) needs 78to be configured before any network traffic starts to flow. For Servers, this 79has to be done before the Endpoint is created. 80 81For Servers, all the encryption information is held internally by the (D)TLS 82context level and the CoAP _context_ level as the Server is listening for new 83incoming traffic based on the Endpoint definition. The (D)TLS and CoAP 84_session_ will not get built until the new traffic starts, which is done by the 85libcoap library. 86 87In principle the set-up sequence for CoAP Servers looks like 88---- 89coap_new_context() 90coap_context_set_pki_root_cas() - if the root CAs need to be updated and using PKI 91coap_context_set_pki() and/or coap_context_set_psk2() - if encryption is required 92coap_new_endpoint() 93---- 94 95Multiple endpoints can be set up per _context_, each listening for a new traffic 96flow with different TCP/UDP protocols, (D)TLS protocols, port numbers, Unix 97pathnames etc. When 98a new traffic flow is started, then the CoAP library will create and start a new 99server _session_. 100 101FUNCTIONS 102--------- 103 104*Function: coap_context_set_pki()* 105 106The *coap_context_set_pki*() function, for a specific _context_, is used to 107configure the (D)TLS context using the _setup_data_ PKI variables as defined in 108the coap_dtls_pki_t structure - see *coap_encryption*(3). 109 110*Function: coap_context_set_pki_root_cas()* 111 112The *coap_context_set_pki_root_cas*() function is used to define a set of 113root CAs to be used instead of the default set of root CAs provided as a part 114of the TLS library. _ca_file_ points to a PEM encoded file containing the 115list of CAs. _ca_file_ can be NULL. _ca_dir_ points to a directory 116containing a set of PEM encoded files containing rootCAs. _ca_dir_ can be 117NULL. One or both of _ca_file_ and _ca_dir_ must be set. + 118*NOTE:* Some TLS libraries send the full list of CAs added by this function 119during the (D)TLS session setup handshakes. To stop this, either provide a 120single CA using the _ca_file_ definition in _pki_key_ in _setup_data_ variable 121when calling *coap_context_set_pki*(), or set _check_common_ca_ to 0 in 122_setup_data_ variable. See *coap_encryption*(3). 123 124*Function: coap_context_set_psk2()* 125 126The *coap_context_set_psk2*() function is used to configure the (D)TLS context 127using the _setup_data_ PSK variables as defined in the 128coap_dtls_spsk_t structure - see *coap_encryption*(3). 129This function can only be used for servers as _setup_data_ provides 130a _hint_, not an _identity_. 131 132*Function: coap_new_endpoint()* 133 134The *coap_new_endpoint*() function creates a new endpoint for _context_ that 135is listening for new traffic as defined in _listen_addr_ 136(see *coap_address_t*(3)). If the address family is AF_INET or AF_INET6, then it 137listens on the IP address and port number defined by _listen_addr_. If the 138port number is 0, then the default CoAP port is used. If the address family is 139AF_UNIX, then it listens on the defined unix domain path which has to be 140unique per endpoint. This unique unix domain path will get deleted on 141clean application exit. 142 143Different CoAP protocols can be defined for _proto_ - the current supported 144list is: 145 146[source, c] 147---- 148COAP_PROTO_UDP 149COAP_PROTO_DTLS 150COAP_PROTO_TCP 151COAP_PROTO_TLS 152COAP_PROTO_WS 153COAP_PROTO_WSS 154---- 155 156*coap_tcp_is_supported*(3), *coap_dtls_is_supported*(3), 157*coap_tls_is_supported*(3), *coap_ws_is_supported*(3) and 158*coap_wss_is_supported*(3) can be used for checking whether the underlying 159TCP, (D)TLS or WebSocket protocol support is available. 160See *coap_tls_library(3)* for further information on the types of (D)TLS 161sessions supported. 162 163When traffic starts to come in from a client, a server CoAP session is created 164associated with this endpoint. This CoAP session is created with a reference 165count of 0. This means that if the server session is not used for 5 minutes, 166then it will get completely freed off. See *coap_session_reference*(3) and 167*coap_session_release*(3) for further information. 168 169*Function: coap_free_endpoint()* 170 171The *coap_free_endpoint*() function must be used to free off the _endpoint_. 172It clears out all the sessions associated with this endpoint along with 173any data associated with the sessions as well as 174deleting the unix domain path if the address family is AF_UNIX. 175 176*Function: coap_endpoint_set_default_mtu()* 177 178The *coap_endpoint_set_default_mtu*() function is used to set the MTU size 179(the maximum message size) of the data in a packet, excluding any IP or 180TCP/UDP overhead to _mtu_ for the _endpoint_. A sensible default is 1280. 181 182*Function: coap_join_mcast_group_intf()* 183 184The *coap_join_mcast_group_intf*() function is used to join the currently 185defined endpoints that are UDP, associated with _context_, to the defined 186multicast group _groupname_. If _ifname_ is not NULL, then the multicast group 187is associated with this interface, otherwise the underlying O/S will choose the 188first appropriate interface. When the endpoint is freed off, the associated 189multicast group will be removed. The registered multicast addresses for CoAP 190are 224.0.1.187, ff0x::fd (Variable-Scope) - i.e. ff02::fd (Link-Local) and 191ff05::fd (Site-Local). 192 193*NOTE:* multicast is not supported for address family type AF_UNIX. 194 195*Function: coap_mcast_per_resource()* 196 197The *coap_mcast_per_resource*() function enables mcast to be controlled on a 198per resource basis giving the server application flexibility in how to respond 199to mcast requests. With this enabled, this is done through additional flag 200definitions when setting up each resource. See *coap_resource*(3). 201 202RETURN VALUES 203------------- 204*coap_context_set_pki*(), *coap_context_set_pki_root_cas*() and 205*coap_context_set_psk2*() return 1 on success, 0 on failure. 206 207*coap_new_endpoint*() returns a newly created endpoint or 208NULL if there is a creation failure. 209 210*coap_join_mcast_group_intf*() returns 0 on success, -1 on failure. 211 212EXAMPLES 213-------- 214*CoAP Server Non-Encrypted Setup* 215 216[source, c] 217---- 218#include <coap@LIBCOAP_API_VERSION@/coap.h> 219 220static coap_context_t * 221setup_server_context (void) { 222 coap_endpoint_t *endpoint; 223 coap_address_t listen_addr; 224 coap_context_t *context = coap_new_context(NULL); 225 226 if (!context) 227 return NULL; 228 /* See coap_block(3) */ 229 coap_context_set_block_mode(context, 230 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 231 232 233 /* See coap_address(3) */ 234 coap_address_init(&listen_addr); 235 listen_addr.addr.sa.sa_family = AF_INET; 236 listen_addr.addr.sin.sin_port = htons (5683); 237 238 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP); 239 if (!endpoint) { 240 coap_free_context(context); 241 return NULL; 242 } 243 244 /* Initialize resources - See coap_resource(3) init_resources() example */ 245 246 return context; 247} 248---- 249 250*CoAP Server Non-Encrypted Unix Domain Setup* 251 252[source, c] 253---- 254#include <coap@LIBCOAP_API_VERSION@/coap.h> 255 256#include <stdio.h> 257#include <unistd.h> 258 259/* This need to be unique per endpoint */ 260#define UNIX_DOMAIN_LISTEN_DGRAM "/tmp/server.dgram" 261 262static coap_context_t * 263setup_server_context (void) { 264 coap_endpoint_t *endpoint; 265 coap_address_t listen_addr; 266 coap_context_t *context = coap_new_context(NULL); 267 268 if (!context) 269 return NULL; 270 /* See coap_block(3) */ 271 coap_context_set_block_mode(context, 272 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 273 274 275 /* See coap_address(3) */ 276 coap_address_set_unix_domain(&listen_addr, 277 (const uint8_t *)UNIX_DOMAIN_LISTEN_DGRAM, 278 strlen(UNIX_DOMAIN_LISTEN_DGRAM)); 279 /* Only do this if you know it is safe to do so */ 280 unlink(listen_addr.addr.cun.sun_path); 281 282 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP); 283 if (!endpoint) { 284 coap_free_context(context); 285 return NULL; 286 } 287 288 /* Initialize resources - See coap_resource(3) init_resources() example */ 289 290 return context; 291} 292---- 293 294*CoAP Server DTLS PKI Setup* 295[source, c] 296---- 297#include <coap@LIBCOAP_API_VERSION@/coap.h> 298 299typedef struct valid_cns_t { 300 size_t count; 301 char **cn_list; 302} valid_cns_t; 303 304/* 305 * Common Name (CN) Callback verifier 306 */ 307static int 308verify_cn_callback(const char *cn, 309 const uint8_t *asn1_public_cert, 310 size_t asn1_length, 311 coap_session_t *c_session, 312 unsigned depth, 313 int validated, 314 void *arg 315) { 316 valid_cns_t *valid_cn_list = (valid_cns_t*)arg; 317 size_t i; 318 /* Remove (void) definition if variable is used */ 319 (void)asn1_public_cert; 320 (void)asn1_length; 321 (void)c_session; 322 (void)depth; 323 (void)validated; 324 325 /* Check that the CN is valid */ 326 for (i = 0; i < valid_cn_list->count; i++) { 327 if (!strcasecmp(cn, valid_cn_list->cn_list[i])) { 328 return 1; 329 } 330 } 331 return 0; 332} 333 334typedef struct sni_def_t { 335 char* sni; 336 coap_dtls_key_t key; 337} sni_def_t; 338 339typedef struct valid_snis_t { 340 size_t count; 341 sni_def_t *sni_list; 342} valid_snis_t; 343 344/* 345 * Subject Name Identifier (SNI) callback verifier 346 */ 347static coap_dtls_key_t * 348verify_pki_sni_callback(const char *sni, 349 void *arg 350) { 351 valid_snis_t *valid_sni_list = (valid_snis_t *)arg; 352 size_t i; 353 354 /* Check that the SNI is valid */ 355 for (i = 0; i < valid_sni_list->count; i++) { 356 if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { 357 return &valid_sni_list->sni_list[i].key; 358 } 359 } 360 return NULL; 361} 362 363/* 364 * Set up PKI encryption information 365 */ 366static coap_context_t * 367setup_server_context_pki (const char *public_cert_file, 368 const char *private_key_file, 369 const char *ca_file, 370 valid_cns_t *valid_cn_list, 371 valid_snis_t *valid_sni_list 372) { 373 coap_endpoint_t *endpoint; 374 coap_address_t listen_addr; 375 coap_dtls_pki_t dtls_pki; 376 coap_context_t *context; 377 378 /* See coap_tls_library(3) */ 379 if (!coap_dtls_is_supported()) 380 return NULL; 381 382 context = coap_new_context(NULL); 383 if (!context) 384 return NULL; 385 /* See coap_block(3) */ 386 coap_context_set_block_mode(context, 387 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 388 389 390 memset (&dtls_pki, 0, sizeof (dtls_pki)); 391 392 /* see coap_encryption(3) */ 393 dtls_pki.version = COAP_DTLS_PKI_SETUP_VERSION; 394 dtls_pki.verify_peer_cert = 1; 395 dtls_pki.check_common_ca = 1; 396 dtls_pki.allow_self_signed = 1; 397 dtls_pki.allow_expired_certs = 1; 398 dtls_pki.cert_chain_validation = 1; 399 dtls_pki.cert_chain_verify_depth = 1; 400 dtls_pki.check_cert_revocation = 1; 401 dtls_pki.allow_no_crl = 1; 402 dtls_pki.allow_expired_crl = 1; 403 dtls_pki.allow_bad_md_hash = 0; 404 dtls_pki.allow_short_rsa_length = 0; 405 dtls_pki.is_rpk_not_cert = 0; /* Set to 1 if RPK */ 406 dtls_pki.validate_cn_call_back = verify_cn_callback; 407 dtls_pki.cn_call_back_arg = valid_cn_list; 408 dtls_pki.validate_sni_call_back = verify_pki_sni_callback; 409 dtls_pki.sni_call_back_arg = valid_sni_list; 410 dtls_pki.additional_tls_setup_call_back = NULL; 411 dtls_pki.client_sni = NULL; 412 dtls_pki.pki_key.key_type = COAP_PKI_KEY_PEM; 413 dtls_pki.pki_key.key.pem.ca_file = ca_file; 414 dtls_pki.pki_key.key.pem.public_cert = public_cert_file; 415 dtls_pki.pki_key.key.pem.private_key = private_key_file; 416 417 if (coap_context_set_pki(context, &dtls_pki)) { 418 coap_free_context(context); 419 return NULL; 420 } 421 422 /* See coap_address(3) */ 423 coap_address_init(&listen_addr); 424 listen_addr.addr.sa.sa_family = AF_INET; 425 listen_addr.addr.sin.sin_port = htons (5684); 426 427 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); 428 if (!endpoint) { 429 coap_free_context(context); 430 return NULL; 431 } 432 433 /* Initialize resources - See coap_resource(3) init_resources() example */ 434 435 return context; 436} 437---- 438 439*CoAP Server DTLS PSK Setup* 440[source, c] 441---- 442#include <coap@LIBCOAP_API_VERSION@/coap.h> 443 444typedef struct id_def_t { 445 char* id; 446 coap_bin_const_t key; 447} id_def_t; 448 449typedef struct valid_ids_t { 450 int count; 451 id_def_t *id_list; 452} valid_ids_t; 453 454/* 455 * PSK Identity Pre-Shared Key selection Callback function 456 */ 457static const coap_bin_const_t * 458verify_id_callback(coap_bin_const_t *identity, 459 coap_session_t *c_session, 460 void *arg 461) { 462 valid_ids_t *valid_id_list = (valid_ids_t*)arg; 463 int i; 464 /* Remove (void) definition if variable is used */ 465 (void)c_session; 466 467 /* Check that the Identity is valid */ 468 for (i = 0; i < valid_id_list->count; i++) { 469 if (!strcasecmp((const char*)identity->s, valid_id_list->id_list[i].id)) { 470 return &valid_id_list->id_list[i].key; 471 } 472 } 473 return NULL; 474} 475 476typedef struct sni_psk_def_t { 477 char* sni; 478 coap_dtls_spsk_info_t psk_info; 479} sni_psk_def_t; 480 481typedef struct valid_psk_snis_t { 482 int count; 483 sni_psk_def_t *sni_list; 484} valid_psk_snis_t; 485 486/* 487 * PSK Subject Name Identifier (SNI) callback verifier 488 */ 489static const coap_dtls_spsk_info_t * 490verify_psk_sni_callback(const char *sni, 491 coap_session_t *c_session, 492 void *arg 493) { 494 valid_psk_snis_t *valid_sni_list = (valid_psk_snis_t *)arg; 495 int i; 496 /* Remove (void) definition if variable is used */ 497 (void)c_session; 498 499 /* Check that the SNI is valid */ 500 for (i = 0; i < valid_sni_list->count; i++) { 501 if (!strcasecmp(sni, valid_sni_list->sni_list[i].sni)) { 502 return &valid_sni_list->sni_list[i].psk_info; 503 } 504 } 505 return NULL; 506} 507 508static coap_context_t * 509setup_server_context_psk (const char *hint, 510 const uint8_t *key, 511 unsigned int key_len, 512 valid_ids_t *valid_id_list, 513 valid_psk_snis_t *valid_sni_list 514) { 515 coap_endpoint_t *endpoint; 516 coap_address_t listen_addr; 517 coap_context_t *context; 518 coap_dtls_spsk_t dtls_psk; 519 520 /* See coap_tls_library(3) */ 521 if (!coap_dtls_is_supported()) 522 return NULL; 523 524 context = coap_new_context(NULL); 525 if (!context) 526 return NULL; 527 /* See coap_block(3) */ 528 coap_context_set_block_mode(context, 529 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 530 531 532 memset (&dtls_psk, 0, sizeof (dtls_psk)); 533 534 /* see coap_encryption(3) */ 535 dtls_psk.version = COAP_DTLS_SPSK_SETUP_VERSION; 536 dtls_psk.validate_id_call_back = verify_id_callback; 537 dtls_psk.id_call_back_arg = valid_id_list; 538 dtls_psk.validate_sni_call_back = verify_psk_sni_callback; 539 dtls_psk.sni_call_back_arg = valid_sni_list; 540 dtls_psk.psk_info.hint.s = (const uint8_t*)hint; 541 dtls_psk.psk_info.hint.length = hint ? strlen(hint) : 0; 542 dtls_psk.psk_info.key.s = key; 543 dtls_psk.psk_info.key.length = key_len; 544 545 if (coap_context_set_psk2(context, &dtls_psk)) { 546 coap_free_context(context); 547 return NULL; 548 } 549 550 /* See coap_address(3) */ 551 coap_address_init(&listen_addr); 552 listen_addr.addr.sa.sa_family = AF_INET; 553 listen_addr.addr.sin.sin_port = htons (5684); 554 555 endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_DTLS); 556 if (!endpoint) { 557 coap_free_context(context); 558 return NULL; 559 } 560 561 /* Initialize resources - See coap_resource(3) init_resources() example */ 562 563 return context; 564} 565---- 566 567SEE ALSO 568-------- 569*coap_address*(3), *coap_block*(3), *coap_context*(3), *coap_encryption*(3), 570*coap_endpoint_client*(3), *coap_resource*(3), *coap_session*(3) and 571*coap_tls_library*(3) 572 573FURTHER INFORMATION 574------------------- 575See 576 577"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]" 578 579"https://rfc-editor.org/rfc/rfc8323[RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets]" 580 581for further information. 582 583BUGS 584---- 585Please report bugs on the mailing list for libcoap: 586libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at 587https://github.com/obgm/libcoap/issues 588 589AUTHORS 590------- 591The libcoap project <libcoap-developers@lists.sourceforge.net> 592