libcoap 4.3.5-develop-fada39d
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#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_NET_IF_H
29#include <net/if.h>
30#endif
31#ifdef HAVE_IFADDRS_H
32#include <ifaddrs.h>
33#endif
34#ifdef HAVE_WS2TCPIP_H
35#include <ws2tcpip.h>
36#endif
37
38#ifdef RIOT_VERSION
39/* FIXME */
40#define IN_MULTICAST(Address) (0)
41#endif /* RIOT_VERSION */
42
43uint16_t
45 assert(addr != NULL);
46 switch (addr->addr.sa.sa_family) {
47#if COAP_IPV4_SUPPORT
48 case AF_INET:
49 return ntohs(addr->addr.sin.sin_port);
50#endif /* COAP_IPV4_SUPPORT */
51#if COAP_IPV6_SUPPORT
52 case AF_INET6:
53 return ntohs(addr->addr.sin6.sin6_port);
54#endif /* COAP_IPV6_SUPPORT */
55 default: /* undefined */
56 ;
57 }
58 return 0;
59}
60
61void
63 assert(addr != NULL);
64 switch (addr->addr.sa.sa_family) {
65#if COAP_IPV4_SUPPORT
66 case AF_INET:
67 addr->addr.sin.sin_port = htons(port);
68 break;
69#endif /* COAP_IPV4_SUPPORT */
70#if COAP_IPV6_SUPPORT
71 case AF_INET6:
72 addr->addr.sin6.sin6_port = htons(port);
73 break;
74#endif /* COAP_IPV6_SUPPORT */
75 default: /* undefined */
76 ;
77 }
78}
79
80int
82 assert(a);
83 assert(b);
84
85 if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
86 return 0;
87
88 /* need to compare only relevant parts of sockaddr_in6 */
89 switch (a->addr.sa.sa_family) {
90#if COAP_IPV4_SUPPORT
91 case AF_INET:
92 return a->addr.sin.sin_port == b->addr.sin.sin_port &&
93 memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
94 sizeof(struct in_addr)) == 0;
95#endif /* COAP_IPV4_SUPPORT */
96#if COAP_IPV6_SUPPORT
97 case AF_INET6:
98 return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
99 memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
100 sizeof(struct in6_addr)) == 0;
101#endif /* COAP_IPV6_SUPPORT */
102#if COAP_AF_UNIX_SUPPORT
103 case AF_UNIX:
104 return memcmp(&a->addr.cun.sun_path, &b->addr.cun.sun_path,
105 sizeof(a->addr.cun.sun_path)) == 0;
106#endif /* COAP_AF_UNIX_SUPPORT */
107 default: /* fall through and signal error */
108 ;
109 }
110 return 0;
111}
112
113int
115#if COAP_AF_UNIX_SUPPORT
116 return a->addr.sa.sa_family == AF_UNIX;
117#else /* ! COAP_AF_UNIX_SUPPORT */
118 (void)a;
119 return 0;
120#endif /* ! COAP_AF_UNIX_SUPPORT */
121}
122
123int
125 if (!a)
126 return 0;
127
128 /* Treat broadcast in same way as multicast */
129 if (coap_is_bcast(a))
130 return 1;
131
132 switch (a->addr.sa.sa_family) {
133#if COAP_IPV4_SUPPORT
134 case AF_INET:
135 return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr));
136#endif /* COAP_IPV4_SUPPORT */
137#if COAP_IPV6_SUPPORT
138 case AF_INET6:
139#if COAP_IPV4_SUPPORT
140 return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr) ||
141 (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr) &&
142 IN_MULTICAST(ntohl(a->addr.sin6.sin6_addr.s6_addr[12])));
143#else /* ! COAP_IPV4_SUPPORT */
144 return a->addr.sin6.sin6_addr.s6_addr[0] == 0xff;
145#endif /* ! COAP_IPV4_SUPPORT */
146#endif /* COAP_IPV6_SUPPORT */
147 default: /* fall through and signal not multicast */
148 ;
149 }
150 return 0;
151}
152
153#ifndef COAP_BCST_CNT
154#define COAP_BCST_CNT 15
155#endif /* COAP_BCST_CNT */
156
157/* How frequently to refresh the list of valid IPv4 broadcast addresses */
158#ifndef COAP_BCST_REFRESH_SECS
159#define COAP_BCST_REFRESH_SECS 30
160#endif /* COAP_BCST_REFRESH_SECS */
161
162#if COAP_IPV4_SUPPORT && defined(HAVE_IFADDRS_H)
163static int bcst_cnt = -1;
164static coap_tick_t last_refresh;
165static struct in_addr b_ipv4[COAP_BCST_CNT];
166#endif /* COAP_IPV4_SUPPORT && HAVE_IFADDRS_H */
167
168int
170#if COAP_IPV4_SUPPORT
171 struct in_addr ipv4;
172#if defined(HAVE_IFADDRS_H)
173 int i;
174 coap_tick_t now;
175#endif /* HAVE_IFADDRS_H */
176#endif /* COAP_IPV4_SUPPORT */
177
178 if (!a)
179 return 0;
180
181 switch (a->addr.sa.sa_family) {
182#if COAP_IPV4_SUPPORT
183 case AF_INET:
184 ipv4.s_addr = a->addr.sin.sin_addr.s_addr;
185 break;
186#endif /* COAP_IPV4_SUPPORT */
187#if COAP_IPV6_SUPPORT
188 case AF_INET6:
189#if COAP_IPV4_SUPPORT
190 if (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr)) {
191 memcpy(&ipv4, &a->addr.sin6.sin6_addr.s6_addr[12], sizeof(ipv4));
192 break;
193 }
194#endif /* COAP_IPV4_SUPPORT */
195 /* IPv6 does not support broadcast */
196 return 0;
197#endif /* COAP_IPV6_SUPPORT */
198 default:
199 return 0;
200 }
201#if COAP_IPV4_SUPPORT
202#ifndef INADDR_BROADCAST
203#define INADDR_BROADCAST ((uint32_t)0xffffffffUL)
204#endif /* !INADDR_BROADCAST */
205 if (ipv4.s_addr == INADDR_BROADCAST)
206 return 1;
207
208#if defined(HAVE_IFADDRS_H)
209 coap_ticks(&now);
210 if (bcst_cnt == -1 ||
211 (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) {
212 /* Determine the list of broadcast interfaces */
213 struct ifaddrs *ifa = NULL;
214 struct ifaddrs *ife;
215
216 if (getifaddrs(&ifa) != 0) {
217 coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n");
218 return 0;
219 }
220 bcst_cnt = 0;
221 last_refresh = now;
222 ife = ifa;
223 while (ife && bcst_cnt < COAP_BCST_CNT) {
224 if (ife->ifa_addr && ife->ifa_addr->sa_family == AF_INET &&
225 ife->ifa_flags & IFF_BROADCAST) {
226 struct in_addr netmask;
227
228 /*
229 * Sometimes the broadcast IP is set to the IP address, even though
230 * netmask is not set to 0xffffffff, so unsafe to use ifa_broadaddr.
231 */
232 netmask.s_addr = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr.s_addr;
233 if (netmask.s_addr != 0xffffffff) {
234 b_ipv4[bcst_cnt].s_addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr |
235 ~netmask.s_addr;
236 bcst_cnt++;
237 }
238 }
239 ife = ife->ifa_next;
240 }
241 if (ife) {
242 coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n");
243 }
244 freeifaddrs(ifa);
245 }
246 for (i = 0; i < bcst_cnt; i++) {
247 if (ipv4.s_addr == b_ipv4[i].s_addr)
248 return 1;
249 }
250#endif /* HAVE_IFADDRS_H */
251 return 0;
252#endif /* COAP_IPV4_SUPPORT */
253}
254
255#endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */
256
257void
259 assert(addr);
260 memset(addr, 0, sizeof(coap_address_t));
261#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
262 /* lwip and Contiki have constant address sizes and don't need the .size part */
263 addr->size = sizeof(addr->addr);
264#endif
265}
266
267int
269 const uint8_t *host, size_t host_len) {
270#if COAP_AF_UNIX_SUPPORT
271 size_t i;
272 size_t ofs = 0;
273
274 coap_address_init(addr);
275 addr->addr.cun.sun_family = AF_UNIX;
276 for (i = 0; i < host_len; i++) {
277 if ((host_len - i) >= 3 && host[i] == '%' && host[i+1] == '2' &&
278 (host[i+2] == 'F' || host[i+2] == 'f')) {
279 addr->addr.cun.sun_path[ofs++] = '/';
280 i += 2;
281 } else {
282 addr->addr.cun.sun_path[ofs++] = host[i];
283 }
284 if (ofs == COAP_UNIX_PATH_MAX)
285 break;
286 }
287 if (ofs < COAP_UNIX_PATH_MAX)
288 addr->addr.cun.sun_path[ofs] = '\000';
289 else
290 addr->addr.cun.sun_path[ofs-1] = '\000';
291 return 1;
292#else /* ! COAP_AF_UNIX_SUPPORT */
293 (void)addr;
294 (void)host;
295 (void)host_len;
296 return 0;
297#endif /* ! COAP_AF_UNIX_SUPPORT */
298}
299
300static void
301update_port(coap_address_t *addr, uint16_t port, uint16_t default_port,
302 int update_port0) {
303 /* Client target port must be set if default of 0 */
304 if (port == 0 && update_port0)
305 port = default_port;
306
307 coap_address_set_port(addr, port);
308 return;
309}
310
311#ifdef HAVE_NETDB_H
312#include <netdb.h>
313#endif
314
315uint32_t
316coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check,
317 coap_proto_t use_unix_proto) {
318 uint32_t scheme_hint_bits = 0;
319 coap_uri_scheme_t scheme;
320
321 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
322 switch (scheme) {
324 scheme_hint_bits |= 1 << scheme;
325 break;
327 if (!(coap_dtls_is_supported() && have_pki_psk))
328 continue;
329 scheme_hint_bits |= 1 << scheme;
330 break;
333 continue;
334 scheme_hint_bits |= 1 << scheme;
335 break;
337 if (!(coap_tls_is_supported() && have_pki_psk))
338 continue;
339 scheme_hint_bits |= 1 << scheme;
340 break;
342 if (!ws_check || !coap_ws_is_supported())
343 continue;
344 scheme_hint_bits |= 1 << scheme;
345 break;
347 if (!ws_check || !(coap_wss_is_supported() && have_pki_psk))
348 continue;
349 scheme_hint_bits |= 1 << scheme;
350 break;
354 default:
355 continue;
356 }
357 }
358
359 switch (use_unix_proto) {
360 /* For AF_UNIX, can only listen on a single endpoint */
361 case COAP_PROTO_UDP:
362 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP;
363 break;
364 case COAP_PROTO_TCP:
365 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_TCP;
366 break;
367 case COAP_PROTO_DTLS:
368 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS;
369 break;
370 case COAP_PROTO_TLS:
371 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_TCP;
372 break;
373 case COAP_PROTO_WS:
374 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_WS;
375 break;
376 case COAP_PROTO_WSS:
377 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_WS;
378 break;
379 case COAP_PROTO_NONE: /* If use_unix_proto was not defined */
380 case COAP_PROTO_LAST:
381 default:
382 break;
383 }
384 return scheme_hint_bits;
385}
386
387static coap_addr_info_t *
389 coap_addr_info_t *info = NULL;
390 coap_proto_t proto = 0;
391
392 switch (scheme) {
394 proto = COAP_PROTO_UDP;
395 break;
398 return NULL;
399 proto = COAP_PROTO_DTLS;
400 break;
403 return NULL;
404 proto = COAP_PROTO_TCP;
405 break;
408 return NULL;
409 proto = COAP_PROTO_TLS;
410 break;
413 return NULL;
414 proto = COAP_PROTO_NONE;
415 break;
418 return NULL;
419 proto = COAP_PROTO_NONE;
420 break;
423 return NULL;
424 proto = COAP_PROTO_WS;
425 break;
428 return NULL;
429 proto = COAP_PROTO_WSS;
430 break;
432 default:
433 return NULL;
434 }
436 if (info == NULL)
437 return NULL;
438 info->next = NULL;
439 info->proto = proto;
440 info->scheme = scheme;
441
442 coap_address_init(&info->addr);
443 return info;
444}
445
446static void
448 uint16_t port, uint16_t secure_port, uint16_t ws_port,
449 uint16_t ws_secure_port,
450 coap_resolve_type_t type) {
451 switch (scheme) {
453 update_port(&info->addr, port, COAP_DEFAULT_PORT,
455 break;
457 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
459 break;
461 update_port(&info->addr, port, COAP_DEFAULT_PORT,
463 break;
465 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
467 break;
469 update_port(&info->addr, port, 80,
471 break;
473 update_port(&info->addr, secure_port, 443,
475 break;
477 update_port(&info->addr, ws_port, 80,
479 break;
481 update_port(&info->addr, ws_secure_port, 443,
483 break;
485 default:
486 break;
487 }
488}
489
492 uint16_t port,
493 uint16_t secure_port,
494 uint16_t ws_port,
495 uint16_t ws_secure_port,
496 int ai_hints_flags,
497 int scheme_hint_bits,
498 coap_resolve_type_t type) {
499#if !defined(RIOT_VERSION) && !defined(WITH_CONTIKI)
500
501 struct addrinfo *res, *ainfo;
502 struct addrinfo hints;
503 static char addrstr[256];
504 int error;
505 coap_addr_info_t *info = NULL;
506 coap_addr_info_t *info_prev = NULL;
507 coap_addr_info_t *info_list = NULL;
508 coap_addr_info_t *info_tmp;
509 coap_uri_scheme_t scheme;
510
511#if COAP_AF_UNIX_SUPPORT
512 if (address && coap_host_is_unix_domain(address)) {
513 /* There can only be one unique filename entry for AF_UNIX */
514 if (address->length >= COAP_UNIX_PATH_MAX) {
515 coap_log_err("Unix Domain host too long\n");
516 return NULL;
517 }
518 /* Need to chose the first defined one in scheme_hint_bits */
519 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
520 if (scheme_hint_bits & (1 << scheme)) {
521 break;
522 }
523 }
524 if (scheme == COAP_URI_SCHEME_LAST) {
525 return NULL;
526 }
527 info = get_coap_addr_info(scheme);
528 if (info == NULL) {
529 return NULL;
530 }
531
532 if (!coap_address_set_unix_domain(&info->addr, address->s,
533 address->length)) {
535 return NULL;
536 }
537 return info;
538 }
539#endif /* COAP_AF_UNIX_SUPPORT */
540
541 memset(addrstr, 0, sizeof(addrstr));
542 if (address && address->length)
543 memcpy(addrstr, address->s, address->length);
544 else
545 memcpy(addrstr, "localhost", 9);
546
547 memset((char *)&hints, 0, sizeof(hints));
548 hints.ai_socktype = 0;
549 hints.ai_family = AF_UNSPEC;
550 hints.ai_flags = ai_hints_flags;
551
552 error = getaddrinfo(addrstr, NULL, &hints, &res);
553
554 if (error != 0) {
555 coap_log_warn("getaddrinfo: %s: %s\n", addrstr, gai_strerror(error));
556 return NULL;
557 }
558
559 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
560#if !defined(WITH_LWIP)
561 if (ainfo->ai_addrlen > (socklen_t)sizeof(info->addr.addr))
562 continue;
563#endif /* ! WITH_LWIP */
564
565 switch (ainfo->ai_family) {
566#if COAP_IPV4_SUPPORT
567 case AF_INET:
568#endif /* COAP_IPV4_SUPPORT */
569#if COAP_IPV6_SUPPORT
570 case AF_INET6:
571#endif /* COAP_IPV6_SUPPORT */
572 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
573 if (scheme_hint_bits & (1 << scheme)) {
574 info = get_coap_addr_info(scheme);
575 if (info == NULL) {
576 continue;
577 }
578
579#if !defined(WITH_LWIP)
580 info->addr.size = (socklen_t)ainfo->ai_addrlen;
581 memcpy(&info->addr.addr, ainfo->ai_addr, ainfo->ai_addrlen);
582#else /* WITH_LWIP */
583 memset(&info->addr, 0, sizeof(info->addr));
584 switch (ainfo->ai_family) {
585#if COAP_IPV6_SUPPORT
586 struct sockaddr_in6 *sock6;
587#endif /* COAP_IPV6_SUPPORT */
588#if COAP_IPV4_SUPPORT
589 struct sockaddr_in *sock4;
590 case AF_INET:
591 sock4 = (struct sockaddr_in *)ainfo->ai_addr;
592 info->addr.port = ntohs(sock4->sin_port);
593 memcpy(&info->addr.addr, &sock4->sin_addr, 4);
594#if LWIP_IPV6
595 info->addr.addr.type = IPADDR_TYPE_V4;
596#endif /* LWIP_IPV6 */
597 break;
598#endif /* COAP_IPV4_SUPPORT */
599#if COAP_IPV6_SUPPORT
600 case AF_INET6:
601 sock6 = (struct sockaddr_in6 *)ainfo->ai_addr;
602 info->addr.port = ntohs(sock6->sin6_port);
603 memcpy(&info->addr.addr, &sock6->sin6_addr, 16);
604#if LWIP_IPV6 && LWIP_IPV4
605 info->addr.addr.type = IPADDR_TYPE_V6;
606#endif /* LWIP_IPV6 && LWIP_IPV4 */
607 break;
608#endif /* COAP_IPV6_SUPPORT */
609 default:
610 ;
611 }
612#endif /* WITH_LWIP */
613 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
614 ws_secure_port, type);
615
616 /* Check there are no duplications */
617 info_tmp = info_list;
618 while (info_tmp) {
619 if (info_tmp->proto == info->proto &&
620 info_tmp->scheme == info->scheme &&
621 coap_address_equals(&info_tmp->addr, &info->addr)) {
622 break;
623 }
624 info_tmp = info_tmp->next;
625 }
626
627 if (info_tmp) {
628 /* Duplicate */
630 } else {
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 }
641 }
642 break;
643 default:
644 break;
645 }
646 }
647
648 freeaddrinfo(res);
649 return info_list;
650
651#elif defined(RIOT_VERSION)
652
653#include "net/utils.h"
654#if COAP_IPV6_SUPPORT
655 ipv6_addr_t addr_ipv6;
656#endif /* COAP_IPV6_SUPPORT */
657#if COAP_IPV4_SUPPORT
658 ipv4_addr_t addr_ipv4;
659#endif /* COAP_IPV4_SUPPORT */
660 netif_t *netif = NULL;
661 coap_addr_info_t *info = NULL;
662 coap_addr_info_t *info_prev = NULL;
663 coap_addr_info_t *info_list = NULL;
664 coap_uri_scheme_t scheme;
665 (void)ai_hints_flags;
666 int family = AF_UNSPEC;
667
668 if (address == NULL || address->length == 0) {
669 memset(&addr_ipv6, 0, sizeof(addr_ipv6));
670#if COAP_IPV6_SUPPORT
671 family = AF_INET6;
672#else /* ! COAP_IPV6_SUPPORT */
673 family = AF_INET;
674#endif /* ! COAP_IPV6_SUPPORT */
675 } else {
676#if COAP_IPV6_SUPPORT
677 if (netutils_get_ipv6(&addr_ipv6, &netif, (const char *)address->s) >= 0) {
678 family = AF_INET6;
679 }
680#endif /* COAP_IPV6_SUPPORT */
681#if COAP_IPV4_SUPPORT
682 if (family == AF_UNSPEC &&
683 netutils_get_ipv4(&addr_ipv4, (const char *)address->s) >= 0) {
684 family = AF_INET;
685 }
686#endif /* COAP_IPV4_SUPPORT */
687 if (family == AF_UNSPEC) {
688 coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
689 return NULL;
690 }
691 }
692 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
693 if (scheme_hint_bits & (1 << scheme)) {
694 info = get_coap_addr_info(scheme);
695 if (info == NULL) {
696 continue;
697 }
698
699 /* Need to return in same order as getaddrinfo() */
700 if (!info_prev) {
701 info_list = info;
702 info_prev = info;
703 } else {
704 info_prev->next = info;
705 info_prev = info;
706 }
707
708 switch (family) {
709#if COAP_IPV6_SUPPORT
710 case AF_INET6:
711 info->addr.riot.family = AF_INET6;
712 memcpy(&info->addr.riot.addr.ipv6, &addr_ipv6,
713 sizeof(info->addr.riot.addr.ipv6));
714 info->addr.riot.netif = netif ? (uint32_t)netif_get_id(netif) : 0;
715 break;
716#endif /* ! COAP_IPV6_SUPPORT */
717#if COAP_IPV4_SUPPORT
718 case AF_INET:
719 info->addr.riot.family = AF_INET;
720 memcpy(&info->addr.riot.addr.ipv4, &addr_ipv4,
721 sizeof(info->addr.riot.addr.ipv4));
722 break;
723#endif /* ! COAP_IPV4_SUPPORT */
724 default:
725 break;
726 }
727
728 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
729 ws_secure_port, type);
730 }
731 }
732 return info_list;
733
734#elif defined(WITH_CONTIKI)
735
736#include <os/net/ipv6/uiplib.h>
737 uip_ipaddr_t addr_ip;
738 coap_addr_info_t *info = NULL;
739 coap_addr_info_t *info_prev = NULL;
740 coap_addr_info_t *info_list = NULL;
741 coap_uri_scheme_t scheme;
742 int parsed_ip = 0;
743
744 (void)ai_hints_flags;
745
746 if (address == NULL || address->length == 0) {
747 memset(&addr_ip, 0, sizeof(addr_ip));
748 } else {
749#if COAP_IPV6_SUPPORT
750 if (uiplib_ip6addrconv((const char *)address->s, (uip_ip6addr_t *)&addr_ip) > 0) {
751 parsed_ip = 1;
752 }
753#endif /* COAP_IPV6_SUPPORT */
754#if COAP_IPV4_SUPPORT
755 if (family == AF_UNSPEC &&
756 uiplib_ip4addrconv((const char *)address->s, (uip_ip4addr_t *)&addr_ip) > 0) {
757 parsed_ip = 1;
758 }
759#endif /* COAP_IPV4_SUPPORT */
760 if (!parsed_ip) {
761 coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
762 return NULL;
763 }
764 }
765 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
766 if (scheme_hint_bits & (1 << scheme)) {
767 info = get_coap_addr_info(scheme);
768 if (info == NULL) {
769 continue;
770 }
771
772 /* Need to return in same order as getaddrinfo() */
773 if (!info_prev) {
774 info_list = info;
775 info_prev = info;
776 } else {
777 info_prev->next = info;
778 info_prev = info;
779 }
780
781 memcpy(&info->addr.addr, &addr_ip, sizeof(info->addr.addr));
782
783 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
784 ws_secure_port, type);
785 }
786 }
787 return info_list;
788#else
789#bad OS type not supported
790 return NULL;
791#endif
792}
793
794void
796 while (info) {
797 coap_addr_info_t *info_next = info->next;
798
800 info = info_next;
801 }
802}
803
804#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
805void
807#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
808 memcpy(dst, src, sizeof(coap_address_t));
809#else
810 memset(dst, 0, sizeof(coap_address_t));
811 dst->size = src->size;
812#if COAP_IPV6_SUPPORT
813 if (src->addr.sa.sa_family == AF_INET6) {
814 dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family;
815 dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr;
816 dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port;
817 dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id;
818 }
819#endif /* COAP_IPV6_SUPPORT */
820#if COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT
821 else
822#endif /* COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT */
823#if COAP_IPV4_SUPPORT
824 if (src->addr.sa.sa_family == AF_INET) {
825 dst->addr.sin = src->addr.sin;
826 }
827#endif /* COAP_IPV4_SUPPORT */
828 else {
829 memcpy(&dst->addr, &src->addr, src->size);
830 }
831#endif
832}
833
834int
836 /* need to compare only relevant parts of sockaddr_in6 */
837 switch (a->addr.sa.sa_family) {
838#if COAP_IPV4_SUPPORT
839 case AF_INET:
840 return a->addr.sin.sin_addr.s_addr == INADDR_ANY;
841#endif /* COAP_IPV4_SUPPORT */
842#if COAP_IPV6_SUPPORT
843 case AF_INET6:
844 return memcmp(&in6addr_any,
845 &a->addr.sin6.sin6_addr,
846 sizeof(in6addr_any)) == 0;
847#endif /* COAP_IPV6_SUPPORT */
848 default:
849 ;
850 }
851
852 return 0;
853}
854#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:312
#define COAPS_DEFAULT_PORT
Definition coap_pdu.h:38
@ COAP_PROTO_WS
Definition coap_pdu.h:318
@ COAP_PROTO_DTLS
Definition coap_pdu.h:315
@ COAP_PROTO_UDP
Definition coap_pdu.h:314
@ COAP_PROTO_NONE
Definition coap_pdu.h:313
@ COAP_PROTO_TLS
Definition coap_pdu.h:317
@ COAP_PROTO_WSS
Definition coap_pdu.h:319
@ COAP_PROTO_TCP
Definition coap_pdu.h:316
@ COAP_PROTO_LAST
Definition coap_pdu.h:320
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