libcoap 4.3.5-develop-783b531
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#if COAP_AF_LLC_SUPPORT
77 case AF_LLC:
78 return addr->addr.llc.sllc_sap;
79#endif /* COAP_AF_LLC_SUPPORT */
80 default: /* undefined */
81 ;
82 }
83 return 0;
84}
85
86void
88 assert(addr != NULL);
89 switch (addr->addr.sa.sa_family) {
90#if COAP_IPV4_SUPPORT
91 case AF_INET:
92 addr->addr.sin.sin_port = htons(port);
93 break;
94#endif /* COAP_IPV4_SUPPORT */
95#if COAP_IPV6_SUPPORT
96 case AF_INET6:
97 addr->addr.sin6.sin6_port = htons(port);
98 break;
99#endif /* COAP_IPV6_SUPPORT */
100#if COAP_AF_LLC_SUPPORT
101 case AF_LLC:
102 addr->addr.llc.sllc_sap = port & 0xFF;
103#endif /* COAP_AF_LLC_SUPPORT */
104 default: /* undefined */
105 ;
106 }
107}
108
109void
111 assert(addr != NULL);
112 switch (addr->addr.sa.sa_family) {
113#if COAP_IPV4_SUPPORT
114 case AF_INET:
115 memset(&addr->addr.sin.sin_addr, 0, sizeof(addr->addr.sin.sin_addr));
116 break;
117#endif /* COAP_IPV4_SUPPORT */
118#if COAP_IPV6_SUPPORT
119 case AF_INET6:
120 memset(&addr->addr.sin6.sin6_addr, 0, sizeof(addr->addr.sin6.sin6_addr));
121 break;
122#endif /* COAP_IPV6_SUPPORT */
123 default: /* undefined */
124 ;
125 }
126}
127
128int
130 assert(a);
131 assert(b);
132
133 if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
134 return 0;
135
136 /* need to compare only relevant parts of sockaddr_in6 */
137 switch (a->addr.sa.sa_family) {
138#if COAP_IPV4_SUPPORT
139 case AF_INET:
140 return a->addr.sin.sin_port == b->addr.sin.sin_port &&
141 memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
142 sizeof(struct in_addr)) == 0;
143#endif /* COAP_IPV4_SUPPORT */
144#if COAP_IPV6_SUPPORT
145 case AF_INET6:
146 return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
147 memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
148 sizeof(struct in6_addr)) == 0;
149#endif /* COAP_IPV6_SUPPORT */
150#if COAP_AF_UNIX_SUPPORT
151 case AF_UNIX:
152 return memcmp(&a->addr.cun.sun_path, &b->addr.cun.sun_path,
153 sizeof(a->addr.cun.sun_path)) == 0;
154#endif /* COAP_AF_UNIX_SUPPORT */
155 default: /* fall through and signal error */
156 ;
157 }
158 return 0;
159}
160
161int
163#if COAP_AF_UNIX_SUPPORT
164 return a->addr.sa.sa_family == AF_UNIX;
165#else /* ! COAP_AF_UNIX_SUPPORT */
166 (void)a;
167 return 0;
168#endif /* ! COAP_AF_UNIX_SUPPORT */
169}
170
171int
173#if COAP_AF_LLC_SUPPORT
174 return a->addr.sa.sa_family == AF_LLC;
175#else /* ! COAP_AF_LLC_SUPPORT */
176 (void)a;
177 return 0;
178#endif /* ! COAP_AF_LLC_SUPPORT */
179}
180
181int
183 if (!a)
184 return 0;
185
186 /* Treat broadcast in same way as multicast */
187 if (coap_is_bcast(a))
188 return 1;
189
190 switch (a->addr.sa.sa_family) {
191#if COAP_IPV4_SUPPORT
192 case AF_INET:
193 return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr));
194#endif /* COAP_IPV4_SUPPORT */
195#if COAP_IPV6_SUPPORT
196 case AF_INET6:
197#if COAP_IPV4_SUPPORT
198 return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr) ||
199 (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr) &&
200 IN_MULTICAST(ntohl(a->addr.sin6.sin6_addr.s6_addr[12])));
201#else /* ! COAP_IPV4_SUPPORT */
202 return a->addr.sin6.sin6_addr.s6_addr[0] == 0xff;
203#endif /* ! COAP_IPV4_SUPPORT */
204#endif /* COAP_IPV6_SUPPORT */
205 default: /* fall through and signal not multicast */
206 ;
207 }
208 return 0;
209}
210
211#ifndef COAP_BCST_CNT
212#define COAP_BCST_CNT 15
213#endif /* COAP_BCST_CNT */
214
215/* How frequently to refresh the list of valid IPv4 broadcast addresses */
216#ifndef COAP_BCST_REFRESH_SECS
217#define COAP_BCST_REFRESH_SECS 30
218#endif /* COAP_BCST_REFRESH_SECS */
219
220#if COAP_IPV4_SUPPORT && !defined(__ZEPHYR__) && (defined(HAVE_GETIFADDRS) || defined(_WIN32))
221static int bcst_cnt = -1;
222static coap_tick_t last_refresh;
223static struct in_addr b_ipv4[COAP_BCST_CNT];
224#endif /* COAP_IPV4_SUPPORT && !defined(__ZEPHYR__) && (defined(HAVE_GETIFADDRS) || defined(_WIN32)) */
225
226int
228#if COAP_IPV4_SUPPORT
229 struct in_addr ipv4;
230#if defined(HAVE_GETIFADDRS) && !defined(__ZEPHYR__)
231 int i;
232 coap_tick_t now;
233#endif /* HAVE_GETIFADDRS && !defined(__ZEPHYR__) */
234#endif /* COAP_IPV4_SUPPORT */
235
236 if (!a)
237 return 0;
238
239 switch (a->addr.sa.sa_family) {
240#if COAP_IPV4_SUPPORT
241 case AF_INET:
242 ipv4.s_addr = a->addr.sin.sin_addr.s_addr;
243 break;
244#endif /* COAP_IPV4_SUPPORT */
245#if COAP_IPV6_SUPPORT
246 case AF_INET6:
247#if COAP_IPV4_SUPPORT
248 if (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr)) {
249 memcpy(&ipv4, &a->addr.sin6.sin6_addr.s6_addr[12], sizeof(ipv4));
250 break;
251 }
252#endif /* COAP_IPV4_SUPPORT */
253 /* IPv6 does not support broadcast */
254 return 0;
255#endif /* COAP_IPV6_SUPPORT */
256 default:
257 return 0;
258 }
259#if COAP_IPV4_SUPPORT
260#ifndef INADDR_BROADCAST
261#define INADDR_BROADCAST ((uint32_t)0xffffffffUL)
262#endif /* !INADDR_BROADCAST */
263 if (ipv4.s_addr == INADDR_BROADCAST)
264 return 1;
265
266#if defined(HAVE_GETIFADDRS) && !defined(__ZEPHYR__)
267 coap_ticks(&now);
268 if (bcst_cnt == -1 ||
269 (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) {
270 /* Determine the list of broadcast interfaces */
271 struct ifaddrs *ifa = NULL;
272 struct ifaddrs *ife;
273
274 if (getifaddrs(&ifa) != 0) {
275 coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n");
276 return 0;
277 }
278 bcst_cnt = 0;
279 last_refresh = now;
280 ife = ifa;
281 while (ife && bcst_cnt < COAP_BCST_CNT) {
282 if (ife->ifa_addr && ife->ifa_addr->sa_family == AF_INET &&
283 ife->ifa_flags & IFF_BROADCAST) {
284 struct in_addr netmask;
285
286 /*
287 * Sometimes the broadcast IP is set to the IP address, even though
288 * netmask is not set to 0xffffffff, so unsafe to use ifa_broadaddr.
289 */
290 netmask.s_addr = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr.s_addr;
291 if (netmask.s_addr != 0xffffffff) {
292 b_ipv4[bcst_cnt].s_addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr |
293 ~netmask.s_addr;
294 bcst_cnt++;
295 }
296 }
297 ife = ife->ifa_next;
298 }
299 if (ife) {
300 coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n");
301 }
302 freeifaddrs(ifa);
303 }
304 for (i = 0; i < bcst_cnt; i++) {
305 if (ipv4.s_addr == b_ipv4[i].s_addr)
306 return 1;
307 }
308#endif /* HAVE_GETIFADDRS && !defined(__ZEPHYR__) */
309
310#if defined(_WIN32)
311
312 int i;
313 coap_tick_t now;
314
315 coap_ticks(&now);
316 if (bcst_cnt == -1 ||
317 (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) {
318 /* Determine the list of broadcast interfaces */
319
320 /* Variables used by GetIpAddrTable */
321 PMIB_IPADDRTABLE pIPAddrTable;
322 DWORD dwSize = 0;
323 DWORD dwRetVal = 0;
324
325 /* Assume just 2 interfaces as a starting point */
326 pIPAddrTable = (MIB_IPADDRTABLE *)coap_malloc_type(COAP_STRING, 2 * sizeof(MIB_IPADDRTABLE));
327
328 if (pIPAddrTable) {
329 /* Check that 2 interfaces are sufficient */
330 if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
331 coap_free_type(COAP_STRING, pIPAddrTable);
332 pIPAddrTable = (MIB_IPADDRTABLE *)coap_malloc_type(COAP_STRING, dwSize);
333
334 }
335 if (pIPAddrTable == NULL) {
336 coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n");
337 return 0;
338 }
339 }
340 /* Now get the actual data */
341 if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
342 coap_log_warn("GetIpAddrTable failed with error %d\n", dwRetVal);
343 return 0;
344 }
345
346 bcst_cnt = 0;
347 last_refresh = now;
348
349 for (i = 0; i < (int)pIPAddrTable->dwNumEntries && bcst_cnt < COAP_BCST_CNT; i++) {
350 struct in_addr netmask;
351
352 /* Unsafe to use dwBCastAddr */
353 netmask.s_addr = (u_long)pIPAddrTable->table[i].dwMask;
354 if (netmask.s_addr != 0xffffffff) {
355 b_ipv4[bcst_cnt].s_addr = (u_long)pIPAddrTable->table[i].dwAddr |
356 ~netmask.s_addr;
357 bcst_cnt++;
358 }
359 }
360 if (i != (int)pIPAddrTable->dwNumEntries) {
361 coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n");
362 }
363
364 if (pIPAddrTable) {
365 coap_free_type(COAP_STRING, pIPAddrTable);
366 pIPAddrTable = NULL;
367 }
368 }
369
370 for (i = 0; i < bcst_cnt; i++) {
371 if (ipv4.s_addr == b_ipv4[i].s_addr)
372 return 1;
373 }
374#endif /* _WIN32 */
375
376#endif /* COAP_IPV4_SUPPORT */
377 return 0;
378}
379
380#endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */
381
382void
384 assert(addr);
385 memset(addr, 0, sizeof(coap_address_t));
386#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
387 /* lwip and Contiki have constant address sizes and don't need the .size part */
388 addr->size = sizeof(addr->addr);
389#endif
390}
391
392int
394 const uint8_t *host, size_t host_len) {
395#if COAP_AF_UNIX_SUPPORT
396 size_t i;
397 size_t ofs = 0;
398
399 coap_address_init(addr);
400 addr->addr.cun.sun_family = AF_UNIX;
401 for (i = 0; i < host_len; i++) {
402 if ((host_len - i) >= 3 && host[i] == '%' && host[i+1] == '2' &&
403 (host[i+2] == 'F' || host[i+2] == 'f')) {
404 addr->addr.cun.sun_path[ofs++] = '/';
405 i += 2;
406 } else {
407 addr->addr.cun.sun_path[ofs++] = host[i];
408 }
409 if (ofs == COAP_UNIX_PATH_MAX)
410 break;
411 }
412 if (ofs < COAP_UNIX_PATH_MAX)
413 addr->addr.cun.sun_path[ofs] = '\000';
414 else
415 addr->addr.cun.sun_path[ofs-1] = '\000';
416 return 1;
417#else /* ! COAP_AF_UNIX_SUPPORT */
418 (void)addr;
419 (void)host;
420 (void)host_len;
421 return 0;
422#endif /* ! COAP_AF_UNIX_SUPPORT */
423}
424
425#if COAP_AF_LLC_SUPPORT
426/* Needed for ether_aton() and ARPHRD_ETHER. */
427#include <netinet/ether.h>
428#endif /* ! COAP_AF_LLC_SUPPORT */
429
430int
432 const uint8_t *host, size_t host_len) {
433#if COAP_AF_LLC_SUPPORT
434 char addrstr[HW_ADDRSTRLEN + 1] = { 0 };
435 struct ether_addr *ether_addr = NULL;
436 char sapstr[3] = { 0 };
437 unsigned long sap;
438
439 if (host_len < LLC_HOST_LEN)
440 coap_log_err("%s(): Invalid address length (%zu)\n", __func__, host_len);
441
442 host += 4;
443 strncpy(addrstr, (const char *)host, HW_ADDRSTRLEN);
444
445 ether_addr = ether_aton(addrstr);
446 if (!ether_addr)
447 return 0;
448
449 host += HW_ADDRSTRLEN + 2;
450 strncpy(sapstr, (const char *)host, 2);
451
452 sap = strtoul(sapstr, NULL, 16);
453 if (sap == ULONG_MAX)
454 return 0;
455
456 coap_address_init(addr);
457
458 addr->size = sizeof(addr->addr.llc);
459
460 addr->addr.llc.sllc_family = AF_LLC;
461 addr->addr.llc.sllc_arphrd = ARPHRD_ETHER;
462 addr->addr.llc.sllc_sap = sap & 0xFF;
463
464 memcpy(addr->addr.llc.sllc_mac, ether_addr, IFHWADDRLEN);
465
466 return 1;
467#else /* ! COAP_AF_LLC_SUPPORT */
468 (void)addr;
469 (void)host;
470 (void)host_len;
471
472 return 0;
473#endif /* ! COAP_AF_LLC_SUPPORT */
474}
475
476static void
477update_port(coap_address_t *addr, uint16_t port, uint16_t default_port,
478 int update_port0) {
479 /* Client target port must be set if default of 0 */
480 if (port == 0 && update_port0)
481 port = default_port;
482
483 coap_address_set_port(addr, port);
484 return;
485}
486
487#ifdef HAVE_NETDB_H
488#include <netdb.h>
489#endif
490
491uint32_t
492coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check,
493 coap_proto_t use_proto) {
494 uint32_t scheme_hint_bits = 0;
495 coap_uri_scheme_t scheme;
496
497 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
498 switch (scheme) {
500 scheme_hint_bits |= 1 << scheme;
501 break;
503 if (!(coap_dtls_is_supported() && have_pki_psk))
504 continue;
505 scheme_hint_bits |= 1 << scheme;
506 break;
509 continue;
510 scheme_hint_bits |= 1 << scheme;
511 break;
513 if (!(coap_tls_is_supported() && have_pki_psk))
514 continue;
515 scheme_hint_bits |= 1 << scheme;
516 break;
518 if (!ws_check || !coap_ws_is_supported())
519 continue;
520 scheme_hint_bits |= 1 << scheme;
521 break;
523 if (!ws_check || !(coap_wss_is_supported() && have_pki_psk))
524 continue;
525 scheme_hint_bits |= 1 << scheme;
526 break;
530 default:
531 continue;
532 }
533 }
534
535 switch (use_proto) {
536 /* For AF_UNIX, can only listen on a single endpoint */
537 case COAP_PROTO_UDP:
538 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP;
539 break;
540 case COAP_PROTO_TCP:
541 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_TCP;
542 break;
543 case COAP_PROTO_DTLS:
544 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS;
545 break;
546 case COAP_PROTO_TLS:
547 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_TCP;
548 break;
549 case COAP_PROTO_WS:
550 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_WS;
551 break;
552 case COAP_PROTO_WSS:
553 scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_WS;
554 break;
555 case COAP_PROTO_NONE: /* If use_proto was not defined */
556 case COAP_PROTO_LAST:
557 default:
558 break;
559 }
560 return scheme_hint_bits;
561}
562
563static coap_addr_info_t *
565 coap_addr_info_t *info = NULL;
566 coap_proto_t proto = 0;
567
568 switch (scheme) {
570 proto = COAP_PROTO_UDP;
571 break;
574 return NULL;
575 proto = COAP_PROTO_DTLS;
576 break;
579 return NULL;
580 proto = COAP_PROTO_TCP;
581 break;
584 return NULL;
585 proto = COAP_PROTO_TLS;
586 break;
589 return NULL;
590 proto = COAP_PROTO_NONE;
591 break;
594 return NULL;
595 proto = COAP_PROTO_NONE;
596 break;
599 return NULL;
600 proto = COAP_PROTO_WS;
601 break;
604 return NULL;
605 proto = COAP_PROTO_WSS;
606 break;
608 default:
609 return NULL;
610 }
612 if (info == NULL)
613 return NULL;
614 info->next = NULL;
615 info->proto = proto;
616 info->scheme = scheme;
617
618 coap_address_init(&info->addr);
619 return info;
620}
621
622static void
624 uint16_t port, uint16_t secure_port, uint16_t ws_port,
625 uint16_t ws_secure_port,
626 coap_resolve_type_t type) {
627 switch (scheme) {
629 update_port(&info->addr, port, COAP_DEFAULT_PORT,
631 break;
633 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
635 break;
637 update_port(&info->addr, port, COAP_DEFAULT_PORT,
639 break;
641 update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
643 break;
645 update_port(&info->addr, port, 80,
647 break;
649 update_port(&info->addr, secure_port, 443,
651 break;
653 update_port(&info->addr, ws_port, 80,
655 break;
657 update_port(&info->addr, ws_secure_port, 443,
659 break;
661 default:
662 break;
663 }
664}
665
666#if defined(WITH_LWIP) && !(LWIP_DNS)
667
670 uint16_t port,
671 uint16_t secure_port,
672 uint16_t ws_port,
673 uint16_t ws_secure_port,
674 int ai_hints_flags,
675 int scheme_hint_bits,
676 coap_resolve_type_t type) {
677 ip_addr_t addr_ip;
678 coap_addr_info_t *info = NULL;
679 coap_addr_info_t *info_prev = NULL;
680 coap_addr_info_t *info_list = NULL;
681 coap_uri_scheme_t scheme;
682
683 (void)ai_hints_flags;
684
685 if (address == NULL || address->length == 0) {
686 memset(&addr_ip, 0, sizeof(addr_ip));
687 } else {
688 if (ipaddr_aton((const char *)address->s, &addr_ip) <= 0) {
689 coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
690 return NULL;
691 }
692 }
693 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
694 if (scheme_hint_bits & (1 << scheme)) {
695 info = get_coap_addr_info(scheme);
696 if (info == NULL) {
697 continue;
698 }
699
700 /* Need to return in same order as getaddrinfo() */
701 if (!info_prev) {
702 info_list = info;
703 info_prev = info;
704 } else {
705 info_prev->next = info;
706 info_prev = info;
707 }
708
709 memcpy(&info->addr.addr, &addr_ip, sizeof(info->addr.addr));
710
711 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
712 ws_secure_port, type);
713 }
714 }
715 return info_list;
716}
717
718#elif !defined(RIOT_VERSION) && !defined(WITH_CONTIKI)
719
722 uint16_t port,
723 uint16_t secure_port,
724 uint16_t ws_port,
725 uint16_t ws_secure_port,
726 int ai_hints_flags,
727 int scheme_hint_bits,
728 coap_resolve_type_t type) {
729
730 struct addrinfo *res, *ainfo;
731 struct addrinfo hints;
732 static char addrstr[256];
733 int error;
734 coap_addr_info_t *info = NULL;
735 coap_addr_info_t *info_prev = NULL;
736 coap_addr_info_t *info_list = NULL;
737 coap_addr_info_t *info_tmp;
738 coap_uri_scheme_t scheme;
739
740#if COAP_AF_UNIX_SUPPORT
741 if (address && coap_host_is_unix_domain(address)) {
742 /* There can only be one unique filename entry for AF_UNIX */
743 if (address->length >= COAP_UNIX_PATH_MAX) {
744 coap_log_err("Unix Domain host too long\n");
745 return NULL;
746 }
747 /* Need to chose the first defined one in scheme_hint_bits */
748 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
749 if (scheme_hint_bits & (1 << scheme)) {
750 break;
751 }
752 }
753 if (scheme == COAP_URI_SCHEME_LAST) {
754 return NULL;
755 }
756 info = get_coap_addr_info(scheme);
757 if (info == NULL) {
758 return NULL;
759 }
760
761 if (!coap_address_set_unix_domain(&info->addr, address->s,
762 address->length)) {
764 return NULL;
765 }
766 return info;
767 }
768#endif /* COAP_AF_UNIX_SUPPORT */
769#if COAP_AF_LLC_SUPPORT
770 if (address && coap_host_is_llc(address)) {
771 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
772 if (scheme_hint_bits & (1 << scheme)) {
773 break;
774 }
775 }
776 if (scheme == COAP_URI_SCHEME_LAST) {
777 return NULL;
778 }
779 info = get_coap_addr_info(scheme);
780 if (info == NULL) {
781 return NULL;
782 }
783
784 if (!coap_address_set_llc(&info->addr, address->s, address->length)) {
786 return NULL;
787 }
788
789 return info;
790 }
791#endif /* COAP_AF_LLC_SUPPORT */
792
793 memset(addrstr, 0, sizeof(addrstr));
794 if (address && address->length) {
795 if (address->length >= sizeof(addrstr)) {
796 coap_log_warn("Host name too long (%" PRIuS " > 255)\n", address->length);
797 return NULL;
798 }
799 memcpy(addrstr, address->s, address->length);
800 } else {
801 memcpy(addrstr, "localhost", 9);
802 }
803
804 memset((char *)&hints, 0, sizeof(hints));
805 hints.ai_socktype = 0;
806 hints.ai_family = AF_UNSPEC;
807 hints.ai_flags = ai_hints_flags;
808
809 error = getaddrinfo(addrstr, NULL, &hints, &res);
810
811 if (error != 0) {
812#if defined(WITH_LWIP)
813 coap_log_warn("getaddrinfo: %s: %d\n", addrstr, error);
814#else /* ! WITH_LWIP */
815 coap_log_warn("getaddrinfo: %s: %s\n", addrstr, gai_strerror(error));
816#endif /* ! WITH_LWIP */
817 return NULL;
818 }
819
820 for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
821#if !defined(WITH_LWIP)
822 if (ainfo->ai_addrlen > (socklen_t)sizeof(info->addr.addr))
823 continue;
824#endif /* ! WITH_LWIP */
825
826 switch (ainfo->ai_family) {
827#if COAP_IPV4_SUPPORT
828 case AF_INET:
829#endif /* COAP_IPV4_SUPPORT */
830#if COAP_IPV6_SUPPORT
831 case AF_INET6:
832#endif /* COAP_IPV6_SUPPORT */
833 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
834 if (scheme_hint_bits & (1 << scheme)) {
835 info = get_coap_addr_info(scheme);
836 if (info == NULL) {
837 continue;
838 }
839
840#if !defined(WITH_LWIP)
841 info->addr.size = (socklen_t)ainfo->ai_addrlen;
842 memcpy(&info->addr.addr, ainfo->ai_addr, ainfo->ai_addrlen);
843#else /* WITH_LWIP */
844 memset(&info->addr, 0, sizeof(info->addr));
845 switch (ainfo->ai_family) {
846#if COAP_IPV6_SUPPORT
847 struct sockaddr_in6 *sock6;
848#endif /* COAP_IPV6_SUPPORT */
849#if COAP_IPV4_SUPPORT
850 struct sockaddr_in *sock4;
851 case AF_INET:
852 sock4 = (struct sockaddr_in *)ainfo->ai_addr;
853 info->addr.port = ntohs(sock4->sin_port);
854 memcpy(&info->addr.addr, &sock4->sin_addr, 4);
855#if LWIP_IPV6
856 info->addr.addr.type = IPADDR_TYPE_V4;
857#endif /* LWIP_IPV6 */
858 break;
859#endif /* COAP_IPV4_SUPPORT */
860#if COAP_IPV6_SUPPORT
861 case AF_INET6:
862 sock6 = (struct sockaddr_in6 *)ainfo->ai_addr;
863 info->addr.port = ntohs(sock6->sin6_port);
864 memcpy(&info->addr.addr, &sock6->sin6_addr, 16);
865#if LWIP_IPV6 && LWIP_IPV4
866 info->addr.addr.type = IPADDR_TYPE_V6;
867#endif /* LWIP_IPV6 && LWIP_IPV4 */
868 break;
869#endif /* COAP_IPV6_SUPPORT */
870 default:
871 ;
872 }
873#endif /* WITH_LWIP */
874 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
875 ws_secure_port, type);
876
877 /* Check there are no duplications */
878 info_tmp = info_list;
879 while (info_tmp) {
880 if (info_tmp->proto == info->proto &&
881 info_tmp->scheme == info->scheme &&
882 coap_address_equals(&info_tmp->addr, &info->addr)) {
883 break;
884 }
885 info_tmp = info_tmp->next;
886 }
887
888 if (info_tmp) {
889 /* Duplicate */
891 } else {
892 /* Need to return in same order as getaddrinfo() */
893 if (!info_prev) {
894 info_list = info;
895 info_prev = info;
896 } else {
897 info_prev->next = info;
898 info_prev = info;
899 }
900 }
901 }
902 }
903 break;
904 default:
905 break;
906 }
907 }
908
909 freeaddrinfo(res);
910 return info_list;
911}
912
913#elif defined(RIOT_VERSION)
914
915#include "net/utils.h"
916
919 uint16_t port,
920 uint16_t secure_port,
921 uint16_t ws_port,
922 uint16_t ws_secure_port,
923 int ai_hints_flags,
924 int scheme_hint_bits,
925 coap_resolve_type_t type) {
926#if COAP_IPV6_SUPPORT
927 ipv6_addr_t addr_ipv6;
928#endif /* COAP_IPV6_SUPPORT */
929#if COAP_IPV4_SUPPORT
930 ipv4_addr_t addr_ipv4;
931#endif /* COAP_IPV4_SUPPORT */
932 netif_t *netif = NULL;
933 coap_addr_info_t *info = NULL;
934 coap_addr_info_t *info_prev = NULL;
935 coap_addr_info_t *info_list = NULL;
936 coap_uri_scheme_t scheme;
937 (void)ai_hints_flags;
938 int family = AF_UNSPEC;
939
940 if (address == NULL || address->length == 0) {
941 memset(&addr_ipv6, 0, sizeof(addr_ipv6));
942#if COAP_IPV6_SUPPORT
943 family = AF_INET6;
944#else /* ! COAP_IPV6_SUPPORT */
945 family = AF_INET;
946#endif /* ! COAP_IPV6_SUPPORT */
947 } else {
948#if COAP_IPV6_SUPPORT
949 if (netutils_get_ipv6(&addr_ipv6, &netif, (const char *)address->s) >= 0) {
950 family = AF_INET6;
951 }
952#endif /* COAP_IPV6_SUPPORT */
953#if COAP_IPV4_SUPPORT
954 if (family == AF_UNSPEC &&
955 netutils_get_ipv4(&addr_ipv4, (const char *)address->s) >= 0) {
956 family = AF_INET;
957 }
958#endif /* COAP_IPV4_SUPPORT */
959 if (family == AF_UNSPEC) {
960 coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
961 return NULL;
962 }
963 }
964 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
965 if (scheme_hint_bits & (1 << scheme)) {
966 info = get_coap_addr_info(scheme);
967 if (info == NULL) {
968 continue;
969 }
970
971 /* Need to return in same order as getaddrinfo() */
972 if (!info_prev) {
973 info_list = info;
974 info_prev = info;
975 } else {
976 info_prev->next = info;
977 info_prev = info;
978 }
979
980 switch (family) {
981#if COAP_IPV6_SUPPORT
982 case AF_INET6:
983 info->addr.riot.family = AF_INET6;
984 memcpy(&info->addr.riot.addr.ipv6, &addr_ipv6,
985 sizeof(info->addr.riot.addr.ipv6));
986 info->addr.riot.netif = netif ? (uint32_t)netif_get_id(netif) : 0;
987 break;
988#endif /* ! COAP_IPV6_SUPPORT */
989#if COAP_IPV4_SUPPORT
990 case AF_INET:
991 info->addr.riot.family = AF_INET;
992 memcpy(&info->addr.riot.addr.ipv4, &addr_ipv4,
993 sizeof(info->addr.riot.addr.ipv4));
994 break;
995#endif /* ! COAP_IPV4_SUPPORT */
996 default:
997 break;
998 }
999
1000 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
1001 ws_secure_port, type);
1002 }
1003 }
1004 return info_list;
1005}
1006
1007#elif defined(WITH_CONTIKI)
1008
1009#include <os/net/ipv6/uiplib.h>
1010
1013 uint16_t port,
1014 uint16_t secure_port,
1015 uint16_t ws_port,
1016 uint16_t ws_secure_port,
1017 int ai_hints_flags,
1018 int scheme_hint_bits,
1019 coap_resolve_type_t type) {
1020 uip_ipaddr_t addr_ip;
1021 coap_addr_info_t *info = NULL;
1022 coap_addr_info_t *info_prev = NULL;
1023 coap_addr_info_t *info_list = NULL;
1024 coap_uri_scheme_t scheme;
1025 int parsed_ip = 0;
1026
1027 (void)ai_hints_flags;
1028
1029 if (address == NULL || address->length == 0) {
1030 memset(&addr_ip, 0, sizeof(addr_ip));
1031 } else {
1032#if COAP_IPV6_SUPPORT
1033 if (uiplib_ip6addrconv((const char *)address->s, (uip_ip6addr_t *)&addr_ip) > 0) {
1034 parsed_ip = 1;
1035 }
1036#endif /* COAP_IPV6_SUPPORT */
1037#if COAP_IPV4_SUPPORT
1038 if (!parsed_ip &&
1039 uiplib_ip4addrconv((const char *)address->s, (uip_ip4addr_t *)&addr_ip) > 0) {
1040 parsed_ip = 1;
1041 }
1042#endif /* COAP_IPV4_SUPPORT */
1043 if (!parsed_ip) {
1044 coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
1045 return NULL;
1046 }
1047 }
1048 for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
1049 if (scheme_hint_bits & (1 << scheme)) {
1050 info = get_coap_addr_info(scheme);
1051 if (info == NULL) {
1052 continue;
1053 }
1054
1055 /* Need to return in same order as getaddrinfo() */
1056 if (!info_prev) {
1057 info_list = info;
1058 info_prev = info;
1059 } else {
1060 info_prev->next = info;
1061 info_prev = info;
1062 }
1063
1064 memcpy(&info->addr.addr, &addr_ip, sizeof(info->addr.addr));
1065
1066 update_coap_addr_port(scheme, info, port, secure_port, ws_port,
1067 ws_secure_port, type);
1068 }
1069 }
1070 return info_list;
1071}
1072
1073#else
1074
1075#error "OS type not supported"
1076
1079 uint16_t port,
1080 uint16_t secure_port,
1081 uint16_t ws_port,
1082 uint16_t ws_secure_port,
1083 int ai_hints_flags,
1084 int scheme_hint_bits,
1085 coap_resolve_type_t type) {
1086 return NULL;
1087}
1088
1089#endif
1090
1091void
1093 while (info) {
1094 coap_addr_info_t *info_next = info->next;
1095
1097 info = info_next;
1098 }
1099}
1100
1101#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
1102void
1104#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
1105 memcpy(dst, src, sizeof(coap_address_t));
1106#else
1107 memset(dst, 0, sizeof(coap_address_t));
1108 dst->size = src->size;
1109#if COAP_IPV6_SUPPORT
1110 if (src->addr.sa.sa_family == AF_INET6) {
1111 dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family;
1112 dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr;
1113 dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port;
1114 dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id;
1115 }
1116#endif /* COAP_IPV6_SUPPORT */
1117#if COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT
1118 else
1119#endif /* COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT */
1120#if COAP_IPV4_SUPPORT
1121 if (src->addr.sa.sa_family == AF_INET) {
1122 dst->addr.sin = src->addr.sin;
1123 }
1124#endif /* COAP_IPV4_SUPPORT */
1125 else {
1126 memcpy(&dst->addr, &src->addr, src->size);
1127 }
1128#endif
1129}
1130
1131int
1133 /* need to compare only relevant parts of sockaddr_in6 */
1134 switch (a->addr.sa.sa_family) {
1135#if COAP_IPV4_SUPPORT
1136 case AF_INET:
1137 return a->addr.sin.sin_addr.s_addr == INADDR_ANY;
1138#endif /* COAP_IPV4_SUPPORT */
1139#if COAP_IPV6_SUPPORT
1140 case AF_INET6:
1141 return memcmp(&in6addr_any,
1142 &a->addr.sin6.sin6_addr,
1143 sizeof(in6addr_any)) == 0;
1144#endif /* COAP_IPV6_SUPPORT */
1145 default:
1146 ;
1147 }
1148
1149 return 0;
1150}
1151#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.
uint32_t coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check, coap_proto_t use_proto)
Determine and set up scheme_hint_bits for a server that can be used in a call to coap_resolve_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.
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...
int coap_address_set_llc(coap_address_t *addr, const uint8_t *host, size_t host_len)
Copy the parsed LLC host into addr, setting other fields as appropriate.
#define COAP_BCST_CNT
int coap_is_af_llc(const coap_address_t *a)
Checks if given address a denotes an AF_LLC address.
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:33
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().
#define NULL
Definition coap_option.h:30
int coap_host_is_llc(const coap_str_const_t *host)
Determines from the host whether this is an LLC socket request.
Definition coap_uri.c:478
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:466
coap_uri_scheme_t
The scheme specifiers.
Definition coap_uri.h:30
@ COAP_URI_SCHEME_COAPS_WS
Definition coap_uri.h:38
@ COAP_URI_SCHEME_COAPS_TCP
Definition coap_uri.h:34
@ COAP_URI_SCHEME_COAPS
Definition coap_uri.h:32
@ COAP_URI_SCHEME_COAP_TCP
Definition coap_uri.h:33
@ COAP_URI_SCHEME_COAP_WS
Definition coap_uri.h:37
@ COAP_URI_SCHEME_HTTPS
Definition coap_uri.h:36
@ COAP_URI_SCHEME_COAP
Definition coap_uri.h:31
@ COAP_URI_SCHEME_LAST
Definition coap_uri.h:39
@ COAP_URI_SCHEME_HTTP
Definition coap_uri.h:35
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:149
#define COAP_TICKS_PER_SECOND
Use ms resolution on POSIX systems.
Definition coap_time.h:164
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:39
coap_proto_t
CoAP protocol types Note: coap_layers_coap[] needs updating if extended.
Definition coap_pdu.h:317
#define COAPS_DEFAULT_PORT
Definition coap_pdu.h:40
@ 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: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:47
const uint8_t * s
read-only string data
Definition coap_str.h:49
size_t length
length of string
Definition coap_str.h:48