blob: 072a05a2b564af64ecf9749b917ea61419a99a1c [file] [log] [blame]
Harald Welteccea8dd2016-12-24 10:27:55 +01001/*
2 * (C) 2013-2016 by Harald Welte <laforge@gnumonks.org>
3 *
Harald Welte8ca17c62016-12-31 20:44:34 +01004 * originally based on earlier code from Dieter Spaar and Holger
Harald Welteccea8dd2016-12-24 10:27:55 +01005 * Freyther, though by now almost entirely rewritten. Nevertheless,
6 * thanks to Dieter and Holger!
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020022
23#include <stdlib.h>
Harald Weltef5d6fee2016-01-13 22:29:10 +010024#include <inttypes.h>
Holger Hans Peter Freyther93b625b2013-05-31 09:52:26 +020025#include <stddef.h>
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020026#include <stdio.h>
27#include <string.h>
Holger Hans Peter Freyther93b625b2013-05-31 09:52:26 +020028#include <time.h>
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020029
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <unistd.h>
33#include <errno.h>
Eric Wilda8ea2dc2020-05-04 16:27:00 +020034#include <signal.h>
35#include <getopt.h>
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020036
Harald Welte211dd6c2016-01-13 00:18:49 +010037#include <osmocom/core/msgb.h>
Harald Welte234b56b2016-12-23 23:44:19 +010038#include <osmocom/core/serial.h>
Harald Weltece2f3962016-12-30 15:48:22 +010039#include <osmocom/core/gsmtap_util.h>
40#include <osmocom/core/gsmtap.h>
Eric Wildacb80082020-12-09 04:24:13 +010041#include <osmocom/core/socket.h>
Eric Wild4846c502020-12-09 04:09:38 +010042#include <osmocom/core/logging.h>
Harald Welte211dd6c2016-01-13 00:18:49 +010043
Harald Weltebd448582016-12-23 23:41:14 +010044#include "diag_io.h"
Harald Weltefaea7542016-12-24 01:21:03 +010045#include "diag_log.h"
Harald Welte0e509162016-12-24 01:32:10 +010046#include "diag_msg.h"
Harald Weltedc2cafc2017-01-01 11:15:35 +010047#include "diag_cmd.h"
Harald Welte4ae09362017-01-07 15:54:41 +010048#include "diag_dpl.h"
Harald Welte84ec50f2016-12-24 10:16:00 +010049#include "protocol/protocol.h"
50#include "protocol/diagcmd.h"
Harald Welte4ae09362017-01-07 15:54:41 +010051#include "protocol/diag_log_gsm.h"
Harald Welte211dd6c2016-01-13 00:18:49 +010052
Eric Wilda8ea2dc2020-05-04 16:27:00 +020053struct diag_instance di;
54static char *serial_path = 0;
55static uint32_t cfg_flags = 0;
Eric Wildacb80082020-12-09 04:24:13 +010056static char *gsmtap_ip = "localhost";
Eric Wilda8ea2dc2020-05-04 16:27:00 +020057
Harald Welte272b4ae2016-12-23 23:28:28 +010058static void do_configure(struct diag_instance *di)
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020059{
Harald Weltef5d6fee2016-01-13 22:29:10 +010060 static uint8_t timestamp[] = { DIAG_TS_F };
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020061 static const uint8_t enable_evt_report[] = {
Harald Weltef5d6fee2016-01-13 22:29:10 +010062 DIAG_EVENT_REPORT_F, 0x01
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020063 };
64 static const uint8_t disable_evt_report[] = {
Harald Weltef5d6fee2016-01-13 22:29:10 +010065 DIAG_EVENT_REPORT_F, 0x00
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020066 };
Eric Wilda8ea2dc2020-05-04 16:27:00 +020067 static const uint8_t disable_log[] = {
68 DIAG_LOG_CONFIG_F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 };
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020070
Eric Wilda8ea2dc2020-05-04 16:27:00 +020071// diag_transceive_buf_ign(di, timestamp, sizeof(timestamp));
Harald Weltef1801992017-01-01 11:47:31 +010072 /* response: 3d 67 a8 81 d4 46 6d d9 00 */
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +020073
Holger Hans Peter Freyther93b625b2013-05-31 09:52:26 +020074 /* enable|disable the event report */
Eric Wilda8ea2dc2020-05-04 16:27:00 +020075#if 0
Harald Weltedc2cafc2017-01-01 11:15:35 +010076 diag_transceive_buf_ign(di, enable_evt_report, sizeof(enable_evt_report));
Harald Weltef5d6fee2016-01-13 22:29:10 +010077#else
Eric Wilda8ea2dc2020-05-04 16:27:00 +020078 diag_transceive_buf_ign(di, disable_log, sizeof(disable_log));
79 diag_msg_config_set_all_rt_mask(di, 0);
80// diag_transceive_buf_ign(di, disable_evt_report, sizeof(disable_evt_report));
Harald Weltef1801992017-01-01 11:47:31 +010081 /* response: 40 00 00 */
Harald Weltef5d6fee2016-01-13 22:29:10 +010082#endif
Eric Wilda8ea2dc2020-05-04 16:27:00 +020083
Eric Wilda8ea2dc2020-05-04 16:27:00 +020084// diag_msg_config_set_rt_mask(di, MSG_SSID_LINUX_DATA, 0xffffffff);
85// /* response: 5d 5d 04 41 00 41 00 01 00 ff ff ff ff */
86// diag_msg_config_set_rt_mask(di, MSG_SSID_DS_ATCOP, 0xffffffff);
87// /* response: 5d 5d 04 94 13 94 13 01 00 ff ff ff ff */
88// diag_msg_config_set_rt_mask(di, MSG_SSID_DS, 0xffffffff);
89// /* response: 5d 5d 04 88 13 88 13 01 00 ff ff ff ff */
90// //diag_msg_config_set_rt_mask(di, MSG_SSID_DS_IPA, 0xffffffff);
91// /* response: 5d 5d 04 a6 13 a6 13 01 00 ff ff ff ff */
92// diag_msg_config_set_rt_mask(di, MSG_SSID_DS_GPRS, 0xffffffff);
93// /* response: 5d 5d 04 91 13 91 13 01 00 ff ff ff ff */
94// diag_msg_config_set_rt_mask(di, MSG_SSID_DS_GSM, 0xffffffff);
95// diag_msg_config_set_rt_mask(di, MSG_SSID_DS_UMTS, 0xffffffff);
96// diag_msg_config_set_rt_mask(di, MSG_SSID_DS_SOCKETS, 0xffffffff);
97// diag_msg_config_set_rt_mask(di, MSG_SSID_DS_SIO, 0xffffffff);
98// diag_msg_config_set_rt_mask(di, MSG_SSID_DS_APPS, 0xffffffff);
99// diag_msg_config_set_rt_mask(di, MSG_SSID_DIAG, 0xffffffff);
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +0200100
Harald Weltefaea7542016-12-24 01:21:03 +0100101#if 0
Harald Weltef5d6fee2016-01-13 22:29:10 +0100102 printf("GSM\n");
103 struct msgb *msg = gen_log_config_set_mask(5, 1064);
104#if 0
105 for (int i = 0; i < 1064; i++)
106 log_config_set_mask_bit(msg, i);
107#endif
108
109 log_config_set_mask_bit(msg, LOG_GSM_RR_CONTROL_CHANNEL_PARAMS_C);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100110
Harald Weltef5d6fee2016-01-13 22:29:10 +0100111 log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_ACKNACK_PARAMS_VER2_C);
112 log_config_set_mask_bit(msg, LOG_GPRS_RLC_DL_ACKNACK_PARAMS_VER2_C);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100113 log_config_set_mask_bit(msg, LOG_EGPRS_RLC_DL_HEADER_C);
114 log_config_set_mask_bit(msg, LOG_EGPRS_RLC_UL_HEADER_C);
115
Harald Weltef5d6fee2016-01-13 22:29:10 +0100116 log_config_set_mask_bit(msg, LOG_GPRS_LLC_PERIODIC_STATS_C);
117
118 log_config_set_mask_bit(msg, LOG_GPRS_SNDCP_UL_TCP_HDR_C);
119 log_config_set_mask_bit(msg, LOG_GPRS_SNDCP_DL_TCP_HDR_C);
Harald Welte211dd6c2016-01-13 00:18:49 +0100120 log_config_set_mask_bit(msg, 546);
121 log_config_set_mask_bit(msg, 547);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100122 log_config_set_mask_bit(msg, LOG_EGPRS_MAC_UL_ACKNACK_C);
123 log_config_set_mask_bit(msg, LOG_EGPRS_MAC_DL_ACKNACK_C);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100124
Harald Weltedc2cafc2017-01-01 11:15:35 +0100125 diag_tranceive_msgb(di, msg);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100126
127 printf("WCDMA\n");
128 msg = gen_log_config_set_mask(4, 1064);
129#if 0
130 for (int i = 0; i < 1064; i++)
131 log_config_set_mask_bit(msg, i);
132#endif
133 log_config_set_mask_bit(msg, 0x125);
134 log_config_set_mask_bit(msg, 0x126);
135 log_config_set_mask_bit(msg, 0x127);
136 log_config_set_mask_bit(msg, 0x128);
137 log_config_set_mask_bit(msg, 0x129);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100138
Harald Weltedc2cafc2017-01-01 11:15:35 +0100139 diag_tranceive_msgb(di, msg);
Harald Weltefaea7542016-12-24 01:21:03 +0100140#else
141 diag_log_enable_all_supported(di);
142#endif
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +0200143}
144
Harald Welte4ae09362017-01-07 15:54:41 +0100145static void enable_pcap(struct diag_instance *di, uint8_t if_num)
146{
147 struct dpl_iid iid = { .flags = 0, .if_name = if_num,
148 .protocol = DIAG_DPL_IID_PROT_NET_IP,
149 .link_instance = 64 };
150#if 1
151 iid.flags &= ~DIAG_DPL_IID_FLAG_DIR_TX;
152 diag_dpl_set_if_log(di, if_num, iid, DIAG_DPL_IID_PROT_LINK_ANY);
153#else
154 iid.flags |= DIAG_DPL_IID_FLAG_DIR_TX;
155 diag_dpl_set_if_log(di, if_num, iid, DIAG_DPL_IID_PROT_LINK_ANY);
156#endif
157}
158
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200159
160static void signal_handler(int s)
161{
162 struct termios tio;
163 switch (s) {
164 case SIGINT:
165 case SIGTERM:
166 diag_log_disable_all_supported(&di);
167 /* graceful exit by immediate read timeout */
168 tcgetattr(di.fd, &tio);
169 tio.c_cflag &= CRTSCTS;
170 tio.c_cc[VMIN] = 0;
171 tio.c_cc[VTIME] = 1;
172 tcsetattr(di.fd, TCSANOW, &tio);
173// exit(0);
174 break;
175 default:
176 break;
177 }
178}
179
180static void print_help()
181{
182 printf( " Some useful help...\n"
183 " -h --help This help text\n"
184 " -s --serial-path path to modem serial port, i.e /dev/ttyUSB0\n"
185 " Any combination of the following output flags:\n"
186 " -G --gsmtap GSMTAP messages sent to localhost\n"
187 " -Q --qcomdbg plain QC DIAG GSMTAP messages\n"
188 " -H --hexdump console output of rx/tx messages\n"
Eric Wildacb80082020-12-09 04:24:13 +0100189 " -i --ip address the GSMTAP packets should be sent to (default 127.0.0.1)\n"
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200190 );
191}
192
193static void handle_options(int argc, char **argv)
194{
195 while (1) {
196 int option_index = 0, c;
197 static struct option long_options[] = {
198 { "help", 0, 0, 'h' },
199 { "gsmtap", 0, 0, 'G' },
200 { "qcomdbg", 0, 0, 'Q' },
201 { "hexdump", 0, 0, 'H' },
202 { "serial-path", 1, 0, 's' },
Eric Wildacb80082020-12-09 04:24:13 +0100203 { "ip", 1, 0, 'i' },
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200204 { 0, 0, 0, 0 }
205 };
206
Eric Wildacb80082020-12-09 04:24:13 +0100207 c = getopt_long(argc, argv, "hGQHs:i:", long_options, &option_index);
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200208 if (c == -1)
209 break;
210
211 switch (c) {
212 case 'h':
213 print_help();
214 exit(0);
215 case 'G':
216 cfg_flags |= DIAG_INST_F_GSMTAP_DECODED;
217 break;
218 case 'Q':
219 cfg_flags |= DIAG_INST_F_GSMTAP_DIAG;
220 break;
221 case 'H':
222 cfg_flags |= DIAG_INST_F_HEXDUMP;
223 break;
224 case 's':
225 serial_path = optarg;
226 break;
Eric Wildacb80082020-12-09 04:24:13 +0100227 case 'i':
228 gsmtap_ip = optarg;
229 break;
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200230 }
231 }
232}
233
Eric Wildacb80082020-12-09 04:24:13 +0100234/* special function that allows to bind to local nonlocal ips like 127.0.0.x with x != 1 */
235static int gsmtap_source_add_local_sink(struct gsmtap_inst *gti)
236{
237 int rc;
238 struct sockaddr_storage ss;
239 socklen_t ss_len = sizeof(ss);
240
241 if (gti->ofd_wq_mode)
242 return -1;
243
244 rc = getpeername(gsmtap_inst_fd(gti), (struct sockaddr *)&ss, &ss_len);
245 if (rc < 0)
246 return rc;
247
248 rc = osmo_sock_init_sa((struct sockaddr *)&ss, SOCK_DGRAM,
249 IPPROTO_UDP,
250 OSMO_SOCK_F_BIND |
251 OSMO_SOCK_F_UDP_REUSEADDR);
252 if (rc >= 0)
253 return rc;
254
255 return -ENODEV;
256}
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200257
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +0200258int main(int argc, char **argv)
259{
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200260 struct termios tio;
Harald Welte4e06b5c2016-12-23 22:56:06 +0100261 int i;
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200262 int rc;
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +0200263
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200264 handle_options(argc, argv);
Eric Wild4846c502020-12-09 04:09:38 +0100265 log_init(0,0);
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200266
267 if (!serial_path) {
268 printf("Invoke with %s -s PATH_TO_SERIAL\n", argv[0]);
269 return EXIT_FAILURE;
270 }
271 if (!cfg_flags) {
272 printf("no output options (-G/-Q/-H) specified?! exiting...\n");
Eric Wild58111312020-05-12 17:03:50 +0200273 print_help();
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +0200274 return EXIT_FAILURE;
275 }
276
Harald Welte272b4ae2016-12-23 23:28:28 +0100277 memset(&di, 0, sizeof(di));
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200278 di.fd = osmo_serial_init(serial_path, 921600);
279 if (di.fd < 0) {
280 printf("can't open serial port: errno %d\n", di.fd);
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +0200281 return EXIT_FAILURE;
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200282 }
283
284 /* blocking reads */
285 rc = tcgetattr(di.fd, &tio);
286 tio.c_cflag &= CRTSCTS;
287 tio.c_cc[VMIN] = 1;
288 tio.c_cc[VTIME] = 0;
289 rc = tcsetattr(di.fd, TCSANOW, &tio);
290
Eric Wildacb80082020-12-09 04:24:13 +0100291 di.gsmtap = gsmtap_source_init(gsmtap_ip, GSMTAP_UDP_PORT, 0);
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200292 if (di.gsmtap == 0) {
293 printf("error initializing gsmtap source!\n");
294 return EXIT_FAILURE;
295 }
296
297 di.flags = cfg_flags;
Eric Wildacb80082020-12-09 04:24:13 +0100298 rc = gsmtap_source_add_local_sink(di.gsmtap);
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200299 if (rc < 0) {
300 printf("error initializing gsmtap sink!\n");
301 return EXIT_FAILURE;
302 }
Harald Weltece2f3962016-12-30 15:48:22 +0100303
Harald Welte4ae09362017-01-07 15:54:41 +0100304 printf("\n===> CONFIGURING\n");
305
306 do_configure(&di);
Eric Wilda8ea2dc2020-05-04 16:27:00 +0200307// diag_dpl_get_sup_if(&di);
308// for (i = 1; i < 0x56; i++) {
309// diag_dpl_get_if_desc(&di, i);
310// enable_pcap(&di, i);
311// }
312
313 /* Handle keyboard interrupts */
314 signal(SIGINT, &signal_handler);
315 signal(SIGTERM, &signal_handler);
316 signal(SIGABRT, &signal_handler);
317 signal(SIGUSR1, &signal_handler);
318 signal(SIGUSR2, &signal_handler);
319
Harald Welte4ae09362017-01-07 15:54:41 +0100320
321 printf("\n===> ENTERING MAIN\n");
322
Harald Weltef5d6fee2016-01-13 22:29:10 +0100323 while (1) {
324 i++;
Harald Weltedc2cafc2017-01-01 11:15:35 +0100325 struct msgb *rx = diag_read_msg(&di);
326 if (rx)
327 diag_process_msg(&di, rx);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100328#if 0
329 /* some packets need to be explicitly requested and
330 * don't appear automatically */
331 if (i % 10 == 0) {
332 struct msgb *msg = diag_gsm_make_log_pack_req(LOG_GPRS_LLC_PDU_STATS_C , 0, 0);
333 printf("Requesting LLC stats...(%s)\n", osmo_hexdump(msgb_data(msg), msgb_length(msg)));
Harald Welte272b4ae2016-12-23 23:28:28 +0100334 diag_transmit_msgb(&di, msg);
Harald Weltef5d6fee2016-01-13 22:29:10 +0100335 }
336#endif
337
338 }
Martin Haukeb236aa72016-12-28 15:10:37 +0100339
340 return EXIT_SUCCESS;
Holger Hans Peter Freytherae73a052013-05-31 09:51:53 +0200341}