2020-08-26 19:49:06 +02:00
|
|
|
#!/usr/bin/env python3
|
2020-10-27 03:56:28 +01:00
|
|
|
import argparse
|
|
|
|
from enum import Enum
|
2020-08-26 19:49:06 +02:00
|
|
|
import sys
|
2020-10-27 03:56:28 +01:00
|
|
|
import xml.sax
|
2020-08-26 19:49:06 +02:00
|
|
|
|
|
|
|
|
2020-10-27 03:56:28 +01:00
|
|
|
class ParserState(Enum):
|
|
|
|
NOOP = 0
|
|
|
|
DISCARD = 1
|
|
|
|
CAPTURE = 2
|
|
|
|
|
|
|
|
|
|
|
|
class IPDisallowedHandler(xml.sax.ContentHandler):
|
|
|
|
TRANSITIONS = {
|
|
|
|
"address": ParserState.CAPTURE,
|
|
|
|
"source": ParserState.CAPTURE,
|
|
|
|
"destination": ParserState.CAPTURE,
|
|
|
|
"global": ParserState.CAPTURE,
|
|
|
|
}
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self._reset()
|
|
|
|
|
|
|
|
def _reset(self):
|
|
|
|
self._state = ParserState.NOOP
|
|
|
|
self._address = None
|
|
|
|
self._source = None
|
|
|
|
self._destination = None
|
|
|
|
self._global = None
|
|
|
|
self._content = ""
|
|
|
|
|
|
|
|
def _processElement(self, name):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def startElement(self, name, attrs):
|
|
|
|
if name == "record":
|
|
|
|
self._state = ParserState.DISCARD
|
|
|
|
return
|
|
|
|
if self._state == ParserState.NOOP:
|
|
|
|
return
|
|
|
|
|
|
|
|
self._state = self.TRANSITIONS.get(name, ParserState.DISCARD)
|
2020-08-26 19:49:06 +02:00
|
|
|
|
2020-10-27 03:56:28 +01:00
|
|
|
def endElement(self, name):
|
|
|
|
if name == "record":
|
|
|
|
if self._address is not None:
|
|
|
|
self._processElement()
|
|
|
|
self._reset()
|
|
|
|
if self._state == ParserState.NOOP:
|
|
|
|
return
|
|
|
|
|
|
|
|
if self._content == "":
|
|
|
|
return
|
|
|
|
self._content = self._content.strip()
|
|
|
|
if name == "address":
|
|
|
|
self._address = self._content.split(", ")
|
|
|
|
if name == "source":
|
|
|
|
self._source = self._content == "True"
|
|
|
|
if name == "destination":
|
|
|
|
self._destination = self._content == "True"
|
|
|
|
if name == "global":
|
|
|
|
self._global = self._content == "True"
|
|
|
|
self._content = ""
|
|
|
|
self._state = ParserState.DISCARD
|
|
|
|
|
|
|
|
def characters(self, content):
|
|
|
|
if self._state != ParserState.CAPTURE:
|
|
|
|
return
|
|
|
|
self._content += content
|
|
|
|
|
|
|
|
|
|
|
|
class IPDisallowedInboundHandler(IPDisallowedHandler):
|
|
|
|
def _processElement(self):
|
|
|
|
if not self._source:
|
|
|
|
for address in self._address:
|
|
|
|
print(address)
|
|
|
|
|
|
|
|
|
|
|
|
class IPDisallowedOutboundHandler(IPDisallowedHandler):
|
|
|
|
def _processElement(self):
|
|
|
|
# Document states:
|
|
|
|
# > If the value of "Destination" is FALSE, the values of
|
|
|
|
# > "Forwardable" and "Globally Reachable" must also be false.
|
|
|
|
# So, `self._destination == False` implies `self._global ==
|
|
|
|
# False.` For this reason, it's enough to test for
|
|
|
|
# `self._global == False`.
|
|
|
|
if not self._global:
|
|
|
|
for address in self._address:
|
|
|
|
print(address)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("direction", choices=["inbound", "outbound"])
|
|
|
|
args = parser.parse_args()
|
2020-08-26 19:49:06 +02:00
|
|
|
|
2020-10-27 03:56:28 +01:00
|
|
|
if args.direction == "inbound":
|
|
|
|
handler = IPDisallowedInboundHandler()
|
|
|
|
else:
|
|
|
|
handler = IPDisallowedOutboundHandler()
|
|
|
|
xml.sax.parse(sys.stdin, handler)
|