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