diff -r 4e120851ff52 -r a81ca751664d pvl/syslog/dhcp.py --- a/pvl/syslog/dhcp.py Fri Jan 25 22:02:55 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +0,0 @@ -""" - Parse ISC dhcpd messages in syslog. -""" - -import re - -class DHCPSyslogFilter (object) : - """ - Parse SyslogMessages from SyslogParser for ISC dhcp semantics. - """ - - ## various message types sent/recieved by dhcpd - # from server/dhcp.c - TYPE_NAMES = ( - "DHCPDISCOVER", - "DHCPOFFER", - "DHCPREQUEST", - "DHCPDECLINE", - "DHCPACK", - "DHCPNAK", - "DHCPRELEASE", - "DHCPINFORM", - "type 9", - "DHCPLEASEQUERY", - "DHCPLEASEUNASSIGNED", - "DHCPLEASEUNKNOWN", - "DHCPLEASEACTIVE" - ) - - # message-parsing regexp.. - RECV_MESSAGE_RE = ( - # dhcpdiscover/ack_lease: info/error - # hwaddr: - # hostname: Hostname Unsuitable for Printing - # error: - # peer holds all free leases - # network %s: no free leases - re.compile(r'(?PDHCPDISCOVER) from (?P.+?)( \((?P.+?)\))? via (?P.+?)(: (?P.+?))?$'), - - # dhcprequest - # error: - # wrong network. - # ignored (not authoritative). - # ignored (unknown subnet). - # lease %s unavailable. - # unknown lease %s. - re.compile(r'(?PDHCPREQUEST) for (?P.+?)( \((?P.+?)\))? from (?P.+?)( \((?P.+?)\))? via (?P.+?)(: (?P.+?))?$'), - - # dhcprelease - re.compile(r'(?PDHCPRELEASE) of (?P.+?) from (?P.+?)( \((?P.+?)\))? via (?P.+?) \((?P.+?)\)$'), - - # dhcpdecline - # status: - # abandoned - # not found - # ignored - re.compile(r'(?PDHCPDECLINE) of (?P.+?) from (?P.+?)( \((?P.+?)\))? via (?P.+?): (?P.+?)$'), - - # dhcpinform - # error: - # ignored (null source address). - # unknown subnet for relay address %s - # unknown subnet for %s address %s - # not authoritative for subnet %s - re.compile(r'(?PDHCPINFORM) from (?P.+?) via (?P.+?)(: (?P.+?))?$'), - - # dhcpleasequery - re.compile(r'(?PDHCPLEASEQUERY) from (?P.+?)( for (?PIP|client-id|MAC address) (?P.+?))?(: (?P.+?))?$'), - - # dhcp: generic/unknown packet - re.compile(r'(?P\w+) from (?P.+?) via (?P.+?): (?P.+?)$'), - ) - - SEND_MESSAGE_RE = ( - # dhcp_reply - re.compile(r'(?PDHCPACK|DHCPOFFER|BOOTREPLY) on (?P.+?) to (?P.+?)( \((?P.+?)\))? via (?P.+?)$'), - - # dhcpinform - # hwaddr: - re.compile(r'(?PDHCPACK) to (?P.+?) \((?P.+?)\) via (?P.+?)$'), - - # nak_lease - re.compile(r'(?PDHCPNAK) on (?P.+?) to (?P.+?) via (?P.+?)$'), - - # dhcpleasequery - re.compile(r'(?PDHCPLEASEUNKNOWN|DHCPLEASEACTIVE|DHCPLEASEUNASSIGNED) to (?P.+?) for (?PIP|client-id|MAC address) (?P.+?) \((?P\d+) associated IPs\)$'), - ) - - MESSAGE_ERROR_RE = ( - ('peer-all-free-leases', re.compile('peer holds all free leases')), - ('no-free-leases', re.compile(r'network (?P.+?): no free leases')), - ('wrong-network', re.compile(r'wrong network')), - ('ignored-not-auth', re.compile(r'ignored \(not authoritative\)')), - ('ignored-unknown-subnet', re.compile(r'ignored \(unknown subnet\)')), - ('lease-unavailable', re.compile(r'lease (?P.+?) unavailable')), - ('lease-unknown', re.compile(r'unknown lease (?P.+?).$')), - ) - - ERROR_RE = ( - # find_lease - ('duplicate-uid-lease', - re.compile(r'uid lease (?P.+?) for client (?P.+?) is duplicate on (?P.+?)$')), - - # dhcprelease - ('dhcprelease-requested-address', - re.compile(r'DHCPRELEASE from (?P.+?) specified requested-address.')), - - # ??? - ('unexpected-icmp-echo-reply', - re.compile(r'unexpected ICMP Echo Reply from (?P.+?)$')), - - ('host-unknown', - re.compile(r'(?P.+?): host unknown.')), - ) - - IGNORE_RE = ( - re.compile(r'Wrote (?P\d+) (?P.+?) to leases file.'), - ) - - def parse (self, line) : - """ - Match line against our regexps, returning a - - { - tag: send/recv/error, - type: ..., - [error]: ..., - ... - } - - dict if matched - - Returns False if the message is ignored, or None if the no regexp matched. - """ - - for tag, re_list in ( - ('recv', self.RECV_MESSAGE_RE), - ('send', self.SEND_MESSAGE_RE), - ) : - for re in re_list : - # test - match = re.match(line) - - if match : - data = match.groupdict() - data['tag'] = tag - - return data - - # error? - for type, re in self.ERROR_RE: - match = re.match(line) - - if match : - data = match.groupdict() - data['tag'] = 'error' - data['type'] = type - - return data - - # ignore - for re in self.IGNORE_RE : - if re.match(line) : - # ignore - return False - - # unknown - return None - - def parse_error (self, error) : - """ - Match given error status from send/recv against known types, returning a type name or None. - """ - - for type, re in self.MESSAGE_ERROR_RE : - match = re.match(error) - - if match : - return type - - # nope - return None - -if __name__ == '__main__' : - import logging - - logging.basicConfig() - - import doctest - doctest.testmod() -