• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// -*- mode:doc; -*-
2// vim: set syntax=asciidoc tw=0
3
4coap_endpoint_client(3)
5=======================
6:doctype: manpage
7:man source:   coap_endpoint_client
8:man version:  @PACKAGE_VERSION@
9:man manual:   libcoap Manual
10
11NAME
12----
13coap_endpoint_client,
14coap_new_client_session,
15coap_new_client_session_psk2,
16coap_new_client_session_pki,
17coap_session_set_mtu,
18coap_session_max_pdu_size
19- Work with CoAP client endpoints
20
21SYNOPSIS
22--------
23*#include <coap@LIBCOAP_API_VERSION@/coap.h>*
24
25*coap_session_t *coap_new_client_session(coap_context_t *_context_,
26const coap_address_t *_local_if_, const coap_address_t *_server_,
27coap_proto_t _proto_);*
28
29*coap_session_t *coap_new_client_session_psk2(coap_context_t *_context_,
30const coap_address_t *_local_if_, const coap_address_t *_server_, coap_proto_t
31_proto_, coap_dtls_cpsk_t *_setup_data_);*
32
33*coap_session_t *coap_new_client_session_pki(coap_context_t *_context_,
34const coap_address_t *_local_if_, const coap_address_t *_server_, coap_proto_t
35_proto_, coap_dtls_pki_t *_setup_data_);*
36
37*void coap_session_set_mtu(coap_session_t *_session_, unsigned _mtu_);*
38
39*size_t coap_session_max_pdu_size(const coap_session_t *_session_);*
40
41For specific (D)TLS library support, link with
42*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
43*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*
44or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*.   Otherwise, link with
45*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support.
46
47DESCRIPTION
48-----------
49This man page focuses on the setting up of a CoAP client endpoint and hence
50creation of a CoAP _session_ used to connect to a server.  For a CoAP server
51endpoint, see *coap_endpoint_server*(3). There is no need to call
52*coap_new_endpoint*(3) for a client as well as one of the
53*coap_new_client_server**() functions.
54
55The CoAP stack's global state is stored in a coap_context_t _context_ object.
56Resources, Endpoints and Sessions are associated with this _context_ object.
57There can be more than one coap_context_t object per application, it is up to
58the application to manage each one accordingly.
59
60A CoAP _session_ maintains the state of an ongoing connection between a Client
61and Server which is stored in a coap_session_t _session_ object. A CoAP
62_session_ is tracked by local port, CoAP protocol, remote IP address and
63remote port, or in the case of Unix Domain sockets, the local path and the
64remote path.
65
66The _session_ network traffic can be encrypted or un-encrypted if there is an
67underlying TLS library.
68
69If (D)TLS is going to be used for encrypting the network traffic, then the
70(D)TLS
71information for Pre-Shared Keys (PSK) or Public Key Infrastructure (PKI) needs
72to be configured before any network traffic starts to flow. For Clients, this
73is done during the Client _session_ set up.
74
75For Clients, all the encryption information can be held at the (D)TLS
76context and CoAP _context_ levels, or at the (D)TLS session and CoAP
77_session_ levels.  If defined at the _context_ level, then when a _session_ is
78created, it will inherit the _context_ definitions, unless they have separately
79been defined for the _session_ level, in which case the _session_ version will
80get used.  Typically the information will be configured at the _session_ level
81for Clients.
82
83In principle the set-up sequence for CoAP client endpoints looks like
84----
85coap_new_context()
86coap_context_set_pki_root_cas() - if the root CAs need to be updated and using PKI
87coap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk2()
88----
89
90Multiple client endpoints and hence sessions are supported per _context_.
91
92Different CoAP protocols can be defined for _proto_ - the current supported
93list is:
94
95[source, c]
96----
97COAP_PROTO_UDP
98COAP_PROTO_DTLS
99COAP_PROTO_TCP
100COAP_PROTO_TLS
101COAP_PROTO_WS
102COAP_PROTO_WSS
103----
104
105*coap_tcp_is_supported*(3), *coap_dtls_is_supported*(3),
106*coap_tls_is_supported*(3), *coap_ws_is_supported*(3) and
107*coap_wss_is_supported*(3) can be used for checking whether the underlying
108TCP, (D)TLS or WebSocket protocol support is available.
109See *coap_tls_library(3)* for further information on the types of (D)TLS
110sessions supported.
111
112Libcoap supports 3 different socket types:
113
114[source, c]
115----
116AF_INET  IPv4 IP addresses and ports
117AF_INET6 IPv6 IP addresses and ports and can be dual IPv4/IPv6 stacked
118AF_UNIX  Unix Domain using file path names
119----
120
121For AF_INET and AF_INET6, the client does not need to specify a local IP
122address and/or port as default values will get filled in. However for AF_UNIX,
123the local pathname must be provided and must be unique per client session. This
124unique local pathname will get deleted on the session being properly closed at
125application exit.
126
127The client must specify IP and port when defining the *coap_address_t* (see
128*coap_address_t*(3)) for the remote end of the session if AF_INET or AF_INET6.
129If port is 0, then the default CoAP port is used instead.  If AF_UNIX, the
130unix domain path to connect to must be specified.
131
132FUNCTIONS
133---------
134
135*Function: coap_new_client_session()*
136
137The *coap_new_client_session*() function creates a client endpoint for a
138specific _context_ and initiates a new client session to the specified
139_server_ using the CoAP protocol _proto_ as defined above. If the port is set
140to 0 in _server_ (for AF_INET or AF_INET6), then the default CoAP port is used.
141
142Normally _local_if_ would be set to NULL, but by specifying
143_local_if_ the source of the network session can be bound to a specific IP
144address or port. For AF_UNIX, _local_if_ must be specified pointing to an
145appropriate *coap_address_t*.  If _local_if_ is defined, the address families
146for _local_if_ and _server_ must be identical. The session will initially have
147a reference count of 1.
148
149To stop using a client session, the reference count must be decremented to 0
150by calling *coap_session_release*(3). See *coap_session*(3). This will remove
151the client endpoint's _session_ and all its associated information.
152
153*Function: coap_new_client_session_pki()*
154
155The *coap_new_client_session_pki*() function, for a specific _context_, is
156used to configure the (D)TLS context using the _setup_data_ variables as defined
157in the coap_dtls_pki_t structure in the newly created endpoint session -
158see *coap_encryption*(3). The connection is to the specified _server_ using
159the CoAP protocol _proto_ as defined above.  If the port is set to 0 in
160_server_ (for AF_INET or AF_INET6), then the default CoAP port is used.
161
162Normally _local_if_ would be set to NULL, but by specifying
163_local_if_ the source of the network session can be bound to a specific IP
164address or port. For AF_UNIX, _local_if_ must be specified pointing to an
165appropriate *coap_address_t*.  If _local_if_ is defined, the address families
166for _local_if_ and _server_ must be identical. The session will initially have
167a reference count of 1.
168
169To stop using a client session, the reference count must be decremented to 0
170by calling *coap_session_release*(3). See *coap_session*(3). This will remove
171the client endpoint's _session_ and all its associated information.
172
173*Function: coap_new_client_session_psk2()*
174
175The *coap_new_client_session_psk2*() function, for a specific _context_, is
176used to configure the (D)TLS context using the _setup_data_ variables as defined
177in the coap_dtls_cpsk_t structure in the newly created endpoint session -
178see *coap_encryption*(3). The connection is to the specified _server_ using
179the CoAP protocol _proto_ as defined above.  If the port is set to 0 in
180_server_ (for AF_INET or AF_INET6), then the default CoAP port is used.
181
182Normally _local_if_ would be set to NULL, but by specifying
183_local_if_ the source of the network session can be bound to a specific IP
184address or port. For AF_UNIX, _local_if_ must be specified pointing to an
185appropriate *coap_address_t*.  If _local_if_ is defined, the address families
186for _local_if_ and _server_ must be identical. The session will initially have
187a reference count of 1.
188
189To stop using a client session, the reference count must be decremented to 0
190by calling *coap_session_release*(3). See *coap_session*(3). This will remove
191the client endpoint's _session_ and all its associated information.
192
193*Function: coap_session_set_mtu()*
194
195The *coap_session_set_mtu*() function is used to set the MTU size
196(the maximum message size) of the data in a packet, excluding any IP or
197TCP/UDP overhead to _mtu_ for the client endpoint's _session_.  The default
198MTU is 1152.
199
200*Function: coap_session_max_pdu_size()*
201
202The *coap_session_max_pdu_size*() function is used to get the maximum MTU
203size of the data for the client endpoint's _session_.
204
205RETURN VALUES
206-------------
207*coap_new_client_session*(), *coap_new_client_session_psk2*(),
208*coap_new_client_session_pki*() return a newly created client.
209session or NULL if there is a creation failure.
210
211*coap_session_max_pdu_size*() returns the MTU size.
212
213EXAMPLES
214--------
215*CoAP Client Non-Encrypted Setup*
216[source, c]
217----
218#include <coap@LIBCOAP_API_VERSION@/coap.h>
219
220#include <netinet/in.h>
221
222static coap_session_t *
223setup_client_session (struct in_addr ip_address) {
224  coap_session_t *session;
225  coap_address_t server;
226  /* See coap_context(3) */
227  coap_context_t *context = coap_new_context(NULL);
228
229  if (!context)
230    return NULL;
231  /* See coap_block(3) */
232  coap_context_set_block_mode(context,
233                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
234
235
236  /* See coap_address(3) */
237  coap_address_init(&server);
238  server.addr.sa.sa_family = AF_INET;
239  server.addr.sin.sin_addr = ip_address;
240  server.addr.sin.sin_port = htons (5683);
241
242  session = coap_new_client_session(context, NULL, &server, COAP_PROTO_UDP);
243  if (!session) {
244    coap_free_context(context);
245    return NULL;
246  }
247  /* The context is in session->context */
248  return session;
249}
250----
251
252*CoAP Client Non-Encrypted Unix Domain Setup*
253[source, c]
254----
255#include <coap@LIBCOAP_API_VERSION@/coap.h>
256
257#include <stdio.h>
258#include <sys/types.h>
259#include <unistd.h>
260
261static coap_session_t *
262setup_client_session (const char *server_ud) {
263  coap_session_t *session;
264  coap_address_t server;
265  coap_address_t local;
266  /* See coap_context(3) */
267  coap_context_t *context = coap_new_context(NULL);
268
269  if (!context)
270    return NULL;
271  /* See coap_block(3) */
272  coap_context_set_block_mode(context,
273                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
274
275
276  /* See coap_address(3) */
277  coap_address_init(&server);
278  server.addr.sa.sa_family = AF_UNIX;
279  snprintf(server.addr.cun.sun_path, sizeof(server.addr.cun.sun_path),
280           "%s", server_ud);
281
282  /* Need to have a uniquely named local address */
283  coap_address_init(&local);
284  local.addr.sa.sa_family = AF_UNIX;
285  snprintf(local.addr.cun.sun_path, sizeof(server.addr.cun.sun_path),
286           "/tmp/client.%d", getpid());
287  /* Only do this if you know it is safe to do so */
288  unlink(local.addr.cun.sun_path);
289
290  session = coap_new_client_session(context, &local, &server, COAP_PROTO_UDP);
291  if (!session) {
292    coap_free_context(context);
293    return NULL;
294  }
295  /* The context is in session->context */
296  return session;
297}
298----
299
300*CoAP Client PKI Setup*
301[source, c]
302----
303#include <coap@LIBCOAP_API_VERSION@/coap.h>
304
305#include <netinet/in.h>
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 int depth,
313                   int validated,
314                   void *arg
315) {
316  /* Remove (void) definition if variable is used */
317  (void)cn;
318  (void)asn1_public_cert;
319  (void)asn1_length;
320  (void)c_session;
321  (void)depth;
322  (void)validated;
323  (void)arg;
324
325  /* Check that the CN is valid */
326
327  /* ... */
328
329  return 1;
330}
331
332static coap_session_t *
333setup_client_session_pki (struct in_addr ip_address,
334                          const char *public_cert_file,
335                          const char *private_key_file,
336                          const char *ca_file
337) {
338  coap_session_t *session;
339  coap_address_t server;
340  coap_dtls_pki_t dtls_pki;
341  /* See coap_context(3) */
342  coap_context_t *context = coap_new_context(NULL);
343
344  if (!context)
345    return NULL;
346  /* See coap_block(3) */
347  coap_context_set_block_mode(context,
348                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
349
350
351  /* See coap_address(3) */
352  coap_address_init(&server);
353  server.addr.sa.sa_family = AF_INET;
354  server.addr.sin.sin_addr = ip_address;
355  server.addr.sin.sin_port = htons (5684);
356
357  memset (&dtls_pki, 0, sizeof (dtls_pki));
358
359  /* See coap_encryption(3) */
360  dtls_pki.version                 = COAP_DTLS_PKI_SETUP_VERSION;
361  dtls_pki.verify_peer_cert        = 1;
362  dtls_pki.check_common_ca         = 1;
363  dtls_pki.allow_self_signed       = 1;
364  dtls_pki.allow_expired_certs     = 1;
365  dtls_pki.cert_chain_validation   = 1;
366  dtls_pki.cert_chain_verify_depth = 1;
367  dtls_pki.check_cert_revocation   = 1;
368  dtls_pki.allow_no_crl            = 1;
369  dtls_pki.allow_expired_crl       = 1;
370  dtls_pki.allow_bad_md_hash       = 0;
371  dtls_pki.allow_short_rsa_length  = 0;
372  dtls_pki.is_rpk_not_cert         = 0; /* Set to 1 if RPK */
373  dtls_pki.validate_cn_call_back   = verify_cn_callback;
374  dtls_pki.cn_call_back_arg        = NULL;
375  dtls_pki.validate_sni_call_back  = NULL;
376  dtls_pki.sni_call_back_arg       = NULL;
377  dtls_pki.additional_tls_setup_call_back = NULL;
378  dtls_pki.client_sni              = NULL;
379  dtls_pki.pki_key.key_type        = COAP_PKI_KEY_PEM;
380  dtls_pki.pki_key.key.pem.ca_file = ca_file;
381  dtls_pki.pki_key.key.pem.public_cert = public_cert_file;
382  dtls_pki.pki_key.key.pem.private_key = private_key_file;
383
384  session = coap_new_client_session_pki(context, NULL, &server,
385                                        COAP_PROTO_DTLS, &dtls_pki);
386  if (!session) {
387    coap_free_context(context);
388    return NULL;
389  }
390  /* The context is in session->context */
391  return session;
392}
393----
394
395*CoAP Client PSK Setup*
396[source, c]
397----
398#include <coap@LIBCOAP_API_VERSION@/coap.h>
399
400#include <stdio.h>
401#include <netinet/in.h>
402
403#ifndef min
404#define min(a,b) ((a) < (b) ? (a) : (b))
405#endif
406
407static const coap_dtls_cpsk_info_t *
408verify_ih_callback(coap_str_const_t *hint,
409                   coap_session_t *c_session,
410                   void *arg
411) {
412  coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg;
413  /* Remove (void) definition if variable is used */
414  (void)c_session;
415
416  coap_log_info("Identity Hint '%.*s' provided\n", (int)hint->length, hint->s);
417
418  /* Just use the defined information for now as passed in by arg */
419  return psk_info;
420}
421
422static coap_dtls_cpsk_t dtls_psk;
423static char client_sni[256];
424
425static coap_session_t *
426setup_client_session_psk (const char *uri,
427                          struct in_addr ip_address,
428                          const uint8_t *identity,
429                          unsigned int identity_len,
430                          const uint8_t *key,
431                          unsigned int key_len
432) {
433  coap_session_t *session;
434  coap_address_t server;
435  /* See coap_context(3) */
436  coap_context_t *context = coap_new_context(NULL);
437
438  if (!context)
439    return NULL;
440  /* See coap_block(3) */
441  coap_context_set_block_mode(context,
442                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
443
444
445  /* See coap_address(3) */
446  coap_address_init(&server);
447  server.addr.sa.sa_family = AF_INET;
448  server.addr.sin.sin_addr = ip_address;
449  server.addr.sin.sin_port = htons (5684);
450
451  /* See coap_encryption(3) */
452  memset (&dtls_psk, 0, sizeof(dtls_psk));
453  dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION;
454  dtls_psk.validate_ih_call_back = verify_ih_callback;
455  dtls_psk.ih_call_back_arg = &dtls_psk.psk_info;
456  if (uri)
457    memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1));
458  else
459    memcpy(client_sni, "localhost", 9);
460  dtls_psk.client_sni = client_sni;
461  dtls_psk.psk_info.identity.s = identity;
462  dtls_psk.psk_info.identity.length = identity_len;
463  dtls_psk.psk_info.key.s = key;
464  dtls_psk.psk_info.key.length = key_len;
465  session = coap_new_client_session_psk2(context, NULL, &server,
466                                        COAP_PROTO_DTLS, &dtls_psk);
467  if (!session) {
468    coap_free_context(context);
469    return NULL;
470  }
471  /* The context is in session->context */
472  return session;
473}
474----
475
476*CoAP Client Anonymous PKI Setup*
477[source, c]
478----
479#include <coap@LIBCOAP_API_VERSION@/coap.h>
480
481#include <netinet/in.h>
482
483static coap_session_t *
484setup_client_session_dtls (struct in_addr ip_address) {
485  coap_session_t *session;
486  coap_address_t server;
487  /* See coap_context(3) */
488  coap_context_t *context = coap_new_context(NULL);
489
490  if (!context)
491    return NULL;
492  /* See coap_block(3) */
493  coap_context_set_block_mode(context,
494                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
495
496
497  /* See coap_address(3) */
498  coap_address_init(&server);
499  server.addr.sa.sa_family = AF_INET;
500  server.addr.sin.sin_addr = ip_address;
501  server.addr.sin.sin_port = htons (5683);
502
503  session = coap_new_client_session(context, NULL, &server,
504                                        COAP_PROTO_DTLS);
505  if (!session) {
506    coap_free_context(context);
507    return NULL;
508  }
509  /* The context is in session->context */
510  return session;
511}
512----
513
514SEE ALSO
515--------
516*coap_address*(3), *coap_block*(3), *coap_context*(3), *coap_encryption*(3),
517*coap_endpoint_server*(3), *coap_resource*(3), *coap_session*(3) and
518*coap_tls_library*(3)
519
520FURTHER INFORMATION
521-------------------
522See
523
524"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]"
525
526"https://rfc-editor.org/rfc/rfc8323[RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets]"
527
528for further information.
529
530BUGS
531----
532Please report bugs on the mailing list for libcoap:
533libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
534https://github.com/obgm/libcoap/issues
535
536AUTHORS
537-------
538The libcoap project <libcoap-developers@lists.sourceforge.net>
539