"Fossies" - the Fresh Open Source Software Archive 
Member "snort-2.9.17/src/dynamic-preprocessors/s7commplus/s7comm_decode.c" (16 Oct 2020, 4622 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "s7comm_decode.c" see the
Fossies "Dox" file reference documentation.
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License Version 2 as
4 * published by the Free Software Foundation. You may not use, modify or
5 * distribute this program under any other version of the GNU General
6 * Public License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 *
17 * Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved.
18 *
19 * Authors: Jeffrey Gu <jgu@cisco.com>, Pradeep Damodharan <prdamodh@cisco.com>
20 *
21 * Dynamic preprocessor for the S7comm protocol
22 *
23 */
24
25 /*
26 * This is the encapsulation of S7comm/S7comm-plus protocol:
27 * Ethernet | IP | TCP (server port 102) | TPKT | COTP | S7comm or S7comm-plus
28 */
29
30 #include "s7comm_decode.h"
31
32 /* TPKT header */
33 typedef struct _tpkt_header
34 {
35 uint8_t version;
36 uint8_t reserved;
37 uint16_t length;
38 } tpkt_header_t;
39
40 /* COTP header */
41 typedef struct _cotp_header
42 {
43 uint8_t length;
44 uint8_t pdu_type;
45 uint8_t tpdu_num;
46 } cotp_header_t;
47
48 /* S7commplus data structures */
49 typedef struct _s7commplus_header
50 {
51 uint8_t proto_id;
52 uint8_t proto_version;
53 uint16_t data_len;
54 } s7commplus_header_t;
55
56 #pragma pack(1)
57 typedef struct _s7commplus_data_hdr
58 {
59 uint8_t opcode;
60 uint16_t reserved_1;
61 uint16_t function;
62 uint16_t reserved_2;
63 } s7commplus_data_hdr_t;
64 #pragma pack()
65
66 static int S7commplusProtocolDecode(s7commplus_session_data_t *session, SFSnortPacket *packet)
67 {
68 const s7commplus_header_t* s7commplus_header;
69 const s7commplus_data_hdr_t* s7commplus_data_header;
70 int offset;
71
72 offset = sizeof(tpkt_header_t) + sizeof(cotp_header_t);
73
74 s7commplus_header = (const s7commplus_header_t*)(packet->payload + offset);
75 /* Set the session data. Swap byte order for 16-bit fields. */
76 session->s7commplus_proto_id = s7commplus_header->proto_id;
77 session->s7commplus_proto_version= s7commplus_header->proto_version;
78 session->s7commplus_data_len = ntohs(s7commplus_header->data_len);
79
80 /* V1 or V2 header packets */
81 if (s7commplus_header->proto_version <= 0x02)
82 offset += sizeof(s7commplus_header_t);
83 else
84 {
85 /* 33 byte Integrity part for V3 header packets */
86 offset += sizeof(s7commplus_header_t) + INTEGRITY_PART_LEN ;
87 }
88 s7commplus_data_header = (const s7commplus_data_hdr_t *)(packet->payload + offset);
89 /* Set the session data. Swap byte order for 16-bit fields. */
90 session->s7commplus_opcode = s7commplus_data_header->opcode;
91 session->s7commplus_reserved_1 = ntohs(s7commplus_data_header->reserved_1);
92 session->s7commplus_function = ntohs(s7commplus_data_header->function);
93 session->s7commplus_reserved_2 = ntohs(s7commplus_data_header->reserved_2);
94
95 return true;
96 }
97
98 int S7commplusDecode(s7commplus_config_t *config, SFSnortPacket *packet)
99 {
100 s7commplus_session_data_t *session;
101 const tpkt_header_t *tpkt_header;
102 const cotp_header_t *cotp_header;
103 const s7commplus_header_t *s7commplus_header;
104 uint16_t tpkt_length;
105
106 if (packet->payload_size < TPKT_MIN_HDR_LEN) {
107 memset(&session, 0, sizeof(session));
108 return false;
109 }
110
111 session = (s7commplus_session_data_t *)
112 _dpd.sessionAPI->get_application_data(packet->stream_session, PP_S7COMMPLUS);
113 session->s7commplus_proto_id = 0;
114
115 /* Lay the header struct over the payload */
116 tpkt_header = (const tpkt_header_t *) packet->payload;
117 cotp_header = (const cotp_header_t *) (packet->payload + sizeof(tpkt_header_t));
118 tpkt_length = ntohs(tpkt_header->length);
119
120 /* It might be COTP fragment data */
121 if ((tpkt_length == TPKT_MIN_HDR_LEN) || (tpkt_length == TPKT_MIN_DATA_HDR_LEN))
122 {
123 memset(&session, 0, sizeof(session));
124 return true;
125 }
126
127 /* It might be a TPKT/COTP packet for other purpose, e.g. connect */
128 if (cotp_header->length != COTP_HDR_LEN_FOR_S7COMMPLUS ||
129 cotp_header->pdu_type != COTP_HDR_PDU_TYPE_DATA)
130 {
131 memset(&session, 0, sizeof(session));
132 return true;
133 }
134
135 s7commplus_header = (const s7commplus_header_t *)(packet->payload +
136 sizeof(tpkt_header_t) + sizeof(cotp_header_t));
137
138 if (s7commplus_header->proto_id == S7COMMPLUS_PROTOCOL_ID)
139 {
140 return (S7commplusProtocolDecode(session, packet));
141 }
142 else
143 {
144 _dpd.alertAdd(GENERATOR_SPP_S7COMMPLUS, S7COMMPLUS_BAD_PROTO_ID, 1, 0, 3,
145 S7COMMPLUS_BAD_PROTO_ID_STR, 0);
146 return false;
147 }
148 }