diff --git a/README b/README index 66179a1..c8d9987 100644 --- a/README +++ b/README @@ -16,6 +16,11 @@ This requires tcpdump, as well as the required permissions to capture, i.e. on ubuntu this can be conveniently achieved by sudo setcap cap_net_raw,cap_net_admin=ep /usr/sbin/tcpdump +In order to distinguish multiple different modems in the capture file +passing a GSMTAP destination ip is possible with the -i parameter, i.e. +./capture.sh -s /dev/ttyUSB0 -f outfilename.pcap -i 127.0.0.4 +This will "just work" on linux, since there is a default 127.0.0.0/8 route. + Additionally wireshark needs Edit->Preferences->Protocols->NAS-EPS "Force dissect as plain EPS" set to true, since capturing encrypted NAS messages is fairly useless (although possible), so unencrypted diff --git a/capture.sh b/capture.sh index 299df69..5ea53eb 100755 --- a/capture.sh +++ b/capture.sh @@ -3,6 +3,7 @@ while [[ "$#" -gt 0 ]]; do case $1 in -s|--serialpath) serialpath="$2"; shift ;; + -i|--ip) gsmtapip="$2"; shift ;; -f|--filename) filename="$2"; shift ;; -Q|--qcdebug) qcdebug=1 ;; *) echo "unknown parameter: $1"; exit 1 ;; @@ -10,8 +11,16 @@ while [[ "$#" -gt 0 ]]; do shift done -killall tcpdump +#killall tcpdump + +if [ -n "$gsmtapip" ]; then +tcpdump -i any udp port 4729 and dst $gsmtapip -w $filename & +tcpdump_pid=$! +./src/osmo-qcdiag-log -s $serialpath -G -i $gsmtapip +else tcpdump -i any udp port 4729 -w $filename & tcpdump_pid=$! ./src/osmo-qcdiag-log -s $serialpath -G +fi + kill -9 $tcpdump_pid diff --git a/src/osmo-qcdiag-log.c b/src/osmo-qcdiag-log.c index 89f9164..072a05a 100644 --- a/src/osmo-qcdiag-log.c +++ b/src/osmo-qcdiag-log.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include "diag_io.h" @@ -52,6 +53,7 @@ struct diag_instance di; static char *serial_path = 0; static uint32_t cfg_flags = 0; +static char *gsmtap_ip = "localhost"; static void do_configure(struct diag_instance *di) { @@ -184,6 +186,7 @@ static void print_help() " -G --gsmtap GSMTAP messages sent to localhost\n" " -Q --qcomdbg plain QC DIAG GSMTAP messages\n" " -H --hexdump console output of rx/tx messages\n" + " -i --ip address the GSMTAP packets should be sent to (default 127.0.0.1)\n" ); } @@ -197,10 +200,11 @@ static void handle_options(int argc, char **argv) { "qcomdbg", 0, 0, 'Q' }, { "hexdump", 0, 0, 'H' }, { "serial-path", 1, 0, 's' }, + { "ip", 1, 0, 'i' }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "hGQHs:", long_options, &option_index); + c = getopt_long(argc, argv, "hGQHs:i:", long_options, &option_index); if (c == -1) break; @@ -220,10 +224,36 @@ static void handle_options(int argc, char **argv) case 's': serial_path = optarg; break; + case 'i': + gsmtap_ip = optarg; + break; } } } +/* special function that allows to bind to local nonlocal ips like 127.0.0.x with x != 1 */ +static int gsmtap_source_add_local_sink(struct gsmtap_inst *gti) +{ + int rc; + struct sockaddr_storage ss; + socklen_t ss_len = sizeof(ss); + + if (gti->ofd_wq_mode) + return -1; + + rc = getpeername(gsmtap_inst_fd(gti), (struct sockaddr *)&ss, &ss_len); + if (rc < 0) + return rc; + + rc = osmo_sock_init_sa((struct sockaddr *)&ss, SOCK_DGRAM, + IPPROTO_UDP, + OSMO_SOCK_F_BIND | + OSMO_SOCK_F_UDP_REUSEADDR); + if (rc >= 0) + return rc; + + return -ENODEV; +} int main(int argc, char **argv) { @@ -258,15 +288,14 @@ int main(int argc, char **argv) tio.c_cc[VTIME] = 0; rc = tcsetattr(di.fd, TCSANOW, &tio); - - di.gsmtap = gsmtap_source_init("localhost", GSMTAP_UDP_PORT, 0); + di.gsmtap = gsmtap_source_init(gsmtap_ip, GSMTAP_UDP_PORT, 0); if (di.gsmtap == 0) { printf("error initializing gsmtap source!\n"); return EXIT_FAILURE; } di.flags = cfg_flags; - rc = gsmtap_source_add_sink(di.gsmtap); + rc = gsmtap_source_add_local_sink(di.gsmtap); if (rc < 0) { printf("error initializing gsmtap sink!\n"); return EXIT_FAILURE;