1 /*
2 * class Address implementation, just a nice wrapping around struct
3 * sockaddr_storage.
4 */
5 #include "swift.h"
6
7
8 using namespace swift;
9
10 #define addr_debug false
11
Address()12 Address::Address()
13 {
14 if (addr_debug)
15 fprintf(stderr,"Addres::Address()\n");
16 clear();
17 }
18
Address(const char * ip,uint16_t port)19 Address::Address(const char* ip, uint16_t port)
20 {
21 if (addr_debug)
22 fprintf(stderr,"Addres::Address(ip=%s,port=%" PRIu32 ")\n", ip, port);
23 clear();
24 set_ip(ip,AF_UNSPEC);
25 set_port(port);
26 }
27
Address(const char * ip_port)28 Address::Address(const char* ip_port)
29 {
30 if (addr_debug)
31 fprintf(stderr,"Addres::Address(ip_port=%s)\n", ip_port);
32 clear();
33 if (strlen(ip_port)>=1024 || strlen(ip_port) == 0)
34 return;
35 char ipp[1024];
36 strncpy(ipp,ip_port,1024);
37 if (ipp[0] == '[') {
38 // IPV6 in square brackets following RFC2732
39 char* closesb = strchr(ipp,']');
40 if (closesb == NULL)
41 return;
42 char* semi = strchr(closesb,':');
43 *closesb = '\0';
44 if (semi) { // has port
45 *semi = '\0';
46 set_ipv6(ipp+1);
47 set_port(semi+1);
48 } else {
49 set_ipv6(ipp+1);
50 }
51 } else {
52 char* semi = strchr(ipp,':');
53 if (semi) {
54 *semi = 0;
55 set_ipv4(ipp);
56 set_port(semi+1);
57 } else {
58 if (strchr(ipp, '.')) {
59 set_ipv4(ipp);
60 set_port((uint16_t)0);
61 } else { // Arno: if just port, then IPv6
62 set_ipv6("::0");
63 set_port(ipp);
64 }
65 }
66 }
67 }
68
69
Address(uint32_t ipv4addr,uint16_t port)70 Address::Address(uint32_t ipv4addr, uint16_t port)
71 {
72 if (addr_debug)
73 fprintf(stderr,"Addres::Address(ipv4addr=%08x,port=%" PRIu32 ")\n", ipv4addr, port);
74 clear();
75 set_ipv4(ipv4addr);
76 set_port(port);
77 }
78
79
Address(struct in6_addr ipv6addr,uint16_t port)80 Address::Address(struct in6_addr ipv6addr, uint16_t port)
81 {
82 clear();
83 set_ipv6(ipv6addr);
84 set_port(port);
85 }
86
set_port(uint16_t port)87 void Address::set_port(uint16_t port)
88 {
89 if (addr.ss_family == AF_INET) {
90 struct sockaddr_in *addr4ptr = (struct sockaddr_in *)&addr;
91 addr4ptr->sin_port = htons(port);
92 } else {
93 struct sockaddr_in6 *addr6ptr = (struct sockaddr_in6 *)&addr;
94 addr6ptr->sin6_port = htons(port);
95 }
96 }
97
set_port(const char * port_str)98 void Address::set_port(const char* port_str)
99 {
100 int p;
101 if (sscanf(port_str,"%i",&p))
102 set_port(p);
103 }
104
set_ipv4(uint32_t ipv4)105 void Address::set_ipv4(uint32_t ipv4)
106 {
107 addr.ss_family = AF_INET;
108 struct sockaddr_in *addr4ptr = (struct sockaddr_in *)&addr;
109 addr4ptr->sin_addr.s_addr = htonl(ipv4);
110 }
111
set_ipv6(struct in6_addr & ipv6)112 void Address::set_ipv6(struct in6_addr &ipv6)
113 {
114 addr.ss_family = AF_INET6;
115 struct sockaddr_in6 *addr6ptr = (struct sockaddr_in6 *)&addr;
116 memcpy(&addr6ptr->sin6_addr.s6_addr,&ipv6.s6_addr,sizeof(ipv6.s6_addr));
117 }
118
119
clear()120 void Address::clear()
121 {
122 memset(&addr,0,sizeof(struct sockaddr_storage));
123 addr.ss_family = AF_UNSPEC;
124 }
125
ipv4() const126 uint32_t Address::ipv4() const
127 {
128 if (addr.ss_family == AF_INET) {
129 struct sockaddr_in *addr4ptr = (struct sockaddr_in *)&addr;
130 return ntohl(addr4ptr->sin_addr.s_addr);
131 } else
132 return (uint32_t)INADDR_ANY;
133 }
134
ipv6() const135 struct in6_addr Address::ipv6() const {
136 if (addr.ss_family == AF_INET6) {
137 struct sockaddr_in6 *addr6ptr = (struct sockaddr_in6 *)&addr;
138 return addr6ptr->sin6_addr;
139 } else
140 return in6addr_any;
141 }
142
143
port() const144 uint16_t Address::port() const
145 {
146 if (addr.ss_family == AF_INET) {
147 struct sockaddr_in *addr4ptr = (struct sockaddr_in *)&addr;
148 return ntohs(addr4ptr->sin_port);
149 } else {
150 struct sockaddr_in6 *addr6ptr = (struct sockaddr_in6 *)&addr;
151 return ntohs(addr6ptr->sin6_port);
152 }
153 }
154
operator ==(const Address & b) const155 bool Address::operator == (const Address& b) const
156 {
157
158 if (addr.ss_family == AF_UNSPEC && b.addr.ss_family == AF_UNSPEC) {
159 // For comparing empty Address-es
160 return true;
161 } else if (addr.ss_family == AF_INET && b.addr.ss_family == AF_INET) {
162 struct sockaddr_in *aaddr4ptr = (struct sockaddr_in *)&addr;
163 struct sockaddr_in *baddr4ptr = (struct sockaddr_in *)&b.addr;
164 return aaddr4ptr->sin_port == baddr4ptr->sin_port &&
165 aaddr4ptr->sin_addr.s_addr==baddr4ptr->sin_addr.s_addr;
166 } else if (addr.ss_family == AF_INET6 && b.addr.ss_family == AF_INET6) {
167 struct sockaddr_in6 *aaddr6ptr = (struct sockaddr_in6 *)&addr;
168 struct sockaddr_in6 *baddr6ptr = (struct sockaddr_in6 *)&b.addr;
169 return aaddr6ptr->sin6_port == baddr6ptr->sin6_port &&
170 !memcmp(&aaddr6ptr->sin6_addr.s6_addr,&baddr6ptr->sin6_addr.s6_addr,sizeof(struct sockaddr_in6));
171 } else { // IPv4-mapped IP6 addr
172 struct sockaddr_in6 *xaddr6ptr = NULL;
173 struct sockaddr_in *yaddr4ptr = NULL;
174 if (addr.ss_family == AF_INET6 && b.addr.ss_family == AF_INET) {
175 xaddr6ptr = (struct sockaddr_in6 *)&addr;
176 yaddr4ptr = (struct sockaddr_in *)&b.addr;
177 } else {
178 xaddr6ptr = (struct sockaddr_in6 *)&b.addr;
179 yaddr4ptr = (struct sockaddr_in *)&addr;
180 }
181 // Convert IPv4 to IPv4-mapped IPv6 RFC4291
182 struct sockaddr_in6 y6map;
183 y6map.sin6_port = yaddr4ptr->sin_port;
184 int i=0;
185 for (i=0; i<10; i++)
186 y6map.sin6_addr.s6_addr[i] = 0x00;
187 for (i=10; i<12; i++)
188 y6map.sin6_addr.s6_addr[i] = 0xFF;
189 memcpy(&y6map.sin6_addr.s6_addr[i], &yaddr4ptr->sin_addr.s_addr, 4);
190
191 struct sockaddr_in6 *yaddr6ptr = (struct sockaddr_in6 *)&y6map;
192 return xaddr6ptr->sin6_port == yaddr6ptr->sin6_port &&
193 !memcmp(&xaddr6ptr->sin6_addr.s6_addr,&yaddr6ptr->sin6_addr.s6_addr,sizeof(struct in6_addr));
194 }
195 }
196
197
str() const198 std::string Address::str() const
199 {
200 return ipstr(true);
201 }
202
ipstr(bool includeport) const203 std::string Address::ipstr(bool includeport) const
204 {
205 char node[256];
206 char service[256];
207
208 if (addr_debug)
209 fprintf(stderr,"Address::ipstr(includeport=%d): addr family %d\n", includeport, addr.ss_family);
210
211 if (addr.ss_family == AF_UNSPEC)
212 return "AF_UNSPEC";
213
214 /*
215 if (addr.ss_family == AF_INET) {
216 struct sockaddr_in *addr4ptr = (struct sockaddr_in *)&addr;
217 fprintf(stderr,"Address::ipstr:v4 OCTET %08lx\n", addr4ptr->sin_addr.s_addr );
218 }
219 else {
220 struct sockaddr_in6 *addr6ptr = (struct sockaddr_in6 *)&addr;
221 for (int i=0; i<16; i++)
222 fprintf(stderr,"Address::ipstr:v6 OCTET %02x\n", addr6ptr->sin6_addr.s6_addr[i] );
223
224 }*/
225
226 // See RFC3493
227 // Arno, 2013-06-05: pass real IP sockaddr length
228 int ret = getnameinfo((const struct sockaddr *)&addr, get_family_sockaddr_length(),
229 node, (socklen_t)sizeof(node),
230 service, (socklen_t)sizeof(service),
231 NI_NUMERICHOST | NI_NUMERICSERV);
232 if (ret == 0) {
233 // Strip off zone index e.g. 2001:610:110:6e1:7578:776f:e141:d2bb%3435973836
234 std::string nodestr(node);
235 int idx = nodestr.find("%");
236 if (idx != std::string::npos)
237 nodestr = nodestr.substr(0,idx);
238
239 if (includeport)
240 return nodestr+":"+std::string(service);
241 else
242 return nodestr;
243 } else {
244 print_error("getnameinfo error");
245 return "getnameinfo failed";
246 }
247 }
248
249
is_private() const250 bool Address::is_private() const
251 {
252 if (addr.ss_family == AF_INET) {
253 uint32_t no = ipv4();
254 uint8_t no0 = no>>24,no1 = (no>>16)&0xff;
255 if (no0 == 10) return true;
256 else if (no0 == 172 && no1 >= 16 && no1 <= 31) return true;
257 else if (no0 == 192 && no1 == 168) return true;
258 else return false;
259 } else {
260 // IPv6 Link-local address RFC4291
261 struct in6_addr s6 = ipv6();
262 return IN6_IS_ADDR_LINKLOCAL(&s6);
263 }
264 }
265
set_ipv4(const char * ip_str)266 void Address::set_ipv4(const char* ip_str)
267 {
268 set_ip(ip_str,AF_INET);
269 }
270
set_ipv6(const char * ip_str)271 void Address::set_ipv6(const char* ip_str)
272 {
273 set_ip(ip_str,AF_INET6);
274 }
275
276
set_ip(const char * ip_str,int family)277 void Address::set_ip(const char* ip_str, int family)
278 {
279 if (addr_debug)
280 fprintf(stderr,"Address::set_ip: %s family %d\n", ip_str, family);
281
282 struct addrinfo hint;
283 hint.ai_flags = AI_PASSIVE;
284 hint.ai_family = family;
285 hint.ai_socktype = 0;
286 hint.ai_protocol = 0;
287 hint.ai_addrlen = 0;
288 hint.ai_canonname = NULL;
289 hint.ai_addr = NULL;
290 hint.ai_next = NULL;
291
292 struct addrinfo *results=NULL;
293 int ret = getaddrinfo(ip_str, NULL, &hint, &results);
294 if (ret == 0) {
295 // Copy sockaddr to sockaddr_storage
296 memcpy(&addr,results->ai_addr,results->ai_addrlen);
297
298 if (addr_debug)
299 fprintf(stderr,"Address::set_ip: result %s\n", this->str().c_str());
300 }
301 if (results != NULL)
302 freeaddrinfo(results);
303 }
304
305
get_family_sockaddr_length() const306 socklen_t Address::get_family_sockaddr_length() const
307 {
308 if (addr.ss_family == AF_INET) {
309 return sizeof(struct sockaddr_in);
310 } else if (addr.ss_family == AF_INET6) {
311 return sizeof(struct sockaddr_in6);
312 } else {
313 return 0;
314 }
315 }
316