diff options
author | Harald Welte <laforge@gnumonks.org> | 2013-02-27 19:05:34 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2013-02-27 19:05:34 +0100 |
commit | dd46f418be6a5f7cfc7d0d1e60f83f73edcb7743 (patch) | |
tree | 34f68f134973152059474834c08a72f4d7a60fe9 /src | |
parent | 821f3af2ac2d77f0f15bdea02c2f3efd0e1cf419 (diff) |
add new utility to take GPS and AIS messages and fwd them via UDP
this is useful if you wish to send them into gpsd, e.g.
Diffstat (limited to 'src')
-rw-r--r-- | src/util/Makefile.am | 7 | ||||
-rw-r--r-- | src/util/gps_fwd.c | 182 |
2 files changed, 188 insertions, 1 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 3d87a32..3697358 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS = -std=gnu99 -bin_PROGRAMS = libgsmd-tool cell_log +bin_PROGRAMS = libgsmd-tool cell_log gps_fwd libgsmd_tool_SOURCES = libgsmd-tool.c shell.c event.c pin.c atcmd.c \ $(top_srcdir)/src/gsmd/talloc.c @@ -13,4 +13,9 @@ cell_log_SOURCES = cell_log.c \ cell_log_LDADD = $(top_builddir)/src/libgsmd/libgsmd.la cell_log_LDFLAGS = -dynamic +gps_fwd_SOURCES = gps_fwd.c \ + $(top_srcdir)/src/gsmd/talloc.c +gps_fwd_LDADD = $(top_builddir)/src/libgsmd/libgsmd.la +gps_fwd_LDFLAGS = -dynamic + noinst_HEADERS = atcmd.h event.h pin.h shell.h diff --git a/src/util/gps_fwd.c b/src/util/gps_fwd.c new file mode 100644 index 0000000..3270c48 --- /dev/null +++ b/src/util/gps_fwd.c @@ -0,0 +1,182 @@ +/* GPS/AIS client extractor, forwad to gpsd via UDP + * + * (C) 2013 by Harald Welte <laforge@gnumonks.org> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <syslog.h> +#include <stdint.h> +#include <netdb.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include <netinet/in.h> + +#include <libgsmd/libgsmd.h> +#include <libgsmd/event.h> +#include <gsmd/usock.h> +#include <gsmd/ts0705.h> +#include <common/linux_list.h> + +#ifndef __GSMD__ +#define __GSMD__ +#include <gsmd/talloc.h> +#undef __GSMD__ +#endif + +static int out_fd = -1; +static FILE *outf; + +static int celllog_main(struct lgsm_handle *lgsmh) +{ + int rc; + char buf[8192+1]; + fd_set readset; + int gsm_fd = lgsm_fd(lgsmh); + + fcntl(gsm_fd, F_SETFD, O_NONBLOCK); + FD_ZERO(&readset); + + while (1) { + fd_set readset; + FD_SET(gsm_fd, &readset); + + rc = select(gsm_fd+1, &readset, NULL, NULL, NULL); + if (rc < 0) + break; + + if (FD_ISSET(gsm_fd, &readset)) { + /* we've received something on the gsmd socket, pass it + * on to the library */ + rc = read(gsm_fd, buf, sizeof(buf)); + if (rc <= 0) { + syslog(LOG_ERR, "ERROR reading from gsm_fd\n"); + break; + } + rc = lgsm_handle_packet(lgsmh, buf, rc); + if (rc < 0) + syslog(LOG_ERR, "ERROR processing packet: %d(%s)\n", rc, strerror(-rc)); + } + fflush(outf); + } + return 0; +} + +static int gps_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux) +{ + int rc; + + rc = fprintf(outf, "%s\r\n", aux->data); + if (rc < 0) { + syslog(LOG_ERR, "error %d during fprintf() on socket, aborting\n", rc); + exit(3); + } + + return 0; +} + + +/* more or less a copy form libosmocore, we could simply make this a + * dependency... */ +static int out_sock_init(uint16_t family, uint16_t type, uint8_t proto, + const char *host, uint16_t port) +{ + int fd = -1, rc; + struct addrinfo hints, *result, *rp; + char portbuf[16]; + + sprintf(portbuf, "%u", port); + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = family; + + rc = getaddrinfo(host, portbuf, &hints, &result); + if (rc != 0) { + syslog(LOG_ERR, "Error during getaddrinfo(%s:%d)\n", + host, port); + return -EINVAL; + } + + for (rp = result; rp != NULL; rp = rp->ai_next) { + + fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (fd < 0) + continue; + + rc = connect(fd, rp->ai_addr, rp->ai_addrlen); + if (rc != -1 || (rc == -1 && errno == EINPROGRESS)) + break; + + close(fd); + } + freeaddrinfo(result); + + if (rp == NULL) { + syslog(LOG_ERR, "unable to connect socket\n"); + return -ENODEV; + } + + return fd; +} + +int main(int argc, char **argv) +{ + static struct lgsm_handle *lgsmh; + char *host; + int port; + int rc; + + printf("gps_fwd - (C) 2013 by Harald Welte <laforge@gnumonks.org>.\n" + "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n"); + + if (argc < 3) { + fprintf(stderr, "You have to specify the remote hostname + port\n"); + exit(2); + } + + host = argv[1]; + port = atoi(argv[2]); + + openlog("gps_fwd", 0, LOG_LOCAL0); + + lgsmh = lgsm_init(LGSMD_DEVICE_GSMD); + if (!lgsmh) { + fprintf(stderr, "Can't connect to gsmd\n"); + exit(1); + } + + lgsm_evt_handler_register(lgsmh, GSMD_EVT_GPS, &gps_handler); + lgsm_evt_handler_register(lgsmh, GSMD_EVT_AIS, &gps_handler); + + out_fd = out_sock_init(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, host, port); + if (out_fd < 0) + exit(1); + + outf = fdopen(out_fd, "w"); + + celllog_main(lgsmh); + + exit(0); +} |