-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathengine.vala
152 lines (137 loc) · 4.79 KB
/
engine.vala
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
public class ScanEngine {
private int threads;
private Mutex mutexth;
public signal void done();
public signal void result (string ip, int openport);
public ScanEngine() {
this.threads = 0;
}
// This class supports only IPv4 addresses
public string[] getIPAddressesFromRange(string ip_start,string ip_end) {
// This method is just a draft implementation, it expands only 255.255.0.0 addresses
string[] result = {};
string[] s_octects = ip_start.split(".");
string[] e_octects = ip_end.split(".");
for (int i = 0; i < 4; i++) {
int startrange = int.parse(s_octects[i]);
int endrange = int.parse(e_octects[i]);
if (endrange > startrange) {
switch(i) {
case 0:
//TODO
case 1:
//TODO
case 2:
int s = int.parse(s_octects[3]);
int j = startrange;
int le = int.parse(e_octects[3]);
while (j <= endrange) {
if ((j == endrange) && (s > le)) {
break;
}
result += s_octects[0] + "." + s_octects[1] + "." + j.to_string() + "." + s.to_string();
s++;
if (s > 255) {
s = 0;
j++;
}
}
break;
case 3:
for (int s = startrange; s <= endrange; s++) {
result += s_octects[0] + "." + s_octects[1] + "." + s_octects[2] + "." + s.to_string();
}
break;
}
}
}
if (result.length == 0) {
result += ip_start;
}
return result;
}
public void scan(string ip_start, string ip_end) {
stdout.printf("ip_start = %s, ip_end = %s\n", ip_start, ip_end);
string[] ip_addresses = getIPAddressesFromRange(ip_start, ip_end);
foreach (string ip_address in ip_addresses) {
mutexth.lock();
threads++;
mutexth.unlock();
Thread<void*> thread = new Thread<void*> ("Port Scan Thread", () => {
portScan(ip_address);
return null;
});
}
}
public void on_done() {
mutexth.lock();
threads--;
//When all the threads we started to scan each ip have finished, we emit the done() signal
if (threads <= 0) {
threads = 0;
this.done();
}
mutexth.unlock();
}
public void portScan(string ip) {
var ps = new PortScanner(ip, this);
ps.done.connect(on_done);
ps.scan();
}
}
class PortScanner {
private string ip;
private ScanEngine se;
public signal void done();
public PortScanner(string ip, ScanEngine se) {
this.ip = ip;
this.se = se;
}
public void scan() {
int maxthreads = 16;
try {
ThreadPool<ScanWorker> tpool = new ThreadPool<ScanWorker>.with_owned_data ((thr) => {
thr.run ();
}, maxthreads, false);
for (int tid = 0; tid < 16; tid++)
tpool.add(new ScanWorker(tid, ip, se));
while (true) {
uint running_threads = tpool.get_num_threads();
if ((running_threads == 0) && (tpool.unprocessed() == 0)) {
this.done(); //emit signal
break;
}
Thread.usleep (1000000); //wait a second
}
} catch (ThreadError e) {
print ("ThreadError: %s\n", e.message);
}
}
}
class ScanWorker {
private int portstart;
private int portend;
private string ip;
private ScanEngine se;
public ScanWorker(int tid, string ip, ScanEngine se) {
this.portstart = 4096*tid;
this.portend = portstart + 4096;
this.ip = ip;
this.se = se;
}
public void run () {
InetAddress address = new InetAddress.from_string(ip);
for (int p = portstart; p <= portend; p++) {
try {
Socket socket = new Socket (SocketFamily.IPV4, SocketType.STREAM, SocketProtocol.TCP);
socket.set_timeout(3000);
assert (socket != null);
InetSocketAddress inetaddress = new InetSocketAddress (address, (uint16)p);
if (socket.connect(inetaddress)) {
se.result(ip, p);
}
} catch (Error e) {
}
}
}
}