Browse code

Add IPv6 support to clamdscan

Shawn Webb authored on 2014/01/27 04:58:21
Showing 2 changed files
... ...
@@ -64,17 +64,10 @@
64 64
 #include "client.h"
65 65
 #include "proto.h"
66 66
 
67
-#ifndef INADDR_LOOPBACK
68
-#define INADDR_LOOPBACK 0x7f000001
69
-#endif
70
-
71
-struct sockaddr *mainsa = NULL;
72
-int mainsasz;
73 67
 unsigned long int maxstream;
74 68
 #ifndef _WIN32
75 69
 static struct sockaddr_un nixsock;
76 70
 #endif
77
-static struct sockaddr_in tcpsock;
78 71
 extern struct optstruct *clamdopts;
79 72
 
80 73
 /* Inits the communication layer
... ...
@@ -83,7 +76,9 @@ static int isremote(const struct optstruct *opts) {
83 83
     int s, ret;
84 84
     const struct optstruct *opt;
85 85
     static struct sockaddr_in testsock;
86
-    char *ipaddr;
86
+    char *ipaddr, port[10];
87
+    struct addrinfo hints, *info, *p;
88
+    int res;
87 89
 
88 90
 #ifndef _WIN32
89 91
     if((opt = optget(clamdopts, "LocalSocket"))->enabled) {
... ...
@@ -91,43 +86,55 @@ static int isremote(const struct optstruct *opts) {
91 91
         nixsock.sun_family = AF_UNIX;
92 92
         strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path));
93 93
         nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0';
94
-        mainsa = (struct sockaddr *)&nixsock;
95
-        mainsasz = sizeof(nixsock);
96 94
         return 0;
97 95
     }
98 96
 #endif
99 97
     if(!(opt = optget(clamdopts, "TCPSocket"))->enabled)
100 98
         return 0;
101 99
 
102
-    mainsa = (struct sockaddr *)&tcpsock;
103
-    mainsasz = sizeof(tcpsock);
100
+    snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
104 101
 
105 102
     opt = optget(clamdopts, "TCPAddr");
106 103
     while (opt) {
107
-        ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
108
-
109
-        if (cfg_tcpsock(ipaddr, clamdopts, &tcpsock, INADDR_LOOPBACK) == -1) {
110
-            logg("!Can't lookup clamd hostname: %s.\n", strerror(errno));
111
-            mainsa = NULL;
112
-            return 0;
104
+        if (opt->enabled)
105
+            ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg);
106
+        else
107
+            ipaddr = NULL;
108
+
109
+        memset(&hints, 0x00, sizeof(struct addrinfo));
110
+        hints.ai_family = AF_UNSPEC;
111
+        hints.ai_socktype = SOCK_STREAM;
112
+        hints.ai_flags = AI_PASSIVE;
113
+
114
+        if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
115
+            logg("!Can't lookup clamd hostname: %s\n", gai_strerror(res));
116
+            continue;
113 117
         }
114 118
 
115
-        memcpy((void *)&testsock, (void *)&tcpsock, sizeof(testsock));
116
-        testsock.sin_port = htons(INADDR_ANY);
117
-        if((s = socket(testsock.sin_family, SOCK_STREAM, 0)) < 0) {
118
-            logg("isremote: socket() returning: %s.\n", strerror(errno));
119
-            mainsa = NULL;
120
-            return 0;
119
+        for (p = info; p != NULL; p = p->ai_next) {
120
+            if((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
121
+                logg("isremote: socket() returning: %s.\n", strerror(errno));
122
+                continue;
123
+            }
124
+
125
+            ret = (bind(s, (struct sockaddr *)&testsock, (socklen_t)sizeof(testsock)) != 0);
126
+            closesocket(s);
127
+            if (ret) {
128
+                /* 
129
+                 * If we can't bind, then either we're attempting to listen on an IP that isn't
130
+                 * ours or that clamd is already listening on.
131
+                 */
132
+                freeaddrinfo(info);
133
+                return 1;
134
+            }
121 135
         }
122 136
 
123
-        ret = (bind(s, (struct sockaddr *)&testsock, (socklen_t)sizeof(testsock)) != 0);
124
-        closesocket(s);
125
-        if (ret)
126
-            return ret;
137
+        freeaddrinfo(info);
127 138
 
128 139
         opt = opt->nextarg;
129 140
     }
130
-    return ret;
141
+
142
+    return 1;
131 143
 }
132 144
 
133 145
 
... ...
@@ -186,7 +193,6 @@ int get_clamd_version(const struct optstruct *opts)
186 186
 	struct RCVLN rcv;
187 187
 
188 188
     isremote(opts);
189
-    if(!mainsa) return 2;
190 189
     if((sockd = dconnect()) < 0) return 2;
191 190
     recvlninit(&rcv, sockd);
192 191
 
... ...
@@ -214,7 +220,6 @@ int reload_clamd_database(const struct optstruct *opts)
214 214
 	struct RCVLN rcv;
215 215
 
216 216
     isremote(opts);
217
-    if(!mainsa) return 2;
218 217
     if((sockd = dconnect()) < 0) return 2;
219 218
     recvlninit(&rcv, sockd);
220 219
 
... ...
@@ -261,11 +266,6 @@ int client(const struct optstruct *opts, int *infected, int *err)
261 261
 	flags |= CLI_FTW_FOLLOW_FILE_SYMLINK;
262 262
     flags |= CLI_FTW_TRIM_SLASHES;
263 263
 
264
-    if(!mainsa) {
265
-	logg("!Clamd is not configured properly.\n");
266
-	return 2;
267
-    }
268
-
269 264
     *infected = 0;
270 265
 
271 266
     if(scandash) {
... ...
@@ -52,8 +52,6 @@
52 52
 #include "proto.h"
53 53
 #include "client.h"
54 54
 
55
-extern struct sockaddr *mainsa;
56
-extern int mainsasz;
57 55
 extern unsigned long int maxstream;
58 56
 int printinfected;
59 57
 extern struct optstruct *clamdopts;
... ...
@@ -63,19 +61,45 @@ static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES",
63 63
 /* Connects to clamd 
64 64
  * Returns a FD or -1 on error */
65 65
 int dconnect() {
66
-    int sockd;
67
-
68
-    if((sockd = socket(mainsa->sa_family, SOCK_STREAM, 0)) < 0) {
69
-	logg("!Can't create the socket: %s\n", strerror(errno));
70
-	return -1;
66
+    int sockd, res;
67
+    const struct optstruct *opt;
68
+    struct addrinfo hints, *info, *p;
69
+    char port[10];
70
+
71
+    snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg);
72
+
73
+    opt = optget(clamdopts, "TCPAddr");
74
+    while (opt) {
75
+        memset(&hints, 0x00, sizeof(struct addrinfo));
76
+        hints.ai_family = AF_UNSPEC;
77
+        hints.ai_socktype = SOCK_STREAM;
78
+        hints.ai_flags = AI_PASSIVE;
79
+
80
+        if ((res = getaddrinfo(opt->strarg, port, &hints, &info))) {
81
+            continue;
82
+        }
83
+
84
+        for (p = info; p != NULL; p = p->ai_next) {
85
+            if((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
86
+                logg("!Can't create the socket: %s\n", strerror(errno));
87
+                continue;
88
+            }
89
+
90
+            if(connect(sockd, p->ai_addr, p->ai_addrlen) < 0) {
91
+                closesocket(sockd);
92
+                continue;
93
+            }
94
+
95
+            freeaddrinfo(info);
96
+            return sockd;
97
+        }
98
+
99
+        freeaddrinfo(info);
100
+
101
+        opt = opt->nextarg;
71 102
     }
72 103
 
73
-    if(connect(sockd, (struct sockaddr *)mainsa, mainsasz) < 0) {
74
-	closesocket(sockd);
75
-	logg("!Can't connect to clamd: %s\n", strerror(errno));
76
-	return -1;
77
-    }
78
-    return sockd;
104
+    return -1;
79 105
 }
80 106
 
81 107
 /* Issues an INSTREAM command to clamd and streams the given file