~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

« back to all changes in this revision

Viewing changes to clamdtop/clamdtop.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-07-15 01:08:10 UTC
  • mfrom: (0.35.47 sid)
  • Revision ID: package-import@ubuntu.com-20140715010810-ru66ek4fun2iseba
Tags: 0.98.4+dfsg-2~ubuntu13.10.1
No-change backport to saucy (LP: #1341962)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  ClamdTOP
3
3
 *
4
 
 *  Copyright (C) 2008 - 2009 Sourcefire, Inc.
 
4
 *  Copyright (C) 2008 - 2013 Sourcefire, Inc.
5
5
 *
6
6
 *  Authors: Török Edvin
7
7
 *
507
507
        va_end(ap);
508
508
}
509
509
 
 
510
char *get_ip(const char *ip)
 
511
{
 
512
    char *dupip, *p1, *p2;
 
513
    unsigned int i;
 
514
 
 
515
    /*
 
516
     * Expected format of ip:
 
517
     *     1) IPv4
 
518
     *     2) IPv4:Port
 
519
     *     3) IPv6
 
520
     *     4) [IPv6]:Port
 
521
     * 
 
522
     * Use of IPv6:Port is incorrect. An IPv6 address must be enclosed in brackets.
 
523
     */
 
524
 
 
525
    dupip = strdup(ip);
 
526
    if (!(dupip))
 
527
        return NULL;
 
528
 
 
529
    if (dupip[0] == '[') {
 
530
        /* IPv6 */
 
531
        p1 = strchr(dupip, ']');
 
532
        if (!(p1)) {
 
533
            free(dupip);
 
534
            return NULL;
 
535
        }
 
536
 
 
537
        *p1 = '\0';
 
538
 
 
539
        p1 = strdup(dupip+1);
 
540
        free(dupip);
 
541
        return p1;
 
542
    }
 
543
 
 
544
    p1 = dupip;
 
545
    i=0;
 
546
    while ((p1 = strchr(p1, ':'))) {
 
547
        i++;
 
548
        p1++;
 
549
    }
 
550
 
 
551
    if (i == 0 || i > 1)
 
552
        return dupip;
 
553
 
 
554
    if (i == 1) {
 
555
        p1 = strchr(dupip, ':');
 
556
        *p1 = '\0';
 
557
        return dupip;
 
558
    }
 
559
 
 
560
    return dupip;
 
561
}
 
562
 
 
563
char *get_port(const char *ip)
 
564
{
 
565
    char *dupip, *p;
 
566
    unsigned int offset=0;
 
567
 
 
568
    dupip = get_ip(ip);
 
569
    if (!(dupip))
 
570
        return NULL;
 
571
 
 
572
    if (ip[0] == '[')
 
573
        offset += 2;
 
574
 
 
575
    p = (char *)ip + strlen(dupip) + offset;
 
576
    if (*p == ':') {
 
577
        p = strdup(p+1);
 
578
        free(dupip);
 
579
        return p;
 
580
    }
 
581
 
 
582
    return NULL;
 
583
}
 
584
 
 
585
char *make_ip(const char *host, const char *port)
 
586
{
 
587
    char *ip;
 
588
    size_t len;
 
589
    int ipv6;
 
590
 
 
591
    len = strlen(host) + strlen(port);
 
592
 
 
593
    ipv6 = (strchr(host, ':') != NULL);
 
594
 
 
595
    len += (ipv6 ? 4 : 3);
 
596
 
 
597
    ip = calloc(1, len);
 
598
    if (!(ip))
 
599
        return NULL;
 
600
 
 
601
    snprintf(ip, len, "%s%s%s:%s", ipv6 ? "[" : "", host, ipv6 ? "]" : "", port);
 
602
 
 
603
    return ip;
 
604
}
510
605
 
511
606
static int make_connection_real(const char *soname, conn_t *conn)
512
607
{
513
 
        int s;
514
 
        struct timeval tv;
515
 
        conn->tcp = 0;
516
 
#ifdef _WIN32
517
 
    {
518
 
#else
519
 
        if(cli_is_abspath(soname) || (access(soname, F_OK) == 0)) {
520
 
                struct sockaddr_un addr;
521
 
                s = socket(AF_UNIX, SOCK_STREAM, 0);
522
 
                if(s < 0) {
523
 
                        perror("socket");
524
 
                        return -1;
525
 
                }
526
 
                memset(&addr, 0, sizeof(addr));
527
 
                addr.sun_family = AF_UNIX;
528
 
                strncpy(addr.sun_path, soname, sizeof(addr.sun_path));
529
 
                addr.sun_path[sizeof(addr.sun_path) - 1] = 0x0;
530
 
                print_con_info(conn, "Connecting to: %s\n", soname);
531
 
                if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) {
532
 
                        perror("connect");
 
608
    int s;
 
609
    struct timeval tv;
 
610
    char *port=NULL;
 
611
    char *name, *pt = strdup(soname);
 
612
    const char *host = pt;
 
613
    struct addrinfo hints, *res=NULL, *p;
 
614
    int err;
 
615
 
 
616
    conn->tcp = 0;
 
617
 
 
618
#ifndef _WIN32
 
619
    if(cli_is_abspath(soname) || (access(soname, F_OK) == 0)) {
 
620
        struct sockaddr_un addr;
 
621
 
 
622
        s = socket(AF_UNIX, SOCK_STREAM, 0);
 
623
        if(s < 0) {
 
624
            perror("socket");
 
625
            return -1;
 
626
        }
 
627
 
 
628
        memset(&addr, 0, sizeof(addr));
 
629
        addr.sun_family = AF_UNIX;
 
630
        strncpy(addr.sun_path, soname, sizeof(addr.sun_path));
 
631
        addr.sun_path[sizeof(addr.sun_path) - 1] = 0x0;
 
632
 
 
633
        print_con_info(conn, "Connecting to: %s\n", soname);
 
634
        if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) {
 
635
            perror("connect");
533
636
            close(s);
534
 
                        return -1;
535
 
                }
536
 
        } else {
 
637
            return -1;
 
638
        }
 
639
 
 
640
        goto end;
 
641
    }
537
642
#endif
538
 
                struct sockaddr_in server;
539
 
                struct hostent *hp;
540
 
                unsigned port = 0;
541
 
                char *name, *pt = strdup(soname);
542
 
                const char *host = pt;
543
 
        memset(&server, 0x00, sizeof(struct sockaddr_in));
544
 
                conn->tcp=1;
545
 
                name = strchr(pt, ':');
546
 
                if(name) {
547
 
                        *name++ = '\0';
548
 
                        port = atoi(name);
549
 
                }
550
 
                if(!port)
551
 
                        port = 3310;
552
 
                print_con_info(conn, "Looking up: %s\n", host);
553
 
                if((hp = gethostbyname(host)) == NULL) {
554
 
                        fprintf(stderr, "Cannot find host");
555
 
                        return -1;
556
 
                }
557
 
                free(pt);
558
 
                s = socket(AF_INET, SOCK_STREAM, 0);
559
 
                if(s < 0) {
560
 
                        perror("socket");
561
 
                        return -1;
562
 
                }
563
 
                server.sin_family = AF_INET;
564
 
                server.sin_port = htons(port);
565
 
                server.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr;
566
 
                print_con_info(conn, "Connecting to: %s:%u\n", inet_ntoa(server.sin_addr), port);
567
 
                if (connect(s, (struct sockaddr *)&server, (socklen_t)sizeof(server))) {
568
 
                        perror("connect");
 
643
 
 
644
    memset(&hints, 0x00, sizeof(struct addrinfo));
 
645
    hints.ai_family = AF_UNSPEC;
 
646
    hints.ai_socktype = SOCK_STREAM;
 
647
    hints.ai_flags = AI_PASSIVE;
 
648
 
 
649
    host = get_ip(soname);
 
650
    if (!(host))
 
651
        return -1;
 
652
 
 
653
    port = get_port(soname);
 
654
 
 
655
    conn->tcp=1;
 
656
 
 
657
    print_con_info(conn, "Looking up: %s:%s\n", host, port ? port : "3310");
 
658
    if ((err = getaddrinfo(host, (port != NULL) ? port : "3310", &hints, &res))) {
 
659
        print_con_info(conn, "Could not look up %s:%s, getaddrinfo returned: %s\n", host, port ? port : "3310", gai_strerror(err));
 
660
        return -1;
 
661
    }
 
662
 
 
663
    for (p = res; p != NULL; p = p->ai_next) {
 
664
        if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
 
665
            perror("socket");
 
666
            continue;
 
667
        }
 
668
 
 
669
        print_con_info(conn, "Connecting to: %s\n", soname);
 
670
        if (connect(s, p->ai_addr, p->ai_addrlen)) {
 
671
            perror("connect");
569
672
            close(s);
570
 
                        return -1;
571
 
                }
572
 
        }
573
 
        if (conn->remote != soname) {
574
 
            /* when we reconnect, they are the same */
575
 
            if (conn->remote) free(conn->remote);
576
 
            conn->remote = strdup(soname);
577
 
        }
578
 
        conn->sd = s;
579
 
        gettimeofday(&conn->tv_conn, NULL);
580
 
        tv.tv_sec = 30;
581
 
        tv.tv_usec = 0;
582
 
        setsockopt(conn->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
583
 
        return 0;
 
673
            continue;
 
674
        }
 
675
 
 
676
        break;
 
677
    }
 
678
 
 
679
    free(pt);
 
680
 
 
681
    if (res)
 
682
        freeaddrinfo(res);
 
683
 
 
684
    if (p == NULL)
 
685
        return -1;
 
686
 
 
687
end:
 
688
    if (conn->remote != soname) {
 
689
        /* when we reconnect, they are the same */
 
690
        if (conn->remote)
 
691
            free(conn->remote);
 
692
 
 
693
        conn->remote = make_ip(host, (port != NULL) ? port : "3310");
 
694
    }
 
695
    if (port)
 
696
        free(port);
 
697
    conn->sd = s;
 
698
    gettimeofday(&conn->tv_conn, NULL);
 
699
    tv.tv_sec = 30;
 
700
    tv.tv_usec = 0;
 
701
    setsockopt(conn->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
 
702
    return 0;
584
703
}
585
704
 
586
705
static int make_connection(const char *soname, conn_t *conn)
588
707
    int rc;
589
708
 
590
709
    if ((rc = make_connection_real(soname, conn)))
591
 
        return rc;
 
710
        return rc;
 
711
 
592
712
    send_string(conn, "nIDSESSION\nnVERSION\n");
593
713
    free(conn->version);
594
714
    conn->version = NULL;
595
715
    if (!read_version(conn))
596
 
        return 0;
 
716
        return 0;
597
717
 
598
718
    /* clamd < 0.95 */
599
719
    if ((rc = make_connection_real(soname, conn)))
600
 
        return rc;
 
720
        return rc;
 
721
 
601
722
    send_string(conn, "nSESSION\nnVERSION\n");
602
723
    conn->version = NULL;
603
724
    if (!read_version(conn))
604
 
        return 0;
 
725
        return 0;
 
726
 
605
727
    return -1;
606
728
}
607
729
 
1118
1240
/* -------------------------- Initialization ---------------- */
1119
1241
static void setup_connections(int argc, char *argv[])
1120
1242
{
1121
 
        struct optstruct *opts;
1122
 
        struct optstruct *clamd_opts;
1123
 
        unsigned i;
1124
 
        char *conn = NULL;
1125
 
 
1126
 
        opts = optparse(NULL, argc, argv, 1, OPT_CLAMDTOP, 0, NULL);
1127
 
        if (!opts) {
1128
 
            fprintf(stderr, "ERROR: Can't parse command line options\n");
1129
 
            EXIT_PROGRAM(FAIL_CMDLINE);
1130
 
        }
1131
 
 
1132
 
        if(optget(opts, "help")->enabled) {
1133
 
            optfree(opts);
1134
 
            help();
1135
 
            normal_exit = 1;
1136
 
            exit(0);
1137
 
        }
1138
 
 
1139
 
        if(optget(opts, "version")->enabled) {
1140
 
            printf("Clam AntiVirus Monitoring Tool %s\n", get_version());
1141
 
            optfree(opts);
1142
 
            normal_exit = 1;
1143
 
            exit(0);
1144
 
        }
1145
 
 
1146
 
        if(optget(opts, "defaultcolors")->enabled)
1147
 
            default_colors = 1;
1148
 
        memset(&global, 0, sizeof(global));
1149
 
        if (!opts->filename || !opts->filename[0]) {
1150
 
            const struct optstruct *opt;
1151
 
            const char *clamd_conf = optget(opts, "config-file")->strarg;
1152
 
 
1153
 
            if ((clamd_opts = optparse(clamd_conf, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) {
1154
 
                fprintf(stderr, "Can't parse clamd configuration file %s\n", clamd_conf);
1155
 
                EXIT_PROGRAM(FAIL_CMDLINE);
1156
 
            }
1157
 
 
1158
 
            if((opt = optget(clamd_opts, "LocalSocket"))->enabled) {
1159
 
                conn = strdup(opt->strarg);
1160
 
            } else if ((opt = optget(clamd_opts, "TCPSocket"))->enabled) {
1161
 
                char buf[512];
1162
 
                const struct optstruct *opt_addr;
1163
 
                const char *host = "localhost";
1164
 
                if ((opt_addr = optget(clamd_opts, "TCPAddr"))->enabled) {
1165
 
                    host = opt_addr->strarg;
1166
 
                }
1167
 
                snprintf(buf, sizeof(buf), "%s:%llu", host, opt->numarg);
1168
 
                conn = strdup(buf);
1169
 
            } else {
1170
 
                fprintf(stderr, "Can't find how to connect to clamd\n");
1171
 
                EXIT_PROGRAM(FAIL_INITIAL_CONN);
1172
 
            }
1173
 
            optfree(clamd_opts);
1174
 
            global.num_clamd = 1;
1175
 
        } else {
1176
 
            unsigned i = 0;
1177
 
            while (opts->filename[i]) { i++; }
1178
 
            global.num_clamd = i;
1179
 
        }
 
1243
    struct optstruct *opts;
 
1244
    struct optstruct *clamd_opts;
 
1245
    unsigned i;
 
1246
    char *conn = NULL;
 
1247
 
 
1248
    opts = optparse(NULL, argc, argv, 1, OPT_CLAMDTOP, 0, NULL);
 
1249
    if (!opts) {
 
1250
        fprintf(stderr, "ERROR: Can't parse command line options\n");
 
1251
        EXIT_PROGRAM(FAIL_CMDLINE);
 
1252
    }
 
1253
 
 
1254
    if(optget(opts, "help")->enabled) {
 
1255
        optfree(opts);
 
1256
        help();
 
1257
        normal_exit = 1;
 
1258
        exit(0);
 
1259
    }
 
1260
 
 
1261
    if(optget(opts, "version")->enabled) {
 
1262
        printf("Clam AntiVirus Monitoring Tool %s\n", get_version());
 
1263
        optfree(opts);
 
1264
        normal_exit = 1;
 
1265
        exit(0);
 
1266
    }
 
1267
 
 
1268
    if(optget(opts, "defaultcolors")->enabled)
 
1269
        default_colors = 1;
 
1270
 
 
1271
    memset(&global, 0, sizeof(global));
 
1272
    if (!opts->filename || !opts->filename[0]) {
 
1273
        const struct optstruct *opt;
 
1274
        const char *clamd_conf = optget(opts, "config-file")->strarg;
 
1275
 
 
1276
        if ((clamd_opts = optparse(clamd_conf, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) {
 
1277
            fprintf(stderr, "Can't parse clamd configuration file %s\n", clamd_conf);
 
1278
            EXIT_PROGRAM(FAIL_CMDLINE);
 
1279
        }
 
1280
 
 
1281
        if((opt = optget(clamd_opts, "LocalSocket"))->enabled) {
 
1282
            conn = strdup(opt->strarg);
 
1283
            if (!conn) {
 
1284
                fprintf(stderr, "Can't strdup LocalSocket value\n");
 
1285
                EXIT_PROGRAM(FAIL_INITIAL_CONN);
 
1286
            }
 
1287
        } else if ((opt = optget(clamd_opts, "TCPSocket"))->enabled) {
 
1288
            char buf[512];
 
1289
            const struct optstruct *opt_addr;
 
1290
            const char *host = "localhost";
 
1291
            if ((opt_addr = optget(clamd_opts, "TCPAddr"))->enabled) {
 
1292
                host = opt_addr->strarg;
 
1293
            }
 
1294
            snprintf(buf, sizeof(buf), "%lld", opt->numarg);
 
1295
            conn = make_ip(host, buf);
 
1296
        } else {
 
1297
            fprintf(stderr, "Can't find how to connect to clamd\n");
 
1298
            EXIT_PROGRAM(FAIL_INITIAL_CONN);
 
1299
        }
 
1300
 
 
1301
        optfree(clamd_opts);
 
1302
        global.num_clamd = 1;
 
1303
    } else {
 
1304
        unsigned i = 0;
 
1305
        while (opts->filename[i]) { i++; }
 
1306
        global.num_clamd = i;
 
1307
    }
1180
1308
 
1181
1309
#ifdef _WIN32
1182
 
        WSADATA wsaData;
1183
 
        if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) {
1184
 
                fprintf(stderr, "Error at WSAStartup(): %d\n", WSAGetLastError());
1185
 
                EXIT_PROGRAM(FAIL_INITIAL_CONN);
1186
 
        }
 
1310
    WSADATA wsaData;
 
1311
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) {
 
1312
        fprintf(stderr, "Error at WSAStartup(): %d\n", WSAGetLastError());
 
1313
        EXIT_PROGRAM(FAIL_INITIAL_CONN);
 
1314
    }
1187
1315
#endif
1188
 
        /* clamdtop */
1189
 
        puts( "        __                    ____");
1190
 
        puts("  _____/ /___ _____ ___  ____/ / /_____  ____");
1191
 
        puts(" / ___/ / __ `/ __ `__ \\/ __  / __/ __ \\/ __ \\");
1192
 
        puts("/ /__/ / /_/ / / / / / / /_/ / /_/ /_/ / /_/ /");
1193
 
        puts("\\___/_/\\__,_/_/ /_/ /_/\\__,_/\\__/\\____/ .___/");
1194
 
        puts("                                     /_/");
1195
 
        global.all_stats = calloc(global.num_clamd, sizeof(*global.all_stats));
1196
 
        OOM_CHECK(global.all_stats);
1197
 
        global.conn = calloc(global.num_clamd, sizeof(*global.conn));
1198
 
        OOM_CHECK(global.conn);
1199
 
        for (i=0;i < global.num_clamd;i++) {
1200
 
                const char *soname = conn ? conn : opts->filename[i];
1201
 
                global.conn[i].line = i+1;
1202
 
                if (make_connection(soname, &global.conn[i]) < 0) {
1203
 
                        EXIT_PROGRAM(FAIL_INITIAL_CONN);
1204
 
                }
1205
 
        }
1206
 
        optfree(opts);
1207
 
        free(conn);
 
1316
    /* clamdtop */
 
1317
    puts( "        __                    ____");
 
1318
    puts("  _____/ /___ _____ ___  ____/ / /_____  ____");
 
1319
    puts(" / ___/ / __ `/ __ `__ \\/ __  / __/ __ \\/ __ \\");
 
1320
    puts("/ /__/ / /_/ / / / / / / /_/ / /_/ /_/ / /_/ /");
 
1321
    puts("\\___/_/\\__,_/_/ /_/ /_/\\__,_/\\__/\\____/ .___/");
 
1322
    puts("                                     /_/");
 
1323
 
 
1324
    global.all_stats = calloc(global.num_clamd, sizeof(*global.all_stats));
 
1325
    OOM_CHECK(global.all_stats);
 
1326
    global.conn = calloc(global.num_clamd, sizeof(*global.conn));
 
1327
    OOM_CHECK(global.conn);
 
1328
 
 
1329
    for (i=0;i < global.num_clamd;i++) {
 
1330
        const char *soname = conn ? conn : opts->filename[i];
 
1331
        global.conn[i].line = i+1;
 
1332
        if (make_connection(soname, &global.conn[i]) < 0) {
 
1333
            EXIT_PROGRAM(FAIL_INITIAL_CONN);
 
1334
        }
 
1335
    }
 
1336
 
 
1337
    optfree(opts);
 
1338
    free(conn);
1208
1339
#ifndef _WIN32
1209
 
        signal(SIGPIPE, SIG_IGN);
1210
 
        signal(SIGINT, sigint);
 
1340
    signal(SIGPIPE, SIG_IGN);
 
1341
    signal(SIGINT, sigint);
1211
1342
#endif
1212
1343
}
1213
1344