Package dpkt :: Module ethernet
[hide private]
[frames] | no frames]

Source Code for Module dpkt.ethernet

  1  # $Id: ethernet.py 65 2010-03-26 02:53:51Z dugsong $ 
  2   
  3  """Ethernet II, LLC (802.3+802.2), LLC/SNAP, and Novell raw 802.3, 
  4  with automatic 802.1q, MPLS, PPPoE, and Cisco ISL decapsulation.""" 
  5   
  6  import struct 
  7  import dpkt, stp 
  8   
  9  ETH_CRC_LEN     = 4 
 10  ETH_HDR_LEN     = 14 
 11   
 12  ETH_LEN_MIN     = 64            # minimum frame length with CRC 
 13  ETH_LEN_MAX     = 1518          # maximum frame length with CRC 
 14   
 15  ETH_MTU         = (ETH_LEN_MAX - ETH_HDR_LEN - ETH_CRC_LEN) 
 16  ETH_MIN         = (ETH_LEN_MIN - ETH_HDR_LEN - ETH_CRC_LEN) 
 17   
 18  # Ethernet payload types - http://standards.ieee.org/regauth/ethertype 
 19  ETH_TYPE_PUP    = 0x0200                # PUP protocol 
 20  ETH_TYPE_IP     = 0x0800                # IP protocol 
 21  ETH_TYPE_ARP    = 0x0806                # address resolution protocol 
 22  ETH_TYPE_CDP    = 0x2000                # Cisco Discovery Protocol 
 23  ETH_TYPE_DTP    = 0x2004                # Cisco Dynamic Trunking Protocol 
 24  ETH_TYPE_REVARP = 0x8035                # reverse addr resolution protocol 
 25  ETH_TYPE_8021Q  = 0x8100                # IEEE 802.1Q VLAN tagging 
 26  ETH_TYPE_IPX    = 0x8137                # Internetwork Packet Exchange 
 27  ETH_TYPE_IP6    = 0x86DD                # IPv6 protocol 
 28  ETH_TYPE_PPP    = 0x880B                # PPP 
 29  ETH_TYPE_MPLS   = 0x8847                # MPLS 
 30  ETH_TYPE_MPLS_MCAST     = 0x8848        # MPLS Multicast 
 31  ETH_TYPE_PPPoE_DISC     = 0x8863        # PPP Over Ethernet Discovery Stage 
 32  ETH_TYPE_PPPoE          = 0x8864        # PPP Over Ethernet Session Stage 
 33   
 34  # MPLS label stack fields 
 35  MPLS_LABEL_MASK = 0xfffff000 
 36  MPLS_QOS_MASK   = 0x00000e00 
 37  MPLS_TTL_MASK   = 0x000000ff 
 38  MPLS_LABEL_SHIFT= 12 
 39  MPLS_QOS_SHIFT  = 9 
 40  MPLS_TTL_SHIFT  = 0 
 41  MPLS_STACK_BOTTOM=0x0100 
 42   
43 -class Ethernet(dpkt.Packet):
44 __hdr__ = ( 45 ('dst', '6s', ''), 46 ('src', '6s', ''), 47 ('type', 'H', ETH_TYPE_IP) 48 ) 49 _typesw = {} 50
51 - def _unpack_data(self, buf):
52 if self.type == ETH_TYPE_8021Q: 53 self.tag, self.type = struct.unpack('>HH', buf[:4]) 54 buf = buf[4:] 55 elif self.type == ETH_TYPE_MPLS or \ 56 self.type == ETH_TYPE_MPLS_MCAST: 57 # XXX - skip labels (max # of labels is undefined, just use 24) 58 self.labels = [] 59 for i in range(24): 60 entry = struct.unpack('>I', buf[i*4:i*4+4])[0] 61 label = ((entry & MPLS_LABEL_MASK) >> MPLS_LABEL_SHIFT, \ 62 (entry & MPLS_QOS_MASK) >> MPLS_QOS_SHIFT, \ 63 (entry & MPLS_TTL_MASK) >> MPLS_TTL_SHIFT) 64 self.labels.append(label) 65 if entry & MPLS_STACK_BOTTOM: 66 break 67 self.type = ETH_TYPE_IP 68 buf = buf[(i + 1) * 4:] 69 try: 70 self.data = self._typesw[self.type](buf) 71 setattr(self, self.data.__class__.__name__.lower(), self.data) 72 except (KeyError, dpkt.UnpackError): 73 self.data = buf
74
75 - def unpack(self, buf):
76 dpkt.Packet.unpack(self, buf) 77 if self.type > 1500: 78 # Ethernet II 79 self._unpack_data(self.data) 80 elif self.dst.startswith('\x01\x00\x0c\x00\x00') or \ 81 self.dst.startswith('\x03\x00\x0c\x00\x00'): 82 # Cisco ISL 83 self.vlan = struct.unpack('>H', self.data[6:8])[0] 84 self.unpack(self.data[12:]) 85 elif self.data.startswith('\xff\xff'): 86 # Novell "raw" 802.3 87 self.type = ETH_TYPE_IPX 88 self.data = self.ipx = self._typesw[ETH_TYPE_IPX](self.data[2:]) 89 else: 90 # 802.2 LLC 91 self.dsap, self.ssap, self.ctl = struct.unpack('BBB', self.data[:3]) 92 if self.data.startswith('\xaa\xaa'): 93 # SNAP 94 self.type = struct.unpack('>H', self.data[6:8])[0] 95 self._unpack_data(self.data[8:]) 96 else: 97 # non-SNAP 98 dsap = ord(self.data[0]) 99 if dsap == 0x06: # SAP_IP 100 self.data = self.ip = self._typesw[ETH_TYPE_IP](self.data[3:]) 101 elif dsap == 0x10 or dsap == 0xe0: # SAP_NETWARE{1,2} 102 self.data = self.ipx = self._typesw[ETH_TYPE_IPX](self.data[3:]) 103 elif dsap == 0x42: # SAP_STP 104 self.data = self.stp = stp.STP(self.data[3:])
105
106 - def set_type(cls, t, pktclass):
107 cls._typesw[t] = pktclass
108 set_type = classmethod(set_type) 109
110 - def get_type(cls, t):
111 return cls._typesw[t]
112 get_type = classmethod(get_type)
113 114 # XXX - auto-load Ethernet dispatch table from ETH_TYPE_* definitions
115 -def __load_types():
116 g = globals() 117 for k, v in g.iteritems(): 118 if k.startswith('ETH_TYPE_'): 119 name = k[9:] 120 modname = name.lower() 121 try: 122 mod = __import__(modname, g) 123 except ImportError: 124 continue 125 Ethernet.set_type(v, getattr(mod, name))
126 127 if not Ethernet._typesw: 128 __load_types() 129 130 if __name__ == '__main__': 131 import unittest 132
133 - class EthTestCase(unittest.TestCase):
134 - def test_eth(self):
135 s = '\x00\xb0\xd0\xe1\x80r\x00\x11$\x8c\x11\xde\x86\xdd`\x00\x00\x00\x00(\x06@\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x11$\xff\xfe\x8c\x11\xde\xfe\x80\x00\x00\x00\x00\x00\x00\x02\xb0\xd0\xff\xfe\xe1\x80r\xcd\xd3\x00\x16\xffP\xd7\x13\x00\x00\x00\x00\xa0\x02\xff\xffg\xd3\x00\x00\x02\x04\x05\xa0\x01\x03\x03\x00\x01\x01\x08\n}\x18:a\x00\x00\x00\x00' 136 eth = Ethernet(s)
137 138 unittest.main() 139