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