Browse Source

require fully expanded ipv6

xuu 2 years ago
parent
commit
567e413695

+ 1 - 1
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

+ 2 - 2
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

+ 1 - 1
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

+ 1 - 1
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

+ 1 - 1
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

+ 69 - 12
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"})