diff options
-rw-r--r-- | src/libcharon/plugins/lookip/.gitignore | 1 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/Makefile.am | 3 | ||||
-rw-r--r-- | src/libcharon/plugins/lookip/lookip.c | 209 |
3 files changed, 213 insertions, 0 deletions
diff --git a/src/libcharon/plugins/lookip/.gitignore b/src/libcharon/plugins/lookip/.gitignore new file mode 100644 index 000000000..3e0b741d8 --- /dev/null +++ b/src/libcharon/plugins/lookip/.gitignore @@ -0,0 +1 @@ +lookip diff --git a/src/libcharon/plugins/lookip/Makefile.am b/src/libcharon/plugins/lookip/Makefile.am index 5d4603fbc..89614e473 100644 --- a/src/libcharon/plugins/lookip/Makefile.am +++ b/src/libcharon/plugins/lookip/Makefile.am @@ -15,3 +15,6 @@ libstrongswan_lookip_la_SOURCES = lookip_plugin.h lookip_plugin.c \ lookip_listener.h lookip_listener.c lookip_msg.h libstrongswan_lookip_la_LDFLAGS = -module -avoid-version + +ipsec_PROGRAMS = lookip +lookip_SOURCES = lookip.c diff --git a/src/libcharon/plugins/lookip/lookip.c b/src/libcharon/plugins/lookip/lookip.c new file mode 100644 index 000000000..7f5dc8afb --- /dev/null +++ b/src/libcharon/plugins/lookip/lookip.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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. + */ + +#include "lookip_msg.h" + +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <stddef.h> +#include <stdio.h> +#include <errno.h> +#include <getopt.h> + +/** + * Connect to the daemon, return FD + */ +static int make_connection() +{ + struct sockaddr_un addr; + int fd; + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, LOOKIP_SOCKET); + + fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) + { + fprintf(stderr, "opening socket failed: %s\n", strerror(errno)); + return -1; + } + if (connect(fd, (struct sockaddr *)&addr, + offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path)) < 0) + { + fprintf(stderr, "connecting to %s failed: %s\n", + LOOKIP_SOCKET, strerror(errno)); + close(fd); + return -1; + } + return fd; +} + +/** + * Send a request message + */ +static int send_request(int fd, int type, char *vip) +{ + lookip_request_t req = { + .type = type, + }; + + if (vip) + { + snprintf(req.vip, sizeof(req.vip), "%s", vip); + } + if (send(fd, &req, sizeof(req), 0) != sizeof(req)) + { + fprintf(stderr, "writing to socket failed: %s\n", strerror(errno)); + return 2; + } + return 0; +} + +/** + * Receive entries from fd. If block is != 0, the call blocks until closed + */ +static int receive(int fd, int block) +{ + lookip_response_t resp; + char *label; + int res; + + for (;;) + { + res = recv(fd, &resp, sizeof(resp), block ? 0 : MSG_DONTWAIT); + if (res == 0) + { /* closed by server */ + return 0; + } + if (res != sizeof(resp)) + { + if (!block && (errno == EAGAIN || errno == EWOULDBLOCK)) + { /* call would block, but we don't */ + return 0; + } + fprintf(stderr, "reading from socket failed: %s\n", strerror(errno)); + return 1; + } + switch (resp.type) + { + case LOOKIP_ENTRY: + label = "lookup:"; + break; + case LOOKIP_NOTIFY_UP: + label = "up:"; + break; + case LOOKIP_NOTIFY_DOWN: + label = "down:"; + break; + default: + fprintf(stderr, "received invalid message type: %d\n", resp.type); + return 1; + } + resp.vip[sizeof(resp.vip) - 1] = '\0'; + resp.ip[sizeof(resp.ip) - 1] = '\0'; + resp.id[sizeof(resp.id) - 1] = '\0'; + resp.name[sizeof(resp.name) - 1] = '\0'; + + printf("%-8s %16s %16s %20s %s\n", + label, resp.vip, resp.ip, resp.name, resp.id); + } +} + +/** + * Print usage information + */ +static void usage(char *cmd) +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s --help\n", cmd); + fprintf(stderr, " %s --dump\n", cmd); + fprintf(stderr, " %s --lookup <IP>\n", cmd); + fprintf(stderr, " %s --listen-up\n", cmd); + fprintf(stderr, " %s --listen-down\n", cmd); + fprintf(stderr, "Any combination of options is allowed.\n", cmd); +} + +int main(int argc, char *argv[]) +{ + int fd, res = 0, end = 0; + struct option long_opts[] = { + { "help", no_argument, NULL, 'h' }, + { "dump", no_argument, NULL, 'd' }, + { "lookup", required_argument, NULL, 'l' }, + { "listen-up", no_argument, NULL, 'u' }, + { "listen-down", no_argument, NULL, 'c' }, + { 0,0,0,0 } + }; + + if (argc == 1) + { + usage(argv[0]); + return 1; + } + + fd = make_connection(); + if (fd == -1) + { + return 1; + } + + while (res == 0) + { + switch (getopt_long(argc, argv, "", long_opts, NULL)) + { + case EOF: + end = 1; + break; + case 'h': + usage(argv[0]); + break; + case 'd': + res = send_request(fd, LOOKIP_DUMP, NULL); + break; + case 'l': + res = send_request(fd, LOOKIP_LOOKUP, optarg); + break; + case 'u': + res = send_request(fd, LOOKIP_REGISTER_UP, NULL); + break; + case 'c': + res = send_request(fd, LOOKIP_REGISTER_DOWN, NULL); + break; + default: + usage(argv[0]); + res = 1; + break; + } + if (end) + { + break; + } + if (res == 0) + { /* read all currently available results */ + res = receive(fd, 0); + } + } + if (res == 0) + { + /* send close message */ + send_request(fd, LOOKIP_END, NULL); + /* read until socket gets closed */ + res = receive(fd, 1); + } + close(fd); + + return res; +} |