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).
52
53The CoAP stack's global state is stored in a coap_context_t Context object.
54Resources, Endpoints and Sessions are associated with this context object.
55There can be more than one coap_context_t object per application, it is up to
56the application to manage each one accordingly.
57
58A CoAP Ssssion maintains the state of an ongoing connection between a Client
59and Server which is stored in a coap_session_t Session object. A CoAP session
60is tracked by local port, CoAP protocol, remote IP address and remote port.
61
62The Session network traffic can be encrypted or un-encrypted if there is an
63underlying TLS library.
64
65If TLS is going to be used for encrypting the network traffic, then the TLS
66information for Pre-Shared Keys (PSK) or Public Key Infrastructure (PKI) needs
67to be configured before any network traffic starts to flow. For Servers, this
68has to be done before the Endpoint is created, for Clients, this is done
69during the Client Endpoint/Session set up.
70
71For Clients, all the encryption information can be held at the TLS Context and
72CoAP Context levels, or at the TLS Session and CoAP Session levels.  If
73defined at the Context level, then when Sessions are created, they will
74inherit the Context definitions, unless they have separately been defined for
75the Session level, in which case the Session version will get used.
76Typically the information will be configured at the Session level for Clients.
77
78In principle the set-up sequence for CoAP client endpoints looks like
79----
80coap_new_context()
81coap_context_set_pki_root_cas() if the root CAs need to be updated and PKI
82coap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk2()
83----
84
85Multiple client endpoints and hence sessions are supported per Context.
86
87Different CoAP protocols can be defined for _proto_ - the current supported
88list is:
89
90[source, c]
91----
92COAP_PROTO_UDP
93COAP_PROTO_DTLS
94COAP_PROTO_TCP
95COAP_PROTO_TLS
96----
97
98*coap_tcp_is_supported*(), *coap_dtls_is_supported*() and
99*coap_tls_is_supported*() can be used for checking whether the underlying
100TCP or (D)TLS protocol support is available.  See *coap_tls_library(3)* for
101further information.
102
103The *coap_new_client_session*() function creates a client endpoint for a
104specific _context_ and initiates a new client session to the specified _server_
105using the CoAP protocol
106_proto_.  If the port is set to 0 in _server_, then the default CoAP
107port is used.  Normally _local_if_ would be set to NULL, but by specifying
108_local_if_ the source of the network session can be bound to a specific IP
109address or port.  The session will initially have a reference count of 1.
110
111The *coap_new_client_session_pki*() function, for a specific _context_, is
112used to configure the TLS context using the _setup_data_ variables as defined
113in the coap_dtls_pki_t structure in the newly created endpoint session -
114see *coap_encryption*(3). The connection is to the specified _server_ using
115the CoAP protocol _proto_.  If the port is set to 0 in _server_, then the
116default CoAP port is used.  Normally _local_if_ would be set to NULL, but by
117specifying _local_if_ the source of the network session can be bound to a
118specific IP address or port. The session will initially have a reference count
119of 1.
120
121The *coap_new_client_session_psk2*() function, for a specific _context_, is
122used to configure the TLS context using the _setup_data_ variables as defined
123in the coap_dtls_cpsk_t structure in the newly created endpoint session -
124see *coap_encryption*(3). The connection is to the specified _server_ using
125the CoAP protocol _proto_.  If the port is set to 0 in _server_, then the
126default CoAP port is used.  Normally _local_if_ would be set to NULL, but by
127specifying _local_if_ the source of the network session can be bound to a
128specific IP address or port. The session will initially have a reference count
129of 1.
130
131To stop using a client session, the reference count must be decremented to 0
132by calling *coap_session_release*(). See *coap_session*(3). This will remove
133the client endpoint.
134
135The *coap_sesson_set_default_mtu*() function is used to set the MTU size
136(the maximum message size) of the data in a packet, excluding any IP or
137TCP/UDP overhead to _mtu_ for the client endpoint's _session_.  The default
138MTU is 1152.
139
140The *coap_session_max_pdu_size*() function is used to get the maximum MTU
141size of the data for the client endpoint's _session_.
142
143RETURN VALUES
144-------------
145*coap_new_client_session*(), *coap_new_client_session_psk2*(),
146*coap_new_client_session_pki*() functions returns a newly created client
147session or NULL if there is a creation failure.
148
149*coap_session_max_pdu_size*() function returns the MTU size.
150
151EXAMPLES
152--------
153*CoAP Client Non-Encrypted Setup*
154[source, c]
155----
156#include <coap@LIBCOAP_API_VERSION@/coap.h>
157
158#include <netinet/in.h>
159
160static coap_session_t *
161setup_client_session (struct in_addr ip_address) {
162  coap_session_t *session;
163  coap_address_t server;
164  /* See coap_context(3) */
165  coap_context_t *context = coap_new_context(NULL);
166
167  if (!context)
168    return NULL;
169  /* See coap_block(3) */
170  coap_context_set_block_mode(context,
171                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
172
173
174  coap_address_init(&server);
175  server.addr.sa.sa_family = AF_INET;
176  server.addr.sin.sin_addr = ip_address;
177  server.addr.sin.sin_port = htons (5683);
178
179  session = coap_new_client_session(context, NULL, &server, COAP_PROTO_UDP);
180  if (!session) {
181    coap_free_context(context);
182    return NULL;
183  }
184  /* The context is in session->context */
185  return session;
186}
187----
188
189*CoAP Client PKI Setup*
190[source, c]
191----
192#include <coap@LIBCOAP_API_VERSION@/coap.h>
193
194#include <netinet/in.h>
195
196static int
197verify_cn_callback(const char *cn,
198                   const uint8_t *asn1_public_cert,
199                   size_t asn1_length,
200                   coap_session_t *c_session,
201                   unsigned int depth,
202                   int validated,
203                   void *arg
204) {
205  /* Remove (void) definition if variable is used */
206  (void)cn;
207  (void)asn1_public_cert;
208  (void)asn1_length;
209  (void)c_session;
210  (void)depth;
211  (void)validated;
212  (void)arg;
213
214  /* Check that the CN is valid */
215
216  /* ... */
217
218  return 1;
219}
220
221static coap_session_t *
222setup_client_session_pki (struct in_addr ip_address,
223                          const char *public_cert_file,
224                          const char *private_key_file,
225                          const char *ca_file
226) {
227  coap_session_t *session;
228  coap_address_t server;
229  coap_dtls_pki_t dtls_pki;
230  /* See coap_context(3) */
231  coap_context_t *context = coap_new_context(NULL);
232
233  if (!context)
234    return NULL;
235  /* See coap_block(3) */
236  coap_context_set_block_mode(context,
237                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
238
239
240  coap_address_init(&server);
241  server.addr.sa.sa_family = AF_INET;
242  server.addr.sin.sin_addr = ip_address;
243  server.addr.sin.sin_port = htons (5684);
244
245  memset (&dtls_pki, 0, sizeof (dtls_pki));
246
247  /* See coap_encryption(3) */
248  dtls_pki.version                 = COAP_DTLS_PKI_SETUP_VERSION;
249  dtls_pki.verify_peer_cert        = 1;
250  dtls_pki.check_common_ca         = 1;
251  dtls_pki.allow_self_signed       = 1;
252  dtls_pki.allow_expired_certs     = 1;
253  dtls_pki.cert_chain_validation   = 1;
254  dtls_pki.cert_chain_verify_depth = 1;
255  dtls_pki.check_cert_revocation   = 1;
256  dtls_pki.allow_no_crl            = 1;
257  dtls_pki.allow_expired_crl       = 1;
258  dtls_pki.allow_bad_md_hash       = 0;
259  dtls_pki.allow_short_rsa_length  = 0;
260  dtls_pki.is_rpk_not_cert         = 0; /* Set to 1 if RPK */
261  dtls_pki.validate_cn_call_back   = verify_cn_callback;
262  dtls_pki.cn_call_back_arg        = NULL;
263  dtls_pki.validate_sni_call_back  = NULL;
264  dtls_pki.sni_call_back_arg       = NULL;
265  dtls_pki.additional_tls_setup_call_back = NULL;
266  dtls_pki.client_sni              = NULL;
267  dtls_pki.pki_key.key_type        = COAP_PKI_KEY_PEM;
268  dtls_pki.pki_key.key.pem.ca_file = ca_file;
269  dtls_pki.pki_key.key.pem.public_cert = public_cert_file;
270  dtls_pki.pki_key.key.pem.private_key = private_key_file;
271
272  session = coap_new_client_session_pki(context, NULL, &server,
273                                        COAP_PROTO_DTLS, &dtls_pki);
274  if (!session) {
275    coap_free_context(context);
276    return NULL;
277  }
278  /* The context is in session->context */
279  return session;
280}
281----
282
283*CoAP Client PSK Setup*
284[source, c]
285----
286#include <coap@LIBCOAP_API_VERSION@/coap.h>
287
288#include <stdio.h>
289#include <netinet/in.h>
290
291#ifndef min
292#define min(a,b) ((a) < (b) ? (a) : (b))
293#endif
294
295static const coap_dtls_cpsk_info_t *
296verify_ih_callback(coap_str_const_t *hint,
297                   coap_session_t *c_session,
298                   void *arg
299) {
300  coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg;
301  /* Remove (void) definition if variable is used */
302  (void)c_session;
303
304  coap_log(LOG_INFO, "Identity Hint '%.*s' provided\n", (int)hint->length, hint->s);
305
306  /* Just use the defined information for now as passed in by arg */
307  return psk_info;
308}
309
310static coap_dtls_cpsk_t dtls_psk;
311static char client_sni[256];
312
313static coap_session_t *
314setup_client_session_psk (const char *uri,
315                          struct in_addr ip_address,
316                          const uint8_t *identity,
317                          unsigned int identity_len,
318                          const uint8_t *key,
319                          unsigned int key_len
320) {
321  coap_session_t *session;
322  coap_address_t server;
323  /* See coap_context(3) */
324  coap_context_t *context = coap_new_context(NULL);
325
326  if (!context)
327    return NULL;
328  /* See coap_block(3) */
329  coap_context_set_block_mode(context,
330                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
331
332
333  coap_address_init(&server);
334  server.addr.sa.sa_family = AF_INET;
335  server.addr.sin.sin_addr = ip_address;
336  server.addr.sin.sin_port = htons (5684);
337
338  /* See coap_encryption(3) */
339  memset (&dtls_psk, 0, sizeof(dtls_psk));
340  dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION;
341  dtls_psk.validate_ih_call_back = verify_ih_callback;
342  dtls_psk.ih_call_back_arg = &dtls_psk.psk_info;
343  if (uri)
344    memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)-1));
345  else
346    memcpy(client_sni, "localhost", 9);
347  dtls_psk.client_sni = client_sni;
348  dtls_psk.psk_info.identity.s = identity;
349  dtls_psk.psk_info.identity.length = identity_len;
350  dtls_psk.psk_info.key.s = key;
351  dtls_psk.psk_info.key.length = key_len;
352  session = coap_new_client_session_psk2(context, NULL, &server,
353                                        COAP_PROTO_DTLS, &dtls_psk);
354  if (!session) {
355    coap_free_context(context);
356    return NULL;
357  }
358  /* The context is in session->context */
359  return session;
360}
361----
362
363*CoAP Client Anonymous PKI Setup*
364[source, c]
365----
366#include <coap@LIBCOAP_API_VERSION@/coap.h>
367
368#include <netinet/in.h>
369
370static coap_session_t *
371setup_client_session_dtls (struct in_addr ip_address) {
372  coap_session_t *session;
373  coap_address_t server;
374  /* See coap_context(3) */
375  coap_context_t *context = coap_new_context(NULL);
376
377  if (!context)
378    return NULL;
379  /* See coap_block(3) */
380  coap_context_set_block_mode(context,
381                              COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
382
383
384  coap_address_init(&server);
385  server.addr.sa.sa_family = AF_INET;
386  server.addr.sin.sin_addr = ip_address;
387  server.addr.sin.sin_port = htons (5683);
388
389  session = coap_new_client_session(context, NULL, &server,
390                                        COAP_PROTO_DTLS);
391  if (!session) {
392    coap_free_context(context);
393    return NULL;
394  }
395  /* The context is in session->context */
396  return session;
397}
398----
399
400SEE ALSO
401--------
402*coap_block*(3), *coap_context*(3), *coap_encryption*(3),
403*coap_endpoint_server*()3), *coap_resource*(3), *coap_session*(3) and
404*coap_tls_library*(3)
405
406FURTHER INFORMATION
407-------------------
408See "RFC7252: The Constrained Application Protocol (CoAP)" for further
409information.
410
411BUGS
412----
413Please report bugs on the mailing list for libcoap:
414libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
415https://github.com/obgm/libcoap/issues
416
417AUTHORS
418-------
419The libcoap project <libcoap-developers@lists.sourceforge.net>
420