Browse code

Properly support IPv6 in clamdtop.

Shawn Webb authored on 2014/02/21 02:13:47
Showing 1 changed files
... ...
@@ -507,6 +507,89 @@ static void print_con_info(conn_t *conn, const char *fmt, ...)
507 507
 	va_end(ap);
508 508
 }
509 509
 
510
+char *get_ip(const char *ip)
511
+{
512
+    char *dupip, *p1;
513
+
514
+    /*
515
+     * Expected format of ip:
516
+     *     1) IPv4:Port
517
+     *     2) [IPv6]:Port
518
+     * 
519
+     * Use of IPv6:Port is incorrect. An IPv6 address must be enclosed in brackets.
520
+     */
521
+
522
+    dupip = strdup(ip);
523
+    if (!(dupip))
524
+        return NULL;
525
+
526
+    if (dupip[0] == '[') {
527
+        /* IPv6 */
528
+        p1 = strchr(dupip, ']');
529
+        if (!(p1)) {
530
+            free(dupip);
531
+            return NULL;
532
+        }
533
+
534
+        *p1 = '\0';
535
+
536
+        return (dupip+1);
537
+    }
538
+
539
+    p1 = strchr(dupip, ':');
540
+    if (!(p1)) {
541
+        /* Port number is required */
542
+        free(dupip);
543
+        return NULL;
544
+    }
545
+
546
+    *p1++ = '\0';
547
+
548
+    /* Extra sanity checking. If we have another colon, then we're IPv6. */
549
+    p1 = strchr(p1, ':');
550
+    if ((p1)) {
551
+        free(dupip);
552
+        return NULL;
553
+    }
554
+
555
+    return dupip;
556
+}
557
+
558
+char *get_port(const char *ip)
559
+{
560
+    char *dupip, *p;
561
+
562
+    dupip = get_ip(ip);
563
+    if (!(dupip))
564
+        return NULL;
565
+
566
+    p = dupip + strlen(dupip) + 1;
567
+    if (*p == ':')
568
+        return p+1;
569
+
570
+    return p;
571
+}
572
+
573
+char *make_ip(const char *host, const char *port)
574
+{
575
+    char *ip;
576
+    size_t len;
577
+    int ipv6;
578
+
579
+    len = strlen(host) + strlen(port);
580
+
581
+    ipv6 = (strchr(host, ':') != NULL);
582
+
583
+    len += (ipv6 ? 3 : 2);
584
+
585
+    ip = calloc(1, len);
586
+    if (!(ip))
587
+        return NULL;
588
+
589
+    snprintf(ip, len, "%s%s%s:%s", ipv6 ? "[" : "", host, ipv6 ? "]" : "", port);
590
+
591
+    return ip;
592
+}
510 593
 
511 594
 static int make_connection_real(const char *soname, conn_t *conn)
512 595
 {
... ...
@@ -516,6 +599,7 @@ static int make_connection_real(const char *soname, conn_t *conn)
516 516
     char *name, *pt = strdup(soname);
517 517
     const char *host = pt;
518 518
     struct addrinfo hints, *res=NULL, *p;
519
+    int err;
519 520
 
520 521
     conn->tcp = 0;
521 522
 
... ...
@@ -550,18 +634,19 @@ static int make_connection_real(const char *soname, conn_t *conn)
550 550
     hints.ai_socktype = SOCK_STREAM;
551 551
     hints.ai_flags = AI_PASSIVE;
552 552
 
553
+    host = get_ip(soname);
554
+    if (!(host))
555
+        return -1;
556
+
557
+    port = get_port(soname);
558
+
553 559
     conn->tcp=1;
554
-    name = strchr(pt, '/');
555
-    if(name) {
556
-        *name = '\0';
557
-        port = name+1;
558
-    } else {
559
-        port = NULL;
560
-    }
561 560
 
562
-    print_con_info(conn, "Looking up: %s\n", host);
563
-    if (getaddrinfo(host, (port != NULL) ? port : "3310", &hints, &res))
561
+    print_con_info(conn, "Looking up: %s:%s\n", host, port ? port : "3310");
562
+    if ((err = getaddrinfo(host, (port != NULL) ? port : "3310", &hints, &res))) {
563
+        print_con_info(conn, "Could not look up %s:%s, getaddrinfo returned: %s\n", host, port ? port : "3310", gai_strerror(err));
564 564
         return -1;
565
+    }
565 566
 
566 567
     for (p = res; p != NULL; p = p->ai_next) {
567 568
         if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
... ...
@@ -569,7 +654,7 @@ static int make_connection_real(const char *soname, conn_t *conn)
569 569
             continue;
570 570
         }
571 571
 
572
-        print_con_info(conn, "Connecting to: %s:%s\n", host, port);
572
+        print_con_info(conn, "Connecting to: %s\n", soname);
573 573
         if (connect(s, p->ai_addr, p->ai_addrlen)) {
574 574
             perror("connect");
575 575
             close(s);
... ...
@@ -593,7 +678,7 @@ end:
593 593
         if (conn->remote)
594 594
             free(conn->remote);
595 595
 
596
-        conn->remote = strdup(soname);
596
+        conn->remote = make_ip(host, (port != NULL) ? port : "3310");
597 597
     }
598 598
     conn->sd = s;
599 599
     gettimeofday(&conn->tv_conn, NULL);
... ...
@@ -1132,7 +1217,7 @@ static void help(void)
1132 1132
     printf("    --version              -V         Show version\n");
1133 1133
     printf("    --config-file=FILE     -c FILE    Read clamd's configuration files from FILE\n");
1134 1134
     printf("    --defaultcolors	       -d	  Use default terminal colors\n");
1135
-    printf("	host[/port]			  Connect to clamd on host at port (default 3310)\n");
1135
+    printf("	host[:port]			  Connect to clamd on host at port (default 3310)\n");
1136 1136
     printf("    /path/to/clamd.socket		  Connect to clamd over a local socket\n");
1137 1137
     printf("\n");
1138 1138
     return;
... ...
@@ -1192,8 +1277,8 @@ static void setup_connections(int argc, char *argv[])
1192 1192
             if ((opt_addr = optget(clamd_opts, "TCPAddr"))->enabled) {
1193 1193
                 host = opt_addr->strarg;
1194 1194
             }
1195
-            snprintf(buf, sizeof(buf), "%s/%llu", host, opt->numarg);
1196
-            conn = strdup(buf);
1195
+            snprintf(buf, sizeof(buf), "%lld", opt->numarg);
1196
+            conn = make_ip(host, buf);
1197 1197
         } else {
1198 1198
             fprintf(stderr, "Can't find how to connect to clamd\n");
1199 1199
             EXIT_PROGRAM(FAIL_INITIAL_CONN);