1## This file is part of Scapy 2## See http://www.secdev.org/projects/scapy for more informations 3## Copyright (C) Philippe Biondi <phil@secdev.org> 4## This program is published under a GPLv2 license 5 6""" 7PPP (Point to Point Protocol) 8 9[RFC 1661] 10""" 11 12import struct 13from scapy.config import conf 14from scapy.data import DLT_PPP, DLT_PPP_SERIAL, DLT_PPP_ETHER 15from scapy.compat import * 16from scapy.packet import Packet, bind_layers 17from scapy.layers.eap import EAP 18from scapy.layers.l2 import Ether, CookedLinux, GRE_PPTP 19from scapy.layers.inet import IP 20from scapy.layers.inet6 import IPv6 21from scapy.fields import BitField, ByteEnumField, ByteField, \ 22 ConditionalField, FieldLenField, IntField, IPField, \ 23 PacketListField, PacketField, ShortEnumField, ShortField, \ 24 StrFixedLenField, StrLenField, XByteField, XShortField, XStrLenField 25 26 27class PPPoE(Packet): 28 name = "PPP over Ethernet" 29 fields_desc = [ BitField("version", 1, 4), 30 BitField("type", 1, 4), 31 ByteEnumField("code", 0, {0:"Session"}), 32 XShortField("sessionid", 0x0), 33 ShortField("len", None) ] 34 35 def post_build(self, p, pay): 36 p += pay 37 if self.len is None: 38 l = len(p)-6 39 p = p[:4]+struct.pack("!H", l)+p[6:] 40 return p 41 42class PPPoED(PPPoE): 43 name = "PPP over Ethernet Discovery" 44 fields_desc = [ BitField("version", 1, 4), 45 BitField("type", 1, 4), 46 ByteEnumField("code", 0x09, {0x09:"PADI",0x07:"PADO",0x19:"PADR",0x65:"PADS",0xa7:"PADT"}), 47 XShortField("sessionid", 0x0), 48 ShortField("len", None) ] 49 50 51_PPP_proto = { 0x0001: "Padding Protocol", 52 0x0003: "ROHC small-CID [RFC3095]", 53 0x0005: "ROHC large-CID [RFC3095]", 54 0x0021: "Internet Protocol version 4", 55 0x0023: "OSI Network Layer", 56 0x0025: "Xerox NS IDP", 57 0x0027: "DECnet Phase IV", 58 0x0029: "Appletalk", 59 0x002b: "Novell IPX", 60 0x002d: "Van Jacobson Compressed TCP/IP", 61 0x002f: "Van Jacobson Uncompressed TCP/IP", 62 0x0031: "Bridging PDU", 63 0x0033: "Stream Protocol (ST-II)", 64 0x0035: "Banyan Vines", 65 0x0037: "reserved (until 1993) [Typo in RFC1172]", 66 0x0039: "AppleTalk EDDP", 67 0x003b: "AppleTalk SmartBuffered", 68 0x003d: "Multi-Link [RFC1717]", 69 0x003f: "NETBIOS Framing", 70 0x0041: "Cisco Systems", 71 0x0043: "Ascom Timeplex", 72 0x0045: "Fujitsu Link Backup and Load Balancing (LBLB)", 73 0x0047: "DCA Remote Lan", 74 0x0049: "Serial Data Transport Protocol (PPP-SDTP)", 75 0x004b: "SNA over 802.2", 76 0x004d: "SNA", 77 0x004f: "IPv6 Header Compression", 78 0x0051: "KNX Bridging Data [ianp]", 79 0x0053: "Encryption [Meyer]", 80 0x0055: "Individual Link Encryption [Meyer]", 81 0x0057: "Internet Protocol version 6 [Hinden]", 82 0x0059: "PPP Muxing [RFC3153]", 83 0x005b: "Vendor-Specific Network Protocol (VSNP) [RFC3772]", 84 0x0061: "RTP IPHC Full Header [RFC3544]", 85 0x0063: "RTP IPHC Compressed TCP [RFC3544]", 86 0x0065: "RTP IPHC Compressed Non TCP [RFC3544]", 87 0x0067: "RTP IPHC Compressed UDP 8 [RFC3544]", 88 0x0069: "RTP IPHC Compressed RTP 8 [RFC3544]", 89 0x006f: "Stampede Bridging", 90 0x0071: "Reserved [Fox]", 91 0x0073: "MP+ Protocol [Smith]", 92 0x007d: "reserved (Control Escape) [RFC1661]", 93 0x007f: "reserved (compression inefficient [RFC1662]", 94 0x0081: "Reserved Until 20-Oct-2000 [IANA]", 95 0x0083: "Reserved Until 20-Oct-2000 [IANA]", 96 0x00c1: "NTCITS IPI [Ungar]", 97 0x00cf: "reserved (PPP NLID)", 98 0x00fb: "single link compression in multilink [RFC1962]", 99 0x00fd: "compressed datagram [RFC1962]", 100 0x00ff: "reserved (compression inefficient)", 101 0x0201: "802.1d Hello Packets", 102 0x0203: "IBM Source Routing BPDU", 103 0x0205: "DEC LANBridge100 Spanning Tree", 104 0x0207: "Cisco Discovery Protocol [Sastry]", 105 0x0209: "Netcs Twin Routing [Korfmacher]", 106 0x020b: "STP - Scheduled Transfer Protocol [Segal]", 107 0x020d: "EDP - Extreme Discovery Protocol [Grosser]", 108 0x0211: "Optical Supervisory Channel Protocol (OSCP)[Prasad]", 109 0x0213: "Optical Supervisory Channel Protocol (OSCP)[Prasad]", 110 0x0231: "Luxcom", 111 0x0233: "Sigma Network Systems", 112 0x0235: "Apple Client Server Protocol [Ridenour]", 113 0x0281: "MPLS Unicast [RFC3032] ", 114 0x0283: "MPLS Multicast [RFC3032]", 115 0x0285: "IEEE p1284.4 standard - data packets [Batchelder]", 116 0x0287: "ETSI TETRA Network Protocol Type 1 [Nieminen]", 117 0x0289: "Multichannel Flow Treatment Protocol [McCann]", 118 0x2063: "RTP IPHC Compressed TCP No Delta [RFC3544]", 119 0x2065: "RTP IPHC Context State [RFC3544]", 120 0x2067: "RTP IPHC Compressed UDP 16 [RFC3544]", 121 0x2069: "RTP IPHC Compressed RTP 16 [RFC3544]", 122 0x4001: "Cray Communications Control Protocol [Stage]", 123 0x4003: "CDPD Mobile Network Registration Protocol [Quick]", 124 0x4005: "Expand accelerator protocol [Rachmani]", 125 0x4007: "ODSICP NCP [Arvind]", 126 0x4009: "DOCSIS DLL [Gaedtke]", 127 0x400B: "Cetacean Network Detection Protocol [Siller]", 128 0x4021: "Stacker LZS [Simpson]", 129 0x4023: "RefTek Protocol [Banfill]", 130 0x4025: "Fibre Channel [Rajagopal]", 131 0x4027: "EMIT Protocols [Eastham]", 132 0x405b: "Vendor-Specific Protocol (VSP) [RFC3772]", 133 0x8021: "Internet Protocol Control Protocol", 134 0x8023: "OSI Network Layer Control Protocol", 135 0x8025: "Xerox NS IDP Control Protocol", 136 0x8027: "DECnet Phase IV Control Protocol", 137 0x8029: "Appletalk Control Protocol", 138 0x802b: "Novell IPX Control Protocol", 139 0x802d: "reserved", 140 0x802f: "reserved", 141 0x8031: "Bridging NCP", 142 0x8033: "Stream Protocol Control Protocol", 143 0x8035: "Banyan Vines Control Protocol", 144 0x8037: "reserved (until 1993)", 145 0x8039: "reserved", 146 0x803b: "reserved", 147 0x803d: "Multi-Link Control Protocol", 148 0x803f: "NETBIOS Framing Control Protocol", 149 0x8041: "Cisco Systems Control Protocol", 150 0x8043: "Ascom Timeplex", 151 0x8045: "Fujitsu LBLB Control Protocol", 152 0x8047: "DCA Remote Lan Network Control Protocol (RLNCP)", 153 0x8049: "Serial Data Control Protocol (PPP-SDCP)", 154 0x804b: "SNA over 802.2 Control Protocol", 155 0x804d: "SNA Control Protocol", 156 0x804f: "IP6 Header Compression Control Protocol", 157 0x8051: "KNX Bridging Control Protocol [ianp]", 158 0x8053: "Encryption Control Protocol [Meyer]", 159 0x8055: "Individual Link Encryption Control Protocol [Meyer]", 160 0x8057: "IPv6 Control Protovol [Hinden]", 161 0x8059: "PPP Muxing Control Protocol [RFC3153]", 162 0x805b: "Vendor-Specific Network Control Protocol (VSNCP) [RFC3772]", 163 0x806f: "Stampede Bridging Control Protocol", 164 0x8073: "MP+ Control Protocol [Smith]", 165 0x8071: "Reserved [Fox]", 166 0x807d: "Not Used - reserved [RFC1661]", 167 0x8081: "Reserved Until 20-Oct-2000 [IANA]", 168 0x8083: "Reserved Until 20-Oct-2000 [IANA]", 169 0x80c1: "NTCITS IPI Control Protocol [Ungar]", 170 0x80cf: "Not Used - reserved [RFC1661]", 171 0x80fb: "single link compression in multilink control [RFC1962]", 172 0x80fd: "Compression Control Protocol [RFC1962]", 173 0x80ff: "Not Used - reserved [RFC1661]", 174 0x8207: "Cisco Discovery Protocol Control [Sastry]", 175 0x8209: "Netcs Twin Routing [Korfmacher]", 176 0x820b: "STP - Control Protocol [Segal]", 177 0x820d: "EDPCP - Extreme Discovery Protocol Ctrl Prtcl [Grosser]", 178 0x8235: "Apple Client Server Protocol Control [Ridenour]", 179 0x8281: "MPLSCP [RFC3032]", 180 0x8285: "IEEE p1284.4 standard - Protocol Control [Batchelder]", 181 0x8287: "ETSI TETRA TNP1 Control Protocol [Nieminen]", 182 0x8289: "Multichannel Flow Treatment Protocol [McCann]", 183 0xc021: "Link Control Protocol", 184 0xc023: "Password Authentication Protocol", 185 0xc025: "Link Quality Report", 186 0xc027: "Shiva Password Authentication Protocol", 187 0xc029: "CallBack Control Protocol (CBCP)", 188 0xc02b: "BACP Bandwidth Allocation Control Protocol [RFC2125]", 189 0xc02d: "BAP [RFC2125]", 190 0xc05b: "Vendor-Specific Authentication Protocol (VSAP) [RFC3772]", 191 0xc081: "Container Control Protocol [KEN]", 192 0xc223: "Challenge Handshake Authentication Protocol", 193 0xc225: "RSA Authentication Protocol [Narayana]", 194 0xc227: "Extensible Authentication Protocol [RFC2284]", 195 0xc229: "Mitsubishi Security Info Exch Ptcl (SIEP) [Seno]", 196 0xc26f: "Stampede Bridging Authorization Protocol", 197 0xc281: "Proprietary Authentication Protocol [KEN]", 198 0xc283: "Proprietary Authentication Protocol [Tackabury]", 199 0xc481: "Proprietary Node ID Authentication Protocol [KEN]"} 200 201 202class HDLC(Packet): 203 fields_desc = [ XByteField("address",0xff), 204 XByteField("control",0x03) ] 205 206class PPP(Packet): 207 name = "PPP Link Layer" 208 fields_desc = [ ShortEnumField("proto", 0x0021, _PPP_proto) ] 209 @classmethod 210 def dispatch_hook(cls, _pkt=None, *args, **kargs): 211 if _pkt and orb(_pkt[0]) == 0xff: 212 cls = HDLC 213 return cls 214 215_PPP_conftypes = { 1:"Configure-Request", 216 2:"Configure-Ack", 217 3:"Configure-Nak", 218 4:"Configure-Reject", 219 5:"Terminate-Request", 220 6:"Terminate-Ack", 221 7:"Code-Reject", 222 8:"Protocol-Reject", 223 9:"Echo-Request", 224 10:"Echo-Reply", 225 11:"Discard-Request", 226 14:"Reset-Request", 227 15:"Reset-Ack", 228 } 229 230 231### PPP IPCP stuff (RFC 1332) 232 233# All IPCP options are defined below (names and associated classes) 234_PPP_ipcpopttypes = { 1:"IP-Addresses (Deprecated)", 235 2:"IP-Compression-Protocol", 236 3:"IP-Address", 237 4:"Mobile-IPv4", # not implemented, present for completeness 238 129:"Primary-DNS-Address", 239 130:"Primary-NBNS-Address", 240 131:"Secondary-DNS-Address", 241 132:"Secondary-NBNS-Address"} 242 243 244class PPP_IPCP_Option(Packet): 245 name = "PPP IPCP Option" 246 fields_desc = [ ByteEnumField("type" , None , _PPP_ipcpopttypes), 247 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2), 248 StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ] 249 def extract_padding(self, pay): 250 return b"",pay 251 252 registered_options = {} 253 @classmethod 254 def register_variant(cls): 255 cls.registered_options[cls.type.default] = cls 256 @classmethod 257 def dispatch_hook(cls, _pkt=None, *args, **kargs): 258 if _pkt: 259 o = orb(_pkt[0]) 260 return cls.registered_options.get(o, cls) 261 return cls 262 263 264class PPP_IPCP_Option_IPAddress(PPP_IPCP_Option): 265 name = "PPP IPCP Option: IP Address" 266 fields_desc = [ ByteEnumField("type" , 3 , _PPP_ipcpopttypes), 267 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2), 268 IPField("data","0.0.0.0"), 269 ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ] 270 271class PPP_IPCP_Option_DNS1(PPP_IPCP_Option): 272 name = "PPP IPCP Option: DNS1 Address" 273 fields_desc = [ ByteEnumField("type" , 129 , _PPP_ipcpopttypes), 274 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2), 275 IPField("data","0.0.0.0"), 276 ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ] 277 278class PPP_IPCP_Option_DNS2(PPP_IPCP_Option): 279 name = "PPP IPCP Option: DNS2 Address" 280 fields_desc = [ ByteEnumField("type" , 131 , _PPP_ipcpopttypes), 281 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2), 282 IPField("data","0.0.0.0"), 283 ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ] 284 285class PPP_IPCP_Option_NBNS1(PPP_IPCP_Option): 286 name = "PPP IPCP Option: NBNS1 Address" 287 fields_desc = [ ByteEnumField("type" , 130 , _PPP_ipcpopttypes), 288 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2), 289 IPField("data","0.0.0.0"), 290 ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ] 291 292class PPP_IPCP_Option_NBNS2(PPP_IPCP_Option): 293 name = "PPP IPCP Option: NBNS2 Address" 294 fields_desc = [ ByteEnumField("type" , 132 , _PPP_ipcpopttypes), 295 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2), 296 IPField("data","0.0.0.0"), 297 ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ] 298 299 300class PPP_IPCP(Packet): 301 fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes), 302 XByteField("id", 0 ), 303 FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ), 304 PacketListField("options", [], PPP_IPCP_Option, length_from=lambda p:p.len-4,) ] 305 306 307### ECP 308 309_PPP_ecpopttypes = { 0:"OUI", 310 1:"DESE", } 311 312class PPP_ECP_Option(Packet): 313 name = "PPP ECP Option" 314 fields_desc = [ ByteEnumField("type" , None , _PPP_ecpopttypes), 315 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2), 316 StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ] 317 def extract_padding(self, pay): 318 return b"",pay 319 320 registered_options = {} 321 @classmethod 322 def register_variant(cls): 323 cls.registered_options[cls.type.default] = cls 324 @classmethod 325 def dispatch_hook(cls, _pkt=None, *args, **kargs): 326 if _pkt: 327 o = orb(_pkt[0]) 328 return cls.registered_options.get(o, cls) 329 return cls 330 331class PPP_ECP_Option_OUI(PPP_ECP_Option): 332 fields_desc = [ ByteEnumField("type" , 0 , _PPP_ecpopttypes), 333 FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6), 334 StrFixedLenField("oui","",3), 335 ByteField("subtype",0), 336 StrLenField("data", "", length_from=lambda p:p.len-6) ] 337 338 339 340class PPP_ECP(Packet): 341 fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes), 342 XByteField("id", 0 ), 343 FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ), 344 PacketListField("options", [], PPP_ECP_Option, length_from=lambda p:p.len-4,) ] 345 346### Link Control Protocol (RFC 1661) 347 348_PPP_lcptypes = {1: "Configure-Request", 349 2: "Configure-Ack", 350 3: "Configure-Nak", 351 4: "Configure-Reject", 352 5: "Terminate-Request", 353 6: "Terminate-Ack", 354 7: "Code-Reject", 355 8: "Protocol-Reject", 356 9: "Echo-Request", 357 10: "Echo-Reply", 358 11: "Discard-Request"} 359 360 361class PPP_LCP(Packet): 362 name = "PPP Link Control Protocol" 363 fields_desc = [ByteEnumField("code", 5, _PPP_lcptypes), 364 XByteField("id", 0), 365 FieldLenField("len", None, fmt="H", length_of="data", 366 adjust=lambda p, x: x + 4), 367 StrLenField("data", "", 368 length_from=lambda p:p.len-4)] 369 370 def mysummary(self): 371 return self.sprintf('LCP %code%') 372 373 def extract_padding(self, pay): 374 return b"", pay 375 376 @classmethod 377 def dispatch_hook(cls, _pkt = None, *args, **kargs): 378 if _pkt: 379 o = orb(_pkt[0]) 380 if o in [1, 2, 3, 4]: 381 return PPP_LCP_Configure 382 elif o in [5,6]: 383 return PPP_LCP_Terminate 384 elif o == 7: 385 return PPP_LCP_Code_Reject 386 elif o == 8: 387 return PPP_LCP_Protocol_Reject 388 elif o in [9, 10]: 389 return PPP_LCP_Echo 390 elif o == 11: 391 return PPP_LCP_Discard_Request 392 else: 393 return cls 394 return cls 395 396 397_PPP_lcp_optiontypes = {1: "Maximum-Receive-Unit", 398 2: "Async-Control-Character-Map", 399 3: "Authentication-protocol", 400 4: "Quality-protocol", 401 5: "Magic-number", 402 7: "Protocol-Field-Compression", 403 8: "Address-and-Control-Field-Compression", 404 13: "Callback"} 405 406 407class PPP_LCP_Option(Packet): 408 name = "PPP LCP Option" 409 fields_desc = [ByteEnumField("type", None, _PPP_lcp_optiontypes), 410 FieldLenField("len", None, fmt="B", length_of="data", 411 adjust=lambda p,x:x+2), 412 StrLenField("data", None, length_from=lambda p:p.len-2)] 413 414 def extract_padding(self, pay): 415 return b"", pay 416 417 registered_options = {} 418 419 @classmethod 420 def register_variant(cls): 421 cls.registered_options[cls.type.default] = cls 422 423 @classmethod 424 def dispatch_hook(cls, _pkt=None, *args, **kargs): 425 if _pkt: 426 o = orb(_pkt[0]) 427 return cls.registered_options.get(o, cls) 428 return cls 429 430 431class PPP_LCP_MRU_Option(PPP_LCP_Option): 432 fields_desc = [ByteEnumField("type", 1, _PPP_lcp_optiontypes), 433 FieldLenField("len", 4, fmt="B", adjust=lambda p,x:4), 434 ShortField("max_recv_unit", 1500)] 435 436_PPP_LCP_auth_protocols = {0xc023: "Password authentication protocol", 437 0xc223: "Challenge-response authentication protocol", 438 0xc227: "PPP Extensible authentication protocol"} 439 440_PPP_LCP_CHAP_algorithms = {5: "MD5", 441 6: "SHA1", 442 128: "MS-CHAP", 443 129: "MS-CHAP-v2"} 444 445 446class PPP_LCP_ACCM_Option(PPP_LCP_Option): 447 fields_desc = [ByteEnumField("type", 2, _PPP_lcp_optiontypes), 448 FieldLenField("len", 6, fmt="B"), 449 BitField("accm", 0x00000000, 32)] 450 451 452def adjust_auth_len(pkt, x): 453 if pkt.auth_protocol == 0xc223: 454 return 5 455 elif pkt.auth_protocol == 0xc023: 456 return 4 457 else: 458 return x + 4 459 460 461class PPP_LCP_Auth_Protocol_Option(PPP_LCP_Option): 462 fields_desc = [ByteEnumField("type", 3, _PPP_lcp_optiontypes), 463 FieldLenField("len", None, fmt="B", length_of="data", 464 adjust=adjust_auth_len), 465 ShortEnumField("auth_protocol", 0xc023, _PPP_LCP_auth_protocols), 466 ConditionalField(StrLenField("data", '', length_from=lambda p:p.len-4), 467 lambda p:p.auth_protocol != 0xc223), 468 ConditionalField(ByteEnumField("algorithm", 5, _PPP_LCP_CHAP_algorithms), 469 lambda p:p.auth_protocol == 0xc223)] 470 471 472_PPP_LCP_quality_protocols = {0xc025: "Link Quality Report"} 473 474 475class PPP_LCP_Quality_Protocol_Option(PPP_LCP_Option): 476 fields_desc = [ByteEnumField("type", 4, _PPP_lcp_optiontypes), 477 FieldLenField("len", None, fmt="B", length_of="data", 478 adjust=lambda p,x:x+4), 479 ShortEnumField("quality_protocol", 0xc025, _PPP_LCP_quality_protocols), 480 StrLenField("data", "", length_from=lambda p:p.len-4)] 481 482 483class PPP_LCP_Magic_Number_Option(PPP_LCP_Option): 484 fields_desc = [ByteEnumField("type", 5, _PPP_lcp_optiontypes), 485 FieldLenField("len", 6, fmt="B", adjust = lambda p,x:6), 486 IntField("magic_number", None)] 487 488 489_PPP_lcp_callback_operations = {0: "Location determined by user authentication", 490 1: "Dialing string", 491 2: "Location identifier", 492 3: "E.164 number", 493 4: "Distinguished name"} 494 495 496class PPP_LCP_Callback_Option(PPP_LCP_Option): 497 fields_desc = [ByteEnumField("type", 13, _PPP_lcp_optiontypes), 498 FieldLenField("len", None, fmt="B", length_of="message", 499 adjust=lambda p,x:x+3), 500 ByteEnumField("operation", 0, _PPP_lcp_callback_operations), 501 StrLenField("message", "", length_from=lambda p:p.len-3)] 502 503 504class PPP_LCP_Configure(PPP_LCP): 505 fields_desc = [ByteEnumField("code", 1, _PPP_lcptypes), 506 XByteField("id", 0), 507 FieldLenField("len", None, fmt="H", length_of="options", 508 adjust=lambda p,x:x+4), 509 PacketListField("options", [], PPP_LCP_Option, 510 length_from=lambda p:p.len-4)] 511 512 def answers(self, other): 513 return isinstance(other, PPP_LCP_Configure) and self.code in [2, 3, 4]\ 514 and other.code == 1 and other.id == self.id 515 516 517class PPP_LCP_Terminate(PPP_LCP): 518 519 def answers(self, other): 520 return isinstance(other, PPP_LCP_Terminate) and self.code == 6\ 521 and other.code == 5 and other.id == self.id 522 523 524class PPP_LCP_Code_Reject(PPP_LCP): 525 fields_desc = [ByteEnumField("code", 7, _PPP_lcptypes), 526 XByteField("id", 0), 527 FieldLenField("len", None, fmt="H", length_of="rejected_packet", 528 adjust=lambda p,x:x+4), 529 PacketField("rejected_packet", None, PPP_LCP)] 530 531 532class PPP_LCP_Protocol_Reject(PPP_LCP): 533 fields_desc = [ByteEnumField("code", 8, _PPP_lcptypes), 534 XByteField("id", 0), 535 FieldLenField("len", None, fmt="H", length_of="rejected_information", 536 adjust=lambda p,x:x+6), 537 ShortEnumField("rejected_protocol", None, _PPP_proto), 538 PacketField("rejected_information", None, Packet)] 539 540 541class PPP_LCP_Echo(PPP_LCP): 542 fields_desc = [ByteEnumField("code", 9, _PPP_lcptypes), 543 XByteField("id", 0), 544 FieldLenField("len", None, fmt="H", length_of="data", 545 adjust=lambda p,x:x+8), 546 IntField("magic_number", None), 547 StrLenField("data", "", length_from=lambda p:p.len-8)] 548 549 def answers(self, other): 550 return isinstance(other, PPP_LCP_Echo) and self.code == 10\ 551 and other.code == 9 and self.id == other.id 552 553 554class PPP_LCP_Discard_Request(PPP_LCP): 555 fields_desc = [ByteEnumField("code", 11, _PPP_lcptypes), 556 XByteField("id", 0), 557 FieldLenField("len", None, fmt="H", length_of="data", 558 adjust=lambda p,x:x+8), 559 IntField("magic_number", None), 560 StrLenField("data", "", length_from=lambda p:p.len-8)] 561 562### Password authentication protocol (RFC 1334) 563 564_PPP_paptypes = {1: "Authenticate-Request", 565 2: "Authenticate-Ack", 566 3: "Authenticate-Nak"} 567 568 569class PPP_PAP(Packet): 570 name = "PPP Password Authentication Protocol" 571 fields_desc = [ByteEnumField("code", 1, _PPP_paptypes), 572 XByteField("id", 0), 573 FieldLenField("len", None, fmt="!H", length_of="data", 574 adjust=lambda _, x: x + 4), 575 StrLenField("data", "", length_from=lambda p: p.len-4)] 576 577 @classmethod 578 def dispatch_hook(cls, _pkt=None, *_, **kargs): 579 code = None 580 if _pkt: 581 code = orb(_pkt[0]) 582 elif "code" in kargs: 583 code = kargs["code"] 584 if isinstance(code, six.string_types): 585 code = cls.fields_desc[0].s2i[code] 586 587 if code == 1: 588 return PPP_PAP_Request 589 elif code in [2, 3]: 590 return PPP_PAP_Response 591 return cls 592 593 def extract_padding(self, pay): 594 return "", pay 595 596 597class PPP_PAP_Request(PPP_PAP): 598 fields_desc = [ByteEnumField("code", 1, _PPP_paptypes), 599 XByteField("id", 0), 600 FieldLenField("len", None, fmt="!H", length_of="username", 601 adjust=lambda p, x: x + 6 + len(p.password)), 602 FieldLenField("username_len", None, fmt="B", length_of="username"), 603 StrLenField("username", None, length_from=lambda p: p.username_len), 604 FieldLenField("passwd_len", None, fmt="B", length_of="password"), 605 StrLenField("password", None, length_from=lambda p: p.passwd_len)] 606 607 def mysummary(self): 608 return self.sprintf("PAP-Request username=%PPP_PAP_Request.username%" + 609 " password=%PPP_PAP_Request.password%") 610 611 612class PPP_PAP_Response(PPP_PAP): 613 fields_desc = [ByteEnumField("code", 2, _PPP_paptypes), 614 XByteField("id", 0), 615 FieldLenField("len", None, fmt="!H", length_of="message", 616 adjust=lambda _, x: x + 5), 617 FieldLenField("msg_len", None, fmt="B", length_of="message"), 618 StrLenField("message", "", length_from=lambda p: p.msg_len)] 619 620 def answers(self, other): 621 return isinstance(other, PPP_PAP_Request) and other.id == self.id 622 623 def mysummary(self): 624 res = "PAP-Ack" if self.code == 2 else "PAP-Nak" 625 if self.msg_len > 0: 626 res += self.sprintf(" msg=%PPP_PAP_Response.message%") 627 return res 628 629 630### Challenge Handshake Authentication protocol (RFC1994) 631 632_PPP_chaptypes = {1: "Challenge", 633 2: "Response", 634 3: "Success", 635 4: "Failure"} 636 637 638class PPP_CHAP(Packet): 639 name = "PPP Challenge Handshake Authentication Protocol" 640 fields_desc = [ByteEnumField("code", 1, _PPP_chaptypes), 641 XByteField("id", 0), 642 FieldLenField("len", None, fmt="!H", length_of="data", 643 adjust=lambda _, x: x + 4), 644 StrLenField("data", "", length_from=lambda p: p.len - 4)] 645 646 def answers(self, other): 647 return isinstance(other, PPP_CHAP_ChallengeResponse) and other.code == 2\ 648 and self.code in (3, 4) and self.id == other.id 649 650 @classmethod 651 def dispatch_hook(cls, _pkt=None, *_, **kargs): 652 code = None 653 if _pkt: 654 code = orb(_pkt[0]) 655 elif "code" in kargs: 656 code = kargs["code"] 657 if isinstance(code, six.string_types): 658 code = cls.fields_desc[0].s2i[code] 659 660 if code in (1, 2): 661 return PPP_CHAP_ChallengeResponse 662 return cls 663 664 def extract_padding(self, pay): 665 return "", pay 666 667 def mysummary(self): 668 if self.code == 3: 669 return self.sprintf("CHAP Success message=%PPP_CHAP.data%") 670 elif self.code == 4: 671 return self.sprintf("CHAP Failure message=%PPP_CHAP.data%") 672 673 674class PPP_CHAP_ChallengeResponse(PPP_CHAP): 675 fields_desc = [ByteEnumField("code", 1, _PPP_chaptypes), 676 XByteField("id", 0), 677 FieldLenField("len", None, fmt="!H", length_of="value", 678 adjust=lambda p, x: x + len(p.optional_name) + 5), 679 FieldLenField("value_size", None, fmt="B", length_of="value"), 680 XStrLenField("value", b"\0"*8, length_from=lambda p: p.value_size), 681 StrLenField("optional_name", "", length_from=lambda p: p.len - p.value_size - 5)] 682 683 def answers(self, other): 684 return isinstance(other, PPP_CHAP_ChallengeResponse) and other.code == 1\ 685 and self.code == 2 and self.id == other.id 686 687 def mysummary(self): 688 if self.code == 1: 689 return self.sprintf("CHAP challenge=0x%PPP_CHAP_ChallengeResponse.value% " + 690 "optional_name=%PPP_CHAP_ChallengeResponse.optional_name%") 691 elif self.code == 2: 692 return self.sprintf("CHAP response=0x%PPP_CHAP_ChallengeResponse.value% " + 693 "optional_name=%PPP_CHAP_ChallengeResponse.optional_name%") 694 else: 695 return PPP_CHAP.mysummary(self) 696 697 698bind_layers( Ether, PPPoED, type=0x8863) 699bind_layers( Ether, PPPoE, type=0x8864) 700bind_layers( CookedLinux, PPPoED, proto=0x8863) 701bind_layers( CookedLinux, PPPoE, proto=0x8864) 702bind_layers( PPPoE, PPP, code=0) 703bind_layers( HDLC, PPP, ) 704bind_layers( PPP, EAP, proto=0xc227) 705bind_layers( PPP, IP, proto=0x0021) 706bind_layers( PPP, IPv6, proto=0x0057) 707bind_layers( PPP, PPP_CHAP, proto=0xc223) 708bind_layers( PPP, PPP_IPCP, proto=0x8021) 709bind_layers( PPP, PPP_ECP, proto=0x8053) 710bind_layers( PPP, PPP_LCP, proto=0xc021) 711bind_layers( PPP, PPP_PAP, proto=0xc023) 712bind_layers( Ether, PPP_IPCP, type=0x8021) 713bind_layers( Ether, PPP_ECP, type=0x8053) 714bind_layers( GRE_PPTP, PPP, proto=0x880b) 715 716 717conf.l2types.register(DLT_PPP, PPP) 718conf.l2types.register(DLT_PPP_SERIAL, HDLC) 719conf.l2types.register(DLT_PPP_ETHER, PPPoE) 720