1 /*
2  * someip.c
3  *
4  * Copyright (C) 2016 Sorin Zamfir <sorin.zamfir@yahoo.com>
5  *
6  * This file is part of nDPI, an open source deep packet inspection
7  * library based on the OpenDPI and PACE technology by ipoque GmbH
8  *
9  * nDPI is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your omessage_typeion) any later version.
13  *
14  * nDPI is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with nDPI.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23 
24 #include "ndpi_protocol_ids.h"
25 
26 #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_SOMEIP
27 
28 #include "ndpi_api.h"
29 
30 enum SOMEIP_MESSAGE_TYPES {
31   SOMEIP_REQUEST = 0x00,
32   SOMEIP_REQUEST_NO_RETURN = 0x01,
33   SOMEIP_NOTIFICATION = 0x02,
34   SOMEIP_REQUEST_ACK = 0x40,
35   SOMEIP_REQUEST_NO_RETURN_ACK = 0x41,
36   SOMEIP_NOTIFICATION_ACK = 0x42,
37   SOMEIP_RESPONSE = 0x80,
38   SOMEIP_ERROR = 0x81,
39   SOMEIP_RESPONSE_ACK = 0xc0,
40   SOMEIP_ERROR_ACK = 0xc1
41 };
42 
43 enum SOMEIP_RETURN_CODES {
44   E_OK = 0x00,
45   E_NOT_OK = 0x01,
46   E_UNKNOWN_SERVICE = 0x02,
47   E_UNKNOWN_METHOD = 0x03,
48   E_NOT_READY = 0x04,
49   E_NOT_REACHABLE = 0x05,
50   E_TIMEOUT = 0x06,
51   E_WRONG_PROTOCOL_VERSION = 0x07,
52   E_WRONG_INTERFACE_VERSION = 0x08,
53   E_MALFORMED_MESSAGE = 0x09,
54   E_WRONG_MESSAGE_TYPE = 0x0a,
55   E_RETURN_CODE_LEGAL_THRESHOLD = 0x40  //return codes from 0x40 (inclusive) and upwards are illegal.
56 };
57 
58 enum SPECIAL_MESSAGE_IDS {
59   MSG_MAGIC_COOKIE = 0xffff0000,
60   MSG_MAGIC_COOKIE_ACK = 0xffff8000,
61   MSG_SD = 0xffff8100
62 };
63 
64 enum PROTOCOL_VERSION{
65   LEGAL_PROTOCOL_VERSION = 0x01
66 };
67 
68 enum MAGIC_COOKIE_CONSTANTS{
69   MC_REQUEST_ID = 0xDEADBEEF,
70   MC_LENGTH = 0x08,
71   MC_INTERFACE_VERSION = 0x01
72 };
73 
74 enum DEFAULT_PROTOCOL_PORTS{
75   PORT_DEFAULT_CLIENT = 30491,
76   PORT_DEFAULT_SERVER = 30501,
77   PORT_DEFAULT_SD = 30490
78 };
79 
80 /**
81  * Entry point when protocol is identified.
82  */
ndpi_int_someip_add_connection(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)83 static void ndpi_int_someip_add_connection (struct ndpi_detection_module_struct *ndpi_struct,
84 					    struct ndpi_flow_struct *flow)
85 {
86   ndpi_set_detected_protocol(ndpi_struct,flow,NDPI_PROTOCOL_SOMEIP,NDPI_PROTOCOL_UNKNOWN);
87   NDPI_LOG_INFO(ndpi_struct, "found SOME/IP\n");
88 }
89 
someip_data_cover_32(const u_int8_t * data)90 static u_int32_t someip_data_cover_32(const u_int8_t *data)
91 {
92   u_int32_t value;
93 
94   memcpy(&value,data,sizeof(u_int32_t));
95 
96   return value;
97 }
98 /**
99  * Dissector function that searches SOME/IP headers
100  */
ndpi_search_someip(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)101 void ndpi_search_someip (struct ndpi_detection_module_struct *ndpi_struct,
102 			 struct ndpi_flow_struct *flow)
103 {
104   const struct ndpi_packet_struct *packet = &flow->packet;
105 
106   if (packet->payload_packet_len < 16) {
107     NDPI_LOG(NDPI_PROTOCOL_SOMEIP, ndpi_struct, NDPI_LOG_DEBUG,
108 	     "Excluding SOME/IP .. mandatory header not found (not enough data for all fields)\n");
109     NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
110     return;
111   }
112 
113   //####Maybe check carrier protocols?####
114 
115   NDPI_LOG_DBG(ndpi_struct, "search SOME/IP\n");
116 
117   if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_UNKNOWN) {
118     return;
119   }
120 
121   //we extract the Message ID and Request ID and check for special cases later
122   u_int32_t message_id = ntohl(someip_data_cover_32(&packet->payload[0]));
123   u_int32_t request_id = ntohl(someip_data_cover_32(&packet->payload[8]));
124 
125   NDPI_LOG_DBG2(ndpi_struct, "====>>>> SOME/IP Message ID: %08x [len: %u]\n",
126 	   message_id, packet->payload_packet_len);
127   if (packet->payload_packet_len < 16) {
128     NDPI_LOG_DBG(ndpi_struct, "Excluding SOME/IP .. mandatory header not found\n");
129     NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
130     return;
131   }
132 
133   //####Maximum packet size in SOMEIP depends on the carrier protocol, and I'm not certain how well enforced it is, so let's leave that for round 2####
134 
135   // we extract the remaining length
136   u_int32_t someip_len = ntohl(someip_data_cover_32(&packet->payload[4]));
137   if (packet->payload_packet_len != (someip_len + 8)) {
138     NDPI_LOG_DBG(ndpi_struct, "Excluding SOME/IP .. Length field invalid!\n");
139     NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
140     return;
141   }
142 
143   u_int8_t protocol_version = (u_int8_t) (packet->payload[12]);
144   NDPI_LOG_DBG2(ndpi_struct,"====>>>> SOME/IP protocol version: [%d]\n",protocol_version);
145   if (protocol_version != LEGAL_PROTOCOL_VERSION){
146     NDPI_LOG_DBG(ndpi_struct, "Excluding SOME/IP .. invalid protocol version!\n");
147     NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
148     return;
149   }
150 
151   u_int8_t interface_version = (packet->payload[13]);
152 
153   u_int8_t message_type = (u_int8_t) (packet->payload[14]);
154   NDPI_LOG_DBG2(ndpi_struct,"====>>>> SOME/IP message type: [%d]\n",message_type);
155 
156   if ((message_type != SOMEIP_REQUEST) && (message_type != SOMEIP_REQUEST_NO_RETURN) && (message_type != SOMEIP_NOTIFICATION) && (message_type != SOMEIP_REQUEST_ACK) &&
157       (message_type != SOMEIP_REQUEST_NO_RETURN_ACK) && (message_type != SOMEIP_NOTIFICATION_ACK) && (message_type != SOMEIP_RESPONSE) &&
158       (message_type != SOMEIP_ERROR) && (message_type != SOMEIP_RESPONSE_ACK) && (message_type != SOMEIP_ERROR_ACK)) {
159     NDPI_LOG_DBG(ndpi_struct, "Excluding SOME/IP .. invalid message type!\n");
160     NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
161     return;
162   }
163 
164   u_int8_t return_code = (u_int8_t) (packet->payload[15]);
165   NDPI_LOG_DBG2(ndpi_struct,"====>>>> SOME/IP return code: [%d]\n", return_code);
166   if ((return_code >= E_RETURN_CODE_LEGAL_THRESHOLD)) {
167     NDPI_LOG_DBG(ndpi_struct, "Excluding SOME/IP .. invalid return code!\n");
168     NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
169     return;
170   }
171 
172   if (message_id == MSG_MAGIC_COOKIE){
173     if ((someip_len == MC_LENGTH) && (request_id == MC_REQUEST_ID) && (interface_version == MC_INTERFACE_VERSION) &&
174 	(message_type == SOMEIP_REQUEST_NO_RETURN) && (return_code == E_OK)){
175       NDPI_LOG_DBG2(ndpi_struct, "found SOME/IP Magic Cookie 0x%x\n",message_type);
176       ndpi_int_someip_add_connection(ndpi_struct, flow);
177       return;
178     }
179     else{
180       NDPI_LOG_DBG(ndpi_struct, "Excluding SOME/IP, invalid header for Magic Cookie\n");
181       NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
182       return;
183     }
184   }
185 
186   if (message_id == MSG_MAGIC_COOKIE_ACK){
187     if ((someip_len == MC_LENGTH) && (request_id == MC_REQUEST_ID) && (interface_version == MC_INTERFACE_VERSION) &&
188 	(message_type == SOMEIP_REQUEST_NO_RETURN) && (return_code == E_OK)){
189       NDPI_LOG_DBG2(ndpi_struct, "found SOME/IP Magic Cookie ACK 0x%x\n",message_type);
190       ndpi_int_someip_add_connection(ndpi_struct, flow);
191       return;
192     }
193     else{
194       NDPI_LOG_DBG(ndpi_struct, "Excluding SOME/IP, invalid header for Magic Cookie ACK\n");
195       NDPI_ADD_PROTOCOL_TO_BITMASK(flow->excluded_protocol_bitmask, NDPI_PROTOCOL_SOMEIP);
196       return;
197     }
198   }
199 
200   if (message_id == MSG_SD){
201     NDPI_LOG_DBG2(ndpi_struct, "SOME/IP-SD currently not supported [%d]\n", message_type);
202   }
203 
204   //Filtering by port.
205   //This check is NOT a 100% thing - these ports are mentioned in the documentation but the documentation also states they haven't been approved by IANA yet, and that the user is free to use different ports.
206   //This is is PURELY for demo purposes and the rest of the check must be filled in later on!
207   if (packet->l4_protocol == IPPROTO_UDP){
208     if ((packet->udp->dest == ntohs(PORT_DEFAULT_CLIENT)) || (packet->udp->dest == ntohs(PORT_DEFAULT_SERVER)) || (packet->udp->dest == ntohs(PORT_DEFAULT_SD))) {
209       ndpi_int_someip_add_connection(ndpi_struct, flow);
210       return;
211     }
212   }
213   if (packet->l4_protocol == IPPROTO_TCP){
214     if ((packet->tcp->dest == ntohs(PORT_DEFAULT_CLIENT)) || (packet->tcp->dest == ntohs(PORT_DEFAULT_SERVER))) {
215       ndpi_int_someip_add_connection(ndpi_struct, flow);
216       return;
217     }
218   }
219 
220   NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
221 }
222 /**
223  * Entry point for the ndpi library
224  */
init_someip_dissector(struct ndpi_detection_module_struct * ndpi_struct,u_int32_t * id,NDPI_PROTOCOL_BITMASK * detection_bitmask)225 void init_someip_dissector (struct ndpi_detection_module_struct *ndpi_struct,
226 			    u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask)
227 {
228   ndpi_set_bitmask_protocol_detection ("SOME/IP", ndpi_struct, detection_bitmask, *id,
229 				       NDPI_PROTOCOL_SOMEIP,
230 				       ndpi_search_someip,
231 				       NDPI_SELECTION_BITMASK_PROTOCOL_V4_V6_TCP_OR_UDP_WITH_PAYLOAD,
232 				       SAVE_DETECTION_BITMASK_AS_UNKNOWN, ADD_TO_DETECTION_BITMASK);
233   *id +=1;
234 }
235 
236 
237