Annotation of embedaddon/strongswan/src/libcharon/plugins/lookip/lookip.c, revision 1.1.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>