libcoap 4.3.5-develop-022e848
Loading...
Searching...
No Matches
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-2025 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
17
18#if !defined(WITH_CONTIKI) && !defined(WITH_LWIP) && !defined(RIOT_VERSION)
19#ifndef __ZEPHYR__
20#ifdef HAVE_ARPA_INET_H
21#include <arpa/inet.h>
22#endif
23#ifdef HAVE_NETINET_IN_H
24#include <netinet/in.h>
25#endif
26#ifdef HAVE_SYS_SOCKET_H
27#include <sys/socket.h>
28#endif
29#ifdef HAVE_NET_IF_H
30#include <net/if.h>
31#endif
32#ifdef HAVE_IFADDRS_H
33#include <ifaddrs.h>
34#endif
35#ifdef HAVE_WS2TCPIP_H
36#include <ws2tcpip.h>
37#endif
38#else /* __ZEPHYR__ */
39#ifndef IN_MULTICAST
40#define IN_MULTICAST(a) ((((long int) (a)) & 0xf0000000) == 0xe0000000)
41#endif
42#ifndef IN6_IS_ADDR_MULTICAST
43#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
44#endif
45#ifndef IN6_IS_ADDR_V4MAPPED
46#define IN6_IS_ADDR_V4MAPPED(a) \
47 ((((a)->s6_addr32[0]) == 0) && (((a)->s6_addr32[1]) == 0) && \
48 (((a)->s6_addr32[2]) == htonl(0xffff)))
49#endif
50#endif /* __ZEPHYR__ */
51
52#ifdef RIOT_VERSION
53/* FIXME */
54#define IN_MULTICAST(Address) (0)
55#endif /* RIOT_VERSION */
56
57uint16_t
59 assert(addr != NULL);
60 switch (addr->addr.sa.sa_family) {
61#if COAP_IPV4_SUPPORT
62 case AF_INET:
63 return ntohs(addr->addr.sin.sin_port);
64#endif /* COAP_IPV4_SUPPORT */
65#if COAP_IPV6_SUPPORT
66 case AF_INET6:
67 return ntohs(addr->addr.sin6.sin6_port);
68#endif /* COAP_IPV6_SUPPORT */
69 default: /* undefined */
70 ;
71 }
72 return 0;
73}
74
75void
77 assert(addr != NULL);
78 switch (addr->addr.sa.sa_family) {
79#if COAP_IPV4_SUPPORT
80 case AF_INET:
81 addr->addr.sin.sin_port = htons(port);
82 break;
83#endif /* COAP_IPV4_SUPPORT */
84#if COAP_IPV6_SUPPORT
85 case AF_INET6:
86 addr->addr.sin6.sin6_port = htons(port);
87 break;
88#endif /* COAP_IPV6_SUPPORT */
89 default: /* undefined */
90 ;
91 }
92}
93
94int
96 assert(a);
97 assert(b);
98
99 if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
100 return 0;
101
102 /* need to compare only relevant parts of sockaddr_in6 */
103 switch (a->addr.sa.sa_family) {
104#if COAP_IPV4_SUPPORT
105 case AF_INET:
106 return a->addr.sin.sin_port == b->addr.sin.sin_port &&
107 memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
108 sizeof(struct in_addr)) == 0;
109#endif /* COAP_IPV4_SUPPORT */
110#if COAP_IPV6_SUPPORT
111 case AF_INET6:
112 return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
113 memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
114 sizeof(struct in6_addr)) == 0;
115#endif /* COAP_IPV6_SUPPORT */
116#if COAP_AF_UNIX_SUPPORT
117 case AF_UNIX:
118 return memcmp(&a->addr.cun.sun_path, &b->addr.cun.sun_path,
119 sizeof(a->addr.cun.sun_path)) == 0;
120#endif /* COAP_AF_UNIX_SUPPORT */
121 default: /* fall through and signal error */
122 ;
123 }
124 return 0;
125}
126
127int
129#if COAP_AF_UNIX_SUPPORT
130 return a->addr.sa.sa_family == AF_UNIX;
131#else /* ! COAP_AF_UNIX_SUPPORT */
132 (void)a;
133 return 0;
134#endif /* ! COAP_AF_UNIX_SUPPORT */
135}
136
137int
139 if (!a)
140 return 0;
141
142 /* Treat broadcast in same way as multicast */
143 if (coap_is_bcast(a))
144 return 1;
145
146 switch (a->addr.sa.sa_family) {
147#if COAP_IPV4_SUPPORT
148 case AF_INET:
149 return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr));
150#endif /* COAP_IPV4_SUPPORT */
151#if COAP_IPV6_SUPPORT
152 case AF_INET6:
153#if COAP_IPV4_SUPPORT
154 return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr) ||
155 (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr) &&
156 IN_MULTICAST(ntohl(a->addr.sin6.sin6_addr.s6_addr[12])));
157#else /* ! COAP_IPV4_SUPPORT */
158 return a->addr.sin6.sin6_addr.s6_addr[0] == 0xff;
159#endif /* ! COAP_IPV4_SUPPORT */
160#endif /* COAP_IPV6_SUPPORT */
161 default: /* fall through and signal not multicast */
162 ;
163 }
164 return 0;
165}
166
167#ifndef COAP_BCST_CNT
168#define COAP_BCST_CNT 15
169#endif /* COAP_BCST_CNT */
170
171/* How frequently to refresh the list of valid IPv4 broadcast addresses */
172#ifndef COAP_BCST_REFRESH_SECS
173#define COAP_BCST_REFRESH_SECS 30
174#endif /* COAP_BCST_REFRESH_SECS */
175
176#if (COAP_IPV4_SUPPORT && defined(HAVE_IFADDRS_H) && !defined(__ZEPHYR__)) || defined(_WIN32)
177static int bcst_cnt = -1;
178static coap_tick_t last_refresh;
179static struct in_addr b_ipv4[COAP_BCST_CNT];
180#endif /* (COAP_IPV4_SUPPORT && HAVE_IFADDRS_H && !defined(__ZEPHYR__)) || defined(_WIN32) */
181
182int
184#if COAP_IPV4_SUPPORT
185 struct in_addr ipv4;
186#if defined(HAVE_IFADDRS_H) && !defined(__ZEPHYR__)
187 int i;
188 coap_tick_t now;
189#endif /* HAVE_IFADDRS_H && !defined(__ZEPHYR__) */
190#endif /* COAP_IPV4_SUPPORT */
191
192 if (!a)
193 return 0;
194
195 switch (a->addr.sa.sa_family) {
196#if COAP_IPV4_SUPPORT
197 case AF_INET:
198 ipv4.s_addr = a->addr.sin.sin_addr.s_addr;
199 break;
200#endif /* COAP_IPV4_SUPPORT */
201#if COAP_IPV6_SUPPORT
202 case AF_INET6:
203#if COAP_IPV4_SUPPORT
204 if (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr)) {
205 memcpy(&ipv4, &a->addr.sin6.sin6_addr.s6_addr[12], sizeof(ipv4));
206 break;
207 }
208#endif /* COAP_IPV4_SUPPORT */
209 /* IPv6 does not support broadcast */
210 return 0;
211#endif /* COAP_IPV6_SUPPORT */
212 default:
213 return 0;
214 }
215#if COAP_IPV4_SUPPORT
216#ifndef INADDR_BROADCAST
217#define INADDR_BROADCAST ((uint32_t)0xffffffffUL)
218#endif /* !INADDR_BROADCAST */
219 if (ipv4.s_addr == INADDR_BROADCAST)
220 return 1;
221
222#if defined(HAVE_IFADDRS_H) && !defined(__ZEPHYR__) && !defined(_WIN32)
223 coap_ticks(&now);
224 if (bcst_cnt == -1 ||
225 (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) {
226 /* Determine the list of broadcast interfaces */
227 struct ifaddrs *ifa = NULL;
228 struct ifaddrs *ife;
229
230 if (getifaddrs(&ifa) != 0) {
231 coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n");
232 return 0;
233 }
234 bcst_cnt = 0;
235 last_refresh = now;
236 ife = ifa;
237 while (ife && bcst_cnt < COAP_BCST_CNT) {
238 if (ife->ifa_addr && ife->ifa_addr->sa_family == AF_INET &&
239 ife->ifa_flags & IFF_BROADCAST) {
240 struct in_addr netmask;
241
242 /*
243 * Sometimes the broadcast IP is set to the IP address, even though
244 * netmask is not set to 0xffffffff, so unsafe to use ifa_broadaddr.
245 */
246 netmask.s_addr = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr.s_addr;
247 if (netmask.s_addr != 0xffffffff) {
248 b_ipv4[bcst_cnt].s_addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr |
249 ~netmask.s_addr;
250 bcst_cnt++;
251 }
252 }
253 ife = ife->ifa_next;
254 }
255 if (ife) {
256 coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n");
257 }
258 freeifaddrs(ifa);
259 }
260 for (i = 0; i < bcst_cnt; i++) {
261 if (ipv4.s_addr == b_ipv4[i].s_addr)
262 return 1;
263 }
264#endif /* HAVE_IFADDRS_H && !defined(__ZEPHYR__) && !defined(_WIN32) */
265
266#if defined(_WIN32)
267
268#include <iphlpapi.h>
269#if !defined(__MINGW32__)
270#pragma comment(lib, "iphlpapi.lib")
271#endif /* ! __MINGW32__ */
272
273 int i;
274 coap_tick_t now;
275
276 coap_ticks(&now);
277 if (bcst_cnt == -1 ||
278 (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) {
279 /* Determine the list of broadcast interfaces */
280
281 /* Variables used by GetIpAddrTable */
282 PMIB_IPADDRTABLE pIPAddrTable;
283 DWORD dwSize = 0;
284 DWORD dwRetVal = 0;
285
286 /* Assume just 2 interfaces as a starting point */
287 pIPAddrTable = (MIB_IPADDRTABLE *)coap_malloc_type(COAP_STRING, 2 * sizeof(MIB_IPADDRTABLE));
288
289 if (pIPAddrTable) {
290 /* Check that 2 interfaces are sufficient */
291 if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
292 coap_free_type(COAP_STRING, pIPAddrTable);
293 pIPAddrTable = (MIB_IPADDRTABLE *)coap_malloc_type(COAP_STRING, dwSize);
294
295 }
296 if (pIPAddrTable == NULL) {
297 coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n");
298 return 0;
299 }
300 }
301 /* Now get the actual data */
302 if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
303 coap_log_warn("GetIpAddrTable failed with error %d\n", dwRetVal);
304 return 0;
305 }
306
307 bcst_cnt = 0;
308 last_refresh = now;
309
310 for (i = 0; i < (int)pIPAddrTable->dwNumEntries && bcst_cnt < COAP_BCST_CNT; i++) {
311 struct in_addr netmask;
312
313 /* Unsafe to use dwBCastAddr */
314 netmask.s_addr = (u_long)pIPAddrTable->table[i].dwMask;
315 if (netmask.s_addr != 0xffffffff) {
316 b_ipv4[bcst_cnt].s_addr = (u_long)pIPAddrTable->table[i].dwAddr |
317 ~netmask.s_addr;
318 bcst_cnt++;
319 }
320 }
321 if (i != (int)pIPAddrTable->dwNumEntries) {
322 coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n");
323 }
324
325 if (pIPAddrTable) {
326 coap_free_type(COAP_STRING, pIPAddrTable);
327 pIPAddrTable = NULL;
328 }
329 }
330
331 for (i = 0; i < bcst_cnt; i++) {
332 if (ipv4.s_addr == b_ipv4[i].s_addr)
333 return 1;
334 }
335#endif /* _WIN32 */
336
337#endif /* COAP_IPV4_SUPPORT */
338 return 0;
339}
340
341#endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */
342
343void
345 assert(addr);
346 memset(addr, 0, sizeof(coap_address_t));
347#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
348 /* lwip and Contiki have constant address sizes and don't need the .size part */
349 addr->size = sizeof(addr->addr);
350#endif
351}
352
353int
355 const uint8_t *host, size_t host_len) {
356#if COAP_AF_UNIX_SUPPORT
357 size_t i;
358 size_t ofs = 0;
359
360 coap_address_init(addr);
361 addr->addr.cun.sun_family = AF_UNIX;
362 for (i = 0; i < host_len; i++) {
363 if ((host_len - i) >= 3 && host[i] == '%' && host[i+1] == '2' &&
364 (host[i+2] == 'F' || host[i+2] == 'f')) {
365 addr->addr.cun.sun_path[ofs++] = '/';
366 i += 2;
367 } else {
368 addr->addr.cun.sun_path[ofs++] = host[i];
369 }
370 if (ofs == COAP_UNIX_PATH_MAX)
371 break;
372 }
373 if (ofs < COAP_UNIX_PATH_MAX)
374 addr->addr.cun.sun_path[ofs] = '\000';
375 else
376 addr->addr.cun.sun_path[ofs-1] = '\000';
377 return 1;
378#else /* ! COAP_AF_UNIX_SUPPORT */
379 (void)addr;
380 (void)host;
381 (void)host_len;
382 return 0;
383#endif /* ! COAP_AF_UNIX_SUPPORT */
384}
385
386static void
387update_port(coap_address_t *addr, uint16_t port, uint16_t default_port,
388 int update_port0) {
389 /* Client target port must be set if default of 0 */
390 if (port == 0 && update_port0)
391 port = default_port;
392
393 coap_address_set_port(addr, port);
394 return;
395}
396
397#ifdef HAVE_NETDB_H
398#include <netdb.h>
399#endif
400
401uint32_t
402coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check,
403 coap_proto_t use_unix_proto) {
404 uint32_t scheme_hint_bits = 0;
405 coap_uri_scheme_t scheme;
406
407 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
408 switch (scheme) {
410 scheme_hint_bits |= 1 << scheme;
411 break;
413 if (!(coap_dtls_is_supported() && have_pki_psk))
414 continue;
415 scheme_hint_bits |= 1 << scheme;
416 break;
419 continue;
420 scheme_hint_bits |= 1 << scheme;
421 break;
423 if (!(coap_tls_is_supported() && have_pki_psk))
424 continue;
425 scheme_hint_bits |= 1 << scheme;
426 break;
428 if (!ws_check || !coap_ws_is_supported())
429 continue;
430 scheme_hint_bits |= 1 << scheme;
431 break;
433 if (!ws_check || !(coap_wss_is_supported() && have_pki_psk))
434 continue;
435 scheme_hint_bits |= 1 << scheme;
436 break;
440 default:
441 continue;
442 }
443 }
444
445 switch (use_unix_proto) {
446 /* For AF_UNIX, can only listen on a single endpoint */
447 case COAP_PROTO_UDP:
448 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP;
449 break;
450 case COAP_PROTO_TCP:
451 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_TCP;
452 break;
453 case COAP_PROTO_DTLS:
454 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS;
455 break;
456 case COAP_PROTO_TLS:
457 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_TCP;
458 break;
459 case COAP_PROTO_WS:
460 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_WS;
461 break;
462 case COAP_PROTO_WSS:
463 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_WS;
464 break;
465 case COAP_PROTO_NONE: /* If use_unix_proto was not defined */
466 case COAP_PROTO_LAST:
467 default:
468 break;
469 }
470 return scheme_hint_bits;
471}
472
473static coap_addr_info_t *
475 coap_addr_info_t *info = NULL;
476 coap_proto_t proto = 0;
477
478 switch (scheme) {
480 proto = COAP_PROTO_UDP;
481 break;
484 return NULL;
485 proto = COAP_PROTO_DTLS;
486 break;
489 return NULL;
490 proto = COAP_PROTO_TCP;
491 break;
494 return NULL;
495 proto = COAP_PROTO_TLS;
496 break;
499 return NULL;
500 proto = COAP_PROTO_NONE;
501 break;
504 return NULL;
505 proto = COAP_PROTO_NONE;
506 break;
509 return NULL;
510 proto = COAP_PROTO_WS;
511 break;
514 return NULL;
515 proto = COAP_PROTO_WSS;
516 break;
518 default:
519 return NULL;
520 }
522 if (info == NULL)
523 return NULL;
524 info->next = NULL;
525 info->proto = proto;
526 info->scheme = scheme;
527
528 coap_address_init(&info->addr);
529 return info;
530}
531
532static void
534 uint16_t port, uint16_t secure_port, uint16_t ws_port,
535 uint16_t ws_secure_port,
536 coap_resolve_type_t type) {
537 switch (scheme) {
539 update_port(&info->addr, port, COAP_DEFAULT_PORT,
541 break;
543 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
545 break;
547 update_port(&info->addr, port, COAP_DEFAULT_PORT,
549 break;
551 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
553 break;
555 update_port(&info->addr, port, 80,
557 break;
559 update_port(&info->addr, secure_port, 443,
561 break;
563 update_port(&info->addr, ws_port, 80,
565 break;
567 update_port(&info->addr, ws_secure_port, 443,
569 break;
571 default:
572 break;
573 }
574}
575
578 uint16_t port,
579 uint16_t secure_port,
580 uint16_t ws_port,
581 uint16_t ws_secure_port,
582 int ai_hints_flags,
583 int scheme_hint_bits,
584 coap_resolve_type_t type) {
585#if !defined(RIOT_VERSION) && !defined(WITH_CONTIKI)
586
587 struct addrinfo *res, *ainfo;
588 struct addrinfo hints;
589 static char addrstr[256];
590 int error;
591 coap_addr_info_t *info = NULL;
592 coap_addr_info_t *info_prev = NULL;
593 coap_addr_info_t *info_list = NULL;
594 coap_addr_info_t *info_tmp;
595 coap_uri_scheme_t scheme;
596
597#if COAP_AF_UNIX_SUPPORT
598 if (address && coap_host_is_unix_domain(address)) {
599 /* There can only be one unique filename entry for AF_UNIX */
600 if (address->length >= COAP_UNIX_PATH_MAX) {
601 coap_log_err("Unix Domain host too long\n");
602 return NULL;
603 }
604 /* Need to chose the first defined one in scheme_hint_bits */
605 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
606 if (scheme_hint_bits & (1 << scheme)) {
607 break;
608 }
609 }
610 if (scheme == COAP_URI_SCHEME_LAST) {
611 return NULL;
612 }
613 info = get_coap_addr_info(scheme);
614 if (info == NULL) {
615 return NULL;
616 }
617
618 if (!coap_address_set_unix_domain(&info->addr, address->s,
619 address->length)) {
621 return NULL;
622 }
623 return info;
624 }
625#endif /* COAP_AF_UNIX_SUPPORT */
626
627 memset(addrstr, 0, sizeof(addrstr));
628 if (address && address->length)
629 memcpy(addrstr, address->s, address->length);
630 else
631 memcpy(addrstr, "localhost", 9);
632
633 memset((char *)&hints, 0, sizeof(hints));
634 hints.ai_socktype = 0;
635 hints.ai_family = AF_UNSPEC;
636 hints.ai_flags = ai_hints_flags;
637
638 error = getaddrinfo(addrstr, NULL, &hints, &res);
639
640 if (error != 0) {
641 coap_log_warn("getaddrinfo: %s: %s\n", addrstr, gai_strerror(error));
642 return NULL;
643 }
644
645 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
646#if !defined(WITH_LWIP)
647 if (ainfo->ai_addrlen > (socklen_t)sizeof(info->addr.addr))
648 continue;
649#endif /* ! WITH_LWIP */
650
651 switch (ainfo->ai_family) {
652#if COAP_IPV4_SUPPORT
653 case AF_INET:
654#endif /* COAP_IPV4_SUPPORT */
655#if COAP_IPV6_SUPPORT
656 case AF_INET6:
657#endif /* COAP_IPV6_SUPPORT */
658 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
659 if (scheme_hint_bits & (1 << scheme)) {
660 info = get_coap_addr_info(scheme);
661 if (info == NULL) {
662 continue;
663 }
664
665#if !defined(WITH_LWIP)
666 info->addr.size = (socklen_t)ainfo->ai_addrlen;
667 memcpy(&info->addr.addr, ainfo->ai_addr, ainfo->ai_addrlen);
668#else /* WITH_LWIP */
669 memset(&info->addr, 0, sizeof(info->addr));
670 switch (ainfo->ai_family) {
671#if COAP_IPV6_SUPPORT
672 struct sockaddr_in6 *sock6;
673#endif /* COAP_IPV6_SUPPORT */
674#if COAP_IPV4_SUPPORT
675 struct sockaddr_in *sock4;
676 case AF_INET:
677 sock4 = (struct sockaddr_in *)ainfo->ai_addr;
678 info->addr.port = ntohs(sock4->sin_port);
679 memcpy(&info->addr.addr, &sock4->sin_addr, 4);
680#if LWIP_IPV6
681 info->addr.addr.type = IPADDR_TYPE_V4;
682#endif /* LWIP_IPV6 */
683 break;
684#endif /* COAP_IPV4_SUPPORT */
685#if COAP_IPV6_SUPPORT
686 case AF_INET6:
687 sock6 = (struct sockaddr_in6 *)ainfo->ai_addr;
688 info->addr.port = ntohs(sock6->sin6_port);
689 memcpy(&info->addr.addr, &sock6->sin6_addr, 16);
690#if LWIP_IPV6 && LWIP_IPV4
691 info->addr.addr.type = IPADDR_TYPE_V6;
692#endif /* LWIP_IPV6 && LWIP_IPV4 */
693 break;
694#endif /* COAP_IPV6_SUPPORT */
695 default:
696 ;
697 }
698#endif /* WITH_LWIP */
699 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
700 ws_secure_port, type);
701
702 /* Check there are no duplications */
703 info_tmp = info_list;
704 while (info_tmp) {
705 if (info_tmp->proto == info->proto &&
706 info_tmp->scheme == info->scheme &&
707 coap_address_equals(&info_tmp->addr, &info->addr)) {
708 break;
709 }
710 info_tmp = info_tmp->next;
711 }
712
713 if (info_tmp) {
714 /* Duplicate */
716 } else {
717 /* Need to return in same order as getaddrinfo() */
718 if (!info_prev) {
719 info_list = info;
720 info_prev = info;
721 } else {
722 info_prev->next = info;
723 info_prev = info;
724 }
725 }
726 }
727 }
728 break;
729 default:
730 break;
731 }
732 }
733
734 freeaddrinfo(res);
735 return info_list;
736
737#elif defined(RIOT_VERSION)
738
739#include "net/utils.h"
740#if COAP_IPV6_SUPPORT
741 ipv6_addr_t addr_ipv6;
742#endif /* COAP_IPV6_SUPPORT */
743#if COAP_IPV4_SUPPORT
744 ipv4_addr_t addr_ipv4;
745#endif /* COAP_IPV4_SUPPORT */
746 netif_t *netif = NULL;
747 coap_addr_info_t *info = NULL;
748 coap_addr_info_t *info_prev = NULL;
749 coap_addr_info_t *info_list = NULL;
750 coap_uri_scheme_t scheme;
751 (void)ai_hints_flags;
752 int family = AF_UNSPEC;
753
754 if (address == NULL || address->length == 0) {
755 memset(&addr_ipv6, 0, sizeof(addr_ipv6));
756#if COAP_IPV6_SUPPORT
757 family = AF_INET6;
758#else /* ! COAP_IPV6_SUPPORT */
759 family = AF_INET;
760#endif /* ! COAP_IPV6_SUPPORT */
761 } else {
762#if COAP_IPV6_SUPPORT
763 if (netutils_get_ipv6(&addr_ipv6, &netif, (const char *)address->s) >= 0) {
764 family = AF_INET6;
765 }
766#endif /* COAP_IPV6_SUPPORT */
767#if COAP_IPV4_SUPPORT
768 if (family == AF_UNSPEC &&
769 netutils_get_ipv4(&addr_ipv4, (const char *)address->s) >= 0) {
770 family = AF_INET;
771 }
772#endif /* COAP_IPV4_SUPPORT */
773 if (family == AF_UNSPEC) {
774 coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
775 return NULL;
776 }
777 }
778 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
779 if (scheme_hint_bits & (1 << scheme)) {
780 info = get_coap_addr_info(scheme);
781 if (info == NULL) {
782 continue;
783 }
784
785 /* Need to return in same order as getaddrinfo() */
786 if (!info_prev) {
787 info_list = info;
788 info_prev = info;
789 } else {
790 info_prev->next = info;
791 info_prev = info;
792 }
793
794 switch (family) {
795#if COAP_IPV6_SUPPORT
796 case AF_INET6:
797 info->addr.riot.family = AF_INET6;
798 memcpy(&info->addr.riot.addr.ipv6, &addr_ipv6,
799 sizeof(info->addr.riot.addr.ipv6));
800 info->addr.riot.netif = netif ? (uint32_t)netif_get_id(netif) : 0;
801 break;
802#endif /* ! COAP_IPV6_SUPPORT */
803#if COAP_IPV4_SUPPORT
804 case AF_INET:
805 info->addr.riot.family = AF_INET;
806 memcpy(&info->addr.riot.addr.ipv4, &addr_ipv4,
807 sizeof(info->addr.riot.addr.ipv4));
808 break;
809#endif /* ! COAP_IPV4_SUPPORT */
810 default:
811 break;
812 }
813
814 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
815 ws_secure_port, type);
816 }
817 }
818 return info_list;
819
820#elif defined(WITH_CONTIKI)
821
822#include <os/net/ipv6/uiplib.h>
823 uip_ipaddr_t addr_ip;
824 coap_addr_info_t *info = NULL;
825 coap_addr_info_t *info_prev = NULL;
826 coap_addr_info_t *info_list = NULL;
827 coap_uri_scheme_t scheme;
828 int parsed_ip = 0;
829
830 (void)ai_hints_flags;
831
832 if (address == NULL || address->length == 0) {
833 memset(&addr_ip, 0, sizeof(addr_ip));
834 } else {
835#if COAP_IPV6_SUPPORT
836 if (uiplib_ip6addrconv((const char *)address->s, (uip_ip6addr_t *)&addr_ip) > 0) {
837 parsed_ip = 1;
838 }
839#endif /* COAP_IPV6_SUPPORT */
840#if COAP_IPV4_SUPPORT
841 if (family == AF_UNSPEC &&
842 uiplib_ip4addrconv((const char *)address->s, (uip_ip4addr_t *)&addr_ip) > 0) {
843 parsed_ip = 1;
844 }
845#endif /* COAP_IPV4_SUPPORT */
846 if (!parsed_ip) {
847 coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
848 return NULL;
849 }
850 }
851 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
852 if (scheme_hint_bits & (1 << scheme)) {
853 info = get_coap_addr_info(scheme);
854 if (info == NULL) {
855 continue;
856 }
857
858 /* Need to return in same order as getaddrinfo() */
859 if (!info_prev) {
860 info_list = info;
861 info_prev = info;
862 } else {
863 info_prev->next = info;
864 info_prev = info;
865 }
866
867 memcpy(&info->addr.addr, &addr_ip, sizeof(info->addr.addr));
868
869 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
870 ws_secure_port, type);
871 }
872 }
873 return info_list;
874#else
875#bad OS type not supported
876 return NULL;
877#endif
878}
879
880void
882 while (info) {
883 coap_addr_info_t *info_next = info->next;
884
886 info = info_next;
887 }
888}
889
890#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
891void
893#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
894 memcpy(dst, src, sizeof(coap_address_t));
895#else
896 memset(dst, 0, sizeof(coap_address_t));
897 dst->size = src->size;
898#if COAP_IPV6_SUPPORT
899 if (src->addr.sa.sa_family == AF_INET6) {
900 dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family;
901 dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr;
902 dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port;
903 dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id;
904 }
905#endif /* COAP_IPV6_SUPPORT */
906#if COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT
907 else
908#endif /* COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT */
909#if COAP_IPV4_SUPPORT
910 if (src->addr.sa.sa_family == AF_INET) {
911 dst->addr.sin = src->addr.sin;
912 }
913#endif /* COAP_IPV4_SUPPORT */
914 else {
915 memcpy(&dst->addr, &src->addr, src->size);
916 }
917#endif
918}
919
920int
922 /* need to compare only relevant parts of sockaddr_in6 */
923 switch (a->addr.sa.sa_family) {
924#if COAP_IPV4_SUPPORT
925 case AF_INET:
926 return a->addr.sin.sin_addr.s_addr == INADDR_ANY;
927#endif /* COAP_IPV4_SUPPORT */
928#if COAP_IPV6_SUPPORT
929 case AF_INET6:
930 return memcmp(&in6addr_any,
931 &a->addr.sin6.sin6_addr,
932 sizeof(in6addr_any)) == 0;
933#endif /* COAP_IPV6_SUPPORT */
934 default:
935 ;
936 }
937
938 return 0;
939}
940#endif /* ! WITH_LWIP && ! WITH_CONTIKI */
void coap_address_set_port(coap_address_t *addr, uint16_t port)
Set the port field of addr to port (in host byte order).
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.
#define COAP_BCST_REFRESH_SECS
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().
int coap_is_af_unix(const coap_address_t *a)
Checks if given address a denotes a AF_UNIX address.
int coap_is_bcast(const coap_address_t *a)
Checks if given address a denotes a broadcast address.
void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
int coap_is_mcast(const coap_address_t *a)
Checks if given address a denotes a multicast address.
int _coap_address_isany_impl(const coap_address_t *a)
uint16_t coap_address_get_port(const coap_address_t *addr)
Returns the port from addr in host byte order.
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...
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...
#define COAP_BCST_CNT
void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
static void update_coap_addr_port(coap_uri_scheme_t scheme, coap_addr_info_t *info, uint16_t port, uint16_t secure_port, uint16_t ws_port, uint16_t ws_secure_port, coap_resolve_type_t type)
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
static void update_port(coap_address_t *addr, uint16_t port, uint16_t default_port, int update_port0)
static coap_addr_info_t * get_coap_addr_info(coap_uri_scheme_t scheme)
coap_resolve_type_t
coap_resolve_type_t values
@ COAP_RESOLVE_TYPE_LOCAL
local side of session
#define COAP_UNIX_PATH_MAX
Library specific build wrapper for coap_internal.h.
@ COAP_STRING
Definition coap_mem.h:39
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.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
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:389
coap_uri_scheme_t
The scheme specifiers.
Definition coap_uri.h:28
@ COAP_URI_SCHEME_COAPS_WS
Definition coap_uri.h:36
@ COAP_URI_SCHEME_COAPS_TCP
Definition coap_uri.h:32
@ COAP_URI_SCHEME_COAPS
Definition coap_uri.h:30
@ COAP_URI_SCHEME_COAP_TCP
Definition coap_uri.h:31
@ COAP_URI_SCHEME_COAP_WS
Definition coap_uri.h:35
@ COAP_URI_SCHEME_HTTPS
Definition coap_uri.h:34
@ COAP_URI_SCHEME_COAP
Definition coap_uri.h:29
@ COAP_URI_SCHEME_LAST
Definition coap_uri.h:37
@ COAP_URI_SCHEME_HTTP
Definition coap_uri.h:33
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:143
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:158
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
#define coap_log_warn(...)
Definition coap_debug.h:102
#define coap_log_err(...)
Definition coap_debug.h:96
#define COAP_DEFAULT_PORT
Definition coap_pdu.h:37
coap_proto_t
CoAP protocol types.
Definition coap_pdu.h:313
#define COAPS_DEFAULT_PORT
Definition coap_pdu.h:38
@ COAP_PROTO_WS
Definition coap_pdu.h:319
@ COAP_PROTO_DTLS
Definition coap_pdu.h:316
@ COAP_PROTO_UDP
Definition coap_pdu.h:315
@ COAP_PROTO_NONE
Definition coap_pdu.h:314
@ COAP_PROTO_TLS
Definition coap_pdu.h:318
@ COAP_PROTO_WSS
Definition coap_pdu.h:320
@ COAP_PROTO_TCP
Definition coap_pdu.h:317
@ COAP_PROTO_LAST
Definition coap_pdu.h:321
int coap_tcp_is_supported(void)
Check whether TCP is available.
Definition coap_tcp.c:29
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
int coap_ws_is_supported(void)
Check whether WebSockets is available.
Definition coap_ws.c:933
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_wss_is_supported(void)
Check whether Secure WebSockets is available.
Definition coap_ws.c:938
Resolved addresses information.
coap_uri_scheme_t scheme
CoAP scheme to use.
coap_proto_t proto
CoAP protocol to use.
struct coap_addr_info_t * next
Next entry in the chain.
coap_address_t addr
The address to connect / bind to.
Multi-purpose address abstraction.
socklen_t size
size of addr
struct sockaddr_in sin
struct coap_sockaddr_un cun
struct sockaddr_in6 sin6
struct sockaddr sa
union coap_address_t::@0 addr
char sun_path[COAP_UNIX_PATH_MAX]
sa_family_t sun_family
CoAP string data definition with const data.
Definition coap_str.h:46
const uint8_t * s
read-only string data
Definition coap_str.h:48
size_t length
length of string
Definition coap_str.h:47