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