env/utils/openbsd/pf-martians/iana-ip-special-registry-parser.py
Lucas 5db09725a3 martians: overhaul
- Use the XML files instead of the CSV
- Separate output in inbound and outbound tables
- Add script for producing all the outputs
2020-10-27 03:00:25 +00:00

102 lines
2.4 KiB
Python

#!/usr/bin/env python3
import argparse
from enum import Enum
import sys
import xml.sax
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)
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()
if args.direction == "inbound":
handler = IPDisallowedInboundHandler()
else:
handler = IPDisallowedOutboundHandler()
xml.sax.parse(sys.stdin, handler)