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