/* GPS/AIS client extractor, forwad to gpsd via UDP * * (C) 2013 by Harald Welte * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __GSMD__ #define __GSMD__ #include #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 .\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); }