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

Source Code for Module dpkt.pppoe

  1  # $Id: pppoe.py 23 2006-11-08 15:45:33Z dugsong $ 
  2  # -*- coding: utf-8 -*- 
  3  """PPP-over-Ethernet.""" 
  4  from __future__ import absolute_import 
  5   
  6  import struct 
  7  import codecs 
  8   
  9  from . import dpkt 
 10  from . import ppp 
 11  from .decorators import deprecated 
 12   
 13  # RFC 2516 codes 
 14  PPPoE_PADI = 0x09 
 15  PPPoE_PADO = 0x07 
 16  PPPoE_PADR = 0x19 
 17  PPPoE_PADS = 0x65 
 18  PPPoE_PADT = 0xA7 
 19  PPPoE_SESSION = 0x00 
20 21 22 -class PPPoE(dpkt.Packet):
23 """PPP-over-Ethernet. 24 25 TODO: Longer class information.... 26 27 Attributes: 28 __hdr__: Header fields of PPPoE. 29 TODO. 30 """ 31 32 __hdr__ = ( 33 ('_v_type', 'B', 0x11), 34 ('code', 'B', 0), 35 ('session', 'H', 0), 36 ('len', 'H', 0) # payload length 37 ) 38 39 @property
40 - def v(self):
41 return self._v_type >> 4
42 43 @v.setter
44 - def v(self, v):
45 self._v_type = (v << 4) | (self._v_type & 0xf)
46 47 @property
48 - def type(self):
49 return self._v_type & 0xf
50 51 @type.setter
52 - def type(self, t):
53 self._v_type = (self._v_type & 0xf0) | t
54
55 - def unpack(self, buf):
56 dpkt.Packet.unpack(self, buf) 57 try: 58 if self.code == 0: 59 # We need to use the pppoe.PPP header here, because PPPoE 60 # doesn't do the normal encapsulation. 61 self.data = self.ppp = PPP(self.data) 62 except dpkt.UnpackError: 63 pass
64
65 66 -class PPP(ppp.PPP):
67 # Light version for protocols without the usual encapsulation, for PPPoE 68 __hdr__ = ( 69 # Usuaully two-bytes, but while protocol compression is not recommended, it is supported 70 ('p', 'B', ppp.PPP_IP), 71 ) 72
73 - def unpack(self, buf):
74 dpkt.Packet.unpack(self, buf) 75 if self.p & ppp.PFC_BIT == 0: 76 try: 77 self.p = struct.unpack('>H', buf[:2])[0] 78 except struct.error: 79 raise dpkt.NeedData 80 self.data = self.data[1:] 81 try: 82 self.data = self._protosw[self.p](self.data) 83 setattr(self, self.data.__class__.__name__.lower(), self.data) 84 except (KeyError, struct.error, dpkt.UnpackError): 85 pass
86
87 - def pack_hdr(self):
88 try: 89 # Protocol compression is *not* recommended (RFC2516), but we do it anyway 90 if self.p > 0xff: 91 return struct.pack('>H', self.p) 92 return dpkt.Packet.pack_hdr(self) 93 except struct.error as e: 94 raise dpkt.PackError(str(e))
95
96 97 -def test_pppoe_discovery():
98 s = ("11070000002801010000010300046413" 99 "85180102000442524153010400103d0f" 100 "0587062484f2df32b9ddfd77bd5b") 101 s = codecs.decode(s, 'hex') 102 p = PPPoE(s) 103 104 assert p.code == PPPoE_PADO 105 assert p.v == 1 106 assert p.type == 1 107 108 s = ("11190000002801010000010300046413" 109 "85180102000442524153010400103d0f" 110 "0587062484f2df32b9ddfd77bd5b") 111 s = codecs.decode(s, 'hex') 112 p = PPPoE(s) 113 114 assert p.code == PPPoE_PADR 115 116 assert p.pack_hdr() == s[:6]
117
118 119 -def test_pppoe_session():
120 s = "11000011000cc0210101000a050605fcd459" 121 s = codecs.decode(s, 'hex') 122 p = PPPoE(s) 123 124 assert p.code == PPPoE_SESSION 125 assert isinstance(p.ppp, PPP) 126 assert p.data.p == 0xc021 # LCP 127 assert len(p.data.data) == 10 128 129 assert p.data.pack_hdr() == b"\xc0\x21" 130 131 s = ("110000110066005760000000003c3a40fc000000000000000000000000000001" 132 "fc0000000002010000000000000100018100bf291f9700010102030405060708" 133 "090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728" 134 "292a2b2c2d2e2f3031323334") 135 s = codecs.decode(s, 'hex') 136 p = PPPoE(s) 137 assert p.code == PPPoE_SESSION 138 assert isinstance(p.ppp, PPP) 139 assert p.data.p == ppp.PPP_IP6 140 assert p.data.data.p == 58 # ICMPv6 141 142 assert p.ppp.pack_hdr() == b"\x57"
143
144 145 -def test_ppp_packing():
146 p = PPP() 147 assert p.pack_hdr() == b"\x21" 148 149 p.p = 0xc021 # LCP 150 assert p.pack_hdr() == b"\xc0\x21"
151
152 153 -def test_ppp_short():
154 import pytest 155 pytest.raises(dpkt.NeedData, PPP, b"\x00")
156 157 158 # XXX - TODO TLVs, etc. 159