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