1 /* address.c -- representation of network addresses
2 *
3 * Copyright (C) 2015-2016,2019 Olaf Bergmann <bergmann@tzi.org>
4 * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
5 *
6 * This file is part of the CoAP library libcoap. Please see
7 * README for terms of use.
8 */
9
10 #include "coap_internal.h"
11
12 #if !defined(WITH_CONTIKI) && !defined(WITH_LWIP)
13 #ifdef HAVE_ARPA_INET_H
14 #include <arpa/inet.h>
15 #endif
16 #ifdef HAVE_NETINET_IN_H
17 #include <netinet/in.h>
18 #endif
19 #ifdef HAVE_SYS_SOCKET_H
20 #include <sys/socket.h>
21 #endif
22 #ifdef HAVE_WS2TCPIP_H
23 #include <ws2tcpip.h>
24 #endif
25
26 #ifdef RIOT_VERSION
27 /* FIXME */
28 #define IN_MULTICAST(Address) (0)
29 #endif /* RIOT_VERSION */
30
31 int
coap_address_equals(const coap_address_t * a,const coap_address_t * b)32 coap_address_equals(const coap_address_t *a, const coap_address_t *b) {
33 assert(a); assert(b);
34
35 if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
36 return 0;
37
38 /* need to compare only relevant parts of sockaddr_in6 */
39 switch (a->addr.sa.sa_family) {
40 case AF_INET:
41 return
42 a->addr.sin.sin_port == b->addr.sin.sin_port &&
43 memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
44 sizeof(struct in_addr)) == 0;
45 case AF_INET6:
46 return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
47 memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
48 sizeof(struct in6_addr)) == 0;
49 default: /* fall through and signal error */
50 ;
51 }
52 return 0;
53 }
54
55 #ifdef COAP_SUPPORT_SOCKET_BROADCAST
coap_is_bcast(const coap_address_t * a)56 int coap_is_bcast(const coap_address_t *a) {
57 if (a == NULL) {
58 return 0;
59 }
60
61 switch (a->addr.sa.sa_family) {
62 case AF_INET:
63 if (a->addr.sin.sin_addr.s_addr == 0xFFFFFFFF) {
64 return 1;
65 } else {
66 return 0;
67 }
68 case AF_INET6:
69 /* not support ipv6 */
70 return 0;
71 default:
72 return 0;
73 }
74 }
75 #endif
76
coap_is_mcast(const coap_address_t * a)77 int coap_is_mcast(const coap_address_t *a) {
78 if (!a)
79 return 0;
80
81 switch (a->addr.sa.sa_family) {
82 case AF_INET:
83 return IN_MULTICAST(ntohl(a->addr.sin.sin_addr.s_addr));
84 case AF_INET6:
85 return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr);
86 default: /* fall through and signal error */
87 ;
88 }
89 return 0;
90 }
91
92 #endif /* !defined(WITH_CONTIKI) && !defined(WITH_LWIP) */
93
coap_address_init(coap_address_t * addr)94 void coap_address_init(coap_address_t *addr) {
95 assert(addr);
96 memset(addr, 0, sizeof(coap_address_t));
97 #if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
98 /* lwip and Contiki have constant address sizes and don't need the .size part */
99 addr->size = sizeof(addr->addr);
100 #endif
101 }
102
103 #if defined(WITH_LWIP)
104 #include <lwip/inet.h>
105 #endif
106
coap_address_ntop(const coap_address_t * addr,char * dst,int len)107 void coap_address_ntop(const coap_address_t *addr, char *dst, int len) {
108 if ((addr == NULL) || (dst == NULL) || (len < INET6_ADDRSTRLEN)) {
109 return;
110 }
111 #if defined(WITH_LWIP)
112 (void)ipaddr_ntoa_r(&(addr->addr), dst, len);
113 #elif defined(WITH_CONTIKI)
114 /* not supported yet */
115 #else
116 if (addr->addr.sa.sa_family == AF_INET) {
117 const void *addrptr = &addr->addr.sin.sin_addr;
118 (void)inet_ntop(addr->addr.sa.sa_family, addrptr, dst, len);
119 } else {
120 const void *addrptr = &addr->addr.sin6.sin6_addr;
121 (void)inet_ntop(addr->addr.sa.sa_family, addrptr, dst, len);
122 }
123 #endif
124 }
125
126