libcoap 4.3.2rc2

coap_address.c
Go to the documentation of this file.
1/* coap_address.c -- representation of network addresses
2 *
3 * Copyright (C) 2015-2016,2019-2023 Olaf Bergmann <bergmann@tzi.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 *
7 * This file is part of the CoAP library libcoap. Please see
8 * README for terms of use.
9 */
10
16#include "coap3/coap_internal.h"
17
18#if !defined(WITH_CONTIKI) && !defined(WITH_LWIP)
19#ifdef HAVE_ARPA_INET_H
20#include <arpa/inet.h>
21#endif
22#ifdef HAVE_NETINET_IN_H
23#include <netinet/in.h>
24#endif
25#ifdef HAVE_SYS_SOCKET_H
26#include <sys/socket.h>
27#endif
28#ifdef HAVE_WS2TCPIP_H
29#include <ws2tcpip.h>
30#endif
31
32#ifdef RIOT_VERSION
33/* FIXME */
34#define IN_MULTICAST(Address) (0)
35#endif /* RIOT_VERSION */
36
37uint16_t
38 coap_address_get_port(const coap_address_t *addr) {
39 assert(addr != NULL);
40 switch (addr->addr.sa.sa_family) {
41#if COAP_IPV4_SUPPORT
42 case AF_INET:
43 return ntohs(addr->addr.sin.sin_port);
44#endif /* COAP_IPV4_SUPPORT */
45#if COAP_IPV6_SUPPORT
46 case AF_INET6:
47 return ntohs(addr->addr.sin6.sin6_port);
48#endif /* COAP_IPV6_SUPPORT */
49 default: /* undefined */
50 ;
51 }
52 return 0;
53}
54
55 void
56 coap_address_set_port(coap_address_t *addr, uint16_t port) {
57 assert(addr != NULL);
58 switch (addr->addr.sa.sa_family) {
59#if COAP_IPV4_SUPPORT
60 case AF_INET:
61 addr->addr.sin.sin_port = htons(port);
62 break;
63#endif /* COAP_IPV4_SUPPORT */
64#if COAP_IPV6_SUPPORT
65 case AF_INET6:
66 addr->addr.sin6.sin6_port = htons(port);
67 break;
68#endif /* COAP_IPV6_SUPPORT */
69 default: /* undefined */
70 ;
71 }
72}
73
74 int
75 coap_address_equals(const coap_address_t *a, const coap_address_t *b) {
76 assert(a);
77 assert(b);
78
79 if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
80 return 0;
81
82 /* need to compare only relevant parts of sockaddr_in6 */
83 switch (a->addr.sa.sa_family) {
84#if COAP_IPV4_SUPPORT
85 case AF_INET:
86 return a->addr.sin.sin_port == b->addr.sin.sin_port &&
87 memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
88 sizeof(struct in_addr)) == 0;
89#endif /* COAP_IPV4_SUPPORT */
90#if COAP_IPV6_SUPPORT
91 case AF_INET6:
92 return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
93 memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
94 sizeof(struct in6_addr)) == 0;
95#endif /* COAP_IPV6_SUPPORT */
96 default: /* fall through and signal error */
97 ;
98 }
99 return 0;
100}
101
102 int
103 coap_is_af_unix(const coap_address_t *a) {
104#if COAP_AF_UNIX_SUPPORT
105 return a->addr.sa.sa_family == AF_UNIX;
106#else /* ! COAP_AF_UNIX_SUPPORT */
107 (void)a;
108 return 0;
109#endif /* ! COAP_AF_UNIX_SUPPORT */
110}
111
112 int
113 coap_is_mcast(const coap_address_t *a) {
114 if (!a)
115 return 0;
116
117 /* Treat broadcast in same way as multicast */
118 if (coap_is_bcast(a))
119 return 1;
120
121 switch (a->addr.sa.sa_family) {
122#if COAP_IPV4_SUPPORT
123 case AF_INET:
124 return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr));
125#endif /* COAP_IPV4_SUPPORT */
126#if COAP_IPV6_SUPPORT
127 case AF_INET6:
128#if COAP_IPV4_SUPPORT
129 return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr) ||
130 (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr) &&
131 IN_MULTICAST(ntohl(a->addr.sin6.sin6_addr.s6_addr[12])));
132#else /* ! COAP_IPV4_SUPPORT */
133 return a->addr.sin6.sin6_addr.s6_addr[0] == 0xff;
134#endif /* ! COAP_IPV4_SUPPORT */
135#endif /* COAP_IPV6_SUPPORT */
136 default: /* fall through and signal not multicast */
137 ;
138 }
139 return 0;
140}
141
142#if !defined(WIN32)
143
144#ifndef COAP_BCST_CNT
145#define COAP_BCST_CNT 15
146#endif /* COAP_BCST_CNT */
147
148/* How frequently to refresh the list of valid IPv4 broadcast addresses */
149#ifndef COAP_BCST_REFRESH_SECS
150#define COAP_BCST_REFRESH_SECS 30
151#endif /* COAP_BCST_REFRESH_SECS */
152
153#if COAP_IPV4_SUPPORT && !defined(ESPIDF_VERSION)
154 static int bcst_cnt = -1;
155 static coap_tick_t last_refresh;
156 static struct in_addr b_ipv4[COAP_BCST_CNT];
157#endif /* COAP_IPV4_SUPPORT && ! ESPIDF_VERSION */
158
159#if !defined(ESPIDF_VERSION)
160#include <net/if.h>
161#include <ifaddrs.h>
162#endif /* ! ESPIDF_VERSION */
163
164 int
165 coap_is_bcast(const coap_address_t *a) {
166#if COAP_IPV4_SUPPORT
167 struct in_addr ipv4;
168#if !defined(ESPIDF_VERSION)
169 int i;
170 coap_tick_t now;
171#endif /* ! ESPIDF_VERSION */
172#endif /* COAP_IPV4_SUPPORT */
173
174 if (!a)
175 return 0;
176
177 switch (a->addr.sa.sa_family) {
178#if COAP_IPV4_SUPPORT
179 case AF_INET:
180 ipv4.s_addr = a->addr.sin.sin_addr.s_addr;
181 break;
182#endif /* COAP_IPV4_SUPPORT */
183#if COAP_IPV6_SUPPORT
184 case AF_INET6:
185#if COAP_IPV4_SUPPORT
186 if (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr)) {
187 memcpy(&ipv4, &a->addr.sin6.sin6_addr.s6_addr[12], sizeof(ipv4));
188 break;
189 }
190#endif /* COAP_IPV4_SUPPORT */
191 /* IPv6 does not support broadcast */
192 return 0;
193#endif /* COAP_IPV6_SUPPORT */
194 default:
195 return 0;
196 }
197#if COAP_IPV4_SUPPORT
198 if (ipv4.s_addr == INADDR_BROADCAST)
199 return 1;
200
201#if !defined(ESPIDF_VERSION)
202 coap_ticks(&now);
203 if (bcst_cnt == -1 ||
204 (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) {
205 /* Determine the list of broadcast interfaces */
206 struct ifaddrs *ifa = NULL;
207 struct ifaddrs *ife;
208
209 if (getifaddrs(&ifa) != 0) {
210 coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n");
211 return 0;
212 }
213 bcst_cnt = 0;
214 last_refresh = now;
215 ife = ifa;
216 while (ife && bcst_cnt < COAP_BCST_CNT) {
217 if (ife->ifa_addr->sa_family == AF_INET &&
218 ife->ifa_flags & IFF_BROADCAST) {
219 b_ipv4[bcst_cnt].s_addr = ((struct sockaddr_in *)ife->ifa_broadaddr)->sin_addr.s_addr;
220 bcst_cnt++;
221 }
222 ife = ife->ifa_next;
223 }
224 if (ife) {
225 coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n");
226 }
227 freeifaddrs(ifa);
228 }
229 for (i = 0; i < bcst_cnt; i++) {
230 if (ipv4.s_addr == b_ipv4[i].s_addr)
231 return 1;
232 }
233#endif /* ESPIDF_VERSION */
234 return 0;
235#endif /* COAP_IPV4_SUPPORT */
236}
237#else /* WIN32 */
238 int
239 coap_is_bcast(const coap_address_t *a) {
240 (void)a;
241 return 0;
242}
243#endif /* WIN32 || ESPIDF_VERSION */
244
245#endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */
246
247 void
248 coap_address_init(coap_address_t *addr) {
249 assert(addr);
250 memset(addr, 0, sizeof(coap_address_t));
251#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
252 /* lwip and Contiki have constant address sizes and don't need the .size part */
253 addr->size = sizeof(addr->addr);
254#endif
255}
256
257 int
258 coap_address_set_unix_domain(coap_address_t *addr,
259 const uint8_t *host, size_t host_len) {
260#if COAP_AF_UNIX_SUPPORT
261 size_t i;
262 size_t ofs = 0;
263
264 coap_address_init(addr);
265 addr->addr.cun.sun_family = AF_UNIX;
266 for (i = 0; i < host_len; i++) {
267 if ((host_len - i) >= 3 && host[i] == '%' && host[i+1] == '2' &&
268 (host[i+2] == 'F' || host[i+2] == 'f')) {
269 addr->addr.cun.sun_path[ofs++] = '/';
270 i += 2;
271 } else {
272 addr->addr.cun.sun_path[ofs++] = host[i];
273 }
274 if (ofs == COAP_UNIX_PATH_MAX)
275 break;
276 }
277 if (ofs < COAP_UNIX_PATH_MAX)
278 addr->addr.cun.sun_path[ofs] = '\000';
279 else
280 addr->addr.cun.sun_path[ofs-1] = '\000';
281 return 1;
282#else /* ! COAP_AF_UNIX_SUPPORT */
283 (void)addr;
284 (void)host;
285 (void)host_len;
286 return 0;
287#endif /* ! COAP_AF_UNIX_SUPPORT */
288}
289
290#if !defined(WITH_CONTIKI)
291 static void
292 update_port(coap_address_t *addr, uint16_t port, uint16_t default_port,
293 int update_port0) {
294 /* Client target port must be set if default of 0 */
295 if (port == 0 && update_port0)
296 port = default_port;
297
298 coap_address_set_port(addr, port);
299 return;
300}
301
302#ifdef HAVE_NETDB_H
303#include <netdb.h>
304#endif
305
306uint32_t
307 coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check,
308 coap_proto_t use_unix_proto) {
309 uint32_t scheme_hint_bits = 0;
310 coap_uri_scheme_t scheme;
311
312 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
313 switch (scheme) {
314 case COAP_URI_SCHEME_COAP:
315 scheme_hint_bits |= 1 << scheme;
316 break;
317 case COAP_URI_SCHEME_COAPS:
318 if (!(coap_dtls_is_supported() && have_pki_psk))
319 continue;
320 scheme_hint_bits |= 1 << scheme;
321 break;
322 case COAP_URI_SCHEME_COAP_TCP:
323 if (!coap_tcp_is_supported())
324 continue;
325 scheme_hint_bits |= 1 << scheme;
326 break;
327 case COAP_URI_SCHEME_COAPS_TCP:
328 if (!(coap_tls_is_supported() && have_pki_psk))
329 continue;
330 scheme_hint_bits |= 1 << scheme;
331 break;
332 case COAP_URI_SCHEME_COAP_WS:
333 if (!ws_check || !coap_ws_is_supported())
334 continue;
335 scheme_hint_bits |= 1 << scheme;
336 break;
337 case COAP_URI_SCHEME_COAPS_WS:
338 if (!ws_check || !(coap_wss_is_supported() && have_pki_psk))
339 continue;
340 scheme_hint_bits |= 1 << scheme;
341 break;
342 case COAP_URI_SCHEME_HTTP:
343 case COAP_URI_SCHEME_HTTPS:
344 case COAP_URI_SCHEME_LAST:
345 default:
346 continue;
347 }
348 }
349
350 switch (use_unix_proto) {
351 /* For AF_UNIX, can only listen on a single endpoint */
352 case COAP_PROTO_UDP:
353 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP;
354 break;
355 case COAP_PROTO_TCP:
356 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_TCP;
357 break;
358 case COAP_PROTO_DTLS:
359 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS;
360 break;
361 case COAP_PROTO_TLS:
362 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_TCP;
363 break;
364 case COAP_PROTO_WS:
365 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_WS;
366 break;
367 case COAP_PROTO_WSS:
368 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_WS;
369 break;
370 case COAP_PROTO_NONE: /* If use_unix_proto was not defined */
371 case COAP_PROTO_LAST:
372 default:
373 break;
374 }
375 return scheme_hint_bits;
376}
377
378 coap_addr_info_t *
379 coap_resolve_address_info(const coap_str_const_t *address,
380 uint16_t port,
381 uint16_t secure_port,
382 uint16_t ws_port,
383 uint16_t ws_secure_port,
384 int ai_hints_flags,
385 int scheme_hint_bits,
386 coap_resolve_type_t type) {
387#if !defined(RIOT_VERSION)
388
389 struct addrinfo *res, *ainfo;
390 struct addrinfo hints;
391 static char addrstr[256];
392 int error;
393 coap_addr_info_t *info = NULL;
394 coap_addr_info_t *info_prev = NULL;
395 coap_addr_info_t *info_list = NULL;
396 coap_addr_info_t *info_tmp;
397 coap_uri_scheme_t scheme;
398 coap_proto_t proto = 0;
399
400#if COAP_AF_UNIX_SUPPORT
401 if (address && coap_host_is_unix_domain(address)) {
402 /* There can only be one unique filename entry for AF_UNIX */
403 if (address->length >= COAP_UNIX_PATH_MAX) {
404 coap_log_err("Unix Domain host too long\n");
405 return NULL;
406 }
407 /* Need to chose the first defined one in scheme_hint_bits */
408 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
409 if (scheme_hint_bits & (1 << scheme)) {
410 break;
411 }
412 }
413 if (scheme == COAP_URI_SCHEME_LAST) {
414 return NULL;
415 }
416 switch (scheme) {
417 case COAP_URI_SCHEME_COAP:
418 proto = COAP_PROTO_UDP;
419 break;
420 case COAP_URI_SCHEME_COAPS:
421 if (!coap_dtls_is_supported())
422 return NULL;
423 proto = COAP_PROTO_DTLS;
424 break;
425 case COAP_URI_SCHEME_COAP_TCP:
426 if (!coap_tcp_is_supported())
427 return NULL;
428 proto = COAP_PROTO_TCP;
429 break;
430 case COAP_URI_SCHEME_COAPS_TCP:
431 if (!coap_tls_is_supported())
432 return NULL;
433 proto = COAP_PROTO_TLS;
434 break;
435 case COAP_URI_SCHEME_HTTP:
436 if (!coap_tcp_is_supported())
437 return NULL;
438 proto = COAP_PROTO_NONE;
439 break;
440 case COAP_URI_SCHEME_HTTPS:
441 if (!coap_tls_is_supported())
442 return NULL;
443 proto = COAP_PROTO_NONE;
444 break;
445 case COAP_URI_SCHEME_COAP_WS:
446 if (!coap_ws_is_supported())
447 return NULL;
448 proto = COAP_PROTO_WS;
449 break;
450 case COAP_URI_SCHEME_COAPS_WS:
451 if (!coap_wss_is_supported())
452 return NULL;
453 proto = COAP_PROTO_WSS;
454 break;
455 case COAP_URI_SCHEME_LAST:
456 default:
457 return NULL;
458 }
459 info = coap_malloc_type(COAP_STRING, sizeof(coap_addr_info_t));
460 if (info == NULL)
461 return NULL;
462 info->next = NULL;
463 info->proto = proto;
464 info->scheme = scheme;
465
466 coap_address_init(&info->addr);
467 if (!coap_address_set_unix_domain(&info->addr, address->s,
468 address->length)) {
469 coap_free_type(COAP_STRING, info);
470 return NULL;
471 }
472 return info;
473 }
474#endif /* COAP_AF_UNIX_SUPPORT */
475
476 memset(addrstr, 0, sizeof(addrstr));
477 if (address && address->length)
478 memcpy(addrstr, address->s, address->length);
479 else
480 memcpy(addrstr, "localhost", 9);
481
482 memset((char *)&hints, 0, sizeof(hints));
483 hints.ai_socktype = 0;
484 hints.ai_family = AF_UNSPEC;
485 hints.ai_flags = ai_hints_flags;
486
487 error = getaddrinfo(addrstr, NULL, &hints, &res);
488
489 if (error != 0) {
490 coap_log_warn("getaddrinfo: %s\n", gai_strerror(error));
491 return NULL;
492 }
493
494 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
495#if !defined(WITH_LWIP)
496 if (ainfo->ai_addrlen > (socklen_t)sizeof(info->addr.addr))
497 continue;
498#endif /* ! WITH_LWIP */
499
500 switch (ainfo->ai_family) {
501#if COAP_IPV4_SUPPORT
502 case AF_INET:
503#endif /* COAP_IPV4_SUPPORT */
504#if COAP_IPV6_SUPPORT
505 case AF_INET6:
506#endif /* COAP_IPV6_SUPPORT */
507 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
508 if (scheme_hint_bits & (1 << scheme)) {
509 switch (scheme) {
510 case COAP_URI_SCHEME_COAP:
511 proto = COAP_PROTO_UDP;
512 break;
513 case COAP_URI_SCHEME_COAPS:
514 if (!coap_dtls_is_supported())
515 continue;
516 proto = COAP_PROTO_DTLS;
517 break;
518 case COAP_URI_SCHEME_COAP_TCP:
519 if (!coap_tcp_is_supported())
520 continue;
521 proto = COAP_PROTO_TCP;
522 break;
523 case COAP_URI_SCHEME_COAPS_TCP:
524 if (!coap_tls_is_supported())
525 continue;
526 proto = COAP_PROTO_TLS;
527 break;
528 case COAP_URI_SCHEME_HTTP:
529 if (!coap_tcp_is_supported())
530 continue;
531 proto = COAP_PROTO_NONE;
532 break;
533 case COAP_URI_SCHEME_HTTPS:
534 if (!coap_tls_is_supported())
535 continue;
536 proto = COAP_PROTO_NONE;
537 break;
538 case COAP_URI_SCHEME_COAP_WS:
539 if (!coap_ws_is_supported())
540 continue;
541 proto = COAP_PROTO_WS;
542 break;
543 case COAP_URI_SCHEME_COAPS_WS:
544 if (!coap_wss_is_supported())
545 continue;
546 proto = COAP_PROTO_WSS;
547 break;
548 case COAP_URI_SCHEME_LAST:
549 default:
550 continue;
551 }
552
553 info = coap_malloc_type(COAP_STRING, sizeof(coap_addr_info_t));
554 if (info == NULL) {
555 freeaddrinfo(res);
556 /* malloc failure - return what we have so far */
557 return info_list;
558 }
559
560 info->next = NULL;
561 info->scheme = scheme;
562 info->proto = proto;
563 coap_address_init(&info->addr);
564#if !defined(WITH_LWIP)
565 info->addr.size = (socklen_t)ainfo->ai_addrlen;
566 memcpy(&info->addr.addr, ainfo->ai_addr, ainfo->ai_addrlen);
567#else /* WITH_LWIP */
568 memset(&info->addr, 0, sizeof(info->addr));
569 switch (ainfo->ai_family) {
570#if COAP_IPV6_SUPPORT
571 struct sockaddr_in6 *sock6;
572#endif /* COAP_IPV6_SUPPORT */
573#if COAP_IPV4_SUPPORT
574 struct sockaddr_in *sock4;
575 case AF_INET:
576 sock4 = (struct sockaddr_in *)ainfo->ai_addr;
577 info->addr.port = ntohs(sock4->sin_port);
578 memcpy(&info->addr.addr, &sock4->sin_addr, 4);
579#if LWIP_IPV6
580 info->addr.addr.type = IPADDR_TYPE_V4;
581#endif /* LWIP_IPV6 */
582 break;
583#endif /* COAP_IPV4_SUPPORT */
584#if COAP_IPV6_SUPPORT
585 case AF_INET6:
586 sock6 = (struct sockaddr_in6 *)ainfo->ai_addr;
587 info->addr.port = ntohs(sock6->sin6_port);
588 memcpy(&info->addr.addr, &sock6->sin6_addr, 16);
589#if LWIP_IPV6 && LWIP_IPV4
590 info->addr.addr.type = IPADDR_TYPE_V6;
591#endif /* LWIP_IPV6 && LWIP_IPV4 */
592 break;
593#endif /* COAP_IPV6_SUPPORT */
594 default:
595 ;
596 }
597#endif /* WITH_LWIP */
598 switch (scheme) {
599 case COAP_URI_SCHEME_COAP:
600 update_port(&info->addr, port, COAP_DEFAULT_PORT,
601 type == COAP_RESOLVE_TYPE_LOCAL);
602 break;
603 case COAP_URI_SCHEME_COAPS:
604 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
605 type == COAP_RESOLVE_TYPE_LOCAL);
606 break;
607 case COAP_URI_SCHEME_COAP_TCP:
608 update_port(&info->addr, port, COAP_DEFAULT_PORT,
609 type == COAP_RESOLVE_TYPE_LOCAL);
610 break;
611 case COAP_URI_SCHEME_COAPS_TCP:
612 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
613 type == COAP_RESOLVE_TYPE_LOCAL);
614 break;
615 case COAP_URI_SCHEME_HTTP:
616 update_port(&info->addr, port, 80,
617 type == COAP_RESOLVE_TYPE_LOCAL);
618 break;
619 case COAP_URI_SCHEME_HTTPS:
620 update_port(&info->addr, secure_port, 443,
621 type == COAP_RESOLVE_TYPE_LOCAL);
622 break;
623 case COAP_URI_SCHEME_COAP_WS:
624 update_port(&info->addr, ws_port, 80,
625 type == COAP_RESOLVE_TYPE_LOCAL);
626 break;
627 case COAP_URI_SCHEME_COAPS_WS:
628 update_port(&info->addr, ws_secure_port, 443,
629 type == COAP_RESOLVE_TYPE_LOCAL);
630 break;
631 case COAP_URI_SCHEME_LAST:
632 default:
633 break;
634 }
635
636 /* Check there are no duplications */
637 info_tmp = info_list;
638 while (info_tmp) {
639 if (info_tmp->proto == info->proto &&
640 info_tmp->scheme == info->scheme &&
641 coap_address_equals(&info_tmp->addr, &info->addr)) {
642 break;
643 }
644 info_tmp = info_tmp->next;
645 }
646
647 if (info_tmp) {
648 /* Duplicate */
649 coap_free_type(COAP_STRING, info);
650 } else {
651 /* Need to return in same order as getaddrinfo() */
652 if (!info_prev) {
653 info_list = info;
654 info_prev = info;
655 } else {
656 info_prev->next = info;
657 info_prev = info;
658 }
659 }
660 }
661 }
662 break;
663 default:
664 break;
665 }
666 }
667
668 freeaddrinfo(res);
669 return info_list;
670#else /* RIOT_VERSION */
671#if COAP_IPV6_SUPPORT
672#include "net/utils.h"
673 ipv6_addr_t addr_ipv6;
674 netif_t *netif = NULL;
675 coap_addr_info_t *info = NULL;
676 coap_addr_info_t *info_prev = NULL;
677 coap_addr_info_t *info_list = NULL;
678 coap_uri_scheme_t scheme;
679 coap_proto_t proto = 0;
680 (void)ai_hints_flags;
681
682 if (netutils_get_ipv6(&addr_ipv6, &netif, (const char *)address->s) >= 0) {
683 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
684 if (scheme_hint_bits & (1 << scheme)) {
685 switch (scheme) {
686 case COAP_URI_SCHEME_COAP:
687 proto = COAP_PROTO_UDP;
688 break;
689 case COAP_URI_SCHEME_COAPS:
690 if (!coap_dtls_is_supported())
691 continue;
692 proto = COAP_PROTO_DTLS;
693 break;
694 case COAP_URI_SCHEME_COAP_TCP:
695 if (!coap_tcp_is_supported())
696 continue;
697 proto = COAP_PROTO_TCP;
698 break;
699 case COAP_URI_SCHEME_COAPS_TCP:
700 if (!coap_tls_is_supported())
701 continue;
702 proto = COAP_PROTO_TLS;
703 break;
704 case COAP_URI_SCHEME_HTTP:
705 if (!coap_tcp_is_supported())
706 continue;
707 proto = COAP_PROTO_NONE;
708 break;
709 case COAP_URI_SCHEME_HTTPS:
710 if (!coap_tls_is_supported())
711 continue;
712 proto = COAP_PROTO_NONE;
713 break;
714 case COAP_URI_SCHEME_COAP_WS:
715 if (!coap_ws_is_supported())
716 continue;
717 proto = COAP_PROTO_WS;
718 break;
719 case COAP_URI_SCHEME_COAPS_WS:
720 if (!coap_wss_is_supported())
721 continue;
722 proto = COAP_PROTO_WSS;
723 break;
724 case COAP_URI_SCHEME_LAST:
725 default:
726 continue;
727 }
728
729 info = coap_malloc_type(COAP_STRING, sizeof(coap_addr_info_t));
730 if (info == NULL) {
731 /* malloc failure - return what we have so far */
732 return info_list;
733 }
734 info->next = NULL;
735 /* Need to return in same order as getaddrinfo() */
736 if (!info_prev) {
737 info_list = info;
738 info_prev = info;
739 } else {
740 info_prev->next = info;
741 info_prev = info;
742 }
743
744 info->scheme = scheme;
745 info->proto = proto;
746 coap_address_init(&info->addr);
747 info->addr.size = sizeof(struct sockaddr_in6);
748 info->addr.addr.sin6.sin6_family = AF_INET6;
749 memcpy(&info->addr.addr.sin6.sin6_addr, &addr_ipv6,
750 sizeof(info->addr.addr.sin6.sin6_addr));
751 info->addr.addr.sin6.sin6_scope_id = (uint32_t)netif_get_id(netif);
752 switch (scheme) {
753 case COAP_URI_SCHEME_COAP:
754 update_port(&info->addr, port, COAP_DEFAULT_PORT,
755 type == COAP_RESOLVE_TYPE_LOCAL);
756 break;
757 case COAP_URI_SCHEME_COAPS:
758 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
759 type == COAP_RESOLVE_TYPE_LOCAL);
760 break;
761 case COAP_URI_SCHEME_COAP_TCP:
762 update_port(&info->addr, port, COAP_DEFAULT_PORT,
763 type == COAP_RESOLVE_TYPE_LOCAL);
764 break;
765 case COAP_URI_SCHEME_COAPS_TCP:
766 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
767 type == COAP_RESOLVE_TYPE_LOCAL);
768 break;
769 case COAP_URI_SCHEME_HTTP:
770 update_port(&info->addr, port, ws_port,
771 type == COAP_RESOLVE_TYPE_LOCAL);
772 break;
773 case COAP_URI_SCHEME_HTTPS:
774 update_port(&info->addr, secure_port, ws_secure_port,
775 type == COAP_RESOLVE_TYPE_LOCAL);
776 break;
777 case COAP_URI_SCHEME_LAST:
778 default:
779 break;
780 }
781 }
782 }
783 return info_list;
784 }
785#endif /* COAP_IPV6_SUPPORT */
786 return NULL;
787#endif /* RIOT_VERSION */
788}
789#endif /* !WITH_CONTIKI */
790
791 void
792 coap_free_address_info(coap_addr_info_t *info) {
793 while (info) {
794 coap_addr_info_t *info_next = info->next;
795
796 coap_free_type(COAP_STRING, info);
797 info = info_next;
798 }
799}
800
801#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
802 void
803 coap_address_copy(coap_address_t *dst, const coap_address_t *src) {
804#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
805 memcpy(dst, src, sizeof(coap_address_t));
806#else
807 memset(dst, 0, sizeof(coap_address_t));
808 dst->size = src->size;
809#if COAP_IPV6_SUPPORT
810 if (src->addr.sa.sa_family == AF_INET6) {
811 dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family;
812 dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr;
813 dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port;
814 dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id;
815 }
816#endif /* COAP_IPV6_SUPPORT */
817#if COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT
818 else
819#endif /* COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT */
820#if COAP_IPV4_SUPPORT
821 if (src->addr.sa.sa_family == AF_INET) {
822 dst->addr.sin = src->addr.sin;
823 }
824#endif /* COAP_IPV4_SUPPORT */
825 else {
826 memcpy(&dst->addr, &src->addr, src->size);
827 }
828#endif
829}
830
831 int
832_coap_address_isany_impl(const coap_address_t *a) {
833 /* need to compare only relevant parts of sockaddr_in6 */
834 switch (a->addr.sa.sa_family) {
835#if COAP_IPV4_SUPPORT
836 case AF_INET:
837 return a->addr.sin.sin_addr.s_addr == INADDR_ANY;
838#endif /* COAP_IPV4_SUPPORT */
839#if COAP_IPV6_SUPPORT
840 case AF_INET6:
841 return memcmp(&in6addr_any,
842 &a->addr.sin6.sin6_addr,
843 sizeof(in6addr_any)) == 0;
844#endif /* COAP_IPV6_SUPPORT */
845 default:
846 ;
847 }
848
849 return 0;
850}
851#endif /* ! WITH_LWIP && ! WITH_CONTIKI */
coap_address_set_port
void coap_address_set_port(coap_address_t *addr, uint16_t port)
Set the port field of addr to port (in host byte order).
Definition: coap_address.c:56
coap_address_set_unix_domain
int coap_address_set_unix_domain(coap_address_t *addr, const uint8_t *host, size_t host_len)
Copy the parsed unix domain host into coap_address_t structure translating %2F into / on the way.
Definition: coap_address.c:258
COAP_BCST_REFRESH_SECS
#define COAP_BCST_REFRESH_SECS
Definition: coap_address.c:150
coap_free_address_info
void coap_free_address_info(coap_addr_info_t *info)
Free off the one or more linked sets of coap_addr_info_t returned from coap_resolve_address_info().
Definition: coap_address.c:792
coap_is_af_unix
int coap_is_af_unix(const coap_address_t *a)
Checks if given address a denotes a AF_UNIX address.
Definition: coap_address.c:103
coap_is_bcast
int coap_is_bcast(const coap_address_t *a)
Checks if given address a denotes a broadcast address.
Definition: coap_address.c:165
coap_address_init
void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: coap_address.c:248
coap_is_mcast
int coap_is_mcast(const coap_address_t *a)
Checks if given address a denotes a multicast address.
Definition: coap_address.c:113
_coap_address_isany_impl
int _coap_address_isany_impl(const coap_address_t *a)
Definition: coap_address.c:832
coap_address_get_port
uint16_t coap_address_get_port(const coap_address_t *addr)
Returns the port from addr in host byte order.
Definition: coap_address.c:38
coap_get_available_scheme_hint_bits
uint32_t coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check, coap_proto_t use_unix_proto)
Determine and set up scheme_hint_bits for a server that can be used in a call to coap_resolve_address...
Definition: coap_address.c:307
coap_resolve_address_info
coap_addr_info_t * coap_resolve_address_info(const coap_str_const_t *address, uint16_t port, uint16_t secure_port, uint16_t ws_port, uint16_t ws_secure_port, int ai_hints_flags, int scheme_hint_bits, coap_resolve_type_t type)
Resolve the specified address into a set of coap_address_t that can be used to bind() (local) or conn...
Definition: coap_address.c:379
COAP_BCST_CNT
#define COAP_BCST_CNT
Definition: coap_address.c:145
coap_address_copy
void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
Definition: coap_address.c:803
coap_address_equals
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
Definition: coap_address.c:75
update_port
static void update_port(coap_address_t *addr, uint16_t port, uint16_t default_port, int update_port0)
Definition: coap_address.c:292
coap_resolve_type_t
coap_resolve_type_t
coap_resolve_type_t values
Definition: coap_address.h:166
COAP_RESOLVE_TYPE_LOCAL
@ COAP_RESOLVE_TYPE_LOCAL
local side of session
Definition: coap_address.h:167
COAP_UNIX_PATH_MAX
#define COAP_UNIX_PATH_MAX
Definition: coap_address.h:101
coap_internal.h
Pulls together all the internal only header files.
COAP_STRING
@ COAP_STRING
Definition: coap_mem.h:38
coap_malloc_type
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
coap_free_type
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
coap_tcp_is_supported
int coap_tcp_is_supported(void)
Check whether TCP is available.
Definition: coap_tcp.c:37
coap_host_is_unix_domain
int coap_host_is_unix_domain(const coap_str_const_t *host)
Determines from the host whether this is a Unix Domain socket request.
Definition: coap_uri.c:386
coap_uri_scheme_t
coap_uri_scheme_t
The scheme specifiers.
Definition: coap_uri.h:28
COAP_URI_SCHEME_COAPS_WS
@ COAP_URI_SCHEME_COAPS_WS
Definition: coap_uri.h:36
COAP_URI_SCHEME_COAPS_TCP
@ COAP_URI_SCHEME_COAPS_TCP
Definition: coap_uri.h:32
COAP_URI_SCHEME_COAPS
@ COAP_URI_SCHEME_COAPS
Definition: coap_uri.h:30
COAP_URI_SCHEME_COAP_TCP
@ COAP_URI_SCHEME_COAP_TCP
Definition: coap_uri.h:31
COAP_URI_SCHEME_COAP_WS
@ COAP_URI_SCHEME_COAP_WS
Definition: coap_uri.h:35
COAP_URI_SCHEME_HTTPS
@ COAP_URI_SCHEME_HTTPS
Definition: coap_uri.h:34
COAP_URI_SCHEME_COAP
@ COAP_URI_SCHEME_COAP
Definition: coap_uri.h:29
COAP_URI_SCHEME_LAST
@ COAP_URI_SCHEME_LAST
Definition: coap_uri.h:37
COAP_URI_SCHEME_HTTP
@ COAP_URI_SCHEME_HTTP
Definition: coap_uri.h:33
coap_tick_t
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:144
COAP_TICKS_PER_SECOND
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition: coap_time.h:159
coap_ticks
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
coap_tls_is_supported
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:28
coap_dtls_is_supported
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:23
coap_log_warn
#define coap_log_warn(...)
Definition: coap_debug.h:102
coap_log_err
#define coap_log_err(...)
Definition: coap_debug.h:96
COAP_DEFAULT_PORT
#define COAP_DEFAULT_PORT
Definition: coap_pdu.h:37
coap_proto_t
coap_proto_t
CoAP protocol types.
Definition: coap_pdu.h:304
COAPS_DEFAULT_PORT
#define COAPS_DEFAULT_PORT
Definition: coap_pdu.h:38
COAP_PROTO_WS
@ COAP_PROTO_WS
Definition: coap_pdu.h:310
COAP_PROTO_DTLS
@ COAP_PROTO_DTLS
Definition: coap_pdu.h:307
COAP_PROTO_UDP
@ COAP_PROTO_UDP
Definition: coap_pdu.h:306
COAP_PROTO_NONE
@ COAP_PROTO_NONE
Definition: coap_pdu.h:305
COAP_PROTO_TLS
@ COAP_PROTO_TLS
Definition: coap_pdu.h:309
COAP_PROTO_WSS
@ COAP_PROTO_WSS
Definition: coap_pdu.h:311
COAP_PROTO_TCP
@ COAP_PROTO_TCP
Definition: coap_pdu.h:308
COAP_PROTO_LAST
@ COAP_PROTO_LAST
Definition: coap_pdu.h:312
coap_ws_is_supported
int coap_ws_is_supported(void)
Check whether WebSockets is available.
Definition: coap_ws.c:935
coap_wss_is_supported
int coap_wss_is_supported(void)
Check whether Secure WebSockets is available.
Definition: coap_ws.c:940
coap_addr_info_t
Resolved addresses information.
Definition: coap_address.h:140
coap_addr_info_t::scheme
coap_uri_scheme_t scheme
CoAP scheme to use.
Definition: coap_address.h:142
coap_addr_info_t::proto
coap_proto_t proto
CoAP protocol to use.
Definition: coap_address.h:143
coap_addr_info_t::next
struct coap_addr_info_t * next
Next entry in the chain.
Definition: coap_address.h:141
coap_addr_info_t::addr
coap_address_t addr
The address to connect / bind to.
Definition: coap_address.h:144
coap_address_t
Multi-purpose address abstraction.
Definition: coap_address.h:109
coap_address_t::size
socklen_t size
size of addr
Definition: coap_address.h:110
coap_address_t::sin
struct sockaddr_in sin
Definition: coap_address.h:113
coap_address_t::cun
struct coap_sockaddr_un cun
Definition: coap_address.h:115
coap_address_t::sin6
struct sockaddr_in6 sin6
Definition: coap_address.h:114
coap_address_t::sa
struct sockaddr sa
Definition: coap_address.h:112
coap_address_t::addr
union coap_address_t::@0 addr
coap_sockaddr_un::sun_path
char sun_path[COAP_UNIX_PATH_MAX]
Definition: coap_address.h:105
coap_sockaddr_un::sun_family
sa_family_t sun_family
Definition: coap_address.h:104
coap_str_const_t
CoAP string data definition with const data.
Definition: coap_str.h:46
coap_str_const_t::s
const uint8_t * s
read-only string data
Definition: coap_str.h:48
coap_str_const_t::length
size_t length
length of string
Definition: coap_str.h:47