1 /*
2 * rx.c
3 *
4 * Copyright (C) 2012-21 - ntop.org
5 *
6 * Giovanni Mascellani <gio@debian.org>
7 *
8 * This file is part of nDPI, an open source deep packet inspection
9 * library based on the OpenDPI and PACE technology by ipoque GmbH
10 *
11 * nDPI is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * nDPI is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with nDPI. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25 #include "ndpi_protocol_ids.h"
26
27
28 #define NDPI_CURRENT_PROTO NDPI_PROTOCOL_RX
29
30 #include "ndpi_api.h"
31
32 /* See http://web.mit.edu/kolya/afs/rx/rx-spec for protocol description. */
33
34 /* The should be no need for explicit packing, but just in case... */
35 PACK_ON
36 struct ndpi_rx_header {
37 u_int32_t conn_epoch;
38 u_int32_t conn_id;
39 u_int32_t call_number;
40 u_int32_t sequence_number;
41 u_int32_t serial_number;
42 u_int8_t type;
43 u_int8_t flags;
44 u_int8_t status;
45 u_int8_t security;
46 u_int16_t checksum;
47 u_int16_t service_id;
48 } PACK_OFF;
49
50 /* Type values */
51 #define DATA 1
52 #define ACK 2
53 #define BUSY 3
54 #define ABORT 4
55 #define ACKALL 5
56 #define CHALLENGE 6
57 #define RESPONSE 7
58 #define DEBUG 8
59 #define PARAM_1 9
60 #define PARAM_2 10
61 #define PARAM_3 11
62 #define PARAMS_4 12
63 #define VERS 13
64
65 /* Flags values */
66 #define EMPTY 0
67 #define CLIENT_INIT_1 1
68 #define REQ_ACK 2
69 #define PLUS_0 3
70 #define LAST_PKT 4
71 #define PLUS_1 5
72 #define PLUS_2 6
73 #define MORE_1 9
74 #define CLIENT_INIT_2 33
75
76
77
ndpi_check_rx(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)78 void ndpi_check_rx(struct ndpi_detection_module_struct *ndpi_struct,
79 struct ndpi_flow_struct *flow)
80 {
81 struct ndpi_packet_struct *packet = &flow->packet;
82 u_int32_t payload_len = packet->payload_packet_len;
83
84 NDPI_LOG_DBG2(ndpi_struct, "RX: pck: %d, dir[0]: %d, dir[1]: %d\n",
85 flow->packet_counter, flow->packet_direction_counter[0], flow->packet_direction_counter[1]);
86
87 /* Check that packet is long enough */
88 if (payload_len < sizeof(struct ndpi_rx_header)) {
89 NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
90 return;
91 }
92
93 struct ndpi_rx_header *header = (struct ndpi_rx_header*) packet->payload;
94
95 /**
96 * Useless check: a session could be detected also after it starts
97 * and this check limit the correct detection for -d option (disable guess)
98 * TODO - maybe to improve
99 **/
100 /* Check whether the packet has counters beginning from one; the
101 Sequence Number can be zero if the packet is just an ACK. */
102 /* if ((ntohl(header->sequence_number) | 1) != 1 || ntohl(header->serial_number) != 1) */
103
104
105 /**
106 * Check the TYPE and FLAGS fields of an RX packet header.
107 * This check is necessary because we could detect an RX session already begun
108 **/
109
110 /* TYPE field */
111 if((header->type < DATA) || (header->type > VERS)) {
112 NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
113 return;
114 }
115
116 /* FLAGS fields */
117 if(header->flags == EMPTY || header->flags == LAST_PKT ||
118 header->flags == PLUS_0 || header->flags == PLUS_1 ||
119 header->flags == PLUS_2 || header->flags == REQ_ACK ||
120 header->flags == MORE_1 || header->flags == CLIENT_INIT_1 ||
121 header->flags == CLIENT_INIT_2) {
122
123 /* TYPE and FLAGS combo */
124 switch(header->type)
125 {
126 case DATA:
127 if(header->flags == LAST_PKT || header->flags == EMPTY ||
128 header->flags == PLUS_0 || header->flags == PLUS_1 ||
129 header->flags == PLUS_2 || header->flags == REQ_ACK ||
130 header->flags == MORE_1)
131 goto security;
132 /* Fall-through */
133 case ACK:
134 if(header->flags == CLIENT_INIT_1 || header->flags == CLIENT_INIT_2 ||
135 header->flags == EMPTY)
136 goto security;
137 /* Fall-through */
138 case CHALLENGE:
139 if(header->flags == EMPTY || header->call_number == 0)
140 goto security;
141 /* Fall-through */
142 case RESPONSE:
143 if(header->flags == EMPTY || header->call_number == 0)
144 goto security;
145 /* Fall-through */
146 case ACKALL:
147 if(header->flags == EMPTY)
148 goto security;
149 /* Fall-through */
150 case BUSY:
151 goto security;
152 case ABORT:
153 goto security;
154 case DEBUG:
155 goto security;
156 case PARAM_1:
157 goto security;
158 case PARAM_2:
159 goto security;
160 case PARAM_3:
161 goto security;
162 case VERS:
163 goto security;
164 default:
165 NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
166 return;
167 } // switch
168 } else { // FLAG
169 NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
170 return;
171 }
172
173 security:
174 /* SECURITY field */
175 if(header->security > 3)
176 {
177 NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
178 return;
179 }
180
181 /* If we have already seen one packet in the other direction, then
182 the two must have matching connection numbers. Otherwise store
183 them. */
184 if(flow->packet_direction_counter[!packet->packet_direction] != 0)
185 {
186 if (flow->l4.udp.rx_conn_epoch == header->conn_epoch &&
187 flow->l4.udp.rx_conn_id == header->conn_id)
188 {
189 NDPI_LOG_INFO(ndpi_struct, "found RX\n");
190 ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_RX, NDPI_PROTOCOL_UNKNOWN);
191 }
192 /* https://www.central.org/frameless/numbers/rxservice.html. */
193 else
194 {
195 NDPI_EXCLUDE_PROTO(ndpi_struct, flow);
196 return;
197 }
198 } else {
199 flow->l4.udp.rx_conn_epoch = header->conn_epoch;
200 flow->l4.udp.rx_conn_id = header->conn_id;
201 {
202 NDPI_LOG_INFO(ndpi_struct, "found RX\n");
203 ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_RX, NDPI_PROTOCOL_UNKNOWN);
204 }
205 }
206 }
207
ndpi_search_rx(struct ndpi_detection_module_struct * ndpi_struct,struct ndpi_flow_struct * flow)208 void ndpi_search_rx(struct ndpi_detection_module_struct *ndpi_struct,
209 struct ndpi_flow_struct *flow)
210 {
211 struct ndpi_packet_struct *packet = &flow->packet;
212
213 NDPI_LOG_DBG(ndpi_struct, "search RX\n");
214 if (packet->detected_protocol_stack[0] != NDPI_PROTOCOL_RX) {
215 ndpi_check_rx(ndpi_struct, flow);
216 }
217 }
218
init_rx_dissector(struct ndpi_detection_module_struct * ndpi_struct,u_int32_t * id,NDPI_PROTOCOL_BITMASK * detection_bitmask)219 void init_rx_dissector(struct ndpi_detection_module_struct *ndpi_struct,
220 u_int32_t *id,
221 NDPI_PROTOCOL_BITMASK *detection_bitmask)
222 {
223 ndpi_set_bitmask_protocol_detection("RX", ndpi_struct, detection_bitmask, *id,
224 NDPI_PROTOCOL_RX,
225 ndpi_search_rx,
226 NDPI_SELECTION_BITMASK_PROTOCOL_UDP_WITH_PAYLOAD,
227 SAVE_DETECTION_BITMASK_AS_UNKNOWN,
228 ADD_TO_DETECTION_BITMASK);
229
230 *id += 1;
231 }
232
233