diff --git a/check-pol b/check-pol index 9586ce971..bc8abaf3e 100755 --- a/check-pol +++ b/check-pol @@ -13,6 +13,6 @@ cd "$BASE" || exit 1 git diff --name-only $1 | while IFS='/' read -ra LINE; do if [[ "${LINE[0]}" = "data" ]]; then - utils/schema-check/dn42-schema.py policy ${LINE[1]} ${LINE[2]} $2 + utils/schema-check/dn42-schema.py -v policy ${LINE[1]} ${LINE[2]} $2 fi done diff --git a/check-remote b/check-remote index 846756888..b17bdc3bb 100755 --- a/check-remote +++ b/check-remote @@ -17,7 +17,7 @@ if ! git config "remote.$1.url" > /dev/null; then fi git fetch "$1" 2> /dev/null git merge --no-ff --no-commit "$1/$2" 2> /dev/null -./check-pol HEAD "$3" 2> /dev/null || (echo "Policy Check FAILED"; clean_up; exit 1) -./check-my-stuff "$3" 2> /dev/null || (echo "Schema Check FAILED"; clean_up; exit 1) +./check-pol HEAD "$3" || (echo "Policy Check FAILED"; clean_up; exit 1) +./check-my-stuff "$3" || (echo "Schema Check FAILED"; clean_up; exit 1) echo OK clean_up diff --git a/data/inet6num/fd42:d42:d42::_48 b/data/inet6num/fd42:d42:d42::_48 index 4e29cb409..f91af8242 100644 --- a/data/inet6num/fd42:d42:d42::_48 +++ b/data/inet6num/fd42:d42:d42::_48 @@ -1,4 +1,4 @@ -inet6num: FD42:D42:D42:: - FD42:d42:d42:ffff:ffff:ffff:ffff:ffff +inet6num: fd42:0d42:0d42:0000:0000:0000:0000:0000 - fd42:0d42:0d42:ffff:ffff:ffff:ffff:ffff cidr: fd42:d42:d42::/48 netname: ROOT-DN42-INF descr: DN42 Infrastructure diff --git a/data/inet6num/fd56:5799:d8f6:1b75::_64 b/data/inet6num/fd56:5799:d8f6:1b75::_64 index d2fcb9f1f..139a53e5b 100644 --- a/data/inet6num/fd56:5799:d8f6:1b75::_64 +++ b/data/inet6num/fd56:5799:d8f6:1b75::_64 @@ -1,4 +1,4 @@ -inet6num: fd56:5799:d8f6:1b75:0:0:0:0 - fd56:5799:d8f6:1b75:ffff:ffff:ffff:ffff +inet6num: fd56:5799:d8f6:1b75:0000:0000:0000:0000 - fd56:5799:d8f6:1b75:ffff:ffff:ffff:ffff cidr: fd56:5799:d8f6:1b75::/64 netname: XUU-ULA-ZTNET descr: Xuu ZeroTier Network diff --git a/data/inet6num/fdea:a15a:77b9::_48 b/data/inet6num/fdea:a15a:77b9::_48 index b9dcc3314..7107b7d97 100644 --- a/data/inet6num/fdea:a15a:77b9::_48 +++ b/data/inet6num/fdea:a15a:77b9::_48 @@ -1,4 +1,4 @@ -inet6num: fdea:a15a:77b9:0:0:0:0:0 - fdea:a15a:77b9:ffff:ffff:ffff:ffff:ffff +inet6num: fdea:a15a:77b9:0000:0000:0000:0000:0000 - fdea:a15a:77b9:ffff:ffff:ffff:ffff:ffff cidr: fdea:a15a:77b9::/48 netname: XUU-ULA-IP6NET descr: Xuu IPv6 Network diff --git a/utils/schema-check/dn42-schema.py b/utils/schema-check/dn42-schema.py index 8e61b4c51..3af4a983c 100755 --- a/utils/schema-check/dn42-schema.py +++ b/utils/schema-check/dn42-schema.py @@ -138,6 +138,10 @@ class SchemaDOM: log.error("%s Line %d: Key %s references object %s in %s but does not exist." % ( f.src, l, k, val, refs)) status = "FAIL" + if status != "FAIL": + ck = sanity_check(f) + if ck == "FAIL": + status = ck print("CHECK\t%-54s\t%s\tMNTNERS: %s" %(f.src, status, ','.join(f.mntner))) return status @@ -172,12 +176,12 @@ class FileDOM: if len(i) < 2: continue - dom.append([i[0].strip(), ':'.join(i[1:]).strip(), lineno]) + dom.append([i[0].strip(), ':'.join(i[1:]).strip(), lineno - 1]) if i[0].strip() not in keys: keys[i[0].strip()] = [] - keys[i[0].strip()].append(lineno) + keys[i[0].strip()].append(lineno - 1) last_multi = None @@ -205,6 +209,15 @@ class FileDOM: s += " " * (length + 1) + m + "\n" return s + + def get(self, key, index=0, default=None): + if key not in self.keys: + return default + if index > len(self.keys[key]) or index < -len(self.keys[key]): + return default + return self.dom[self.keys[key][index]][1] + + def main(infile, schema): log.debug("Check File: %s" % (infile)) @@ -224,7 +237,6 @@ def main(infile, schema): s = SchemaDOM(f.schema) return s.check_file(f) - def check_schemas(path): schemas = {} for fn in glob.glob(path+"/*"): @@ -241,7 +253,6 @@ def check_schemas(path): return ok - def scan_index(infile, mntner=None): idx = {} schemas = {} @@ -257,7 +268,6 @@ def scan_index(infile, mntner=None): return __scan_index(idx, schemas, mntner) - def scan_files(path, mntner=None, use_file=None): arr = __index_files(path, use_file) @@ -273,7 +283,6 @@ def scan_files(path, mntner=None, use_file=None): return __scan_index(idx, schemas, mntner, use_file) - def __scan_index(idx, schemas, mntner, use_file): ok = True for k, v in idx.items(): @@ -302,7 +311,6 @@ def __scan_index(idx, schemas, mntner, use_file): return ok - def __index_files(path, use_file): xlat = { "dns/": SCHEMA_NAMESPACE + "domain", @@ -339,14 +347,11 @@ def __index_files(path, use_file): dom = FileDOM(use_file) yield (dom.schema, dom.src.split("/")[-1].replace("_", "/"), dom.src, ",".join(dom.mntner)) - - def index_files(path): idx = __index_files(path) for i in idx: print("%s\t%s\t%s\t%s" % i) - def http_get(server, url, query=None, headers=None): import urllib.parse import http.client @@ -401,6 +406,22 @@ def to_num(ip): def to_ip(num): return '.'.join([str(i) for i in [num >> 24, (num >> 16) & 0xFF, (num >> 8) & 0xFF, num & 0xFF]]) +def pretty_ip(addr): + if addr.startswith("00000000000000000000ffff"): + addr = addr[-8:] + addr = int(addr, 16) + return to_ip(addr) + return ":".join([addr[i:i+4] for i in range(0, len(addr), 4)]) + +# addr = ["%x" % (int(addr[i:i+4],16)) for i in range(0, len(addr), 4)] +# +# last_seg = 8 +# for i, seg in enumerate(addr[::-1]): +# if seg == "0": last_seg = 7 - i +# else: break +# +# return ":".join(addr[:last_seg]) + ("::" if last_seg < 8 else "") + def expand_ipv6(addr): addr = addr.lower() if "::" in addr: @@ -411,14 +432,14 @@ def expand_ipv6(addr): return False return ''.join((i.zfill(4) for i in addr.split(":"))) -def ip4to6(ip): +def ip4_to_ip6(ip): return "::ffff:%04x:%04x" % (ip >> 16, ip & 0xffff) def inetrange(inet): ip, mask = inet.split('/') mask = int(mask) ip = to_num(ip) & (0xFFFFFFFF << 32 - mask) - ip6 = ip4to6(ip) + ip6 = ip4_to_ip6(ip) return inet6range("%s/%d" % (ip6, mask + 96)) def inet6range(inet): @@ -501,6 +522,7 @@ def test_policy(obj_type, name, mntner): Lnet, Hnet, mask = inetrange(name) else: Lnet, Hnet, mask = inet6range(name) + mask = "%03d" %(mask) log.info([Lnet, Hnet, mask]) @@ -718,6 +740,30 @@ def test_policy(obj_type, name, mntner): log.error("%s does not pass checks for %s %s" %(mntner, obj_type, name)) return "FAIL" +def sanity_check(dom): + ck = "PASS" + if dom.schema == "dn42.inetnum": + cidr = dom.get("cidr") + Lnet, Hnet, mask = inetrange(cidr) + cidr_range = pretty_ip(Lnet) + " - " + pretty_ip(Hnet) + file_range = dom.get("inetnum") + + if cidr_range != file_range: + log.error("inetnum range [%s] does not match: [%s]" %(file_range, cidr_range)) + ck = "FAIL" + + if dom.schema == "dn42.inet6num": + cidr = dom.get("cidr") + Lnet, Hnet, mask = inet6range(cidr) + cidr_range = pretty_ip(Lnet) + " - " + pretty_ip(Hnet) + file_range = dom.get("inet6num") + + if cidr_range != file_range: + log.error("inetnum range [%s] does not match: [%s]" %(file_range, cidr_range)) + ck = "FAIL" + + return ck + def get_args(): """Get and parse command line arguments""" @@ -769,6 +815,10 @@ def get_args(): parser_fmt.add_argument('-i', '--in-place', help="Format file in place", action="store_true") + parser_sane = subparsers.add_parser('sanity-check', help='Check the file for sane-ness') + parser_sane.add_argument( + 'infile', nargs="?", help="Path for dn42 data file", type=str) + parser_pol = subparsers.add_parser('policy', help='Format file') parser_pol.add_argument('type', nargs="?", type=str, help="dn42 object type") parser_pol.add_argument('name', nargs="?", type=str, help="dn42 object name") @@ -850,6 +900,13 @@ if __name__ == '__main__': if status != "PASS": sys.exit(1) + elif args["command"] == "sanity-check": + dom = FileDOM(args["infile"]) + ck = sanity_check(dom) + print("SANITY %-8s\t%20s\t%s" %(dom.schema.split(".")[1], args["infile"], ck)) + if ck != "PASS": + sys.exit(1) + elif args["command"] == "match-routes": lis = find(["mnt-by","cidr","route","@netlevel", "@netmin", "@netmax", "@uri"], {"@family":"ipv4"})