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