10ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# This file is part of Scapy
20ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# Scapy is free software: you can redistribute it and/or modify
30ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# it under the terms of the GNU General Public License as published by
40ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# the Free Software Foundation, either version 2 of the License, or
50ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# any later version.
60ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter#
70ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# Scapy is distributed in the hope that it will be useful,
80ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# but WITHOUT ANY WARRANTY; without even the implied warranty of
90ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# GNU General Public License for more details.
110ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter#
120ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# You should have received a copy of the GNU General Public License
130ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# along with Scapy. If not, see <http://www.gnu.org/licenses/>.
140ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
150ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# author: <jellch@harris.com>
160ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
170ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# scapy.contrib.description = PPI
180ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# scapy.contrib.status = loads
190ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
200ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
210ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter"""
220ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterPPI (Per-Packet Information).
230ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter"""
24b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALETimport logging
25b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALETimport struct
26b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALET
27b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALET
280ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterfrom scapy.config import conf
29b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALETfrom scapy.data import DLT_EN10MB, DLT_IEEE802_11, DLT_PPI
300ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterfrom scapy.packet import *
310ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterfrom scapy.fields import *
320ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterfrom scapy.layers.l2 import Ether
330ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterfrom scapy.layers.dot11 import Dot11
340ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
350ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# Dictionary to map the TLV type to the class name of a sub-packet
360ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter_ppi_types = {}
370ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterdef addPPIType(id, value):
380ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    _ppi_types[id] = value
390ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterdef getPPIType(id, default="default"):
400ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    return _ppi_types.get(id, _ppi_types.get(default, None))
410ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
420ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
430ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter# Default PPI Field Header
440ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterclass PPIGenericFldHdr(Packet):
450ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    name = "PPI Field Header"
460ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    fields_desc = [ LEShortField('pfh_type', 0),
470ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter                    FieldLenField('pfh_length', None, length_of="value", fmt='<H', adjust=lambda p,x:x+4),
480ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter                    StrLenField("value", "", length_from=lambda p:p.pfh_length) ]
490ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
500ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    def extract_padding(self, p):
51aaf1370d4578765810d3789767c32b3d9d025d21gpotter        return b"",p
520ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
530ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterdef _PPIGuessPayloadClass(p, **kargs):
540ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    """ This function tells the PacketListField how it should extract the
550ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        TLVs from the payload.  We pass cls only the length string
560ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        pfh_len says it needs.  If a payload is returned, that means
570ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        part of the sting was unused.  This converts to a Raw layer, and
580ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        the remainder of p is added as Raw's payload.  If there is no
590ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        payload, the remainder of p is added as out's payload.
600ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    """
610ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    if len(p) >= 4:
620ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        t,pfh_len = struct.unpack("<HH", p[:4])
630ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        # Find out if the value t is in the dict _ppi_types.
640ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        # If not, return the default TLV class
650ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        cls = getPPIType(t, "default")
660ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        pfh_len += 4
670ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        out = cls(p[:pfh_len], **kargs)
680ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        if (out.payload):
690ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter            out.payload = conf.raw_layer(out.payload.load)
70aaf1370d4578765810d3789767c32b3d9d025d21gpotter            out.payload.underlayer = out
710ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter            if (len(p) > pfh_len):
720ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter                out.payload.payload = conf.padding_layer(p[pfh_len:])
73aaf1370d4578765810d3789767c32b3d9d025d21gpotter                out.payload.payload.underlayer = out.payload
740ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        elif (len(p) > pfh_len):
750ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter            out.payload = conf.padding_layer(p[pfh_len:])
76aaf1370d4578765810d3789767c32b3d9d025d21gpotter            out.payload.underlayer = out
770ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    else:
780ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        out = conf.raw_layer(p, **kargs)
790ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    return out
800ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
810ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
820ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
830ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
840ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotterclass PPI(Packet):
850ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    name = "PPI Packet Header"
860ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    fields_desc = [ ByteField('pph_version', 0),
870ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter                    ByteField('pph_flags', 0),
880ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter                    FieldLenField('pph_len', None, length_of="PPIFieldHeaders", fmt="<H", adjust=lambda p,x:x+8 ),
890ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter                    LEIntField('dlt', None),
900ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter                    PacketListField("PPIFieldHeaders", [],  _PPIGuessPayloadClass, length_from=lambda p:p.pph_len-8,) ]
910ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter    def guess_payload_class(self,payload):
920ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter        return conf.l2types.get(self.dlt, Packet.guess_payload_class(self, payload))
930ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
940ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter#Register PPI
950ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotteraddPPIType("default", PPIGenericFldHdr)
960ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
97b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALETconf.l2types.register(DLT_PPI, PPI)
980ef62bfe3120bcc901bbf38c7582d4d3645a733cgpotter
99b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALETbind_layers(PPI, Dot11, dlt=DLT_IEEE802_11)
100b4d6c78846baf0254ab9a7556ffcfad97280501aPierre LALETbind_layers(PPI, Ether, dlt=DLT_EN10MB)
101