1
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 from __future__ import print_function
6 from __future__ import absolute_import
7
8 import struct
9 import codecs
10 from zlib import crc32
11
12 from . import dpkt
13 from . import llc
14 from .compat import iteritems
15
16 try:
17 isinstance("", basestring)
19 return isinstance(s, basestring)
20 except NameError:
22 return isinstance(s, str)
23
24 ETH_CRC_LEN = 4
25 ETH_HDR_LEN = 14
26
27 ETH_LEN_MIN = 64
28 ETH_LEN_MAX = 1518
29
30 ETH_MTU = (ETH_LEN_MAX - ETH_HDR_LEN - ETH_CRC_LEN)
31 ETH_MIN = (ETH_LEN_MIN - ETH_HDR_LEN - ETH_CRC_LEN)
32
33
34 ETH_TYPE_PUP = 0x0200
35 ETH_TYPE_IP = 0x0800
36 ETH_TYPE_ARP = 0x0806
37 ETH_TYPE_AOE = 0x88a2
38 ETH_TYPE_CDP = 0x2000
39 ETH_TYPE_DTP = 0x2004
40 ETH_TYPE_REVARP = 0x8035
41 ETH_TYPE_8021Q = 0x8100
42 ETH_TYPE_IPX = 0x8137
43 ETH_TYPE_IP6 = 0x86DD
44 ETH_TYPE_PPP = 0x880B
45 ETH_TYPE_MPLS = 0x8847
46 ETH_TYPE_MPLS_MCAST = 0x8848
47 ETH_TYPE_PPPoE_DISC = 0x8863
48 ETH_TYPE_PPPoE = 0x8864
49 ETH_TYPE_LLDP = 0x88CC
50 ETH_TYPE_TEB = 0x6558
54 """Ethernet.
55
56 Ethernet II, LLC (802.3+802.2), LLC/SNAP, and Novell raw 802.3,
57 with automatic 802.1q, MPLS, PPPoE, and Cisco ISL decapsulation.
58
59 Attributes:
60 __hdr__: Header fields of Ethernet.
61 TODO.
62 """
63
64 __hdr__ = (
65 ('dst', '6s', ''),
66 ('src', '6s', ''),
67 ('type', 'H', ETH_TYPE_IP)
68 )
69 _typesw = {}
70 _typesw_rev = {}
71
78
113
147
149 tags_buf = b''
150 new_type = self.type
151 is_isl = False
152
153
154
155 if isinstance(self.data, dpkt.Packet):
156 new_type = self._typesw_rev.get(self.data.__class__, new_type)
157
158 if getattr(self, 'mpls_labels', None):
159
160 for lbl in self.mpls_labels:
161 lbl.s = 0
162 lbl.s = 1
163
164
165 if not (self.type == ETH_TYPE_MPLS or self.type == ETH_TYPE_MPLS_MCAST):
166 new_type = ETH_TYPE_MPLS
167 tags_buf = b''.join(lbl.pack_hdr() for lbl in self.mpls_labels)
168
169 elif getattr(self, 'vlan_tags', None):
170
171 t1 = self.vlan_tags[0]
172 if len(self.vlan_tags) == 1:
173 if isinstance(t1, VLANtag8021Q):
174 t1.type = self.type
175 new_type = ETH_TYPE_8021Q
176 elif isinstance(t1, VLANtagISL):
177 t1.type = 0
178 is_isl = True
179 elif len(self.vlan_tags) == 2:
180 t2 = self.vlan_tags[1]
181 if isinstance(t1, VLANtag8021Q) and isinstance(t2, VLANtag8021Q):
182 t2.type = self.type
183 new_type = t1.type = ETH_TYPE_8021Q
184 else:
185 raise dpkt.PackError('maximum is 2 VLAN tags per Ethernet frame')
186 tags_buf = b''.join(tag.pack_hdr() for tag in self.vlan_tags)
187
188
189
190 if isinstance(self.data, llc.LLC):
191 new_type = len(self.data)
192
193 hdr_buf = dpkt.Packet.pack_hdr(self)[:-2] + struct.pack('>H', new_type)
194 if not is_isl:
195 return hdr_buf + tags_buf
196 else:
197 return tags_buf + hdr_buf
198
200 tail = b''
201 if isinstance(self.data, llc.LLC):
202 if hasattr(self, 'fcs'):
203 if self.fcs:
204 fcs = self.fcs
205 else:
206
207 fcs_buf = self.pack_hdr() + bytes(self.data) + getattr(self, 'trailer', '')
208
209 if getattr(self, 'vlan_tags', None):
210 if isinstance(self.vlan_tags[0], VLANtagISL):
211 fcs_buf = fcs_buf[VLANtagISL.__hdr_len__:]
212 revcrc = crc32(fcs_buf) & 0xffffffff
213 fcs = struct.unpack('<I', struct.pack('>I', revcrc))[0]
214 tail = getattr(self, 'trailer', b'') + struct.pack('>I', fcs)
215 return str(dpkt.Packet.__bytes__(self) + tail)
216
223
224 @classmethod
228
229 @classmethod
232
233 @classmethod
236
252
258
259
260
261
262
263 -class MPLSlabel(dpkt.Packet):
264 """A single entry in MPLS label stack"""
265
266 __hdr__ = (
267 ('_val_exp_s_ttl', 'I', 0),
268 )
269
270
278
287
289 return (self.val, self.exp, self.ttl)
290
293 """IEEE 802.1q VLAN tag"""
294
295 __hdr__ = (
296 ('_pri_cfi_id', 'H', 0),
297 ('type', 'H', ETH_TYPE_IP)
298 )
299
306
314
316 return (self.id, self.pri, self.cfi)
317
320 """Cisco Inter-Switch Link VLAN tag"""
321
322 __hdr__ = (
323 ('da', '5s', b'\x01\x00\x0c\x00\x00'),
324 ('_type_pri', 'B', 3),
325 ('sa', '6s', ''),
326 ('len', 'H', 0),
327 ('snap', '3s', b'\xaa\xaa\x03'),
328 ('hsa', '3s', b'\x00\x00\x0c'),
329 ('_id_bpdu', 'H', 0),
330 ('indx', 'H', 0),
331 ('res', 'H', 0)
332 )
333
341
346
352 from . import ip
353 from . import ip6
354 from . import tcp
355 s = (b'\x00\xb0\xd0\xe1\x80\x72\x00\x11\x24\x8c\x11\xde\x86\xdd\x60\x00\x00\x00'
356 b'\x00\x28\x06\x40\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x11\x24\xff\xfe\x8c'
357 b'\x11\xde\xfe\x80\x00\x00\x00\x00\x00\x00\x02\xb0\xd0\xff\xfe\xe1\x80\x72'
358 b'\xcd\xd3\x00\x16\xff\x50\xd7\x13\x00\x00\x00\x00\xa0\x02\xff\xff\x67\xd3'
359 b'\x00\x00\x02\x04\x05\xa0\x01\x03\x03\x00\x01\x01\x08\x0a\x7d\x18\x3a\x61'
360 b'\x00\x00\x00\x00')
361 eth = Ethernet(s)
362 assert eth
363 assert isinstance(eth.data, ip6.IP6)
364 assert isinstance(eth.data.data, tcp.TCP)
365 assert str(eth) == str(s)
366 assert len(eth) == len(s)
367
383
386 s = b'\x00\x01\x0b\xff'
387 m = MPLSlabel(s)
388 assert m.val == 16
389 assert m.exp == 5
390 assert m.s == 1
391 assert m.ttl == 255
392 assert str(m) == str(s)
393 assert len(m) == len(s)
394
397 s = b'\xa0\x76\x01\x65'
398 t = VLANtag8021Q(s)
399 assert t.pri == 5
400 assert t.cfi == 0
401 assert t.id == 118
402 assert str(t) == str(s)
403 t.cfi = 1
404 assert str(t) == str(b'\xb0\x76\x01\x65')
405 assert len(t) == len(s)
406
409 s = (b'\x01\x00\x0c\x00\x00\x03\x00\x02\xfd\x2c\xb8\x97\x00\x00\xaa\xaa\x03\x00\x00\x00\x04\x57'
410 b'\x00\x00\x00\x00')
411 t = VLANtagISL(s)
412 assert t.pri == 3
413 assert t.id == 555
414 assert t.bpdu == 1
415 assert str(t) == str(s)
416 assert len(t) == len(s)
417
420 from . import ip
421 s = (b'\x00\x60\x08\x9f\xb1\xf3\x00\x40\x05\x40\xef\x24\x81\x00\x90\x20\x08'
422 b'\x00\x45\x00\x00\x34\x3b\x64\x40\x00\x40\x06\xb7\x9b\x83\x97\x20\x81'
423 b'\x83\x97\x20\x15\x04\x95\x17\x70\x51\xd4\xee\x9c\x51\xa5\x5b\x36\x80'
424 b'\x10\x7c\x70\x12\xc7\x00\x00\x01\x01\x08\x0a\x00\x04\xf0\xd4\x01\x99'
425 b'\xa3\xfd')
426 eth = Ethernet(s)
427 assert eth.cfi == 1
428 assert eth.vlanid == 32
429 assert eth.priority == 4
430 assert len(eth.vlan_tags) == 1
431 assert eth.vlan_tags[0].type == ETH_TYPE_IP
432 assert isinstance(eth.data, ip.IP)
433
434
435 assert str(eth) == str(s), 'pack 1'
436 assert str(eth) == str(s), 'pack 2'
437 assert len(eth) == len(s)
438
439
440 eth2 = Ethernet(src=eth.src, dst=eth.dst, vlan_tags=eth.vlan_tags, data=eth.data)
441 assert str(eth2) == str(s)
442
443
444 del eth.vlan_tags, eth.cfi, eth.vlanid, eth.priority
445 assert str(eth) == str(s[:12] + b'\x08\x00' + s[18:])
446
449 from . import arp
450 from . import ip
451 s = (b'\x00\x1b\xd4\x1b\xa4\xd8\x00\x13\xc3\xdf\xae\x18\x81\x00\x00\x76\x81\x00\x00\x0a\x08\x00'
452 b'\x45\x00\x00\x64\x00\x0f\x00\x00\xff\x01\x92\x9b\x0a\x76\x0a\x01\x0a\x76\x0a\x02\x08\x00'
453 b'\xce\xb7\x00\x03\x00\x00\x00\x00\x00\x00\x00\x1f\xaf\x70\xab\xcd\xab\xcd\xab\xcd\xab\xcd'
454 b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd'
455 b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd'
456 b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd')
457 eth = Ethernet(s)
458 assert eth.type == ETH_TYPE_IP
459 assert len(eth.vlan_tags) == 2
460 assert eth.vlan_tags[0].id == 118
461 assert eth.vlan_tags[1].id == 10
462 assert eth.vlan_tags[0].type == ETH_TYPE_8021Q
463 assert eth.vlan_tags[1].type == ETH_TYPE_IP
464 assert [t.as_tuple() for t in eth.vlan_tags] == [(118, 0, 0), (10, 0, 0)]
465 assert isinstance(eth.data, ip.IP)
466
467
468 assert str(eth) == str(s), 'pack 1'
469 assert str(eth) == str(s), 'pack 2'
470 assert len(eth) == len(s)
471
472
473 eth2 = Ethernet(src=eth.src, dst=eth.dst, vlan_tags=eth.vlan_tags, data=eth.data)
474 assert str(eth2) == str(s)
475
476
477 del eth.vlan_tags, eth.cfi, eth.vlanid, eth.priority
478 assert str(eth) == str(s[:12] + b'\x08\x00' + s[22:])
479
480
481 s = (b'\xff\xff\xff\xff\xff\xff\xca\x03\x0d\xb4\x00\x1c\x81\x00\x00\x64\x81\x00\x00\xc8\x08\x06'
482 b'\x00\x01\x08\x00\x06\x04\x00\x01\xca\x03\x0d\xb4\x00\x1c\xc0\xa8\x02\xc8\x00\x00\x00\x00'
483 b'\x00\x00\xc0\xa8\x02\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
484 eth = Ethernet(s)
485 assert len(eth.vlan_tags) == 2
486 assert eth.vlan_tags[0].type == ETH_TYPE_8021Q
487 assert eth.vlan_tags[1].type == ETH_TYPE_ARP
488 assert isinstance(eth.data, arp.ARP)
489
492 from . import ip
493 s = (b'\x00\x30\x96\xe6\xfc\x39\x00\x30\x96\x05\x28\x38\x88\x47\x00\x01\x20\xff\x00\x01\x01\xff'
494 b'\x45\x00\x00\x64\x00\x50\x00\x00\xff\x01\xa7\x06\x0a\x1f\x00\x01\x0a\x22\x00\x01\x08\x00'
495 b'\xbd\x11\x0f\x65\x12\xa0\x00\x00\x00\x00\x00\x53\x9e\xe0\xab\xcd\xab\xcd\xab\xcd\xab\xcd'
496 b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd'
497 b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd'
498 b'\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd\xab\xcd')
499 eth = Ethernet(s)
500 assert len(eth.mpls_labels) == 2
501 assert eth.mpls_labels[0].val == 18
502 assert eth.mpls_labels[1].val == 16
503 assert eth.labels == [(18, 0, 255), (16, 0, 255)]
504 assert isinstance(eth.data, ip.IP)
505
506
507 assert str(eth) == str(s), 'pack 1'
508 assert str(eth) == str(s), 'pack 2'
509 assert len(eth) == len(s)
510
511
512 eth2 = Ethernet(src=eth.src, dst=eth.dst, mpls_labels=eth.mpls_labels, data=eth.data)
513 assert str(eth2) == str(s)
514
515
516 del eth.labels, eth.mpls_labels
517 assert str(eth) == str(s[:12] + b'\x08\x00' + s[22:])
518
521 from . import stp
522 s = (b'\x01\x00\x0c\x00\x00\x03\x00\x02\xfd\x2c\xb8\x97\x00\x00\xaa\xaa\x03\x00\x00\x00\x02\x9b'
523 b'\x00\x00\x00\x00\x01\x80\xc2\x00\x00\x00\x00\x02\xfd\x2c\xb8\x98\x00\x26\x42\x42\x03\x00'
524 b'\x00\x00\x00\x00\x80\x00\x00\x02\xfd\x2c\xb8\x83\x00\x00\x00\x00\x80\x00\x00\x02\xfd\x2c'
525 b'\xb8\x83\x80\x26\x00\x00\x14\x00\x02\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x41\xc6'
526 b'\x75\xd6')
527 eth = Ethernet(s)
528 assert eth.vlan == 333
529 assert len(eth.vlan_tags) == 1
530 assert eth.vlan_tags[0].id == 333
531 assert eth.vlan_tags[0].pri == 3
532
533
534 assert eth.fcs == 0x41c675d6
535 assert eth.trailer == b'\x00' * 8
536
537
538 assert isinstance(eth.data, llc.LLC)
539 assert isinstance(eth.data.data, stp.STP)
540
541
542 assert str(eth) == str(s), 'pack 1'
543 assert str(eth) == str(s), 'pack 2'
544 assert len(eth) == len(s)
545
546
547 eth2 = Ethernet(src=eth.src, dst=eth.dst, vlan_tags=eth.vlan_tags, data=eth.data)
548 eth2.trailer = eth.trailer
549 eth2.fcs = None
550
551 assert str(eth2) == str(s)
552
553
554 del eth.vlan_tags, eth.vlan
555 assert str(eth) == str(s[26:])
556
559 from . import cdp
560 s = (b'\x01\x00\x0c\xcc\xcc\xcc\xc4\x022k\x00\x00\x01T\xaa\xaa\x03\x00\x00\x0c \x00\x02\xb4,B'
561 b'\x00\x01\x00\x06R2\x00\x05\x00\xffCisco IOS Software, 3700 Software (C3745-ADVENTERPRI'
562 b'SEK9_SNA-M), Version 12.4(25d), RELEASE SOFTWARE (fc1)\nTechnical Support: http://www.'
563 b'cisco.com/techsupport\nCopyright (c) 1986-2010 by Cisco Systems, Inc.\nCompiled Wed 18'
564 b'-Aug-10 08:18 by prod_rel_team\x00\x06\x00\x0eCisco 3745\x00\x02\x00\x11\x00\x00\x00\x01'
565 b'\x01\x01\xcc\x00\x04\n\x00\x00\x02\x00\x03\x00\x13FastEthernet0/0\x00\x04\x00\x08\x00'
566 b'\x00\x00)\x00\t\x00\x04\x00\x0b\x00\x05\x00')
567 eth = Ethernet(s)
568
569
570 assert isinstance(eth.data, llc.LLC)
571 assert isinstance(eth.data.data, cdp.CDP)
572 assert len(eth.data.data.data) == 8
573 assert str(eth) == str(s), 'pack 1'
574 assert str(eth) == str(s), 'pack 2'
575 assert len(eth) == len(s)
576
579 from . import ipx
580 s = (b'\xff\xff\xff\xff\xff\xff\x00\xb0\xd0\x22\xf7\xf3\x00\x54\xe0\xe0\x03\xff\xff\x00\x50\x00'
581 b'\x14\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x04\x55\x00\x00\x00\x00\x00\xb0\xd0\x22\xf7'
582 b'\xf3\x04\x55\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
583 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x02\x5f\x5f\x4d\x53\x42'
584 b'\x52\x4f\x57\x53\x45\x5f\x5f\x02\x01\x00')
585 eth = Ethernet(s)
586
587
588 assert isinstance(eth.data, llc.LLC)
589 assert isinstance(eth.data.data, ipx.IPX)
590 assert eth.data.data.pt == 0x14
591 assert str(eth) == str(s), 'pack 1'
592 assert str(eth) == str(s), 'pack 2'
593 assert len(eth) == len(s)
594
597 from . import ip
598 from . import ip6
599 from . import ppp
600 from . import pppoe
601 from . import udp
602 s = (b'\xca\x01\x0e\x88\x00\x06\xcc\x05\x0e\x88\x00\x00\x88\x64\x11\x00\x00\x11\x00\x64\x57\x6e'
603 b'\x00\x00\x00\x00\x3a\x11\xff\xfe\x80\x00\x00\x00\x00\x00\x00\xce\x05\x0e\xff\xfe\x88\x00'
604 b'\x00\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x02\x02\x22\x02\x23\x00'
605 b'\x3a\x1a\x67\x01\xfc\x24\xab\x00\x08\x00\x02\x05\xe9\x00\x01\x00\x0a\x00\x03\x00\x01\xcc'
606 b'\x05\x0e\x88\x00\x00\x00\x06\x00\x06\x00\x19\x00\x17\x00\x18\x00\x19\x00\x0c\x00\x09\x00'
607 b'\x01\x00\x00\x00\x00\x00\x00\x00\x00')
608 eth = Ethernet(s)
609
610
611 assert isinstance(eth.data, pppoe.PPPoE)
612 assert isinstance(eth.data.data, ppp.PPP)
613 assert isinstance(eth.data.data.data, ip6.IP6)
614 assert isinstance(eth.data.data.data.data, udp.UDP)
615
616
617 assert str(eth) == str(s)
618 assert len(eth) == len(s)
619
620
621
622
623
624 if __name__ == '__main__':
625 test_eth()
626 test_eth_init_with_data()
627 test_mpls_label()
628 test_802dot1q_tag()
629 test_isl_tag()
630 test_eth_802dot1q()
631 test_eth_802dot1q_stacked()
632 test_eth_mpls_stacked()
633 test_isl_eth_llc_stp()
634 test_eth_llc_snap_cdp()
635 test_eth_llc_ipx()
636 test_eth_pppoe()
637
638 print('Tests Successful...')
639