cours-snt/internet/filius_simple/rendu_filius/correction.py
2022-02-19 17:36:17 +01:00

200 lines
7.5 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/python
import bs4
from lxml import etree
import sys
import random
def extractstring (tree, xpathstr):
"""Dirty helper"""
name = tree.xpath(xpathstr)
return name[0].text if len(name) > 0 else ''
types = {
'Ordinateur': 'Ordinateur',
'Portable': 'Ordinateur',
'Rechner': 'Ordinateur',
'Notebook': 'Ordinateur',
'Routeur': 'Routeur',
'Vermittlungsrechner': 'Routeur',
'Switch': 'Switch',
}
class Knot:
def __init__ (self, ident, typ, name, ips, gw, dns, rip=None, dnsrecords={}):
"""Dirty knot. netmask is fixed to /24"""
self.id = ident
self.typ = types[typ]
self.name = name
self.ips = ips
self.gw = gw
self.dns = dns
self.rip = rip
self.dnsrecords = dnsrecords
def __str__ (self):
return f"{self.typ}:{self.name}:{self.ips}"
def has_gw (self):
return self.gw != ''
class Network:
def __init__ (self, filename):
self.filename = filename
self.knots = {}
self.wires = []
with open(filename, 'r') as f:
soup = bs4.BeautifulSoup(f , 'lxml')
for element in soup.findAll(class_="filius.gui.netzwerksicht.GUIKnotenItem"):
tree = etree.XML(str(element))
ident = element.attrs['id'] if 'id' in element.attrs else random.randint(0,10000)
self.knots[ident] = Knot(
ident,
extractstring(tree, '//*[@property="typ"]/string'),
extractstring(tree, '//*[@property="name"]/string'),
[ip.text for ip in tree.xpath('//*[@property="ip"]/string')],
extractstring(tree, '//*[@property="gateway"]/string'),
extractstring(tree, '//*[@property="dns"]/string'),
extractstring(tree, '//*[@property="ripEnabled"]/boolean') == 'true',
{ s.split(' ')[0].upper():s.split(' ')[-1] for s in (extractstring(tree, '//*[@property="dateiInhalt"]/string') or '').split('\n') if s != ''},
)
for element in soup.findAll(property="kabelpanel"):
tree = etree.XML(str(element))
self.wires.append((
tree.xpath('//*[@property="ziel1"]/object')[0].attrib['idref'],
tree.xpath('//*[@property="ziel2"]/object')[0].attrib['idref'],
))
def same_network (self, ip1, ip2):
return ip1.split('.')[0:2] == ip2.split('.')[0:2]
def ips_of (self, ident):
return self.knots[ident].ips if ident in self.knots else []
def gw_of (self, ident):
return self.knots[ident].gw if ident in self.knots else None
def dns_of (self, ident):
return self.knots[ident].dns if ident in self.knots else None
def ident_of (self, name):
for k in self.knots:
if self.knots[k].name.upper() == name.upper():
return k
return None
def gateway_of (self, ident):
"""Returns gws id of ident"""
for k in self.knots:
if self.knots[ident].gw in self.knots[k].ips:
return k
def ip_duplicates (self):
ips = []
for k in self.knots:
for ip in self.knots[k].ips:
if ip in ips:
return True
else:
ips.append(ip)
return False
def connected_to (self, ident):
"""Returns a list of knot connected to ident"""
return [ w[(i+1)%2] for w in self.wires for i in range(2) if w[i] == ident]
def local_path_exists (self, ident, ip):
"""Test if a local network path exists between ident and ip. Assuming there is no loops on a local network :D"""
visited = []
tovisit = [ident]
while len(tovisit) > 0:
knot = tovisit.pop()
visited.append(knot)
for k in self.connected_to(knot):
if ip in self.knots[k].ips:
return True
elif k not in visited:
tovisit.append(k)
return False
def get_routers (self):
return [ k for k in self.knots if self.knots[k].typ == 'Routeur' ]
def ping (self, knot, dest):
k = self.knots[knot]
# Is the destination on our local network?
for ip in k.ips:
if self.same_network(ip, dest):
return self.local_path_exists(knot, dest)
# Have we got a reachable gw?
if k.has_gw() and self.local_path_exists(knot, k.gw):
return self.local_path_exists(self.gateway_of(knot), dest)
return False
def correction (filename):
"""Returns dict criterion:mark, mark, total"""
res = {}
n = Network(filename)
for num, lettre in enumerate(['D', 'E', 'F']):
num +=1
ident = n.ident_of(lettre)
ips = n.knots[ident].ips if ident is not None else []
res[f'- Lordinateur {lettre} peut pinger ladresse IP 10.1.200.{num}'] = int(n.ping(ident, f'10.1.200.{num}')) if ident is not None else 0
res[f'- Lordinateur {lettre} a une IP valide'] = int(len(ips) == 1 and ips[0].startswith('10.2.200.'))
res['- Il ny a pas dadresses IP en double'] = int(not n.ip_duplicates())
ident = n.ident_of('serveur')
ips = n.knots[ident].ips if ident is not None else []
res[f'- Le serveur a une adresse IP valide'] = int(len(ips) == 1 and not ips[0].startswith('10.1.200.') and not ips[0].startswith('10.2.200.'))
routers = n.get_routers()
ips_routers = n.knots[routers[0]].ips if len(routers) == 1 else []
if ips_routers == []:
print(routers, file=sys.stderr)
for k in n.knots:
print(n.knots[k], file=sys.stderr)
res[f'- Le routeur a ladresse IP 10.1.200.254'] = int('10.1.200.254' in ips_routers)
res[f'- Le routeur a ladresse IP 10.2.200.254'] = int('10.2.200.254' in ips_routers)
ip_router = ''
for ip in ips_routers:
if not ip.startswith('10.2.200.') and not ip.startswith('10.1.200.'):
ip_router = ip
break
res['- Le routeur a une adresse IP vers le serveur'] = int(ip_router != '')
res['- Le routage est activé'] = int(n.knots[routers[0]].rip) if len(routers) == 1 else 0
res['- Le routeur et le serveur ont des adresses IP avec la même partie réseau'] = int(ip_router.startswith('.'.join(ips[0].split('.')[0:2]))) if len(ips) == 1 else 0
for num, lettre in enumerate(['A', 'B', 'C']):
num +=1
ident = n.ident_of(lettre)
res[f'- Lordinateur {lettre} a ladresse IP 10.1.200.{num}'] = int(f'10.1.200.{num}' in n.ips_of(ident))
res[f'- Lordinateur {lettre} a la passerelle 10.1.200.254'] = int('10.1.200.254' == n.gw_of(ident))
res[f'- Lordinateur {lettre} a le serveur DNS configuré'] = int(ips[0] == n.dns_of(ident)) if len(ips) == 1 else 0
found = False
for k in n.knots:
if n.knots[k].dnsrecords != '' and 'A.' in n.knots[k].dnsrecords and n.knots[k].dnsrecords['A.'] == '10.1.200.1':
found = True
break
res[f'- Le nom DNS A se traduit par ladresse IP 10.1.200.1'] = int(found)
return res, sum(res.values()), len(res) # Assuming all questions are worth 1 points
if __name__ == '__main__':
if len(sys.argv) != 2:
print(f'Usage:\n {sys.argv[0]} <konfiguration.xml>')
exit(1)
res, note, total = correction(sys.argv[1])
for line in res:
print(line, '', res[line])
print()
print(f'Total : {note}/{total}')
# TODO critères suivants
# quelques traductions DNS