Commit | Line | Data |
---|---|---|
0e23f538 TJ |
1 | /* |
2 | The software in this package is distributed under the GNU General | |
3 | Public License version 2 (with a special exception described below). | |
4 | ||
5 | A copy of GNU General Public License (GPL) is included in this distribution, | |
6 | in the file COPYING.GPL. | |
7 | ||
8 | As a special exception, if other files instantiate templates or use macros | |
9 | or inline functions from this file, or you compile this file and link it | |
10 | with other works to produce a work based on this file, this file | |
11 | does not by itself cause the resulting work to be covered | |
12 | by the GNU General Public License. | |
13 | ||
14 | However the source code for this file must still be made available | |
15 | in accordance with section (3) of the GNU General Public License. | |
16 | ||
17 | This exception does not invalidate any other reasons why a work based | |
18 | on this file might be covered by the GNU General Public License. | |
19 | */ | |
e93545dd GE |
20 | /*************************************************************************** |
21 | ip_functions.cpp - description | |
22 | ------------------- | |
23 | begin : Sat Feb 07 2004 | |
24 | copyright : (C) 2004 by Intra2net AG | |
e93545dd GE |
25 | ***************************************************************************/ |
26 | ||
27 | #include <string> | |
28 | #include <sstream> | |
c24a8a9c | 29 | #include <stdexcept> |
a74046f1 | 30 | #include <stdio.h> |
e93545dd GE |
31 | |
32 | #include <arpa/inet.h> | |
e9852ad9 | 33 | #include <netdb.h> |
7050bac5 | 34 | #include <string.h> |
e93545dd GE |
35 | |
36 | #include <ipfunc.hxx> | |
37 | ||
38 | using namespace std; | |
c24a8a9c | 39 | using namespace ip_type; |
e93545dd | 40 | |
bb20d988 GE |
41 | IP_RANGE& IP_RANGE::operator=(const IP_RANGE& other) |
42 | { | |
43 | IP_RANGE temp(other); | |
44 | temp.swap(*this); | |
45 | return *this; | |
46 | } | |
47 | ||
48 | void IP_RANGE::swap(IP_RANGE& other) | |
49 | { | |
50 | std::swap(ip,other.ip); | |
51 | std::swap(mask,other.mask); | |
52 | std::swap(end,other.end); | |
53 | std::swap(t,other.t); | |
54 | } | |
55 | ||
c24a8a9c | 56 | // can decode IP, IP-IP (as range) and IP/MASK (as network) |
a0105b80 | 57 | void IP_RANGE::load(const std::string& ip) |
c24a8a9c | 58 | { |
63dc9939 | 59 | string::size_type delim_pos; |
ac4ebb48 | 60 | |
c24a8a9c GE |
61 | if ((delim_pos=ip.find('/')) != string::npos || |
62 | (delim_pos=ip.find('-')) != string::npos) | |
63 | { | |
64 | if (delim_pos+1 >= ip.size()) | |
7a1513b2 | 65 | throw runtime_error("invalid IP given: "+ip); |
ac4ebb48 | 66 | |
c24a8a9c GE |
67 | if (ip.at(delim_pos) == '/') |
68 | t=NETWORK; | |
69 | else | |
70 | t=RANGE; | |
ac4ebb48 | 71 | |
c24a8a9c GE |
72 | load(t,ip.substr(0,delim_pos),ip.substr(delim_pos+1)); |
73 | } | |
74 | else | |
75 | { | |
ac4ebb48 | 76 | load(IP,ip,""); |
c24a8a9c GE |
77 | } |
78 | } | |
79 | ||
80 | void IP_RANGE::load(type t, const std::string& ip, const std::string& mask_or_end) | |
81 | { | |
82 | struct in_addr ia_ip1, ia_ip2; | |
83 | ||
84 | this->t=t; | |
85 | ||
86 | if (t==IP) | |
87 | { | |
88 | if(!inet_aton(ip.c_str(),&ia_ip1)) | |
7a1513b2 | 89 | throw runtime_error("invalid IP given: "+ip); |
c24a8a9c GE |
90 | |
91 | this->ip=ia_ip1.s_addr; | |
92 | this->mask=0xFFFFFFFF; | |
93 | this->end=this->ip; | |
94 | } | |
95 | else if (t==NETWORK) | |
96 | { | |
180ad61f TJ |
97 | // TODO: Better IP checks: "16" != "0.0.0.16" |
98 | if(!inet_aton(ip.c_str(),&ia_ip1)) | |
7a1513b2 | 99 | throw runtime_error("invalid IP given: "+ip); |
c24a8a9c | 100 | |
180ad61f TJ |
101 | // Check if mask is in cidr notation |
102 | if (mask_or_end.find(".") == string::npos) { | |
103 | unsigned int calc_mask = 0; | |
104 | istringstream in(mask_or_end); | |
105 | in >> calc_mask; | |
106 | ||
107 | if(calc_mask > 32) | |
7a1513b2 | 108 | throw runtime_error("invalid cidr mask given: "+mask_or_end); |
180ad61f TJ |
109 | |
110 | ia_ip2.s_addr = calc_netmask_from_cidr(calc_mask); | |
111 | } else | |
112 | if (!inet_aton(mask_or_end.c_str(),&ia_ip2)) | |
7a1513b2 | 113 | throw runtime_error("invalid IP given: "+mask_or_end); |
180ad61f | 114 | |
c24a8a9c GE |
115 | this->ip=ia_ip1.s_addr; |
116 | this->mask=ia_ip2.s_addr; | |
117 | ||
118 | // make sure ip is really the network address | |
119 | this->ip=(this->ip & this->mask); | |
120 | ||
121 | // calculate end of the network (=broadcast addr) | |
122 | this->end=((this->mask ^ 0xFFFFFFFF) | this->ip); | |
123 | } | |
124 | else if (t==RANGE) | |
125 | { | |
1a1dcc97 | 126 | if(!inet_aton(ip.c_str(),&ia_ip1)) |
7a1513b2 | 127 | throw runtime_error("invalid IP given: "+ip); |
1a1dcc97 GE |
128 | |
129 | if(!inet_aton(mask_or_end.c_str(),&ia_ip2)) | |
130 | throw runtime_error("invalid IP given: "+mask_or_end); | |
131 | ||
c24a8a9c GE |
132 | this->ip=ia_ip1.s_addr; |
133 | this->end=ia_ip2.s_addr; | |
939b5544 | 134 | |
d16d1d55 | 135 | // Automatically turn IP if IP & end are swapped |
939b5544 TJ |
136 | if (turn_ip(this->ip) > turn_ip(this->end)) { |
137 | unsigned int tmp = this->ip; | |
138 | this->ip = this->end; | |
139 | this->end = tmp; | |
140 | } | |
c24a8a9c GE |
141 | } |
142 | } | |
143 | ||
a0105b80 GE |
144 | void IP_RANGE::load(type t, unsigned int ip, unsigned int mask_or_end) |
145 | { | |
a0105b80 | 146 | this->t=t; |
ac4ebb48 | 147 | |
a0105b80 GE |
148 | if (t==IP) |
149 | { | |
150 | this->ip=ip; | |
151 | this->mask=0xFFFFFFFF; | |
152 | this->end=this->ip; | |
153 | } | |
154 | else if (t==NETWORK) | |
155 | { | |
156 | this->ip=ip; | |
157 | this->mask=mask_or_end; | |
ac4ebb48 | 158 | |
a0105b80 GE |
159 | // make sure ip is really the network address |
160 | this->ip=(this->ip & this->mask); | |
ac4ebb48 | 161 | |
a0105b80 GE |
162 | // calculate end of the network (=broadcast addr) |
163 | this->end=((this->mask ^ 0xFFFFFFFF) | this->ip); | |
164 | } | |
165 | else if (t==RANGE) | |
166 | { | |
167 | this->ip=ip; | |
168 | this->end=mask_or_end; | |
ac4ebb48 | 169 | |
a0105b80 GE |
170 | // Automatically turn IP if IP & end are swapped |
171 | if (turn_ip(this->ip) > turn_ip(this->end)) { | |
172 | unsigned int tmp = this->ip; | |
173 | this->ip = this->end; | |
174 | this->end = tmp; | |
175 | } | |
176 | } | |
177 | } | |
178 | ||
c24a8a9c GE |
179 | bool IP_RANGE::is_within(const IP_RANGE& a) const |
180 | { | |
181 | if (t != RANGE && a.t != RANGE) | |
182 | { | |
183 | // mask checking possible | |
184 | if ((ip & a.mask) == a.ip && mask >= a.mask) | |
185 | return true; | |
186 | } | |
187 | else | |
188 | { | |
189 | // no mask checking since we have a range somewhere | |
190 | // use turn_ip because of network byte order | |
191 | if (turn_ip(ip) >= turn_ip(a.ip) && turn_ip(end) <= turn_ip(a.end)) | |
192 | return true; | |
193 | } | |
194 | ||
195 | return false; | |
196 | } | |
197 | ||
198 | bool IP_RANGE::overlapping(const IP_RANGE& a) const | |
199 | { | |
200 | if (t != RANGE && a.t != RANGE) | |
201 | { | |
202 | // mask checking possible | |
203 | if ((ip & a.mask) == a.ip || | |
204 | (a.ip & mask) == ip) | |
205 | return true; | |
206 | } | |
207 | else | |
208 | { | |
209 | // no mask checking since we have a range somewhere | |
210 | // use turn_ip because of network byte order | |
211 | if ((turn_ip(ip) >= turn_ip(a.ip) && turn_ip(ip) <= turn_ip(a.end)) || | |
212 | (turn_ip(a.ip) >= turn_ip(ip) && turn_ip(a.ip) <= turn_ip(end))) | |
213 | return true; | |
214 | } | |
215 | ||
216 | return false; | |
217 | } | |
218 | ||
9141afbd GE |
219 | /** @brief map this IP_RANGE to another network (resembles iptables NETMAP-target) |
220 | @param original_net the original net that is netmapped. *this needs to be within it. | |
221 | @param target_net the net that original_net is netmapped to. | |
222 | @retval true if the netmap was successful, false in case of an error | |
223 | @note no support for overlapping nets or ranges | |
224 | */ | |
225 | bool IP_RANGE::netmap(const IP_RANGE& original_net, const IP_RANGE& target_net) | |
226 | { | |
227 | // input validation | |
228 | if (original_net.t != ip_type::NETWORK || | |
229 | target_net.t != ip_type::NETWORK) | |
230 | return false; | |
231 | ||
232 | if (original_net.mask != target_net.mask) | |
233 | return false; | |
234 | ||
235 | // only map if we are within the original net | |
236 | if (!is_within(original_net)) | |
237 | return false; | |
238 | ||
239 | // everything ok, ready to go | |
240 | ||
241 | // difference to start of original net | |
242 | int ipno=turn_ip(ip)-turn_ip(original_net.ip); | |
243 | ||
244 | // add that difference to the target net | |
245 | ip=turn_ip(turn_ip(target_net.ip)+ipno); | |
246 | ||
247 | // turn the end too | |
248 | ipno=turn_ip(end)-turn_ip(original_net.ip); | |
249 | end=turn_ip(turn_ip(target_net.ip)+ipno); | |
250 | ||
251 | return true; | |
252 | } | |
253 | ||
939b5544 TJ |
254 | IP_RANGE operator+(const IP_RANGE &base, const int &ips) |
255 | { | |
256 | IP_RANGE ret=base; | |
257 | ||
258 | ret.ip = ret.turn_ip(ret.turn_ip(ret.ip) + ips); | |
259 | ret.end = ret.turn_ip(ret.turn_ip(ret.end) + ips); | |
260 | ||
261 | // Check if this is still a valid network | |
262 | // If not: Convert network to range | |
263 | if (ret.t == NETWORK && (ret.ip&ret.mask) != ret.ip) { | |
264 | ret.t = RANGE; | |
265 | ret.mask = 0; | |
266 | } | |
267 | ||
268 | if (ret.t == RANGE && ret.turn_ip(ret.end) < ret.turn_ip(ret.ip)) | |
3a488cb3 | 269 | throw range_error("range end lower than begin"); |
939b5544 TJ |
270 | |
271 | return ret; | |
272 | } | |
273 | ||
274 | int IP_RANGE::operator-(const IP_RANGE &other) | |
275 | { | |
276 | return turn_ip(ip)-turn_ip(other.ip); | |
277 | } | |
278 | ||
d9ed3132 GE |
279 | bool operator<(const IP_RANGE& a, const IP_RANGE& b) |
280 | { | |
281 | return ((IP_RANGE::turn_ip(a.ip) < IP_RANGE::turn_ip(b.ip)) || | |
282 | ((a.ip==b.ip) && IP_RANGE::turn_ip(a.end) < IP_RANGE::turn_ip(b.end))); | |
283 | } | |
284 | ||
f4e41f93 GE |
285 | unsigned int IP_RANGE::get_netmask() const |
286 | { | |
287 | if (t==ip_type::RANGE) | |
288 | throw out_of_range("no netmask for ip range"); | |
289 | ||
290 | return mask; | |
291 | } | |
292 | ||
2910669d | 293 | std::string IP_RANGE::to_string(bool always_mask, bool cidr_only) const |
c24a8a9c GE |
294 | { |
295 | struct in_addr ia_ip; | |
296 | static const int bufsize=16; | |
297 | char buffer[bufsize]; | |
298 | string output; | |
299 | ||
300 | ia_ip.s_addr=ip; | |
301 | if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize)) | |
302 | return ""; | |
303 | ||
304 | output=buffer; | |
305 | ||
306 | if (t==NETWORK) | |
307 | { | |
2910669d TJ |
308 | if (cidr_only) { |
309 | ostringstream out; | |
310 | out << "/" << get_mask_bits(); | |
311 | output+=out.str(); | |
312 | } else { | |
313 | ia_ip.s_addr=mask; | |
314 | if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize)) | |
315 | return ""; | |
316 | ||
317 | output=output+"/"+buffer; | |
318 | } | |
c24a8a9c GE |
319 | } |
320 | else if (t==RANGE) | |
321 | { | |
322 | ia_ip.s_addr=end; | |
323 | if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize)) | |
324 | return ""; | |
325 | ||
326 | output=output+"-"+buffer; | |
327 | } | |
2910669d TJ |
328 | else if (t==IP && always_mask) { |
329 | if (cidr_only) | |
330 | output+="/32"; | |
331 | else | |
332 | output+="/255.255.255.255"; | |
333 | } | |
334 | ||
322771b2 | 335 | return output; |
c24a8a9c GE |
336 | } |
337 | ||
a0105b80 | 338 | vector<IP_RANGE> IP_RANGE::to_cidr(void) const |
180ad61f | 339 | { |
a0105b80 | 340 | vector<IP_RANGE> cidrs; |
180ad61f | 341 | |
a0105b80 GE |
342 | if (t==IP || t==NETWORK) { |
343 | cidrs.push_back(*this); | |
344 | } else { | |
180ad61f TJ |
345 | // do the real work |
346 | unsigned int cidr_addr = turn_ip(ip), cidr_end = turn_ip(end); | |
347 | ||
348 | // special case: 0.0.0.0-255.255.255.255 | |
349 | if (cidr_addr == 0 && cidr_end == 0xFFFFFFFF) { | |
a0105b80 | 350 | cidrs.push_back(IP_RANGE(ip_type::NETWORK,0,0)); |
180ad61f | 351 | } else { |
180ad61f TJ |
352 | unsigned int bit = 0, mask = 0; |
353 | while (cidr_addr <= cidr_end) { | |
354 | mask |= (1 << bit); | |
355 | if ((cidr_addr & mask) || ((cidr_addr | mask) > cidr_end)) { | |
a0105b80 | 356 | cidrs.push_back(IP_RANGE(ip_type::NETWORK,turn_ip(cidr_addr),calc_netmask_from_cidr(32-bit))); |
180ad61f TJ |
357 | |
358 | cidr_addr += (1 << bit); | |
359 | bit = 0; | |
360 | mask = 0; | |
361 | } else { | |
362 | bit++; | |
363 | } | |
364 | } | |
365 | } | |
366 | } | |
367 | ||
368 | return cidrs; | |
369 | } | |
370 | ||
63f9b745 TJ |
371 | vector<IP_RANGE> IP_RANGE::substract(const std::set<IP_RANGE> &to_substract) const |
372 | { | |
373 | vector<IP_RANGE> rtn; | |
374 | ||
375 | unsigned int ip_pos = turn_ip(ip), ip_end = turn_ip(end); | |
376 | ||
377 | set<IP_RANGE>::const_iterator sub = to_substract.begin(), to_substract_end = to_substract.end(); | |
83d700e9 | 378 | for (sub = to_substract.begin(); sub != to_substract_end; ++sub) { |
63f9b745 TJ |
379 | if (!sub->is_within(*this)) |
380 | throw runtime_error("IP_RANGE::substract error: "+ sub->to_string() + " is not within " + to_string()); | |
381 | ||
9f9289e1 | 382 | // Get begin of network/range/IP |
63f9b745 TJ |
383 | unsigned int sub_begin = turn_ip(sub->get_base()); |
384 | ||
385 | // Got a fragment? | |
9f9289e1 TJ |
386 | if (ip_pos < sub_begin) { |
387 | if (ip_pos == sub_begin-1) | |
388 | rtn.push_back(IP_RANGE(ip_type::IP, turn_ip(ip_pos))); | |
389 | else | |
390 | rtn.push_back(IP_RANGE(ip_type::RANGE, turn_ip(ip_pos), turn_ip(sub_begin-1))); | |
391 | } | |
392 | ||
63f9b745 TJ |
393 | // Set position to end if end is higher than current position |
394 | if (ip_pos < turn_ip(sub->get_broadcast())+1) | |
395 | ip_pos = turn_ip(sub->get_broadcast())+1; | |
396 | } | |
397 | ||
398 | // Last fragment | |
399 | if (ip_pos == ip_end) | |
400 | rtn.push_back(IP_RANGE(ip_type::IP, turn_ip(ip_pos))); | |
401 | else if (ip_pos < ip_end) | |
402 | rtn.push_back(IP_RANGE(ip_type::RANGE, turn_ip(ip_pos), turn_ip(ip_end))); | |
403 | ||
404 | return rtn; | |
405 | } | |
406 | ||
c24a8a9c | 407 | unsigned int IP_RANGE::turn_ip(unsigned int src) |
e93545dd GE |
408 | { |
409 | int dst; | |
410 | char* si=(char*)&src; | |
411 | char* di=(char*)&dst; | |
412 | ||
413 | di[0]=si[3]; | |
414 | di[1]=si[2]; | |
415 | di[2]=si[1]; | |
416 | di[3]=si[0]; | |
417 | ||
418 | return dst; | |
419 | } | |
420 | ||
c24a8a9c | 421 | unsigned int IP_RANGE::calc_netmask_bits(unsigned int netmask) |
e93545dd | 422 | { |
180ad61f TJ |
423 | netmask = turn_ip(netmask); |
424 | ||
c24a8a9c GE |
425 | switch (netmask) |
426 | { | |
e93545dd GE |
427 | case 0x00000000: |
428 | return 0; | |
429 | case 0x80000000: | |
430 | return 1; | |
431 | case 0xC0000000: | |
432 | return 2; | |
433 | case 0xE0000000: | |
434 | return 3; | |
435 | case 0xF0000000: | |
436 | return 4; | |
437 | case 0xF8000000: | |
438 | return 5; | |
439 | case 0xFC000000: | |
440 | return 6; | |
441 | case 0xFE000000: | |
442 | return 7; | |
443 | case 0xFF000000: | |
444 | return 8; | |
445 | case 0xFF800000: | |
446 | return 9; | |
447 | case 0xFFC00000: | |
448 | return 10; | |
449 | case 0xFFE00000: | |
450 | return 11; | |
451 | case 0xFFF00000: | |
452 | return 12; | |
453 | case 0xFFF80000: | |
454 | return 13; | |
455 | case 0xFFFC0000: | |
456 | return 14; | |
457 | case 0xFFFE0000: | |
458 | return 15; | |
459 | case 0xFFFF0000: | |
460 | return 16; | |
461 | case 0xFFFF8000: | |
462 | return 17; | |
463 | case 0xFFFFC000: | |
464 | return 18; | |
465 | case 0xFFFFE000: | |
466 | return 19; | |
467 | case 0xFFFFF000: | |
468 | return 20; | |
469 | case 0xFFFFF800: | |
470 | return 21; | |
471 | case 0xFFFFFC00: | |
472 | return 22; | |
473 | case 0xFFFFFE00: | |
474 | return 23; | |
475 | case 0xFFFFFF00: | |
476 | return 24; | |
477 | case 0xFFFFFF80: | |
478 | return 25; | |
479 | case 0xFFFFFFC0: | |
480 | return 26; | |
481 | case 0xFFFFFFE0: | |
482 | return 27; | |
483 | case 0xFFFFFFF0: | |
484 | return 28; | |
485 | case 0xFFFFFFF8: | |
486 | return 29; | |
487 | case 0xFFFFFFFC: | |
488 | return 30; | |
489 | case 0xFFFFFFFE: | |
490 | return 31; | |
491 | case 0xFFFFFFFF: | |
492 | default: | |
493 | return 32; | |
494 | } | |
495 | } | |
496 | ||
180ad61f TJ |
497 | unsigned int IP_RANGE::calc_netmask_from_cidr(unsigned int cidr) |
498 | { | |
499 | unsigned int rtn=0; | |
500 | ||
501 | switch (cidr) | |
502 | { | |
503 | case 0: | |
504 | rtn=0x00000000; | |
505 | break; | |
506 | case 1: | |
507 | rtn=0x80000000; | |
508 | break; | |
509 | case 2: | |
510 | rtn=0xC0000000; | |
511 | break; | |
512 | case 3: | |
513 | rtn=0xE0000000; | |
514 | break; | |
515 | case 4: | |
516 | rtn=0xE0000000; | |
517 | break; | |
518 | case 5: | |
519 | rtn=0xF8000000; | |
520 | break; | |
521 | case 6: | |
522 | rtn=0xFC000000; | |
523 | break; | |
524 | case 7: | |
525 | rtn=0xFE000000; | |
526 | break; | |
527 | case 8: | |
528 | rtn=0xFF000000; | |
529 | break; | |
530 | case 9: | |
531 | rtn=0xFF800000; | |
532 | break; | |
533 | case 10: | |
534 | rtn=0xFFC00000; | |
535 | break; | |
536 | case 11: | |
537 | rtn=0xFFE00000; | |
538 | break; | |
539 | case 12: | |
540 | rtn=0xFFF00000; | |
541 | break; | |
542 | case 13: | |
543 | rtn=0xFFF80000; | |
544 | break; | |
545 | case 14: | |
546 | rtn=0xFFFC0000; | |
547 | break; | |
548 | case 15: | |
549 | rtn=0xFFFE0000; | |
550 | break; | |
551 | case 16: | |
552 | rtn=0xFFFF0000; | |
553 | break; | |
554 | case 17: | |
555 | rtn=0xFFFF8000; | |
556 | break; | |
557 | case 18: | |
558 | rtn=0xFFFFC000; | |
559 | break; | |
560 | case 19: | |
561 | rtn=0xFFFFE000; | |
562 | break; | |
563 | case 20: | |
564 | rtn=0xFFFFF000; | |
565 | break; | |
566 | case 21: | |
567 | rtn=0xFFFFF800; | |
568 | break; | |
569 | case 22: | |
570 | rtn=0xFFFFFC00; | |
571 | break; | |
572 | case 23: | |
573 | rtn=0xFFFFFE00; | |
574 | break; | |
575 | case 24: | |
576 | rtn=0xFFFFFF00; | |
577 | break; | |
578 | case 25: | |
579 | rtn=0xFFFFFF80; | |
580 | break; | |
581 | case 26: | |
582 | rtn=0xFFFFFFC0; | |
583 | break; | |
584 | case 27: | |
585 | rtn=0xFFFFFFE0; | |
586 | break; | |
587 | case 28: | |
588 | rtn=0xFFFFFFF0; | |
589 | break; | |
590 | case 29: | |
591 | rtn=0xFFFFFFF8; | |
592 | break; | |
593 | case 30: | |
594 | rtn=0xFFFFFFFC; | |
595 | break; | |
596 | case 31: | |
597 | rtn=0xFFFFFFFE; | |
598 | break; | |
599 | case 32: | |
600 | default: | |
601 | rtn=0xFFFFFFFF; | |
602 | } | |
603 | ||
604 | return turn_ip(rtn); | |
605 | } | |
606 | ||
c24a8a9c | 607 | std::string IP_RANGE::ip_string(unsigned int ip) |
e93545dd | 608 | { |
c24a8a9c GE |
609 | struct in_addr ia_ip; |
610 | static const int bufsize=16; | |
611 | char buffer[bufsize]; | |
612 | ||
613 | ia_ip.s_addr=ip; | |
614 | if (!inet_ntop(AF_INET,&ia_ip,buffer,bufsize)) | |
615 | return ""; | |
616 | else | |
617 | return buffer; | |
e93545dd | 618 | } |
f4e41f93 GE |
619 | |
620 | std::string IP_RANGE::ip_num_string(unsigned int ip) | |
621 | { | |
622 | string target; | |
623 | static const int bufsize=16; | |
624 | unsigned char a0,a1,a2,a3; | |
625 | char buf[bufsize]; | |
626 | ||
627 | a0=((char*)&ip)[0]; | |
628 | a1=((char*)&ip)[1]; | |
629 | a2=((char*)&ip)[2]; | |
630 | a3=((char*)&ip)[3]; | |
631 | snprintf(buf,13,"%03u%03u%03u%03u",a0,a1,a2,a3); | |
632 | buf[12]=0; | |
633 | target=buf; | |
634 | ||
635 | return target; | |
636 | } | |
e9852ad9 | 637 | |
7050bac5 | 638 | string IP_RANGE::resolve_ip(const string &iporname, const bool enable_ipv6) |
e9852ad9 TJ |
639 | { |
640 | struct in_addr ip_adr; | |
7050bac5 | 641 | |
e9852ad9 TJ |
642 | if (inet_aton(iporname.c_str(),&ip_adr) != 0) |
643 | { | |
644 | // is already a ip | |
645 | return iporname; | |
646 | } | |
647 | ||
648 | // we need dns | |
7050bac5 TJ |
649 | struct addrinfo hints, *result = NULL; |
650 | memset(&hints, 0, sizeof(struct addrinfo)); | |
651 | if (enable_ipv6) | |
652 | hints.ai_family = AF_UNSPEC; | |
653 | else | |
654 | hints.ai_family = AF_INET; | |
e9852ad9 | 655 | |
7050bac5 TJ |
656 | if (getaddrinfo(iporname.c_str(), NULL, &hints, &result) != 0) |
657 | throw dns_exception("no corresponding ip found for: "+iporname); | |
e9852ad9 | 658 | |
7050bac5 | 659 | if (result == NULL || result->ai_addrlen == 0 || result->ai_addr == NULL) |
7a1513b2 | 660 | throw dns_exception("no corresponding ip found for: "+iporname); |
e9852ad9 | 661 | |
7050bac5 TJ |
662 | // Convert addr to ip string |
663 | char str_ip[NI_MAXHOST], dummy_serv[NI_MAXSERV]; | |
664 | if (getnameinfo(result->ai_addr, result->ai_addrlen, str_ip, NI_MAXHOST, dummy_serv, NI_MAXSERV, NI_NUMERICHOST) != 0) | |
665 | throw dns_exception("can't convert ip for: "+iporname); | |
666 | ||
667 | freeaddrinfo(result); | |
668 | ||
669 | return string(str_ip); | |
e9852ad9 | 670 | } |