Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > dca483b59ba61f3fa092de932ddd570e > files > 782

nuface-2.0.14-2mdv2009.1.i586.rpm

import re
from IPy import IP
from sys import stderr
from checkdesc.tools import IPmakenet

# Network address regex
NETWORK_REGEX = r'[0-9.]+/[0-9]{1,2}'

# IP address or network address regex
IP_OR_NETWORK_REGEX = r'[0-9.]+(?:/[0-9]{1,2})?'

# Interface name regex (eg. "eth0")
INTERFACE_REGEX = r'[a-z0-9]+'

class TextParser:
    """
    Very basic plain text parser useful to read one line after the other.

    It calls a different function for each line, and each function returns
    next function to be called for next line.

    Interresting methods and attributes:
    - line_number is the current line number of input file (starting at 1)
    - reset(): function called when parser is created
    - stop(): function called when the parser is done
    - parserError(): raise an exception with reason and line number
    """
    def __init__(self, input, first_parser, filename=None):
        """
        Parse input file object, first_parser is the first function
        used to parse the file content.
        """
        self.input = input
        self.line_number = 0
        self.filename = filename
        self.first_parser = first_parser
        self.reset()
        self.runParser()

    def _formatError(self, error, message):
        if self.filename:
            where = "in %s, line %s" % (self.filename, self.line_number)
        else:
            where = "at line %s" % self.line_number
        return "%s %s: %s" % (error, where, message)

    def parserWarning(self, message):
        print >>stderr, self._formatError("Warning", message)

    def parserError(self, message):
        raise SyntaxError(self._formatError("Error", message))

    def reset(self):
        pass

    def stop(self):
        pass

    def runParser(self):
        parser = self.first_parser
        while True:
            line = self.input.readline()
            if len(line) == 0:
                break
            line = line.rstrip()
            self.line_number += 1
            new_parser = parser(line)
            if new_parser:
                parser = new_parser
        self.stop()

class Address:
    def __init__(self, ip, scope=None):
        self.ip = IP(ip.split('/', 1)[0])
        self.network = IPmakenet(ip)
        self.scope = scope
        self.peer = None

    def __repr__(self):
        info = ['ip=%s' % self.ip, 'network=%s' % self.network]
        if self.scope:
            info.append('scope=%s' % self.scope)
        if self.peer:
            info.append('peer=%s' % self.peer)
        return "<Address %s>" % ' '.join(info)

    def __str__(self):
        return self.__repr__()

    def __eq__(self, addr):
        if self.network != addr.network:
            return False
        if self.scope != addr.scope:
            return False
        if self.peer != addr.peer:
            return False
        return True

class IpAddrParser(TextParser):
    # 2: eth0: <BROADCAST,MULTICAST,PROMISC,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
    # 3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,10000> mtu 1500 qdisc pfifo_fast qlen 100
    HEADER_REGEX = re.compile(r"^[0-9]+: (%s): " % INTERFACE_REGEX)

    # link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    # link/[65534]
    LINK_REGEX = re.compile(r"^\s+link/([^ ]+)")

    # inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
    # inet 10.8.0.66 peer 10.8.0.65/32 scope global tun0
    INET_REGEX = re.compile(r"^\s+inet (?P<address>%s)" % IP_OR_NETWORK_REGEX)

    # "scope global"
    SCOPE_REGEX = re.compile(r"scope ([^ ]+)")

    # "peer 10.8.0.65/32"
    PEER_REGEX = re.compile(r"peer (%s)" % NETWORK_REGEX)

    def __init__(self, input, filename=None):
        self.interface = None
        self.interfaces = []
        self.interfaces_dict = {}
        TextParser.__init__(self, input, self.parseHeader, filename)

    def saveInterface(self):
        if self.interface is None:
            return
        name = self.interface['name']
        if 'addr' not in self.interface:
            self.parserWarning(
                "Unable to find IPv4 address of interface %s (skip this interface)"
                % name)
        elif name not in self.interfaces_dict:
            self.interfaces_dict[name] = self.interface
            self.interfaces.append(self.interface)
        self.interface = None

    def parseHeader(self, line):
        match = self.HEADER_REGEX.search(line)
        if match:
            self.saveInterface()
            name = match.group(1)
            try:
                self.interface = self.interfaces_dict[name]
            except KeyError:
                self.interface = {}
                self.interface['name'] = name
            return self.parseLink
        return self.parseHeader

    def parseLink(self, line):
        match = self.LINK_REGEX.search(line)
        if not match:
            self.parserError("Unable to parse link type: %r" % line)
        self.interface['link'] = match.group(1)
        return self.parseParameters

    def parseParameters(self, line):
        if self.HEADER_REGEX.search(line):
            return self.parseHeader(line)

        match = self.INET_REGEX.search(line)
        if match:
            addr = match.group('address')
            if '/' not in addr:
                addr += '/32'
            addr = Address(addr)
            match = self.PEER_REGEX.search(line)
            if match:
                addr.peer = IP(match.group(1))
            match = self.SCOPE_REGEX.search(line)
            if match:
                addr.scope = match.group(1)
            try:
                self.interface['addr'].append(addr)
            except KeyError:
                self.interface['addr'] = [addr]
        return self.parseParameters

    def stop(self):
        self.saveInterface()

class IfconfigParser(TextParser):
    # eth0      Lien encap:Ethernet  HWaddr 00:15:C5:AA:35:38
    # lo        Lien encap:Boucle locale
    HEADER_REGEX = re.compile(r"^([a-z0-9]+)(:[0-9]+)?\s+")

    # inet adr:192.168.33.170  Bcast:192.168.33.255  Mask:255.255.255.128
    # inet adr:127.0.0.1  Masque:255.0.0.0
    INET_REGEX = re.compile(r"^\s+inet [^: ]+:([^ ]+) +(?:[^: ]+:[^ ]+ +){0,2}[^: ]+:([0-9.]+)$")

    def __init__(self, input, filename=None):
        self.interface = None
        self.interfaces = []
        self.interfaces_dict = {}
        TextParser.__init__(self, input, self.parseHeader, filename)

    def saveInterface(self):
        if self.interface is None:
            return
        name = self.interface['name']
        if 'addr' not in self.interface:
            self.parserWarning(
                "Unable to find IPv4 address of interface %s (skip this interface)"
                % name)
        elif name.endswith(":avah"):
            self.parserWarning(
                "Skip \"avahi\" interace: %s" % name)
        elif name not in self.interfaces_dict:
            self.interfaces_dict[name] = self.interface
            self.interfaces.append(self.interface)
        self.interface = None

    def parseHeader(self, line):
        match = self.HEADER_REGEX.search(line)
        if match:
            self.saveInterface()
            name = match.group(1)
            try:
                self.interface = self.interfaces_dict[name]
            except KeyError:
                self.interface = {}
                self.interface['name'] = name
            return self.parseParameters
        return self.parseHeader

    def parseParameters(self, line):
        if not line:
            return self.parseHeader
        match = self.INET_REGEX.match(line)
        if match:
            # Hack to be compatible with IpAddrParser
            self.interface['link'] = 'ether'
            addr = "%s/%s" % (match.group(1), match.group(2))
            addr = Address(addr)
            try:
                self.interface['addr'].append(addr)
            except KeyError:
                self.interface['addr'] = [addr]
        return self.parseParameters

    def stop(self):
        self.saveInterface()

class RouteParser(TextParser):
    IP_REGEX = r"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
    ROUTE_REGEX = re.compile(
        # ip ip ip
        r"(?P<dest>%s)\s+(?P<gateway>%s)\s+(?P<genmask>%s)\s+" % (IP_REGEX, IP_REGEX,  IP_REGEX)
        # UG 1000 0 0 eth0
        + r"\S+\s+[0-9]+\s+[0-9]+\s+[0-9]+\s+(?P<interface>\S+)")

    def __init__(self, input, filename=None, ignore_interfaces=set()):
        self.routes = []
        self.ignore_interfaces = ignore_interfaces
        TextParser.__init__(self, input, self.parseRoute, filename)

    def parseRoute(self, line):
        match = self.ROUTE_REGEX.match(line)
        if match:
            route = match.groupdict()
            if route['interface'] not in self.ignore_interfaces:
                self.routes.append(route)
            else:
                print >>stderr, "INFO: Skip route %r (ignore interface %r)" % (
                    line, route['interface'])
        return self.parseRoute