"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 }