diff --git a/internet/filius_simple/rendu_filius/correction.py b/internet/filius_simple/rendu_filius/correction.py new file mode 100644 index 0000000..d9c1bff --- /dev/null +++ b/internet/filius_simple/rendu_filius/correction.py @@ -0,0 +1,199 @@ +#!/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'- L’ordinateur {lettre} peut pinger l’adresse IP 10.1.200.{num}'] = int(n.ping(ident, f'10.1.200.{num}')) if ident is not None else 0 + res[f'- L’ordinateur {lettre} a une IP valide'] = int(len(ips) == 1 and ips[0].startswith('10.2.200.')) + + res['- Il n’y a pas d’adresses 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 l’adresse IP 10.1.200.254'] = int('10.1.200.254' in ips_routers) + res[f'- Le routeur a l’adresse 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'- L’ordinateur {lettre} a l’adresse IP 10.1.200.{num}'] = int(f'10.1.200.{num}' in n.ips_of(ident)) + res[f'- L’ordinateur {lettre} a la passerelle 10.1.200.254'] = int('10.1.200.254' == n.gw_of(ident)) + res[f'- L’ordinateur {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 l’adresse 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]} ') + 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 diff --git a/internet/filius_simple/rendu_filius/correction.sh b/internet/filius_simple/rendu_filius/correction.sh new file mode 100755 index 0000000..dff119d --- /dev/null +++ b/internet/filius_simple/rendu_filius/correction.sh @@ -0,0 +1,45 @@ + +tmp="$(mktemp)" + +. venv/bin/activate + +function evaluate () { + t="$(mktemp)" + echo "# TP réseau sur filius" + echo "# Correction $1" + unzip -p "$1" projekt/konfiguration.xml > "$t" + python3 correction.py $t + rm $t +} + + +# If first arg is a file, then show its details +# Else processe all dir +if [ -f "$1" ] && [ "$1" != "details" ] ; then + file="$1" + evaluate "$file" detail +elif [ -d "$1" ] && [ "$1" != "details" ] ; then + d="$1" + for f in "$d"/* ; do + #evaluate "$f" detail + evaluate "$f" "$1" + done + +else + for d in * ; do + if [ ! -d "$d" ] ; then continue ; fi + if [[ "$d" = res_* ]] || [ "$d" = venv ] ; then continue ; fi + echo === $d + resd="res_$d" + mkdir -p "$resd" + rm "$resd"/* + + for f in "$d"/*.fls ; do + echo "$f" + evaluate "$f" details > "tmp" + pandoc -f markdown "tmp" -o "$resd/$(basename "${f%.fls}").pdf" + done + done +fi + +rm "$tmp"