Coverage Report

Created: 2026-08-13 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/src/coap_address.c
Line
Count
Source
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
11
/**
12
 * @file coap_address.c
13
 * @brief Handling of network addresses
14
 */
15
16
#include "coap3/coap_libcoap_build.h"
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
64
uint16_t
65
0
coap_address_get_port(const coap_address_t *addr) {
66
0
  assert(addr != NULL);
67
0
  switch (addr->addr.sa.sa_family) {
68
0
#if COAP_IPV4_SUPPORT
69
0
  case AF_INET:
70
0
    return ntohs(addr->addr.sin.sin_port);
71
0
#endif /* COAP_IPV4_SUPPORT */
72
0
#if COAP_IPV6_SUPPORT
73
0
  case AF_INET6:
74
0
    return ntohs(addr->addr.sin6.sin6_port);
75
0
#endif /* COAP_IPV6_SUPPORT */
76
0
#if COAP_AF_LLC_SUPPORT
77
0
  case AF_LLC:
78
0
    return addr->addr.llc.sllc_sap;
79
0
#endif /* COAP_AF_LLC_SUPPORT */
80
0
  default: /* undefined */
81
0
    ;
82
0
  }
83
0
  return 0;
84
0
}
85
86
void
87
0
coap_address_set_port(coap_address_t *addr, uint16_t port) {
88
0
  assert(addr != NULL);
89
0
  switch (addr->addr.sa.sa_family) {
90
0
#if COAP_IPV4_SUPPORT
91
0
  case AF_INET:
92
0
    addr->addr.sin.sin_port = htons(port);
93
0
    break;
94
0
#endif /* COAP_IPV4_SUPPORT */
95
0
#if COAP_IPV6_SUPPORT
96
0
  case AF_INET6:
97
0
    addr->addr.sin6.sin6_port = htons(port);
98
0
    break;
99
0
#endif /* COAP_IPV6_SUPPORT */
100
0
#if COAP_AF_LLC_SUPPORT
101
0
  case AF_LLC:
102
0
    addr->addr.llc.sllc_sap = port & 0xFF;
103
0
#endif /* COAP_AF_LLC_SUPPORT */
104
0
  default: /* undefined */
105
0
    ;
106
0
  }
107
0
}
108
109
void
110
0
coap_address_clr_addr(coap_address_t *addr) {
111
0
  assert(addr != NULL);
112
0
  switch (addr->addr.sa.sa_family) {
113
0
#if COAP_IPV4_SUPPORT
114
0
  case AF_INET:
115
0
    memset(&addr->addr.sin.sin_addr, 0, sizeof(addr->addr.sin.sin_addr));
116
0
    break;
117
0
#endif /* COAP_IPV4_SUPPORT */
118
0
#if COAP_IPV6_SUPPORT
119
0
  case AF_INET6:
120
0
    memset(&addr->addr.sin6.sin6_addr, 0, sizeof(addr->addr.sin6.sin6_addr));
121
0
    break;
122
0
#endif /* COAP_IPV6_SUPPORT */
123
0
  default: /* undefined */
124
0
    ;
125
0
  }
126
0
}
127
128
int
129
0
coap_address_equals(const coap_address_t *a, const coap_address_t *b) {
130
0
  assert(a);
131
0
  assert(b);
132
133
0
  if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
134
0
    return 0;
135
136
  /* need to compare only relevant parts of sockaddr_in6 */
137
0
  switch (a->addr.sa.sa_family) {
138
0
#if COAP_IPV4_SUPPORT
139
0
  case AF_INET:
140
0
    return a->addr.sin.sin_port == b->addr.sin.sin_port &&
141
0
           memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
142
0
                  sizeof(struct in_addr)) == 0;
143
0
#endif /* COAP_IPV4_SUPPORT */
144
0
#if COAP_IPV6_SUPPORT
145
0
  case AF_INET6:
146
0
    return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
147
0
           memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
148
0
                  sizeof(struct in6_addr)) == 0;
149
0
#endif /* COAP_IPV6_SUPPORT */
150
0
#if COAP_AF_UNIX_SUPPORT
151
0
  case AF_UNIX:
152
0
    return memcmp(&a->addr.cun.sun_path, &b->addr.cun.sun_path,
153
0
                  sizeof(a->addr.cun.sun_path)) == 0;
154
0
#endif /* COAP_AF_UNIX_SUPPORT */
155
0
  default: /* fall through and signal error */
156
0
    ;
157
0
  }
158
0
  return 0;
159
0
}
160
161
int
162
0
coap_is_af_unix(const coap_address_t *a) {
163
0
#if COAP_AF_UNIX_SUPPORT
164
0
  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
0
}
170
171
int
172
27
coap_is_af_llc(const coap_address_t *a) {
173
27
#if COAP_AF_LLC_SUPPORT
174
27
  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
27
}
180
181
int
182
67
coap_is_mcast(const coap_address_t *a) {
183
67
  if (!a)
184
0
    return 0;
185
186
  /* Treat broadcast in same way as multicast */
187
67
  if (coap_is_bcast(a))
188
0
    return 1;
189
190
67
  switch (a->addr.sa.sa_family) {
191
0
#if COAP_IPV4_SUPPORT
192
58
  case AF_INET:
193
58
    return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr));
194
0
#endif /* COAP_IPV4_SUPPORT */
195
0
#if COAP_IPV6_SUPPORT
196
0
  case  AF_INET6:
197
0
#if COAP_IPV4_SUPPORT
198
0
    return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr) ||
199
0
           (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr) &&
200
0
            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
0
#endif /* COAP_IPV6_SUPPORT */
205
9
  default:  /* fall through and signal not multicast */
206
9
    ;
207
67
  }
208
9
  return 0;
209
67
}
210
211
#ifndef COAP_BCST_CNT
212
4
#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
57
#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))
221
static int bcst_cnt = -1;
222
static coap_tick_t last_refresh;
223
static struct in_addr b_ipv4[COAP_BCST_CNT];
224
#endif /* COAP_IPV4_SUPPORT && !defined(__ZEPHYR__) && (defined(HAVE_GETIFADDRS) || defined(_WIN32)) */
225
226
int
227
67
coap_is_bcast(const coap_address_t *a) {
228
67
#if COAP_IPV4_SUPPORT
229
67
  struct in_addr ipv4;
230
67
#if defined(HAVE_GETIFADDRS) && !defined(__ZEPHYR__)
231
67
  int i;
232
67
  coap_tick_t now;
233
67
#endif /* HAVE_GETIFADDRS && !defined(__ZEPHYR__) */
234
67
#endif /* COAP_IPV4_SUPPORT */
235
236
67
  if (!a)
237
0
    return 0;
238
239
67
  switch (a->addr.sa.sa_family) {
240
0
#if COAP_IPV4_SUPPORT
241
58
  case AF_INET:
242
58
    ipv4.s_addr = a->addr.sin.sin_addr.s_addr;
243
58
    break;
244
0
#endif /* COAP_IPV4_SUPPORT */
245
0
#if COAP_IPV6_SUPPORT
246
0
  case  AF_INET6:
247
0
#if COAP_IPV4_SUPPORT
248
0
    if (IN6_IS_ADDR_V4MAPPED(&a->addr.sin6.sin6_addr)) {
249
0
      memcpy(&ipv4, &a->addr.sin6.sin6_addr.s6_addr[12], sizeof(ipv4));
250
0
      break;
251
0
    }
252
0
#endif /* COAP_IPV4_SUPPORT */
253
    /* IPv6 does not support broadcast */
254
0
    return 0;
255
0
#endif /* COAP_IPV6_SUPPORT */
256
9
  default:
257
9
    return 0;
258
67
  }
259
58
#if COAP_IPV4_SUPPORT
260
#ifndef INADDR_BROADCAST
261
#define INADDR_BROADCAST ((uint32_t)0xffffffffUL)
262
#endif /* !INADDR_BROADCAST */
263
58
  if (ipv4.s_addr == INADDR_BROADCAST)
264
0
    return 1;
265
266
58
#if defined(HAVE_GETIFADDRS) && !defined(__ZEPHYR__)
267
58
  coap_ticks(&now);
268
58
  if (bcst_cnt == -1 ||
269
57
      (now - last_refresh) > (COAP_BCST_REFRESH_SECS * COAP_TICKS_PER_SECOND)) {
270
    /* Determine the list of broadcast interfaces */
271
1
    struct ifaddrs *ifa = NULL;
272
1
    struct ifaddrs *ife;
273
274
1
    if (getifaddrs(&ifa) != 0) {
275
0
      coap_log_warn("coap_is_bcst: Cannot determine any broadcast addresses\n");
276
0
      return 0;
277
0
    }
278
1
    bcst_cnt = 0;
279
1
    last_refresh = now;
280
1
    ife = ifa;
281
5
    while (ife && bcst_cnt < COAP_BCST_CNT) {
282
4
      if (ife->ifa_addr && ife->ifa_addr->sa_family == AF_INET &&
283
2
          ife->ifa_flags & IFF_BROADCAST) {
284
1
        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
1
        netmask.s_addr = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr.s_addr;
291
1
        if (netmask.s_addr != 0xffffffff) {
292
1
          b_ipv4[bcst_cnt].s_addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr |
293
1
                                    ~netmask.s_addr;
294
1
          bcst_cnt++;
295
1
        }
296
1
      }
297
4
      ife = ife->ifa_next;
298
4
    }
299
1
    if (ife) {
300
0
      coap_log_warn("coap_is_bcst: Insufficient space for broadcast addresses\n");
301
0
    }
302
1
    freeifaddrs(ifa);
303
1
  }
304
116
  for (i = 0; i < bcst_cnt; i++) {
305
58
    if (ipv4.s_addr == b_ipv4[i].s_addr)
306
0
      return 1;
307
58
  }
308
58
#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
58
#endif /* COAP_IPV4_SUPPORT */
377
58
  return 0;
378
58
}
379
380
#endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */
381
382
void
383
81
coap_address_init(coap_address_t *addr) {
384
81
  assert(addr);
385
81
  memset(addr, 0, sizeof(coap_address_t));
386
81
#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
81
  addr->size = sizeof(addr->addr);
389
81
#endif
390
81
}
391
392
int
393
coap_address_set_unix_domain(coap_address_t *addr,
394
0
                             const uint8_t *host, size_t host_len) {
395
0
#if COAP_AF_UNIX_SUPPORT
396
0
  size_t i;
397
0
  size_t ofs = 0;
398
399
0
  coap_address_init(addr);
400
0
  addr->addr.cun.sun_family = AF_UNIX;
401
0
  for (i = 0; i < host_len; i++) {
402
0
    if ((host_len - i) >= 3 && host[i] == '%' && host[i+1] == '2' &&
403
0
        (host[i+2] == 'F' || host[i+2] == 'f')) {
404
0
      addr->addr.cun.sun_path[ofs++] = '/';
405
0
      i += 2;
406
0
    } else {
407
0
      addr->addr.cun.sun_path[ofs++] = host[i];
408
0
    }
409
0
    if (ofs == COAP_UNIX_PATH_MAX)
410
0
      break;
411
0
  }
412
0
  if (ofs < COAP_UNIX_PATH_MAX)
413
0
    addr->addr.cun.sun_path[ofs] = '\000';
414
0
  else
415
0
    addr->addr.cun.sun_path[ofs-1] = '\000';
416
0
  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
0
}
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
430
int
431
coap_address_set_llc(coap_address_t *addr,
432
0
                     const uint8_t *host, size_t host_len) {
433
0
#if COAP_AF_LLC_SUPPORT
434
0
  char addrstr[HW_ADDRSTRLEN + 1] = { 0 };
435
0
  struct ether_addr *ether_addr = NULL;
436
0
  char sapstr[3] = { 0 };
437
0
  unsigned long sap;
438
439
0
  if (host_len < LLC_HOST_LEN)
440
0
    coap_log_err("%s(): Invalid address length (%zu)\n", __func__, host_len);
441
442
0
  host += 4;
443
0
  strncpy(addrstr, (const char *)host, HW_ADDRSTRLEN);
444
445
0
  ether_addr = ether_aton(addrstr);
446
0
  if (!ether_addr)
447
0
    return 0;
448
449
0
  host += HW_ADDRSTRLEN + 2;
450
0
  strncpy(sapstr, (const char *)host, 2);
451
452
0
  sap = strtoul(sapstr, NULL, 16);
453
0
  if (sap == ULONG_MAX)
454
0
    return 0;
455
456
0
  coap_address_init(addr);
457
458
0
  addr->size = sizeof(addr->addr.llc);
459
460
0
  addr->addr.llc.sllc_family = AF_LLC;
461
0
  addr->addr.llc.sllc_arphrd = ARPHRD_ETHER;
462
0
  addr->addr.llc.sllc_sap = sap & 0xFF;
463
464
0
  memcpy(addr->addr.llc.sllc_mac, ether_addr, IFHWADDRLEN);
465
466
0
  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
0
}
475
476
static void
477
update_port(coap_address_t *addr, uint16_t port, uint16_t default_port,
478
0
            int update_port0) {
479
  /* Client target port must be set if default of 0 */
480
0
  if (port == 0 && update_port0)
481
0
    port = default_port;
482
483
0
  coap_address_set_port(addr, port);
484
0
  return;
485
0
}
486
487
#ifdef HAVE_NETDB_H
488
#include <netdb.h>
489
#endif
490
491
uint32_t
492
coap_get_available_scheme_hint_bits(int have_pki_psk, int ws_check,
493
0
                                    coap_proto_t use_proto) {
494
0
  uint32_t scheme_hint_bits = 0;
495
0
  coap_uri_scheme_t scheme;
496
497
0
  for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
498
0
    switch (scheme) {
499
0
    case COAP_URI_SCHEME_COAP:
500
0
      scheme_hint_bits |= 1 << scheme;
501
0
      break;
502
0
    case COAP_URI_SCHEME_COAPS:
503
0
      if (!(coap_dtls_is_supported() && have_pki_psk))
504
0
        continue;
505
0
      scheme_hint_bits |= 1 << scheme;
506
0
      break;
507
0
    case COAP_URI_SCHEME_COAP_TCP:
508
0
      if (!coap_tcp_is_supported())
509
0
        continue;
510
0
      scheme_hint_bits |= 1 << scheme;
511
0
      break;
512
0
    case COAP_URI_SCHEME_COAPS_TCP:
513
0
      if (!(coap_tls_is_supported() && have_pki_psk))
514
0
        continue;
515
0
      scheme_hint_bits |= 1 << scheme;
516
0
      break;
517
0
    case COAP_URI_SCHEME_COAP_WS:
518
0
      if (!ws_check || !coap_ws_is_supported())
519
0
        continue;
520
0
      scheme_hint_bits |= 1 << scheme;
521
0
      break;
522
0
    case COAP_URI_SCHEME_COAPS_WS:
523
0
      if (!ws_check || !(coap_wss_is_supported() && have_pki_psk))
524
0
        continue;
525
0
      scheme_hint_bits |= 1 << scheme;
526
0
      break;
527
0
    case COAP_URI_SCHEME_HTTP:
528
0
    case COAP_URI_SCHEME_HTTPS:
529
0
    case COAP_URI_SCHEME_LAST:
530
0
    default:
531
0
      continue;
532
0
    }
533
0
  }
534
535
0
  switch (use_proto) {
536
  /* For AF_UNIX, can only listen on a single endpoint */
537
0
  case COAP_PROTO_UDP:
538
0
    scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP;
539
0
    break;
540
0
  case COAP_PROTO_TCP:
541
0
    scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_TCP;
542
0
    break;
543
0
  case COAP_PROTO_DTLS:
544
0
    scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS;
545
0
    break;
546
0
  case COAP_PROTO_TLS:
547
0
    scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_TCP;
548
0
    break;
549
0
  case COAP_PROTO_WS:
550
0
    scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP_WS;
551
0
    break;
552
0
  case COAP_PROTO_WSS:
553
0
    scheme_hint_bits = 1 << COAP_URI_SCHEME_COAPS_WS;
554
0
    break;
555
0
  case COAP_PROTO_NONE: /* If use_proto was not defined */
556
0
  case COAP_PROTO_LAST:
557
0
  default:
558
0
    break;
559
0
  }
560
0
  return scheme_hint_bits;
561
0
}
562
563
static coap_addr_info_t *
564
0
get_coap_addr_info(coap_uri_scheme_t scheme) {
565
0
  coap_addr_info_t *info = NULL;
566
0
  coap_proto_t proto = 0;
567
568
0
  switch (scheme) {
569
0
  case COAP_URI_SCHEME_COAP:
570
0
    proto = COAP_PROTO_UDP;
571
0
    break;
572
0
  case COAP_URI_SCHEME_COAPS:
573
0
    if (!coap_dtls_is_supported())
574
0
      return NULL;
575
0
    proto = COAP_PROTO_DTLS;
576
0
    break;
577
0
  case COAP_URI_SCHEME_COAP_TCP:
578
0
    if (!coap_tcp_is_supported())
579
0
      return NULL;
580
0
    proto = COAP_PROTO_TCP;
581
0
    break;
582
0
  case COAP_URI_SCHEME_COAPS_TCP:
583
0
    if (!coap_tls_is_supported())
584
0
      return NULL;
585
0
    proto = COAP_PROTO_TLS;
586
0
    break;
587
0
  case COAP_URI_SCHEME_HTTP:
588
0
    if (!coap_tcp_is_supported())
589
0
      return NULL;
590
0
    proto = COAP_PROTO_NONE;
591
0
    break;
592
0
  case COAP_URI_SCHEME_HTTPS:
593
0
    if (!coap_tls_is_supported())
594
0
      return NULL;
595
0
    proto = COAP_PROTO_NONE;
596
0
    break;
597
0
  case COAP_URI_SCHEME_COAP_WS:
598
0
    if (!coap_ws_is_supported())
599
0
      return NULL;
600
0
    proto = COAP_PROTO_WS;
601
0
    break;
602
0
  case COAP_URI_SCHEME_COAPS_WS:
603
0
    if (!coap_wss_is_supported())
604
0
      return NULL;
605
0
    proto = COAP_PROTO_WSS;
606
0
    break;
607
0
  case COAP_URI_SCHEME_LAST:
608
0
  default:
609
0
    return NULL;
610
0
  }
611
0
  info = coap_malloc_type(COAP_STRING, sizeof(coap_addr_info_t));
612
0
  if (info == NULL)
613
0
    return NULL;
614
0
  info->next = NULL;
615
0
  info->proto = proto;
616
0
  info->scheme = scheme;
617
618
0
  coap_address_init(&info->addr);
619
0
  return info;
620
0
}
621
622
static void
623
update_coap_addr_port(coap_uri_scheme_t scheme, coap_addr_info_t *info,
624
                      uint16_t port, uint16_t secure_port, uint16_t ws_port,
625
                      uint16_t ws_secure_port,
626
0
                      coap_resolve_type_t type) {
627
0
  switch (scheme) {
628
0
  case COAP_URI_SCHEME_COAP:
629
0
    update_port(&info->addr, port, COAP_DEFAULT_PORT,
630
0
                type == COAP_RESOLVE_TYPE_LOCAL);
631
0
    break;
632
0
  case COAP_URI_SCHEME_COAPS:
633
0
    update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
634
0
                type == COAP_RESOLVE_TYPE_LOCAL);
635
0
    break;
636
0
  case COAP_URI_SCHEME_COAP_TCP:
637
0
    update_port(&info->addr, port, COAP_DEFAULT_PORT,
638
0
                type == COAP_RESOLVE_TYPE_LOCAL);
639
0
    break;
640
0
  case COAP_URI_SCHEME_COAPS_TCP:
641
0
    update_port(&info->addr, secure_port, COAPS_DEFAULT_PORT,
642
0
                type == COAP_RESOLVE_TYPE_LOCAL);
643
0
    break;
644
0
  case COAP_URI_SCHEME_HTTP:
645
0
    update_port(&info->addr, port, 80,
646
0
                type == COAP_RESOLVE_TYPE_LOCAL);
647
0
    break;
648
0
  case COAP_URI_SCHEME_HTTPS:
649
0
    update_port(&info->addr, secure_port, 443,
650
0
                type == COAP_RESOLVE_TYPE_LOCAL);
651
0
    break;
652
0
  case COAP_URI_SCHEME_COAP_WS:
653
0
    update_port(&info->addr, ws_port, 80,
654
0
                type == COAP_RESOLVE_TYPE_LOCAL);
655
0
    break;
656
0
  case COAP_URI_SCHEME_COAPS_WS:
657
0
    update_port(&info->addr, ws_secure_port, 443,
658
0
                type == COAP_RESOLVE_TYPE_LOCAL);
659
0
    break;
660
0
  case COAP_URI_SCHEME_LAST:
661
0
  default:
662
0
    break;
663
0
  }
664
0
}
665
666
#if defined(WITH_LWIP) && !(LWIP_DNS)
667
668
coap_addr_info_t *
669
coap_resolve_address_info_lkd(const coap_str_const_t *address,
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
  coap_lock_check_locked();
686
687
  if (address == NULL || address->length == 0) {
688
    memset(&addr_ip, 0, sizeof(addr_ip));
689
  } else {
690
    if (ipaddr_aton((const char *)address->s, &addr_ip) <= 0) {
691
      coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
692
      return NULL;
693
    }
694
  }
695
  for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
696
    if (scheme_hint_bits & (1 << scheme)) {
697
      info = get_coap_addr_info(scheme);
698
      if (info == NULL) {
699
        continue;
700
      }
701
702
      /* Need to return in same order as getaddrinfo() */
703
      if (!info_prev) {
704
        info_list = info;
705
        info_prev = info;
706
      } else {
707
        info_prev->next = info;
708
        info_prev = info;
709
      }
710
711
      memcpy(&info->addr.addr, &addr_ip, sizeof(info->addr.addr));
712
713
      update_coap_addr_port(scheme, info, port, secure_port, ws_port,
714
                            ws_secure_port, type);
715
    }
716
  }
717
  return info_list;
718
}
719
720
#elif !defined(RIOT_VERSION) && !defined(WITH_CONTIKI)
721
722
coap_addr_info_t *
723
coap_resolve_address_info_lkd(const coap_str_const_t *address,
724
                              uint16_t port,
725
                              uint16_t secure_port,
726
                              uint16_t ws_port,
727
                              uint16_t ws_secure_port,
728
                              int ai_hints_flags,
729
                              int scheme_hint_bits,
730
0
                              coap_resolve_type_t type) {
731
732
0
  struct addrinfo *res, *ainfo;
733
0
  struct addrinfo hints;
734
#if COAP_CONSTRAINED_STACK
735
  static char addrstr[256];
736
#else /* ! COAP_CONSTRAINED_STACK */
737
0
  char addrstr[256];
738
0
#endif /* ! COAP_CONSTRAINED_STACK */
739
0
  int error;
740
0
  coap_addr_info_t *info = NULL;
741
0
  coap_addr_info_t *info_prev = NULL;
742
0
  coap_addr_info_t *info_list = NULL;
743
0
  coap_addr_info_t *info_tmp;
744
0
  coap_uri_scheme_t scheme;
745
746
0
  coap_lock_check_locked();
747
748
0
#if COAP_AF_UNIX_SUPPORT
749
0
  if (address && coap_host_is_unix_domain(address)) {
750
    /* There can only be one unique filename entry for AF_UNIX */
751
0
    if (address->length >= COAP_UNIX_PATH_MAX) {
752
0
      coap_log_err("Unix Domain host too long\n");
753
0
      return NULL;
754
0
    }
755
    /* Need to chose the first defined one  in scheme_hint_bits */
756
0
    for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
757
0
      if (scheme_hint_bits & (1 << scheme)) {
758
0
        break;
759
0
      }
760
0
    }
761
0
    if (scheme == COAP_URI_SCHEME_LAST) {
762
0
      return NULL;
763
0
    }
764
0
    info = get_coap_addr_info(scheme);
765
0
    if (info == NULL) {
766
0
      return NULL;
767
0
    }
768
769
0
    if (!coap_address_set_unix_domain(&info->addr, address->s,
770
0
                                      address->length)) {
771
0
      coap_free_type(COAP_STRING, info);
772
0
      return NULL;
773
0
    }
774
0
    return info;
775
0
  }
776
0
#endif /* COAP_AF_UNIX_SUPPORT */
777
0
#if COAP_AF_LLC_SUPPORT
778
0
  if (address && coap_host_is_llc(address)) {
779
0
    for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
780
0
      if (scheme_hint_bits & (1 << scheme)) {
781
0
        break;
782
0
      }
783
0
    }
784
0
    if (scheme == COAP_URI_SCHEME_LAST) {
785
0
      return NULL;
786
0
    }
787
0
    info = get_coap_addr_info(scheme);
788
0
    if (info == NULL) {
789
0
      return NULL;
790
0
    }
791
792
0
    if (!coap_address_set_llc(&info->addr, address->s, address->length)) {
793
0
      coap_free_type(COAP_STRING, info);
794
0
      return NULL;
795
0
    }
796
797
0
    return info;
798
0
  }
799
0
#endif /* COAP_AF_LLC_SUPPORT */
800
801
0
  memset(addrstr, 0, sizeof(addrstr));
802
0
  if (address && address->length) {
803
0
    if (address->length >= sizeof(addrstr)) {
804
0
      coap_log_warn("Host name too long (%" PRIuS " > 255)\n", address->length);
805
0
      return NULL;
806
0
    }
807
0
    memcpy(addrstr, address->s, address->length);
808
0
  } else {
809
0
    memcpy(addrstr, "localhost", 9);
810
0
  }
811
812
0
  memset((char *)&hints, 0, sizeof(hints));
813
0
  hints.ai_socktype = 0;
814
0
  hints.ai_family = AF_UNSPEC;
815
0
  hints.ai_flags = ai_hints_flags;
816
817
0
  error = getaddrinfo(addrstr, NULL, &hints, &res);
818
819
0
  if (error != 0) {
820
#if defined(WITH_LWIP)
821
    coap_log_warn("getaddrinfo: %s: %d\n", addrstr, error);
822
#else /* ! WITH_LWIP */
823
0
    coap_log_warn("getaddrinfo: %s: %s\n", addrstr, gai_strerror(error));
824
0
#endif /* ! WITH_LWIP */
825
0
    return NULL;
826
0
  }
827
828
0
  for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
829
0
#if !defined(WITH_LWIP)
830
0
    if (ainfo->ai_addrlen > (socklen_t)sizeof(info->addr.addr))
831
0
      continue;
832
0
#endif /* ! WITH_LWIP */
833
834
0
    switch (ainfo->ai_family) {
835
0
#if COAP_IPV4_SUPPORT
836
0
    case AF_INET:
837
0
#endif /* COAP_IPV4_SUPPORT */
838
0
#if COAP_IPV6_SUPPORT
839
0
    case AF_INET6:
840
0
#endif /* COAP_IPV6_SUPPORT */
841
0
      for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
842
0
        if (scheme_hint_bits & (1 << scheme)) {
843
0
          info = get_coap_addr_info(scheme);
844
0
          if (info == NULL) {
845
0
            continue;
846
0
          }
847
848
0
#if !defined(WITH_LWIP)
849
0
          info->addr.size = (socklen_t)ainfo->ai_addrlen;
850
0
          memcpy(&info->addr.addr, ainfo->ai_addr, ainfo->ai_addrlen);
851
#else /* WITH_LWIP */
852
          memset(&info->addr, 0, sizeof(info->addr));
853
          switch (ainfo->ai_family) {
854
#if COAP_IPV6_SUPPORT
855
            struct sockaddr_in6 *sock6;
856
#endif /* COAP_IPV6_SUPPORT */
857
#if COAP_IPV4_SUPPORT
858
            struct sockaddr_in *sock4;
859
          case AF_INET:
860
            sock4 = (struct sockaddr_in *)ainfo->ai_addr;
861
            info->addr.port = ntohs(sock4->sin_port);
862
            memcpy(&info->addr.addr, &sock4->sin_addr, 4);
863
#if LWIP_IPV6
864
            info->addr.addr.type = IPADDR_TYPE_V4;
865
#endif /* LWIP_IPV6 */
866
            break;
867
#endif /* COAP_IPV4_SUPPORT */
868
#if COAP_IPV6_SUPPORT
869
          case AF_INET6:
870
            sock6 = (struct sockaddr_in6 *)ainfo->ai_addr;
871
            info->addr.port = ntohs(sock6->sin6_port);
872
            memcpy(&info->addr.addr, &sock6->sin6_addr, 16);
873
#if LWIP_IPV6 && LWIP_IPV4
874
            info->addr.addr.type = IPADDR_TYPE_V6;
875
#endif /* LWIP_IPV6 && LWIP_IPV4 */
876
            break;
877
#endif /* COAP_IPV6_SUPPORT */
878
          default:
879
            ;
880
          }
881
#endif /* WITH_LWIP */
882
0
          update_coap_addr_port(scheme, info, port, secure_port, ws_port,
883
0
                                ws_secure_port, type);
884
885
          /* Check there are no duplications */
886
0
          info_tmp = info_list;
887
0
          while (info_tmp) {
888
0
            if (info_tmp->proto == info->proto &&
889
0
                info_tmp->scheme == info->scheme &&
890
0
                coap_address_equals(&info_tmp->addr, &info->addr)) {
891
0
              break;
892
0
            }
893
0
            info_tmp = info_tmp->next;
894
0
          }
895
896
0
          if (info_tmp) {
897
            /* Duplicate */
898
0
            coap_free_type(COAP_STRING, info);
899
0
          } else {
900
            /* Need to return in same order as getaddrinfo() */
901
0
            if (!info_prev) {
902
0
              info_list = info;
903
0
              info_prev = info;
904
0
            } else {
905
0
              info_prev->next = info;
906
0
              info_prev = info;
907
0
            }
908
0
          }
909
0
        }
910
0
      }
911
0
      break;
912
0
    default:
913
0
      break;
914
0
    }
915
0
  }
916
917
0
  freeaddrinfo(res);
918
0
  return info_list;
919
0
}
920
921
#elif defined(RIOT_VERSION)
922
923
#include "net/utils.h"
924
925
coap_addr_info_t *
926
coap_resolve_address_info_lkd(const coap_str_const_t *address,
927
                              uint16_t port,
928
                              uint16_t secure_port,
929
                              uint16_t ws_port,
930
                              uint16_t ws_secure_port,
931
                              int ai_hints_flags,
932
                              int scheme_hint_bits,
933
                              coap_resolve_type_t type) {
934
#if COAP_IPV6_SUPPORT
935
  ipv6_addr_t addr_ipv6;
936
#endif /* COAP_IPV6_SUPPORT */
937
#if COAP_IPV4_SUPPORT
938
  ipv4_addr_t addr_ipv4;
939
#endif /* COAP_IPV4_SUPPORT */
940
  netif_t *netif = NULL;
941
  coap_addr_info_t *info = NULL;
942
  coap_addr_info_t *info_prev = NULL;
943
  coap_addr_info_t *info_list = NULL;
944
  coap_uri_scheme_t scheme;
945
  (void)ai_hints_flags;
946
  int family = AF_UNSPEC;
947
948
  coap_lock_check_locked();
949
950
  if (address == NULL || address->length == 0) {
951
    memset(&addr_ipv6, 0, sizeof(addr_ipv6));
952
#if COAP_IPV6_SUPPORT
953
    family = AF_INET6;
954
#else /* ! COAP_IPV6_SUPPORT */
955
    family = AF_INET;
956
#endif /* ! COAP_IPV6_SUPPORT */
957
  } else {
958
#if COAP_IPV6_SUPPORT
959
    if (netutils_get_ipv6(&addr_ipv6, &netif, (const char *)address->s) >= 0) {
960
      family = AF_INET6;
961
    }
962
#endif /* COAP_IPV6_SUPPORT */
963
#if COAP_IPV4_SUPPORT
964
    if (family == AF_UNSPEC &&
965
        netutils_get_ipv4(&addr_ipv4, (const char *)address->s) >= 0) {
966
      family = AF_INET;
967
    }
968
#endif /* COAP_IPV4_SUPPORT */
969
    if (family == AF_UNSPEC) {
970
      coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
971
      return NULL;
972
    }
973
  }
974
  for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
975
    if (scheme_hint_bits & (1 << scheme)) {
976
      info = get_coap_addr_info(scheme);
977
      if (info == NULL) {
978
        continue;
979
      }
980
981
      /* Need to return in same order as getaddrinfo() */
982
      if (!info_prev) {
983
        info_list = info;
984
        info_prev = info;
985
      } else {
986
        info_prev->next = info;
987
        info_prev = info;
988
      }
989
990
      switch (family) {
991
#if COAP_IPV6_SUPPORT
992
      case AF_INET6:
993
        info->addr.riot.family = AF_INET6;
994
        memcpy(&info->addr.riot.addr.ipv6, &addr_ipv6,
995
               sizeof(info->addr.riot.addr.ipv6));
996
        info->addr.riot.netif = netif ? (uint32_t)netif_get_id(netif) : 0;
997
        break;
998
#endif /* ! COAP_IPV6_SUPPORT */
999
#if COAP_IPV4_SUPPORT
1000
      case AF_INET:
1001
        info->addr.riot.family = AF_INET;
1002
        memcpy(&info->addr.riot.addr.ipv4, &addr_ipv4,
1003
               sizeof(info->addr.riot.addr.ipv4));
1004
        break;
1005
#endif /* ! COAP_IPV4_SUPPORT */
1006
      default:
1007
        break;
1008
      }
1009
1010
      update_coap_addr_port(scheme, info, port, secure_port, ws_port,
1011
                            ws_secure_port, type);
1012
    }
1013
  }
1014
  return info_list;
1015
}
1016
1017
#elif defined(WITH_CONTIKI)
1018
1019
#include <os/net/ipv6/uiplib.h>
1020
1021
coap_addr_info_t *
1022
coap_resolve_address_info_lkd(const coap_str_const_t *address,
1023
                              uint16_t port,
1024
                              uint16_t secure_port,
1025
                              uint16_t ws_port,
1026
                              uint16_t ws_secure_port,
1027
                              int ai_hints_flags,
1028
                              int scheme_hint_bits,
1029
                              coap_resolve_type_t type) {
1030
  uip_ipaddr_t addr_ip;
1031
  coap_addr_info_t *info = NULL;
1032
  coap_addr_info_t *info_prev = NULL;
1033
  coap_addr_info_t *info_list = NULL;
1034
  coap_uri_scheme_t scheme;
1035
  int parsed_ip = 0;
1036
1037
  (void)ai_hints_flags;
1038
1039
  coap_lock_check_locked();
1040
1041
  if (address == NULL || address->length == 0) {
1042
    memset(&addr_ip, 0, sizeof(addr_ip));
1043
  } else {
1044
#if COAP_IPV6_SUPPORT
1045
    if (uiplib_ip6addrconv((const char *)address->s, (uip_ip6addr_t *)&addr_ip) > 0) {
1046
      parsed_ip = 1;
1047
    }
1048
#endif /* COAP_IPV6_SUPPORT */
1049
#if COAP_IPV4_SUPPORT
1050
    if (!parsed_ip &&
1051
        uiplib_ip4addrconv((const char *)address->s, (uip_ip4addr_t *)&addr_ip) > 0) {
1052
      parsed_ip = 1;
1053
    }
1054
#endif /* COAP_IPV4_SUPPORT */
1055
    if (!parsed_ip) {
1056
      coap_log_err("coap_resolve_address_info: Unable to parse '%s'\n", address->s);
1057
      return NULL;
1058
    }
1059
  }
1060
  for (scheme = 0; scheme < COAP_URI_SCHEME_LAST; scheme++) {
1061
    if (scheme_hint_bits & (1 << scheme)) {
1062
      info = get_coap_addr_info(scheme);
1063
      if (info == NULL) {
1064
        continue;
1065
      }
1066
1067
      /* Need to return in same order as getaddrinfo() */
1068
      if (!info_prev) {
1069
        info_list = info;
1070
        info_prev = info;
1071
      } else {
1072
        info_prev->next = info;
1073
        info_prev = info;
1074
      }
1075
1076
      memcpy(&info->addr.addr, &addr_ip, sizeof(info->addr.addr));
1077
1078
      update_coap_addr_port(scheme, info, port, secure_port, ws_port,
1079
                            ws_secure_port, type);
1080
    }
1081
  }
1082
  return info_list;
1083
}
1084
1085
#else
1086
1087
#error "OS type not supported"
1088
1089
coap_addr_info_t *
1090
coap_resolve_address_info_lkd(const coap_str_const_t *address,
1091
                              uint16_t port,
1092
                              uint16_t secure_port,
1093
                              uint16_t ws_port,
1094
                              uint16_t ws_secure_port,
1095
                              int ai_hints_flags,
1096
                              int scheme_hint_bits,
1097
                              coap_resolve_type_t type) {
1098
  return NULL;
1099
}
1100
1101
#endif
1102
1103
COAP_API coap_addr_info_t *
1104
coap_resolve_address_info(const coap_str_const_t *address,
1105
                          uint16_t port,
1106
                          uint16_t secure_port,
1107
                          uint16_t ws_port,
1108
                          uint16_t ws_secure_port,
1109
                          int ai_hints_flags,
1110
                          int scheme_hint_bits,
1111
0
                          coap_resolve_type_t type) {
1112
0
  coap_addr_info_t *info_list;
1113
1114
0
  coap_lock_lock(return NULL);
1115
0
  info_list = coap_resolve_address_info_lkd(address, port, secure_port, ws_port,
1116
0
                                            ws_secure_port, ai_hints_flags,
1117
0
                                            scheme_hint_bits, type);
1118
0
  coap_lock_unlock();
1119
0
  return info_list;
1120
0
}
1121
1122
void
1123
0
coap_free_address_info(coap_addr_info_t *info) {
1124
0
  while (info) {
1125
0
    coap_addr_info_t *info_next = info->next;
1126
1127
0
    coap_free_type(COAP_STRING, info);
1128
0
    info = info_next;
1129
0
  }
1130
0
}
1131
1132
#if !defined(WITH_LWIP) && !defined(WITH_CONTIKI) && !defined(RIOT_VERSION)
1133
void
1134
90
coap_address_copy(coap_address_t *dst, const coap_address_t *src) {
1135
#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
1136
  memcpy(dst, src, sizeof(coap_address_t));
1137
#else
1138
90
  memset(dst, 0, sizeof(coap_address_t));
1139
90
  dst->size = src->size;
1140
90
#if COAP_IPV6_SUPPORT
1141
90
  if (src->addr.sa.sa_family == AF_INET6) {
1142
0
    dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family;
1143
0
    dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr;
1144
0
    dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port;
1145
0
    dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id;
1146
0
  }
1147
90
#endif /* COAP_IPV6_SUPPORT */
1148
90
#if COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT
1149
90
  else
1150
90
#endif /* COAP_IPV4_SUPPORT && COAP_IPV6_SUPPORT */
1151
90
#if COAP_IPV4_SUPPORT
1152
90
    if (src->addr.sa.sa_family == AF_INET) {
1153
90
      dst->addr.sin = src->addr.sin;
1154
90
    }
1155
0
#endif /* COAP_IPV4_SUPPORT */
1156
0
    else {
1157
0
      memcpy(&dst->addr, &src->addr, src->size);
1158
0
    }
1159
90
#endif
1160
90
}
1161
1162
int
1163
0
_coap_address_isany_impl(const coap_address_t *a) {
1164
  /* need to compare only relevant parts of sockaddr_in6 */
1165
0
  switch (a->addr.sa.sa_family) {
1166
0
#if COAP_IPV4_SUPPORT
1167
0
  case AF_INET:
1168
0
    return a->addr.sin.sin_addr.s_addr == INADDR_ANY;
1169
0
#endif /* COAP_IPV4_SUPPORT */
1170
0
#if COAP_IPV6_SUPPORT
1171
0
  case AF_INET6:
1172
0
    return memcmp(&in6addr_any,
1173
0
                  &a->addr.sin6.sin6_addr,
1174
0
                  sizeof(in6addr_any)) == 0;
1175
0
#endif /* COAP_IPV6_SUPPORT */
1176
0
  default:
1177
0
    ;
1178
0
  }
1179
1180
0
  return 0;
1181
0
}
1182
#endif /* ! WITH_LWIP && ! WITH_CONTIKI */