Annotation of embedaddon/strongswan/src/libcharon/plugins/lookip/lookip.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2012 Martin Willi
! 3: * Copyright (C) 2012 revosec AG
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15:
! 16: #include "lookip_msg.h"
! 17:
! 18: #include <sys/socket.h>
! 19: #include <sys/un.h>
! 20: #include <unistd.h>
! 21: #include <stddef.h>
! 22: #include <stdio.h>
! 23: #include <stdlib.h>
! 24: #include <errno.h>
! 25: #include <getopt.h>
! 26: #include <arpa/inet.h>
! 27:
! 28: /**
! 29: * Connect to the daemon, return FD
! 30: */
! 31: static int make_connection()
! 32: {
! 33: union {
! 34: struct sockaddr_un un;
! 35: struct sockaddr_in in;
! 36: struct sockaddr sa;
! 37: } addr;
! 38: int fd, len;
! 39:
! 40: if (getenv("TCP_PORT"))
! 41: {
! 42: addr.in.sin_family = AF_INET;
! 43: addr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
! 44: addr.in.sin_port = htons(atoi(getenv("TCP_PORT")));
! 45: len = sizeof(addr.in);
! 46: }
! 47: else
! 48: {
! 49: addr.un.sun_family = AF_UNIX;
! 50: strcpy(addr.un.sun_path, LOOKIP_SOCKET);
! 51:
! 52: len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.un.sun_path);
! 53: }
! 54: fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
! 55: if (fd < 0)
! 56: {
! 57: fprintf(stderr, "opening socket failed: %s\n", strerror(errno));
! 58: return -1;
! 59: }
! 60: if (connect(fd, &addr.sa, len) < 0)
! 61: {
! 62: fprintf(stderr, "connecting failed: %s\n", strerror(errno));
! 63: close(fd);
! 64: return -1;
! 65: }
! 66: return fd;
! 67: }
! 68:
! 69: static int read_all(int fd, void *buf, size_t len, int flags)
! 70: {
! 71: ssize_t ret, done = 0;
! 72:
! 73: while (done < len)
! 74: {
! 75: ret = recv(fd, buf, len - done, flags);
! 76: if (ret == -1 && errno == EINTR)
! 77: { /* interrupted, try again */
! 78: continue;
! 79: }
! 80: if (ret == 0)
! 81: {
! 82: return 0;
! 83: }
! 84: if (ret < 0)
! 85: {
! 86: return -1;
! 87: }
! 88: done += ret;
! 89: buf += ret;
! 90: }
! 91: return len;
! 92: }
! 93:
! 94: static int write_all(int fd, void *buf, size_t len)
! 95: {
! 96: ssize_t ret, done = 0;
! 97:
! 98: while (done < len)
! 99: {
! 100: ret = write(fd, buf, len - done);
! 101: if (ret == -1 && errno == EINTR)
! 102: { /* interrupted, try again */
! 103: continue;
! 104: }
! 105: if (ret < 0)
! 106: {
! 107: return -1;
! 108: }
! 109: done += ret;
! 110: buf += ret;
! 111: }
! 112: return len;
! 113: }
! 114:
! 115: /**
! 116: * Send a request message
! 117: */
! 118: static int send_request(int fd, int type, char *vip)
! 119: {
! 120: lookip_request_t req = {
! 121: .type = htonl(type),
! 122: };
! 123:
! 124: if (vip)
! 125: {
! 126: snprintf(req.vip, sizeof(req.vip), "%s", vip);
! 127: }
! 128: if (write_all(fd, &req, sizeof(req)) != sizeof(req))
! 129: {
! 130: fprintf(stderr, "writing to socket failed: %s\n", strerror(errno));
! 131: return 2;
! 132: }
! 133: return 0;
! 134: }
! 135:
! 136: /**
! 137: * Receive entries from fd. If block is != 0, the call blocks until closed
! 138: */
! 139: static int receive(int fd, int block, int loop)
! 140: {
! 141: lookip_response_t resp;
! 142: char *label, name[32];
! 143: int res;
! 144:
! 145: do
! 146: {
! 147: res = read_all(fd, &resp, sizeof(resp), block ? 0 : MSG_DONTWAIT);
! 148: if (res == 0)
! 149: { /* closed by server */
! 150: return 0;
! 151: }
! 152: if (res != sizeof(resp))
! 153: {
! 154: if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
! 155: { /* call would block, but we don't */
! 156: return 0;
! 157: }
! 158: fprintf(stderr, "reading from socket failed: %s\n", strerror(errno));
! 159: return 1;
! 160: }
! 161: switch (ntohl(resp.type))
! 162: {
! 163: case LOOKIP_ENTRY:
! 164: label = "lookup:";
! 165: break;
! 166: case LOOKIP_NOT_FOUND:
! 167: label = "not found:";
! 168: break;
! 169: case LOOKIP_NOTIFY_UP:
! 170: label = "up:";
! 171: break;
! 172: case LOOKIP_NOTIFY_DOWN:
! 173: label = "down:";
! 174: break;
! 175: default:
! 176: fprintf(stderr, "received invalid message type: %d\n", resp.type);
! 177: return 1;
! 178: }
! 179: resp.vip[sizeof(resp.vip) - 1] = '\0';
! 180: resp.ip[sizeof(resp.ip) - 1] = '\0';
! 181: resp.id[sizeof(resp.id) - 1] = '\0';
! 182: resp.name[sizeof(resp.name) - 1] = '\0';
! 183:
! 184: snprintf(name, sizeof(name), "%s[%u]", resp.name, ntohl(resp.unique_id));
! 185: printf("%-12s %16s %16s %20s %s\n",
! 186: label, resp.vip, resp.ip, name, resp.id);
! 187: }
! 188: while (loop);
! 189:
! 190: return 0;
! 191: }
! 192:
! 193: /**
! 194: * Interactive IP lookup shell
! 195: */
! 196: static int interactive(int fd)
! 197: {
! 198: printf("Enter IP address or 'quit'\n");
! 199:
! 200: while (1)
! 201: {
! 202: char line[64], *pos;
! 203: int res;
! 204:
! 205: printf("> ");
! 206: fflush(stdout);
! 207:
! 208: if (fgets(line, sizeof(line), stdin))
! 209: {
! 210: pos = strchr(line, '\n');
! 211: if (pos)
! 212: {
! 213: *pos = '\0';
! 214: }
! 215: if (strlen(line) == 0)
! 216: {
! 217: continue;
! 218: }
! 219: if (strcmp(line, "quit") == 0)
! 220: {
! 221: return send_request(fd, LOOKIP_END, NULL);
! 222: }
! 223: res = send_request(fd, LOOKIP_LOOKUP, line);
! 224: if (res != 0)
! 225: {
! 226: return res;
! 227: }
! 228: res = receive(fd, 1, 0);
! 229: if (res != 0)
! 230: {
! 231: return res;
! 232: }
! 233: }
! 234: }
! 235: }
! 236:
! 237: /**
! 238: * Print usage information
! 239: */
! 240: static void usage(char *cmd)
! 241: {
! 242: fprintf(stderr, "Usage:\n");
! 243: fprintf(stderr, " %s --help\n", cmd);
! 244: fprintf(stderr, " %s --dump\n", cmd);
! 245: fprintf(stderr, " %s --lookup <IP>\n", cmd);
! 246: fprintf(stderr, " %s --listen-up\n", cmd);
! 247: fprintf(stderr, " %s --listen-down\n", cmd);
! 248: fprintf(stderr, "Any combination of options is allowed.\n");
! 249: }
! 250:
! 251: int main(int argc, char *argv[])
! 252: {
! 253: int fd, res = 0, end = 0;
! 254: struct option long_opts[] = {
! 255: { "help", no_argument, NULL, 'h' },
! 256: { "dump", no_argument, NULL, 'd' },
! 257: { "lookup", required_argument, NULL, 'l' },
! 258: { "listen-up", no_argument, NULL, 'u' },
! 259: { "listen-down", no_argument, NULL, 'c' },
! 260: { 0,0,0,0 }
! 261: };
! 262:
! 263: fd = make_connection();
! 264: if (fd == -1)
! 265: {
! 266: return 1;
! 267: }
! 268:
! 269: if (argc == 1)
! 270: {
! 271: res = interactive(fd);
! 272: close(fd);
! 273: return res;
! 274: }
! 275:
! 276: while (res == 0)
! 277: {
! 278: switch (getopt_long(argc, argv, "", long_opts, NULL))
! 279: {
! 280: case EOF:
! 281: end = 1;
! 282: break;
! 283: case 'h':
! 284: usage(argv[0]);
! 285: break;
! 286: case 'd':
! 287: res = send_request(fd, LOOKIP_DUMP, NULL);
! 288: break;
! 289: case 'l':
! 290: res = send_request(fd, LOOKIP_LOOKUP, optarg);
! 291: break;
! 292: case 'u':
! 293: res = send_request(fd, LOOKIP_REGISTER_UP, NULL);
! 294: break;
! 295: case 'c':
! 296: res = send_request(fd, LOOKIP_REGISTER_DOWN, NULL);
! 297: break;
! 298: default:
! 299: usage(argv[0]);
! 300: res = 1;
! 301: break;
! 302: }
! 303: if (end)
! 304: {
! 305: break;
! 306: }
! 307: if (res == 0)
! 308: { /* read all currently available results */
! 309: res = receive(fd, 0, 1);
! 310: }
! 311: }
! 312: if (res == 0)
! 313: {
! 314: /* send close message */
! 315: send_request(fd, LOOKIP_END, NULL);
! 316: /* read until socket gets closed */
! 317: res = receive(fd, 1, 1);
! 318: }
! 319: close(fd);
! 320:
! 321: return res;
! 322: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>