Commit cd40c5df authored by Simon Redman's avatar Simon Redman

Merge branch 'match-contains' into 'master'

Allow asking one match whether it is the superset of another

See merge request !6
parents c306c56e adb86688
Pipeline #3037 passed with stages
in 15 seconds
import os
import sys
import ipaddress
import json
import socket
from nlsdn.util import CustomJsonEncoder
......@@ -64,6 +65,61 @@ class Match(Resource):
self.action = action_id
self.family = family
def __contains__(self, item):
"""
A match is defined to be "in" this match if the values of the other's keys are either equal to or "in" this
match.
If a key in this object and the other is undefined, it does not contribute to being "in"
If a key is defined in this object but not the other, the other's key is considered "in"
If a key is not defined in this object but is in the other, the other is considered not "in"
"""
mtype = getattr(self, 'type')
otype = getattr(item, 'type')
if not mtype == otype:
# Maybe there is a sane way to compare different-type things, but I don't want to think about it
return False
for key in self.NL_KEYS:
# This could be more clearly written as some kind of filter, but the idea is to look at
# every key. If the key makes the comparison "not in", return False immediately, otherwise
# keep looking at the rest of the keys. If we run out of keys and have not exited with False,
# return True
if key in ['src_len', 'dst_len']:
# These get used as part of comparing src and dst, so skip here
continue
mval = getattr(self, key)
oval = getattr(item, key)
if oval is None:
# An unspecified key in the other is always acceptable
continue
elif mval is None:
# The key is not defined in this object but is in the other, which means the other is
# more specific and "not in"
return False
if key in ['src', 'dst']:
# IP address support subnet comparison
mlen = str(getattr(self, key + '_len'))
olen = str(getattr(item, key + '_len'))
maddr = ipaddress.ip_interface(mval + "/" + mlen)
oaddr = ipaddress.ip_interface(oval + "/" + olen)
# Check if the other network is a subnet of this network
if oaddr.ip in maddr.network and oaddr.network.prefixlen >= maddr.network.prefixlen:
continue
else:
return False
# All other values are primitives, so do not support the "in" operator. Check equality
if mval == oval:
continue
else:
return False
return True
class RuleMatch(Match):
DB_KEYS = list(Match.DB_KEYS)
DB_KEYS.extend(['action_id'])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment