Beispiel #1
0
    def parse(self, raw):
        assert isinstance(raw, bytes)
        self.next = None  # In case of unfinished parsing
        self.raw = raw
        dlen = len(raw)
        if dlen < arp.MIN_LEN:
            self.msg(
                '(arp parse) warning IP packet data too short to parse header: data len %u'
                % dlen)
            return

        (self.hwtype, self.prototype, self.hwlen, self.protolen,self.opcode) =\
        struct.unpack('!HHBBH', raw[:8])

        if self.hwtype != arp.HW_TYPE_ETHERNET:
            self.msg('(arp parse) hw type unknown %u' % self.hwtype)
            return
        if self.hwlen != 6:
            self.msg('(arp parse) unknown hw len %u' % self.hwlen)
            return
        else:
            self.hwsrc = EthAddr(raw[8:14])
            self.hwdst = EthAddr(raw[18:24])
        if self.prototype != arp.PROTO_TYPE_IP:
            self.msg('(arp parse) proto type unknown %u' % self.prototype)
            return
        if self.protolen != 4:
            self.msg('(arp parse) unknown proto len %u' % self.protolen)
            return
        else:
            self.protosrc = IPAddr(struct.unpack('!I', raw[14:18])[0])
            self.protodst = IPAddr(struct.unpack('!I', raw[24:28])[0])

        self.next = raw[28:]
        self.parsed = True
Beispiel #2
0
    def parse (self, raw):
        assert isinstance(raw, bytes)
        self.next = None # In case of unfinished parsing
        self.raw = raw
        dlen = len(raw)
        if dlen < arp.MIN_LEN:
            self.msg('(arp parse) warning IP packet data too short to parse header: data len %u' % dlen)
            return

        (self.hwtype, self.prototype, self.hwlen, self.protolen,self.opcode) =\
        struct.unpack('!HHBBH', raw[:8])

        if self.hwtype != arp.HW_TYPE_ETHERNET:
            self.msg('(arp parse) hw type unknown %u' % self.hwtype)
            return
        if self.hwlen != 6:
            self.msg('(arp parse) unknown hw len %u' % self.hwlen)
            return
        else:
            self.hwsrc = EthAddr(raw[8:14])
            self.hwdst = EthAddr(raw[18:24])
        if self.prototype != arp.PROTO_TYPE_IP:
            self.msg('(arp parse) proto type unknown %u' % self.prototype)
            return
        if self.protolen != 4:
            self.msg('(arp parse) unknown proto len %u' % self.protolen)
            return
        else:
            self.protosrc = IPAddr(struct.unpack('!I',raw[14:18])[0])
            self.protodst = IPAddr(struct.unpack('!I',raw[24:28])[0])

        self.next = raw[28:]
        self.parsed = True
Beispiel #3
0
    def _to_str(self):
        op = str(self.opcode)

        eth_type = None
        # Ethernet
        if hasattr(self.prev, 'type'):
            eth_type = self.prev.type
        # Vlan
        elif hasattr(self.prev, 'eth_type'):
            eth_type = self.prev.eth_type
        else:
            self.err('(arp) unknown datalink type')
            eth_type = ethernet.ARP_TYPE

        if eth_type == ethernet.ARP_TYPE:
            if self.opcode == arp.REQUEST:
                op = "REQUEST"
            elif self.opcode == arp.REPLY:
                op = "REPLY"
        elif eth_type == ethernet.RARP_TYPE:
            if self.opcode == arp.REV_REQUEST:
                op = "REV_REQUEST"
            elif self.opcode == arp.REV_REPLY:
                op = "REV_REPLY"

        s = "[ARP {0} hw:{1} p:{2} {3}>{4} {5}>{6}]".format(
            op, self.hwtype, self.prototype, EthAddr(self.hwsrc),
            EthAddr(self.hwdst), IPAddr(self.protosrc), IPAddr(self.protodst))
        return s
Beispiel #4
0
    def __str__(self):
        if self.subtype == chassis_id.SUB_MAC:
            assert len(self.id) == 6
            id_str = str(EthAddr(self.id))
        else:
            id_str = ":".join(["%02x" % (ord(x), ) for x in self.id])

        return ''.join(['<port ID:', id_str, '>'])
Beispiel #5
0
class arp (packet_base):
    "ARP/RARP packet struct"

    MIN_LEN = 28

    HW_TYPE_ETHERNET = 1
    PROTO_TYPE_IP    = 0x0800

    # OPCODES
    REQUEST     = 1 # ARP
    REPLY       = 2 # ARP
    REV_REQUEST = 3 # RARP
    REV_REPLY   = 4 # RARP

    def __init__(self, raw=None, prev=None, **kw):
        packet_base.__init__(self)

        self.prev = prev

        self.hwtype     = arp.HW_TYPE_ETHERNET
        self.prototype  = arp.PROTO_TYPE_IP
        self.hwsrc      = ETHER_ANY
        self.hwdst      = ETHER_ANY
        self.hwlen      = 6
        self.opcode     = 0
        self.protolen   = 4
        self.protosrc   = IP_ANY
        self.protodst   = IP_ANY
        self.next       = b''

        if raw is not None:
            self.parse(raw)

        self._init(kw)

    def parse (self, raw):
        assert isinstance(raw, bytes)
        self.next = None # In case of unfinished parsing
        self.raw = raw
        dlen = len(raw)
        if dlen < arp.MIN_LEN:
            self.msg('(arp parse) warning IP packet data too short to parse header: data len %u' % dlen)
            return

        (self.hwtype, self.prototype, self.hwlen, self.protolen,self.opcode) =\
        struct.unpack('!HHBBH', raw[:8])

        if self.hwtype != arp.HW_TYPE_ETHERNET:
            self.msg('(arp parse) hw type unknown %u' % self.hwtype)
            return
        if self.hwlen != 6:
            self.msg('(arp parse) unknown hw len %u' % self.hwlen)
            return
        else:
            self.hwsrc = EthAddr(raw[8:14])
            self.hwdst = EthAddr(raw[18:24])
        if self.prototype != arp.PROTO_TYPE_IP:
            self.msg('(arp parse) proto type unknown %u' % self.prototype)
            return
        if self.protolen != 4:
            self.msg('(arp parse) unknown proto len %u' % self.protolen)
            return
        else:
            self.protosrc = IPAddr(struct.unpack('!I',raw[14:18])[0])
            self.protodst = IPAddr(struct.unpack('!I',raw[24:28])[0])

        self.next = raw[28:]
        self.parsed = True

    def hdr(self, payload):
        buf = struct.pack('!HHBBH', self.hwtype, self.prototype,
            self.hwlen, self.protolen,self.opcode)
        if type(self.hwsrc) == bytes:
            buf += self.hwsrc
        else:
            buf += self.hwsrc.toRaw()
        if type(self.protosrc) is IPAddr:
          buf += struct.pack('!I',self.protosrc.toUnsigned())
        else:
          buf += struct.pack('!I',self.protosrc)
        if type(self.hwdst) == bytes:
            buf += self.hwdst
        else:
            buf += self.hwdst.toRaw()
        if type(self.protodst) is IPAddr:
          buf += struct.pack('!I',self.protodst.toUnsigned())
        else:
          buf += struct.pack('!I',self.protodst)
        return buf

    def _to_str(self):
        op = str(self.opcode)

        eth_type = None
        # Ethernet
        if hasattr(self.prev, 'type'):
            eth_type = self.prev.type
        # Vlan
        elif hasattr(self.prev, 'eth_type'):
            eth_type = self.prev.eth_type
        else:
            self.err('(arp) unknown datalink type')
            eth_type = ethernet.ARP_TYPE

        if eth_type == ethernet.ARP_TYPE:
            if self.opcode == arp.REQUEST:
                op = "REQUEST"
            elif self.opcode == arp.REPLY:
                op = "REPLY"
        elif eth_type == ethernet.RARP_TYPE:
            if self.opcode == arp.REV_REQUEST:
                op = "REV_REQUEST"
            elif self.opcode == arp.REV_REPLY:
                op = "REV_REPLY"

        s = "[ARP {0} hw:{1} p:{2} {3}>{4} {5}>{6}]".format(op,
                                                  self.hwtype,
                                                  self.prototype,
                                                  EthAddr(self.hwsrc),
                                                  EthAddr(self.hwdst),
                                                  IPAddr(self.protosrc),
                                                  IPAddr(self.protodst))
        return s
Beispiel #6
0
 def _unpack_new (cls, raw, offset, t, length, prev):
   return offset+length,cls(address = EthAddr(raw[offset:offset+length]),
       prev=prev)
Beispiel #7
0
 def _init (self, *args, **kw):
   a = kw.pop('address',None)
   if a is None:
     self.address = None
   else:
     self.address = EthAddr(a)
Beispiel #8
0
class arp(packet_base):
    "ARP/RARP packet struct"

    MIN_LEN = 28

    HW_TYPE_ETHERNET = 1
    PROTO_TYPE_IP = 0x0800

    # OPCODES
    REQUEST = 1  # ARP
    REPLY = 2  # ARP
    REV_REQUEST = 3  # RARP
    REV_REPLY = 4  # RARP

    def __init__(self, raw=None, prev=None, **kw):
        packet_base.__init__(self)

        self.prev = prev

        self.hwtype = arp.HW_TYPE_ETHERNET
        self.prototype = arp.PROTO_TYPE_IP
        self.hwsrc = ETHER_ANY
        self.hwdst = ETHER_ANY
        self.hwlen = 6
        self.opcode = 0
        self.protolen = 4
        self.protosrc = IP_ANY
        self.protodst = IP_ANY
        self.next = b''

        if raw is not None:
            self.parse(raw)

        self._init(kw)

    def parse(self, raw):
        assert isinstance(raw, bytes)
        self.next = None  # In case of unfinished parsing
        self.raw = raw
        dlen = len(raw)
        if dlen < arp.MIN_LEN:
            self.msg(
                '(arp parse) warning IP packet data too short to parse header: data len %u'
                % dlen)
            return

        (self.hwtype, self.prototype, self.hwlen, self.protolen,self.opcode) =\
        struct.unpack('!HHBBH', raw[:8])

        if self.hwtype != arp.HW_TYPE_ETHERNET:
            self.msg('(arp parse) hw type unknown %u' % self.hwtype)
            return
        if self.hwlen != 6:
            self.msg('(arp parse) unknown hw len %u' % self.hwlen)
            return
        else:
            self.hwsrc = EthAddr(raw[8:14])
            self.hwdst = EthAddr(raw[18:24])
        if self.prototype != arp.PROTO_TYPE_IP:
            self.msg('(arp parse) proto type unknown %u' % self.prototype)
            return
        if self.protolen != 4:
            self.msg('(arp parse) unknown proto len %u' % self.protolen)
            return
        else:
            self.protosrc = IPAddr(struct.unpack('!I', raw[14:18])[0])
            self.protodst = IPAddr(struct.unpack('!I', raw[24:28])[0])

        self.next = raw[28:]
        self.parsed = True

    def hdr(self, payload):
        buf = struct.pack('!HHBBH', self.hwtype, self.prototype, self.hwlen,
                          self.protolen, self.opcode)
        if type(self.hwsrc) == bytes:
            buf += self.hwsrc
        else:
            buf += self.hwsrc.toRaw()
        if type(self.protosrc) is IPAddr:
            buf += struct.pack('!I', self.protosrc.toUnsigned())
        else:
            buf += struct.pack('!I', self.protosrc)
        if type(self.hwdst) == bytes:
            buf += self.hwdst
        else:
            buf += self.hwdst.toRaw()
        if type(self.protodst) is IPAddr:
            buf += struct.pack('!I', self.protodst.toUnsigned())
        else:
            buf += struct.pack('!I', self.protodst)
        return buf

    def _to_str(self):
        op = str(self.opcode)

        eth_type = None
        # Ethernet
        if hasattr(self.prev, 'type'):
            eth_type = self.prev.type
        # Vlan
        elif hasattr(self.prev, 'eth_type'):
            eth_type = self.prev.eth_type
        else:
            self.err('(arp) unknown datalink type')
            eth_type = ethernet.ARP_TYPE

        if eth_type == ethernet.ARP_TYPE:
            if self.opcode == arp.REQUEST:
                op = "REQUEST"
            elif self.opcode == arp.REPLY:
                op = "REPLY"
        elif eth_type == ethernet.RARP_TYPE:
            if self.opcode == arp.REV_REQUEST:
                op = "REV_REQUEST"
            elif self.opcode == arp.REV_REPLY:
                op = "REV_REPLY"

        s = "[ARP {0} hw:{1} p:{2} {3}>{4} {5}>{6}]".format(
            op, self.hwtype, self.prototype, EthAddr(self.hwsrc),
            EthAddr(self.hwdst), IPAddr(self.protosrc), IPAddr(self.protodst))
        return s
Beispiel #9
0
class dns(packet_base):
    "DNS Packet struct"

    MDNS_ADDRESS  = IPAddr('224.0.0.251')
    MDNS6_ADDRESS = IPAddr6('ff02::fb')
    MDNS_ETH      = EthAddr('01:00:5E:00:00:fb')
    MDNS6_ETH     = EthAddr('33:33:00:00:00:fb')

    SERVER_PORT = 53
    MDNS_PORT   = 5353
    MIN_LEN     = 12

    def __init__(self, raw=None, prev=None, **kw):
        packet_base.__init__(self)

        self.prev = prev

        self.questions   = []
        self.answers     = []
        self.authorities = []
        self.additional  = []

        self.id = 0
        self.qr = False # Is Query
        self.opcode = 0
        self.aa = False # Authoritative Answer
        self.tc = False # Truncated
        self.rd = False # Recursion Desired
        self.ra = False # Recursion Available
        self.z = False
        self.ad = False
        self.cd = False
        self.rcode = 0
        # TODO: everything else here

        if raw is not None:
            self.parse(raw)

        self._init(kw)

    def _exc (self, e, part = None):
      """
      Turn exception into log message
      """
      msg = "(dns)"
      if part is not None:
        msg += " " + part
      msg += ": "
      msg += str(e)
      if isinstance(e, Trunc):
        self.msg(msg)
      else:
        self.err(msg)

    def hdr (self, payload):
        bits0 = 0
        if self.qr: bits0 |= 0x80
        bits0 |= (self.opcode & 0x7) << 4
        if self.rd: bits0 |= 1
        if self.tc: bits0 |= 2
        if self.aa: bits0 |= 4
        bits1 = 0
        if self.ra: bits1 |= 0x80
        if self.z: bits1 |= 0x40
        if self.ad: bits1 |= 0x20
        if self.cd: bits1 |= 0x10
        bits1 |= (self.rcode & 0xf)

        s = struct.pack("!HBBHHHH", self.id, bits0, bits1,
                        len(self.questions), len(self.answers),
                        len(self.authorities), len(self.additional))

        def makeName (labels, term):
          o = '' #TODO: unicode
          for l in labels.split('.'):
            o += chr(len(l))
            o += l
          if term: o += '\x00'
          return o

        name_map = {}

        def putName (s, name):
          pre = ''
          post = name
          while True:
            at = s.find(makeName(post, True))
            if at == -1:
              if post in name_map:
                at = name_map[post]
            if at == -1:
              post = post.split('.', 1)
              if pre: pre += '.'
              pre += post[0]
              if len(post) == 1:
                if len(pre) == 0:
                  s += '\x00'
                else:
                  name_map[name] = len(s)
                  s += makeName(pre, True)
                break
              post = post[1]
            else:
              if len(pre) > 0:
                name_map[name] = len(s)
                s += makeName(pre, False)
              s += struct.pack("!H", at | 0xc000)
              break
          return s

        def putData (s, r):
          if r.qtype in (2,12,5,15): # NS, PTR, CNAME, MX
            return putName(s, r.rddata)
          elif r.qtype == 1: # A
            assert isinstance(r.rddata, IPAddr)
            return s + r.rddata.raw
          elif r.qtype == 28: # AAAA
            assert isinstance(r.rddata, IPAddr6)
            return s + r.rddata.raw
          else:
            return s + r.rddata

        for r in self.questions:
          s = putName(s, r.name)
          s += struct.pack("!HH", r.qtype, r.qclass)

        rest = self.answers + self.authorities + self.additional
        for r in rest:
          s = putName(s, r.name)
          s += struct.pack("!HHIH", r.qtype, r.qclass, r.ttl, 0)
          fixup = len(s) - 2
          s = putData(s, r)
          fixlen = len(s) - fixup - 2
          s = s[:fixup] + struct.pack('!H', fixlen) + s[fixup+2:]

        return s

    def parse(self, raw):
        assert isinstance(raw, bytes)
        self.raw = raw
        dlen = len(raw)
        if dlen < dns.MIN_LEN:
            self.msg('(dns) packet data too short to '
                     + 'parse header: data len %u' % (dlen,))
            return None

        bits0 = 0
        bits1 = 0
        total_questions = 0
        total_answers = 0
        total_auth_rr = 0
        total_add_rr = 0
        (self.id, bits0,bits1, total_questions, total_answers,
         total_auth_rr, total_add_rr)\
             = struct.unpack('!HBBHHHH', raw[:12])

        self.qr = True if (bits0 & 0x80) else False
        self.opcode = (bits0 >> 4) & (0x07)
        self.aa     = True if (bits0 & (0x04)) else False
        self.tc     = True if (bits0 & (0x02)) else False
        self.rd     = True if (bits0 & (0x01)) else False
        self.ra     = True if (bits1 & 0x80) else False
        self.z      = True if (bits1 & 0x40) else False
        self.ad     = True if (bits1 & 0x20) else False
        self.cd     = True if (bits1 & 0x10) else False
        self.rcode  = bits1 & 0x0f

        query_head = 12

        # questions
        for i in range(0,total_questions):
            try:
                query_head = self.next_question(raw, query_head)
            except Exception, e:
                self._exc(e, 'parsing questions')
                return None

        # answers
        for i in range(0,total_answers):
            try:
                query_head = self.next_rr(raw, query_head, self.answers)
            except Exception, e:
                self._exc(e, 'parsing answers')
                return None