From 5bf1e15c55340f236d84f70d3d04c871403d3503 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 25 Dec 2017 18:22:18 +0100 Subject: abisip-find: add -l to list base stations instead of streaming replies To get an overview of what base stations are present in a network, particularly with many base stations being present, it is particularly useful to get a list of connected base stations instead of just output of received replies. Keep a sorted list of known base stations, which time out after 10 seconds. Print additions and removals, and total amount of replies received. On each change, print the entire list. Output a running total of replies received, to provide comfort to the reader that something is still happening, and to confirm that the shown listing is still up-to-date (updated on the same line by means of '\r'). It looks like: ----- Mon Dec 25 18:59:43 2017 0: MAC_Address='00:02:95:07:dc:bd' IP_Address='192.168.0.124' Unit_ID='1/1/1' Location_1='Unknown' Location_2='3GAP' Equipment_Version='237B015_C' Software_Version='unknown' Unit_Name='Unknown' Serial_Number='000295-0000152614' 1: MAC_Address='00:02:95:07:dd:57' IP_Address='192.168.0.15' Unit_ID='1/1/1' Location_1='Unknown' Location_2='3GAP' Equipment_Version='237B015_C' Software_Version='unknown' Unit_Name='Unknown' Serial_Number='000295-0000154153' Total: 2 RX: 11 ----- Mon Dec 25 19:00:12 2017 LOST: MAC_Address='00:02:95:07:dd:57' IP_Address='192.168.0.15' Unit_ID='1/1/1' Location_1='Unknown' Location_2='3GAP' Equipment_Version='237B015_C' Software_Version='unknown' Unit_Name='Unknown' Serial_Number='000295-0000154153' ----- Mon Dec 25 19:00:12 2017 0: MAC_Address='00:02:95:07:dc:bd' IP_Address='192.168.0.124' Unit_ID='1/1/1' Location_1='Unknown' Location_2='3GAP' Equipment_Version='237B015_C' Software_Version='unknown' Unit_Name='Unknown' Serial_Number='000295-0000152614' Total: 1 RX: 15 ----- Mon Dec 25 19:00:28 2017 New: MAC_Address='00:02:95:07:dd:57' IP_Address='192.168.0.15' Unit_ID='1/1/1' Location_1='Unknown' Location_2='3GAP' Equipment_Version='237B015_C' Software_Version='unknown' Unit_Name='Unknown' Serial_Number='000295-0000154153' ----- Mon Dec 25 19:00:28 2017 0: MAC_Address='00:02:95:07:dc:bd' IP_Address='192.168.0.124' Unit_ID='1/1/1' Location_1='Unknown' Location_2='3GAP' Equipment_Version='237B015_C' Software_Version='unknown' Unit_Name='Unknown' Serial_Number='000295-0000152614' 1: MAC_Address='00:02:95:07:dd:57' IP_Address='192.168.0.15' Unit_ID='1/1/1' Location_1='Unknown' Location_2='3GAP' Equipment_Version='237B015_C' Software_Version='unknown' Unit_Name='Unknown' Serial_Number='000295-0000154153' RX: 18 Change-Id: I4201876431029b303dbd10e46492228379c9782a --- src/ipaccess/abisip-find.c | 148 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 140 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ipaccess/abisip-find.c b/src/ipaccess/abisip-find.c index 46205dd20..2f8d80f16 100644 --- a/src/ipaccess/abisip-find.c +++ b/src/ipaccess/abisip-find.c @@ -25,17 +25,22 @@ #include #include #include +#include +#include #include #include +#include #include #include #include static struct { const char *ifname; + bool list_view; } cmdline_opts = { .ifname = NULL, + .list_view = false, }; static void print_help() @@ -44,6 +49,9 @@ static void print_help() printf("Usage: abisip-find [-l] []\n"); printf(" Specify the outgoing network interface,\n" " e.g. 'eth0'\n"); + printf(" -l --list-view Instead of printing received responses,\n" + " output a sorted list of currently present\n" + " base stations and change events.\n"); } static void handle_options(int argc, char **argv) @@ -52,10 +60,11 @@ static void handle_options(int argc, char **argv) int option_index = 0, c; static struct option long_options[] = { {"help", 0, 0, 'h'}, + {"list-view", 0, 0, 'l'}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "h", + c = getopt_long(argc, argv, "hl", long_options, &option_index); if (c == -1) break; @@ -64,6 +73,9 @@ static void handle_options(int argc, char **argv) case 'h': print_help(); exit(EXIT_SUCCESS); + case 'l': + cmdline_opts.list_view = true; + break; default: /* catch unknown options *as well as* missing arguments. */ fprintf(stderr, "Error in command line options. Exiting. Try --help.\n"); @@ -159,22 +171,137 @@ static int bcast_find(int fd) return sendto(fd, find_pkt, sizeof(find_pkt), 0, (struct sockaddr *) &sa, sizeof(sa)); } -static int parse_response(unsigned char *buf, int len) +static char *parse_response(void *ctx, unsigned char *buf, int len) { uint8_t t_len; uint8_t t_tag; uint8_t *cur = buf; + char *out = talloc_zero_size(ctx, 512); while (cur < buf + len) { t_len = *cur++; t_tag = *cur++; - printf("%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); + out = talloc_asprintf_append(out, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); cur += t_len; } - printf("\n"); - return 0; + + return out; +} + +struct base_station { + struct llist_head entry; + char *line; + time_t timestamp; +}; + +LLIST_HEAD(base_stations); + +void *ctx = NULL; + +void print_timestamp() +{ + time_t now = time(NULL); + printf("\n\n----- %s\n", ctime(&now)); +} + +struct base_station *base_station_parse(unsigned char *buf, int len) +{ + struct base_station *new_bs = talloc_zero(ctx, struct base_station); + new_bs->line = parse_response(new_bs, buf, len); + new_bs->timestamp = time(NULL); + return new_bs; +} + +bool base_stations_add(struct base_station *new_bs) +{ + struct base_station *bs; + + llist_for_each_entry(bs, &base_stations, entry) { + int c = strcmp(new_bs->line, bs->line); + if (!c) { + /* entry already exists. */ + bs->timestamp = new_bs->timestamp; + return false; + } + + if (c < 0) { + /* found the place to add the entry */ + break; + } + } + + print_timestamp(); + printf("New:\n%s\n", new_bs->line); + + llist_add_tail(&new_bs->entry, &bs->entry); + return true; +} + +bool base_stations_timeout() +{ + struct base_station *bs, *next_bs; + time_t now = time(NULL); + bool changed = false; + + llist_for_each_entry_safe(bs, next_bs, &base_stations, entry) { + if (now - bs->timestamp < 10) + continue; + print_timestamp(); + printf("LOST:\n%s\n", bs->line); + + llist_del(&bs->entry); + talloc_free(bs); + changed = true; + } + return changed; +} + +void base_stations_print() +{ + struct base_station *bs; + int count = 0; + + print_timestamp(); + llist_for_each_entry(bs, &base_stations, entry) { + printf("%3d: %s\n", count, bs->line); + count++; + } + printf("\nTotal: %d\n", count); +} + +static void base_stations_bump(bool known_changed) +{ + bool changed = known_changed; + if (base_stations_timeout()) + changed = true; + + if (changed) + base_stations_print(); +} + +static void handle_response(unsigned char *buf, int len) +{ + static unsigned int responses = 0; + responses++; + + if (cmdline_opts.list_view) { + bool changed = false; + struct base_station *bs = base_station_parse(buf, len); + if (base_stations_add(bs)) + changed = true; + else + talloc_free(bs); + base_stations_bump(changed); + printf("RX: %u \r", responses); + fflush(stdout); + } else { + char *line = parse_response(ctx, buf, len); + printf(line); + printf("\n"); + talloc_free(line); + } } static int read_response(int fd) @@ -195,7 +322,8 @@ static int read_response(int fd) if (buf[4] != IPAC_MSGT_ID_RESP) return 0; - return parse_response(buf+6, len-6); + handle_response(buf+6, len-6); + return 0; } static int bfd_cb(struct osmo_fd *bfd, unsigned int flags) @@ -217,6 +345,8 @@ static void timer_cb(void *_data) bfd->when |= BSC_FD_WRITE; + base_stations_bump(false); + osmo_timer_schedule(&timer, 5, 0); } @@ -231,8 +361,10 @@ int main(int argc, char **argv) handle_options(argc, argv); if (!cmdline_opts.ifname) - fprintf(stdout, "you might need to specify the outgoing\n" - " network interface, e.g. ``%s eth0''\n", argv[0]); + fprintf(stdout, "- You might need to specify the outgoing\n" + " network interface, e.g. ``%s eth0''\n", argv[0]); + if (!cmdline_opts.list_view) + fprintf(stdout, "- You may find the --list-view option convenient.\n"); bfd.cb = bfd_cb; bfd.when = BSC_FD_READ | BSC_FD_WRITE; -- cgit v1.2.3