-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathipaddr.d
More file actions
133 lines (120 loc) · 3.67 KB
/
Copy pathipaddr.d
File metadata and controls
133 lines (120 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
module ipaddr;
import std.stdio, std.string, std.conv, std.algorithm;
/* count number of bits set from right, but return like from left */
@safe pure nothrow
int bitcount (uint v)
{
import core.bitop:bsf;
return v ? 32-bsf(v) : 32; //BSF result undefined for 0 input
}
struct IPv4
{
uint addr;
uint mask;
this (string ipstr) { this = fromString(ipstr); }
static IPv4 fromString(string ipstr)
{
IPv4 ret;
string adstr = ipstr;
string nmstr = null;
auto f = findSplit(ipstr, "/");
if (f[1].length)
{
adstr = f[0];
nmstr = f[2];
ret.mask = uint.max<<(32-to!uint(nmstr));
}
auto arr = adstr.split('.');
if (arr.length>4)
throw new Exception("bad IP address: " ~ adstr);
if (nmstr is null)
ret.mask = uint.max<<(32-arr.length*8);
assert(ret.addr == 0);
for(ubyte i,sh=24; i<arr.length; i++,sh-=8)
ret.addr |= to!ubyte(arr[i])<<sh;
return ret;
}
static string toString(IPv4 s, bool mask=false)
{
if (mask)
return format("%d.%d.%d.%d/%d", s.addr>>24, s.addr<<8>>24, s.addr<<16>>24, s.addr<<24>>24, bitcount(s.mask));
else
return format("%d.%d.%d.%d", s.addr>>24, s.addr<<8>>24, s.addr<<16>>24, s.addr<<24>>24);
}
string toString(bool mask=false) { return toString(this, mask); }
bool isin(IPv4 rhs) { return ((addr & rhs.mask) == (rhs.addr & rhs.mask)); }
uint netPart() { return addr & mask; }
uint hstPart() { return addr & !mask; }
/* reversed string (domain) for usage in reversed zones */
string toReverseZone()
{
char[] ret; ret.length = 30;
uint pos = "in-addr.arpa".length;
ret[$-pos..$] = "in-addr.arpa";
for(uint a=addr,sh=0; a>0&&sh<=32; sh+=8)
{
a = addr<<sh>>24;
if (a)
{
string num = to!string(a) ~ ".";
auto end = ret.length - pos;
pos += num.length;
//debug stderr.writefln("BOUNDS: %d .. %d, %d", ret.length-pos, end, num.length);
ret[$-pos..end] = num;
}
}
ret = ret[$-pos..$];
//debug stderr.writefln("RET: %s", ret);
return cast(immutable) ret;
//return format("%d.%d.%d.in-addr.arpa", addr<<16>>24, addr<<8>>24, addr>>24);
}
/* obraceny string IP adresy pro pouziti v reverznich zonach
net mask 24-32 -> d
net mask 16-23 -> d.c
net mask 8-15 -> d.c.b
net mask 0-7 -> d.c.b.a
*/
string toReverseHost(string net)
{
import std.array: join;
import zones: currentZone;
IPv4 network = fromString(net);
version(assert) if (! isin(network))
stderr.writefln("Warning%s: host %s not inside network %s",
currentZone is null ? null : " zone " ~ currentZone.name, this.toString(true), network.toString(true));
uint netbits = network.mask.bitcount;
string[] ret; ret.reserve(3);
for(int sh=24; sh>=0; sh-=8)
{
ret ~= to!string( addr<<sh>>24 );
if (sh <= netbits)
break;
}
//debug stderr.writeln("RET: ", join(ret, "."));
return join(ret, ".");
}
}
struct IPv6
{
ubyte[16] addr;
ubyte[16] mask;
this (string ipstr) { }
}
unittest
{
auto ip1 = IPv4("192.168.0.1");
auto ip2 = IPv4("192.168.0.0/24");
assert(ip1.toString(true) == "192.168.0.1/32");
assert(ip2.toString(true) == "192.168.0.0/24");
assert(ip1.isin(ip2));
static assert(IPv4.fromString("172.16.10.1").mask.bitcount == 32);
static assert(IPv4.fromString("172.16.10.1").addr == 0xAC100A01);
static assert(IPv4.fromString("172.16.10.1/30").mask.bitcount == 30);
static assert(IPv4.fromString("172.16.10").mask.bitcount == 24);
static assert(IPv4.fromString("172.16").mask.bitcount == 16);
static assert(IPv4.fromString("10").mask.bitcount == 8);
assert(ip1.toReverseHost("192.168.0") == "1");
assert(ip1.toReverseHost("192.168.0.0/16") == "1.0");
assert(ip1.toReverseHost("192.168.255.255/15") == "1.0.168");
assert(ip1.toReverseHost("192.168.255.255/7") == "1.0.168.192");
}