• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# This file is part of Scapy
2# Scapy is free software: you can redistribute it and/or modify
3# it under the terms of the GNU General Public License as published by
4# the Free Software Foundation, either version 2 of the License, or
5# any later version.
6#
7# Scapy is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10# GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with Scapy. If not, see <http://www.gnu.org/licenses/>.
14
15# Copyright (C) 2016 Gauthier Sebaux
16
17# scapy.contrib.description = ProfinetIO base layer
18# scapy.contrib.status = loads
19
20"""
21A simple and non exhaustive Profinet IO layer for scapy
22"""
23
24# Scapy imports
25from __future__ import absolute_import
26from scapy.all import Packet, bind_layers, Ether, UDP
27from scapy.fields import XShortEnumField
28from scapy.modules.six.moves import range
29
30# Some constants
31PNIO_FRAME_IDS = {
32    0x0020:"PTCP-RTSyncPDU-followup",
33    0x0080:"PTCP-RTSyncPDU",
34    0xFC01:"Alarm High",
35    0xFE01:"Alarm Low",
36    0xFEFC:"DCP-Hello-Req",
37    0xFEFD:"DCP-Get-Set",
38    0xFEFE:"DCP-Identify-ReqPDU",
39    0xFEFF:"DCP-Identify-ResPDU",
40    0xFF00:"PTCP-AnnouncePDU",
41    0xFF20:"PTCP-FollowUpPDU",
42    0xFF40:"PTCP-DelayReqPDU",
43    0xFF41:"PTCP-DelayResPDU-followup",
44    0xFF42:"PTCP-DelayFuResPDU",
45    0xFF43:"PTCP-DelayResPDU",
46    }
47for i in range(0x0100, 0x1000):
48    PNIO_FRAME_IDS[i] = "RT_CLASS_3"
49for i in range(0x8000, 0xC000):
50    PNIO_FRAME_IDS[i] = "RT_CLASS_1"
51for i in range(0xC000, 0xFC00):
52    PNIO_FRAME_IDS[i] = "RT_CLASS_UDP"
53for i in range(0xFF80, 0xFF90):
54    PNIO_FRAME_IDS[i] = "FragmentationFrameID"
55
56#################
57## PROFINET IO ##
58#################
59
60class ProfinetIO(Packet):
61    """Basic PROFINET IO dispatcher"""
62    fields_desc = [XShortEnumField("frameID", 0, PNIO_FRAME_IDS)]
63    overload_fields = {
64        Ether: {"type": 0x8892},
65        UDP: {"dport": 0x8892},
66        }
67
68    def guess_payload_class(self, payload):
69        # For frameID in the RT_CLASS_* range, use the RTC packet as payload
70        if (self.frameID >= 0x0100 and self.frameID < 0x1000) or \
71                (self.frameID >= 0x8000 and self.frameID < 0xFC00):
72            from scapy.contrib.pnio_rtc import PNIORealTime
73            return PNIORealTime
74        else:
75            return Packet.guess_payload_class(self, payload)
76
77bind_layers(Ether, ProfinetIO, type=0x8892)
78bind_layers(UDP, ProfinetIO, dport=0x8892)
79
80