1 /*
2  * address.h -- representation of network addresses
3  *
4  * Copyright (C) 2010-2011,2015-2016 Olaf Bergmann <bergmann@tzi.org>
5  *
6  * SPDX-License-Identifier: BSD-2-Clause
7  *
8  * This file is part of the CoAP library libcoap. Please see README for terms
9  * of use.
10  */
11 
12 /**
13  * @file address.h
14  * @brief Representation of network addresses
15  */
16 
17 #ifndef COAP_ADDRESS_H_
18 #define COAP_ADDRESS_H_
19 
20 #include <assert.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include "libcoap.h"
25 
26 #if defined(WITH_LWIP)
27 
28 #include <lwip/ip_addr.h>
29 
30 typedef struct coap_address_t {
31   uint16_t port;
32   ip_addr_t addr;
33 } coap_address_t;
34 
35 /**
36  * Returns the port from @p addr in host byte order.
37  */
38 COAP_STATIC_INLINE uint16_t
coap_address_get_port(const coap_address_t * addr)39 coap_address_get_port(const coap_address_t *addr) {
40   return ntohs(addr->port);
41 }
42 
43 /**
44  * Sets the port field of @p addr to @p port (in host byte order).
45  */
46 COAP_STATIC_INLINE void
coap_address_set_port(coap_address_t * addr,uint16_t port)47 coap_address_set_port(coap_address_t *addr, uint16_t port) {
48   addr->port = htons(port);
49 }
50 
51 #define _coap_address_equals_impl(A, B) \
52         ((A)->port == (B)->port        \
53         && (!!ip_addr_cmp(&(A)->addr,&(B)->addr)))
54 
55 #define _coap_address_isany_impl(A)  ip_addr_isany(&(A)->addr)
56 
57 #define _coap_is_mcast_impl(Address) ip_addr_ismulticast(&(Address)->addr)
58 
59 #elif defined(WITH_CONTIKI)
60 
61 #include "uip.h"
62 
63 typedef struct coap_address_t {
64   uip_ipaddr_t addr;
65   uint16_t port;
66 } coap_address_t;
67 
68 /**
69  * Returns the port from @p addr in host byte order.
70  */
71 COAP_STATIC_INLINE uint16_t
coap_address_get_port(const coap_address_t * addr)72 coap_address_get_port(const coap_address_t *addr) {
73   return uip_ntohs(addr->port);
74 }
75 
76 /**
77  * Sets the port field of @p addr to @p port (in host byte order).
78  */
79 COAP_STATIC_INLINE void
coap_address_set_port(coap_address_t * addr,uint16_t port)80 coap_address_set_port(coap_address_t *addr, uint16_t port) {
81   addr->port = uip_htons(port);
82 }
83 
84 #define _coap_address_equals_impl(A,B) \
85         ((A)->port == (B)->port        \
86         && uip_ipaddr_cmp(&((A)->addr),&((B)->addr)))
87 
88 /** @todo implementation of _coap_address_isany_impl() for Contiki */
89 #define _coap_address_isany_impl(A)  0
90 
91 #define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr))
92 
93 #else /* WITH_LWIP || WITH_CONTIKI */
94 
95  /** multi-purpose address abstraction */
96 typedef struct coap_address_t {
97   socklen_t size;           /**< size of addr */
98   union {
99     struct sockaddr         sa;
100     struct sockaddr_in      sin;
101     struct sockaddr_in6     sin6;
102   } addr;
103 } coap_address_t;
104 
105 /**
106  * Returns the port from @p addr in host byte order.
107  */
108 uint16_t coap_address_get_port(const coap_address_t *addr);
109 
110 /**
111  * Set the port field of @p addr to @p port (in host byte order).
112  */
113 void coap_address_set_port(coap_address_t *addr, uint16_t port);
114 
115 /**
116  * Compares given address objects @p a and @p b. This function returns @c 1 if
117  * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be
118  * @c NULL;
119  */
120 int coap_address_equals(const coap_address_t *a, const coap_address_t *b);
121 
122 COAP_STATIC_INLINE int
_coap_address_isany_impl(const coap_address_t * a)123 _coap_address_isany_impl(const coap_address_t *a) {
124   /* need to compare only relevant parts of sockaddr_in6 */
125   switch (a->addr.sa.sa_family) {
126   case AF_INET:
127     return a->addr.sin.sin_addr.s_addr == INADDR_ANY;
128   case AF_INET6:
129     return memcmp(&in6addr_any,
130                   &a->addr.sin6.sin6_addr,
131                   sizeof(in6addr_any)) == 0;
132   default:
133     ;
134   }
135 
136   return 0;
137 }
138 #endif /* WITH_LWIP || WITH_CONTIKI */
139 
140 /**
141  * Resets the given coap_address_t object @p addr to its default values. In
142  * particular, the member size must be initialized to the available size for
143  * storing addresses.
144  *
145  * @param addr The coap_address_t object to initialize.
146  */
147 void coap_address_init(coap_address_t *addr);
148 
149 /* Convenience function to copy IPv6 addresses without garbage. */
150 
151 COAP_STATIC_INLINE void
coap_address_copy(coap_address_t * dst,const coap_address_t * src)152 coap_address_copy( coap_address_t *dst, const coap_address_t *src ) {
153 #if defined(WITH_LWIP) || defined(WITH_CONTIKI)
154   memcpy( dst, src, sizeof( coap_address_t ) );
155 #else
156   memset( dst, 0, sizeof( coap_address_t ) );
157   dst->size = src->size;
158   if ( src->addr.sa.sa_family == AF_INET6 ) {
159     dst->addr.sin6.sin6_family = src->addr.sin6.sin6_family;
160     dst->addr.sin6.sin6_addr = src->addr.sin6.sin6_addr;
161     dst->addr.sin6.sin6_port = src->addr.sin6.sin6_port;
162     dst->addr.sin6.sin6_scope_id = src->addr.sin6.sin6_scope_id;
163   } else if ( src->addr.sa.sa_family == AF_INET ) {
164     dst->addr.sin = src->addr.sin;
165   } else {
166     memcpy( &dst->addr, &src->addr, src->size );
167   }
168 #endif
169 }
170 
171 #if defined(WITH_LWIP) || defined(WITH_CONTIKI)
172 /**
173  * Compares given address objects @p a and @p b. This function returns @c 1 if
174  * addresses are equal, @c 0 otherwise. The parameters @p a and @p b must not be
175  * @c NULL;
176  */
177 COAP_STATIC_INLINE int
coap_address_equals(const coap_address_t * a,const coap_address_t * b)178 coap_address_equals(const coap_address_t *a, const coap_address_t *b) {
179   assert(a); assert(b);
180   return _coap_address_equals_impl(a, b);
181 }
182 #endif
183 
184 /**
185  * Checks if given address object @p a denotes the wildcard address. This
186  * function returns @c 1 if this is the case, @c 0 otherwise. The parameters @p
187  * a must not be @c NULL;
188  */
189 COAP_STATIC_INLINE int
coap_address_isany(const coap_address_t * a)190 coap_address_isany(const coap_address_t *a) {
191   assert(a);
192   return _coap_address_isany_impl(a);
193 }
194 
195 #if !defined(WITH_LWIP) && !defined(WITH_CONTIKI)
196 
197 /**
198  * Checks if given address @p a denotes a multicast address. This function
199  * returns @c 1 if @p a is multicast, @c 0 otherwise.
200  */
201 int coap_is_mcast(const coap_address_t *a);
202 #else /* !WITH_LWIP && !WITH_CONTIKI */
203 /**
204  * Checks if given address @p a denotes a multicast address. This function
205  * returns @c 1 if @p a is multicast, @c 0 otherwise.
206  */
207 COAP_STATIC_INLINE int
coap_is_mcast(const coap_address_t * a)208 coap_is_mcast(const coap_address_t *a) {
209   return a && _coap_is_mcast_impl(a);
210 }
211 #endif /* !WITH_LWIP && !WITH_CONTIKI */
212 
213 #endif /* COAP_ADDRESS_H_ */
214