-
Notifications
You must be signed in to change notification settings - Fork 0
/
lab.py
275 lines (214 loc) · 9.72 KB
/
lab.py
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
import os
import subprocess
import io
import math
import random
import fcntl as fcntl
import select as select
from scapy.all import *
import pyshark
from scapy.layers.inet import IP, TCP, ICMP, UDP
from scapy.layers.l2 import ARP
class LaneData:
def __init__(self, name):
self.laneName = name
self.laneWeight = 0
self.laneMachines = []
self.radiansUsed = 1
# Set in main.py
self.x = 0
self.y = 0
# Set by calcualteAllAvaliablePoints
self.avaliablePoints = []
def calcualteAllAvaliablePoints(self):
ox, oy = self.x, self.y
px, py = ox + 50, oy + 50
radianQuantity = 12
if self.laneWeight > 12:
radianQuantity = self.laneWeight
for i in range(0, radianQuantity, 1):
self.avaliablePoints.append((
ox + math.cos(math.radians((360 / radianQuantity) * i)) * (px - ox) - math.sin(math.radians((360 / radianQuantity) * i)) * (py - oy),
oy + math.sin(math.radians((360 / radianQuantity) * i)) * (px - ox) + math.cos(math.radians((360 / radianQuantity) * i)) * (py - oy),
0
))
# Below proves it does not care for anything but the smallest gird number
#self.avaliablePoints.append((25, 25))
def getClosestAvaliablePoint(self, _x, _y):
closest = 50000
point = None
for p in self.avaliablePoints:
pthag = math.sqrt(((_x - p[0]) ** 2) + ((_y - p[1]) ** 2))
if pthag < closest:
#if p[2] == 0:
point = list(p)
closest = pthag
#point[0] = point[0] + random.randrange(-40, 40)
#point[1] = point[1] + random.randrange(-40, 40)
return point
def getAllPoints(self):
return self.avaliablePoints
def getLaneWeight(self):
return self.laneWeight
class MachineData:
# Setup a new Machine Object
def __init__(self, name):
self.machineName = name
self.machineConnections = []
# Append a new connection
def addConnection(self, ethDev, wireName, macAddr, ipAddr):
self.machineConnections.append((ethDev, wireName, macAddr, ipAddr))
# Info dump to stdout
def printMachineData(self):
print("[ " + self.machineName + " ]")
for con in self.machineConnections:
print("-> connection -> " + con[0] + " - on line - " + con[1])
# How many different lanes this machine connets to
def getNetworkWeight(self):
dist = []
for con in self.machineConnections:
if con[1] not in dist:
dist.append(con[1])
return len(dist)
class NetkitLab:
# Searches the Lab.Conf file for references to the Machines List
def searchLabConf(self):
with open(self.labConf, "r") as f:
searchlines = f.readlines()
j = len(searchlines) - 1
for i, line in enumerate(searchlines):
if "machines=\"" in line.lower() and line.find("#") == -1:
return line
return False
# If the Lab.Conf search fails, the directory will be searched instead
def searchLabDir(self):
machineList = []
for file in os.listdir(self.labDirectory):
if file.endswith(".startup"):
machineList.append(file.replace(".startup", ""))
return machineList
# Search for the machines list
# Calls searchLabConf, searchLabDir
def getMachineList(self):
machines = self.searchLabConf()
if machines == False:
return self.searchLabDir()
else:
str = machines.replace("machines=", "").replace("\"", "")
return str.split(" ")
def startLab(self):
os.system('cd ' + self.labDirectory + ' && ~/netkit-jh/bin/lstart')
def stopLab(self):
os.system('cd ' + self.labDirectory + ' && lcrash')
def getMachineInfo(self, line):
# Dump list into array and clear spaces
line = line.replace("\n", "").replace(",", "")
lineSplit = line.split(' ')
lineSplit = list(filter(None, lineSplit))
# Create new Machine Object with its Name
nk = MachineData(lineSplit[1])
# Browse the string for the Machines networking data
for i in range(0, len(lineSplit), 1):
if lineSplit[i] == "@":
with open(self.labDirectory + "/" + nk.machineName + ".startup") as f:
content = f.readlines()
content = [x.strip() for x in content]
mac, ip = "?", "?"
for line in content:
# If this is an ifconfig command
if line.find("ifconfig", 0) != -1:
# If the line is not commented out
if line.find("#", 0, line.find("ifconfig", 0) + 1) == -1:
# If the line contains the current ethernet port
if line.find(lineSplit[i - 1]) != -1:
# This contains the MAC address
if line.find(":", line.find("ifconfig", 0)) != -1:
mac = line[
line.index("ether ") + len("ether "):
line.index("ether ") + len("ether ") + 17:
1
]
# This contains the IP address
elif line.find(".", line.find("ifconfig", 0)) != -1:
ip = line[
line.index(lineSplit[i - 1] + " ") + len(lineSplit[i - 1] + " "):
line.index(lineSplit[i - 1] + " ") + len(lineSplit[i - 1] + " ") + len(line) - line.index(lineSplit[i - 1] + " ") + len(lineSplit[i - 1] + " "):
1
].replace(" ", "")
nk.addConnection(lineSplit[i - 1], lineSplit[i + 1], mac, ip)
# Return the Machine object
return nk
def beginVdumpLab(self):
pass
def moveLabTerminal(self, termName, x, y):
os.system('xdotool search --name "' + termName + '" windowactivate windowmove -- ' + str(x) + ' ' + str(y) + ' windowsize 250 150')
def pingCommand(self, termName, pingMachine):
os.system('xdotool search --name "' + termName + '" windowactivate key Return')
os.system('xdotool search --name "' + termName + '" windowactivate type "ping -c1 ' + pingMachine + ' "')
os.system('xdotool search --name "' + termName + '" windowactivate key Return')
def probeLab(self):
# Cleanup any old data
self.machineData = []
proc = subprocess.Popen("cd " + self.labDirectory + " && vlist", stdout=subprocess.PIPE, shell=True)
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
if "@" in line and len(line) > 5:
self.machineData.append(self.getMachineInfo(line))
return self.machineData
def expandPacket(self, x):
yield x
while x.payload:
x = x.payload
yield x
def beginVdump(self, lane):
try:
os.remove(self.labDirectory + "/" + lane + "-out-dump-NK-Probe.pcap")
except:
pass
proc = subprocess.Popen("cd " + self.labDirectory + " && vdump " + lane + " >> " + lane + "-out-dump-NK-Probe.pcap", shell=True)
time.sleep(1)
while os.stat(self.labDirectory + "/" + lane + "-out-dump-NK-Probe.pcap").st_size == 0:
time.sleep(.05)
bufferReadPcap = PcapReader(self.labDirectory + "/" + lane + "-out-dump-NK-Probe.pcap")
def follow(fl):
while True:
try:
pack = fl.next()
except:
pack = None
if not pack or pack == None:
time.sleep(.005)
continue
yield pack
capData = follow(bufferReadPcap)
# region Outdated_Old_Useful_Code
# # if IP in test:
# # iptest = test[IP]
# # if TCP in test:
# # tcptest = test[TCP]
# mememe = set((p[IP]) for p in PcapReader("/home/hex/NetkitLabs/CDP/ipsec/ee2.cap") if IP in p)
# Old Code which reads the VDUMP directly from stdout pipe of the terminal - retired as its too difficult to separate/detect packets
# proc = subprocess.Popen("cd " + self.labDirectory + " && vdump " + lane, stdout=subprocess.PIPE, shell=True, stderr=subprocess.PIPE, universal_newlines=False)
# Make the read a non-block
# fd = proc.stdout.fileno()
# fl = fcntl.fcntl(fd, fcntl.F_GETFL)
# fcntl.fcntl(fd, fcntl.F_SETFL, fl | ree = pck os.O_NONBLOCK)
# Select means wait until data arrives
# streams = [proc.stdout]
# temp0 = []
# readable, writable, exceptional = select.select(streams, temp0, temp0, 120)
# if len(readable) == 0:
# raise Exception("Timeout of 2 minutes reached!")
# Read the data into temp [bytearray]
# temp = bytearray(4096)#bytearray(4096)
# numberOfBytesRecieved = proc.stdout.readinto(temp)
# if numberOfBytesRecieved <= 0:
# raise Exception("No data recieved!")
# endregion
return proc, capData
# Constructor
# Create a NetkitLab class based on a selected lab.conf File
def __init__(self, labConfFilePath):
self.labDirectory = os.path.dirname(labConfFilePath)
self.labConf = labConfFilePath
self.machineList = self.getMachineList()
self.machineData = [] # Populated when user probes the Netkit Lab