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

« back to all changes in this revision

Viewing changes to .pc/0009-Workaround-a-bug-in-libc-on-Hurd.patch/clamd/scanner.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
/*
 
2
 *  Copyright (C) 2007-2009 Sourcefire, Inc.
 
3
 *
 
4
 *  Authors: Tomasz Kojm, Török Edvin
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License version 2 as
 
8
 *  published by the Free Software Foundation.
 
9
 *
 
10
 *  This program is distributed in the hope that it will be useful,
 
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 *  GNU General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU General Public License
 
16
 *  along with this program; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
18
 *  MA 02110-1301, USA.
 
19
 */
 
20
 
 
21
#if HAVE_CONFIG_H
 
22
#include "clamav-config.h"
 
23
#endif
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
#ifdef  HAVE_UNISTD_H
 
29
#include <unistd.h>
 
30
#endif
 
31
#include <errno.h>
 
32
#include <sys/stat.h>
 
33
#include <sys/types.h>
 
34
#include <dirent.h>
 
35
#ifndef _WIN32
 
36
#include <sys/time.h>
 
37
#include <sys/wait.h>
 
38
#include <sys/param.h>
 
39
#include <signal.h>
 
40
#include <sys/socket.h>
 
41
#include <netinet/in.h>
 
42
#include <arpa/inet.h>
 
43
#include <netdb.h>
 
44
#endif
 
45
#include <pthread.h>
 
46
 
 
47
#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2)
 
48
#include <limits.h>
 
49
#include <stddef.h>
 
50
#endif
 
51
 
 
52
#include <openssl/ssl.h>
 
53
#include <openssl/err.h>
 
54
#include "libclamav/crypto.h"
 
55
 
 
56
#include "libclamav/clamav.h"
 
57
#include "libclamav/others.h"
 
58
#include "libclamav/scanners.h"
 
59
 
 
60
#include "shared/optparser.h"
 
61
#include "shared/output.h"
 
62
#include "shared/misc.h"
 
63
 
 
64
#include "others.h"
 
65
#include "scanner.h"
 
66
#include "shared.h"
 
67
#include "thrmgr.h"
 
68
#include "server.h"
 
69
 
 
70
#ifdef C_LINUX
 
71
dev_t procdev; /* /proc device */
 
72
#endif
 
73
 
 
74
extern int progexit;
 
75
extern time_t reloaded_time;
 
76
extern pthread_mutex_t reload_mutex;
 
77
 
 
78
void msg_callback(enum cl_msg severity, const char *fullmsg, const char *msg, void *ctx)
 
79
{
 
80
    struct cb_context *c = ctx;
 
81
    const char *filename = (c && c->filename) ? c->filename : "";
 
82
 
 
83
    switch (severity) {
 
84
        case CL_MSG_ERROR:
 
85
            logg("^[LibClamAV] %s: %s", filename, msg);
 
86
            break;
 
87
        case CL_MSG_WARN:
 
88
            logg("~[LibClamAV] %s: %s", filename, msg);
 
89
            break;
 
90
        case CL_MSG_INFO_VERBOSE:
 
91
            logg("*[LibClamAV] %s: %s", filename, msg);
 
92
            break;
 
93
        default:
 
94
            logg("$[LibClamAV] %s: %s", filename, msg);
 
95
            break;
 
96
    }
 
97
}
 
98
 
 
99
void hash_callback(int fd, unsigned long long size, const unsigned char *md5, const char *virname, void *ctx)
 
100
{
 
101
    struct cb_context *c = ctx;
 
102
    if (!c)
 
103
        return;
 
104
    c->virsize = size;
 
105
    strncpy(c->virhash, md5, 32);
 
106
    c->virhash[32] = '\0';
 
107
}
 
108
 
 
109
#define BUFFSIZE 1024
 
110
int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data)
 
111
{
 
112
    struct scan_cb_data *scandata = data->data;
 
113
    const char *virname = NULL;
 
114
    const char **virpp = &virname;
 
115
    int ret;
 
116
    int type = scandata->type;
 
117
    struct cb_context context;
 
118
 
 
119
    /* detect disconnected socket, 
 
120
     * this should NOT detect half-shutdown sockets (SHUT_WR) */
 
121
    if (send(scandata->conn->sd, &ret, 0, 0) == -1 && errno != EINTR) {
 
122
        logg("$Client disconnected while command was active!\n");
 
123
        thrmgr_group_terminate(scandata->conn->group);
 
124
        if (reason == visit_file)
 
125
            free(filename);
 
126
        return CL_BREAK;
 
127
    }
 
128
 
 
129
    if (thrmgr_group_need_terminate(scandata->conn->group)) {
 
130
        logg("^Client disconnected while scanjob was active\n");
 
131
        if (reason == visit_file)
 
132
            free(filename);
 
133
        return CL_BREAK;
 
134
    }
 
135
    scandata->total++;
 
136
    switch (reason) {
 
137
        case error_mem:
 
138
            if (msg)
 
139
                logg("!Memory allocation failed during cli_ftw() on %s\n",
 
140
                     msg);
 
141
            else
 
142
                logg("!Memory allocation failed during cli_ftw()\n");
 
143
            scandata->errors++;
 
144
            return CL_EMEM;
 
145
        case error_stat:
 
146
            conn_reply_errno(scandata->conn, msg, "lstat() failed:");
 
147
            logg("^lstat() failed on: %s\n", msg);
 
148
            scandata->errors++;
 
149
            return CL_SUCCESS;
 
150
        case warning_skipped_dir:
 
151
            logg("^Directory recursion limit reached, skipping %s\n",
 
152
                     msg);
 
153
            return CL_SUCCESS;
 
154
        case warning_skipped_link:
 
155
            logg("$Skipping symlink: %s\n", msg);
 
156
            return CL_SUCCESS;
 
157
        case warning_skipped_special:
 
158
            if (msg == scandata->toplevel_path)
 
159
                conn_reply(scandata->conn, msg, "Not supported file type", "ERROR");
 
160
            logg("*Not supported file type: %s\n", msg);
 
161
            return CL_SUCCESS;
 
162
        case visit_directory_toplev:
 
163
            return CL_SUCCESS;
 
164
        case visit_file:
 
165
            break;
 
166
    }
 
167
 
 
168
    /* check whether the file is excluded */
 
169
#ifdef C_LINUX
 
170
    if(procdev && sb && (sb->st_dev == procdev)) {
 
171
        free(filename);
 
172
        return CL_SUCCESS;
 
173
    }
 
174
#endif
 
175
 
 
176
    if(sb && sb->st_size == 0) { /* empty file */
 
177
        if (msg == scandata->toplevel_path)
 
178
            conn_reply_single(scandata->conn, filename, "Empty file");
 
179
        free(filename);
 
180
        return CL_SUCCESS;
 
181
    }
 
182
 
 
183
    if (type == TYPE_MULTISCAN) {
 
184
        client_conn_t *client_conn = (client_conn_t *) calloc(1, sizeof(struct client_conn_tag));
 
185
        if(client_conn) {
 
186
            client_conn->scanfd = -1;
 
187
            client_conn->sd = scandata->odesc;
 
188
            client_conn->filename = filename;
 
189
            client_conn->cmdtype = COMMAND_MULTISCANFILE;
 
190
            client_conn->term = scandata->conn->term;
 
191
            client_conn->options = scandata->options;
 
192
            client_conn->opts = scandata->opts;
 
193
            client_conn->group = scandata->group;
 
194
            if(cl_engine_addref(scandata->engine)) {
 
195
                logg("!cl_engine_addref() failed\n");
 
196
                free(filename);
 
197
                free(client_conn);
 
198
                return CL_EMEM;
 
199
            } else {
 
200
                client_conn->engine = scandata->engine;
 
201
                pthread_mutex_lock(&reload_mutex);
 
202
                client_conn->engine_timestamp = reloaded_time;
 
203
                pthread_mutex_unlock(&reload_mutex);
 
204
                if(!thrmgr_group_dispatch(scandata->thr_pool, scandata->group, client_conn, 1)) {
 
205
                    logg("!thread dispatch failed\n");
 
206
                    cl_engine_free(scandata->engine);
 
207
                    free(filename);
 
208
                    free(client_conn);
 
209
                    return CL_EMEM;
 
210
                }
 
211
            }
 
212
        } else {
 
213
            logg("!Can't allocate memory for client_conn\n");
 
214
            scandata->errors++;
 
215
            free(filename);
 
216
            return CL_EMEM;
 
217
        }
 
218
        return CL_SUCCESS;
 
219
    }
 
220
 
 
221
    if (access(filename, R_OK)) {
 
222
        if (conn_reply(scandata->conn, filename, "Access denied.", "ERROR") == -1) {
 
223
            free(filename);
 
224
            return CL_ETIMEOUT;
 
225
        }
 
226
        logg("*Access denied: %s\n", filename);
 
227
        scandata->errors++;
 
228
        free(filename);
 
229
        return CL_SUCCESS;
 
230
    }
 
231
 
 
232
    thrmgr_setactivetask(filename, NULL);
 
233
    context.filename = filename;
 
234
    context.virsize = 0;
 
235
    ret = cl_scanfile_callback(filename, virpp, &scandata->scanned, scandata->engine, scandata->options, &context);
 
236
    thrmgr_setactivetask(NULL, NULL);
 
237
 
 
238
    if (scandata->options & CL_SCAN_ALLMATCHES) {
 
239
        virpp = (const char **)*virpp; /* temp hack for scanall mode until api augmentation */
 
240
        if (virpp) virname = virpp[0];
 
241
    }
 
242
 
 
243
    if (thrmgr_group_need_terminate(scandata->conn->group)) {
 
244
        free(filename);
 
245
        if ((scandata->options & CL_SCAN_ALLMATCHES) && (virpp != &virname))
 
246
            free((void *)virpp);
 
247
        logg("*Client disconnected while scanjob was active\n");
 
248
        return ret == CL_ETIMEOUT ? ret : CL_BREAK;
 
249
    }
 
250
 
 
251
    if ((ret == CL_VIRUS) && (virname == NULL)) {
 
252
        logg("*%s: reported CL_VIRUS but no virname returned!\n", filename);
 
253
        ret = CL_EMEM;
 
254
    }
 
255
 
 
256
    if (ret == CL_VIRUS) {
 
257
        scandata->infected++;
 
258
        if (conn_reply_virus(scandata->conn, filename, virname) == -1) {
 
259
            free(filename);
 
260
            if((scandata->options & CL_SCAN_ALLMATCHES) && (virpp != &virname))
 
261
                free((void *)virpp);
 
262
            return CL_ETIMEOUT;
 
263
        }
 
264
        if (scandata->options & CL_SCAN_ALLMATCHES && virpp[1] != NULL) {
 
265
            int i = 1;
 
266
            while (NULL != virpp[i])
 
267
                if (conn_reply_virus(scandata->conn, filename, virpp[i++]) == -1) {
 
268
                    free(filename);
 
269
                    if (virpp != &virname)
 
270
                        free((void *)virpp);
 
271
                    return CL_ETIMEOUT;
 
272
                }
 
273
        }
 
274
        if(context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled)
 
275
            logg("~%s: %s(%s:%llu) FOUND\n", filename, virname, context.virhash, context.virsize);
 
276
        else
 
277
            logg("~%s: %s FOUND\n", filename, virname);
 
278
        virusaction(filename, virname, scandata->opts);
 
279
        if (scandata->options & CL_SCAN_ALLMATCHES && virpp[1] != NULL) {
 
280
            int i = 1;
 
281
            while (NULL != virpp[i])
 
282
                logg("~%s: %s FOUND\n", filename, virpp[i++]);
 
283
        }
 
284
    } else if (ret != CL_CLEAN) {
 
285
        scandata->errors++;
 
286
        if (conn_reply(scandata->conn, filename, cl_strerror(ret), "ERROR") == -1) {
 
287
            if((scandata->options & CL_SCAN_ALLMATCHES) && (virpp != &virname))
 
288
                free((void *)virpp);
 
289
            free(filename);
 
290
            return CL_ETIMEOUT;
 
291
        }
 
292
        logg("~%s: %s ERROR\n", filename, cl_strerror(ret));
 
293
    } else if (logok) {
 
294
        logg("~%s: OK\n", filename);
 
295
    }
 
296
 
 
297
    free(filename);
 
298
    if((scandata->options & CL_SCAN_ALLMATCHES) && (virpp != &virname))
 
299
        free((void *)virpp);
 
300
    if(ret == CL_EMEM) /* stop scanning */
 
301
        return ret;
 
302
 
 
303
    if (type == TYPE_SCAN) {
 
304
        /* virus -> break */
 
305
        return ret;
 
306
    }
 
307
 
 
308
    /* keep scanning always */
 
309
    return CL_SUCCESS;
 
310
}
 
311
 
 
312
int scan_pathchk(const char *path, struct cli_ftw_cbdata *data)
 
313
{
 
314
        struct scan_cb_data *scandata = data->data;
 
315
        const struct optstruct *opt;
 
316
        STATBUF statbuf;
 
317
 
 
318
    if((opt = optget(scandata->opts, "ExcludePath"))->enabled) {
 
319
        while(opt) {
 
320
            if(match_regex(path, opt->strarg) == 1) {
 
321
                if(scandata->type != TYPE_MULTISCAN)
 
322
                    conn_reply_single(scandata->conn, path, "Excluded");
 
323
                return 1;
 
324
            }
 
325
            opt = (const struct optstruct *) opt->nextarg;
 
326
        }
 
327
    }
 
328
 
 
329
    if(!optget(scandata->opts, "CrossFilesystems")->enabled) {
 
330
        if(CLAMSTAT(path, &statbuf) == 0) {
 
331
            if(statbuf.st_dev != scandata->dev) {
 
332
                if(scandata->type != TYPE_MULTISCAN)
 
333
                    conn_reply_single(scandata->conn, path, "Excluded (another filesystem)");
 
334
                return 1;
 
335
            }
 
336
        }
 
337
    }
 
338
 
 
339
    return 0;
 
340
}
 
341
 
 
342
int scanfd(const client_conn_t *conn, unsigned long int *scanned,
 
343
           const struct cl_engine *engine,
 
344
           unsigned int options, const struct optstruct *opts, int odesc, int stream)
 
345
{
 
346
    int ret, fd = conn->scanfd;
 
347
        const char *virname;
 
348
        STATBUF statbuf;
 
349
        struct cb_context context;
 
350
        char fdstr[32];
 
351
        const char*reply_fdstr;
 
352
 
 
353
        if (stream) {
 
354
            struct sockaddr_in sa;
 
355
            socklen_t salen = sizeof(sa);
 
356
            if(getpeername(conn->sd, (struct sockaddr *)&sa, &salen) || salen > sizeof(sa) || sa.sin_family != AF_INET)
 
357
                strncpy(fdstr, "instream(local)", sizeof(fdstr));
 
358
            else
 
359
                snprintf(fdstr, sizeof(fdstr), "instream(%s@%u)", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
 
360
            reply_fdstr = "stream";
 
361
        } else {
 
362
            snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd);
 
363
            reply_fdstr = fdstr;
 
364
        }
 
365
        if(FSTAT(fd, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) {
 
366
                logg("%s: Not a regular file. ERROR\n", fdstr);
 
367
                if (conn_reply(conn, reply_fdstr, "Not a regular file", "ERROR") == -1)
 
368
                    return CL_ETIMEOUT;
 
369
                return -1;
 
370
        }
 
371
 
 
372
        thrmgr_setactivetask(fdstr, NULL);
 
373
        context.filename = fdstr;
 
374
        context.virsize = 0;
 
375
        ret = cl_scandesc_callback(fd, &virname, scanned, engine, options, &context);
 
376
        thrmgr_setactivetask(NULL, NULL);
 
377
 
 
378
        if (thrmgr_group_need_terminate(conn->group)) {
 
379
            logg("*Client disconnected while scanjob was active\n");
 
380
            return ret == CL_ETIMEOUT ? ret : CL_BREAK;
 
381
        }
 
382
 
 
383
        if(ret == CL_VIRUS) {
 
384
                if (conn_reply_virus(conn, reply_fdstr, virname) == -1)
 
385
                    ret = CL_ETIMEOUT;
 
386
                if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled)
 
387
                    logg("%s: %s(%s:%llu) FOUND\n", fdstr, virname, context.virhash, context.virsize);
 
388
                else
 
389
                    logg("%s: %s FOUND\n", fdstr, virname);
 
390
                virusaction(reply_fdstr, virname, opts);
 
391
        } else if(ret != CL_CLEAN) {
 
392
                if (conn_reply(conn, reply_fdstr, cl_strerror(ret), "ERROR") == -1)
 
393
                    ret = CL_ETIMEOUT;
 
394
                logg("%s: %s ERROR\n", fdstr, cl_strerror(ret));
 
395
        } else {
 
396
                if (conn_reply_single(conn, reply_fdstr, "OK") == CL_ETIMEOUT)
 
397
                    ret = CL_ETIMEOUT;
 
398
                if(logok)
 
399
                        logg("%s: OK\n", fdstr);
 
400
        }
 
401
        return ret;
 
402
}
 
403
 
 
404
int scanstream(int odesc, unsigned long int *scanned, const struct cl_engine *engine, unsigned int options, const struct optstruct *opts, char term)
 
405
{
 
406
        int ret, sockfd, acceptd;
 
407
        int tmpd, bread, retval, firsttimeout, timeout, btread;
 
408
        unsigned int port = 0, portscan, min_port, max_port;
 
409
        unsigned long int quota = 0, maxsize = 0;
 
410
        short bound = 0;
 
411
        const char *virname;
 
412
        char buff[FILEBUFF];
 
413
        char peer_addr[32];
 
414
        struct cb_context context;
 
415
        struct sockaddr_in server;
 
416
        struct sockaddr_in peer;
 
417
        socklen_t addrlen;
 
418
        char *tmpname;
 
419
 
 
420
 
 
421
    min_port = optget(opts, "StreamMinPort")->numarg;
 
422
    max_port = optget(opts, "StreamMaxPort")->numarg;
 
423
 
 
424
    /* search for a free port to bind to */
 
425
    port = cli_rndnum(max_port - min_port);
 
426
    bound = 0;
 
427
    for (portscan = 0; portscan < 1000; portscan++) {
 
428
        port = (port - 1) % (max_port - min_port + 1);
 
429
 
 
430
        memset((char *) &server, 0, sizeof(server));
 
431
        server.sin_family = AF_INET;
 
432
        server.sin_port = htons(min_port + port);
 
433
        server.sin_addr.s_addr = htonl(INADDR_ANY);
 
434
 
 
435
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
 
436
            continue;
 
437
 
 
438
        if(bind(sockfd, (struct sockaddr *) &server, (socklen_t)sizeof(struct sockaddr_in)) == -1)
 
439
            closesocket(sockfd);
 
440
        else {
 
441
            bound = 1;
 
442
            break;
 
443
        }
 
444
    }
 
445
    port += min_port;
 
446
 
 
447
    timeout = optget(opts, "ReadTimeout")->numarg;
 
448
    firsttimeout = optget(opts, "CommandReadTimeout")->numarg;
 
449
 
 
450
    if(!bound) {
 
451
        logg("!ScanStream: Can't find any free port.\n");
 
452
        mdprintf(odesc, "Can't find any free port. ERROR%c", term);
 
453
        return -1;
 
454
    } else {
 
455
        if (listen(sockfd, 1) == -1) {
 
456
        logg("!ScanStream: listen() error on socket. Error returned is %s.\n", strerror(errno));
 
457
        closesocket(sockfd);
 
458
        return -1;
 
459
    }
 
460
        if(mdprintf(odesc, "PORT %u%c", port, term) <= 0) {
 
461
            logg("!ScanStream: error transmitting port.\n");
 
462
            closesocket(sockfd);
 
463
            return -1;
 
464
        }
 
465
    }
 
466
 
 
467
    retval = poll_fd(sockfd, firsttimeout, 0);
 
468
    if (!retval || retval == -1) {
 
469
        const char *reason = !retval ? "timeout" : "poll";
 
470
        mdprintf(odesc, "Accept %s. ERROR%c", reason, term);
 
471
        logg("!ScanStream %u: accept %s.\n", port, reason);
 
472
        closesocket(sockfd);
 
473
        return -1;
 
474
    }
 
475
 
 
476
    addrlen = sizeof(peer);
 
477
    if((acceptd = accept(sockfd, (struct sockaddr *) &peer, (socklen_t *)&addrlen)) == -1) {
 
478
        closesocket(sockfd);
 
479
        mdprintf(odesc, "accept() ERROR%c", term);
 
480
        logg("!ScanStream %u: accept() failed.\n", port);
 
481
        return -1;
 
482
    }
 
483
 
 
484
    *peer_addr = '\0';
 
485
    inet_ntop(peer.sin_family, &peer.sin_addr, peer_addr, sizeof(peer_addr));
 
486
    logg("*Accepted connection from %s on port %u, fd %d\n", peer_addr, port, acceptd);
 
487
 
 
488
    if(cli_gentempfd(optget(opts, "TemporaryDirectory")->strarg, &tmpname, &tmpd)) {
 
489
        shutdown(sockfd, 2);
 
490
        closesocket(sockfd);
 
491
        closesocket(acceptd);
 
492
        mdprintf(odesc, "cli_gentempfd() failed. ERROR%c", term);
 
493
        logg("!ScanStream(%s@%u): Can't create temporary file.\n", peer_addr, port);
 
494
        return -1;
 
495
    }
 
496
 
 
497
    quota = maxsize = optget(opts, "StreamMaxLength")->numarg;
 
498
 
 
499
    while((retval = poll_fd(acceptd, timeout, 0)) == 1) {
 
500
        /* only read up to max */
 
501
        btread = (maxsize && (quota < sizeof(buff))) ? quota : sizeof(buff);
 
502
        if (!btread) {
 
503
                logg("^ScanStream(%s@%u): Size limit reached (max: %lu)\n", peer_addr, port, maxsize);
 
504
                break; /* Scan what we have */
 
505
        }
 
506
        bread = recv(acceptd, buff, btread, 0);
 
507
        if(bread <= 0)
 
508
            break;
 
509
 
 
510
        quota -= bread;
 
511
 
 
512
        if(writen(tmpd, buff, bread) != bread) {
 
513
            shutdown(sockfd, 2);
 
514
            closesocket(sockfd);
 
515
            closesocket(acceptd);
 
516
            mdprintf(odesc, "Temporary file -> write ERROR%c", term);
 
517
            logg("!ScanStream(%s@%u): Can't write to temporary file.\n", peer_addr, port);
 
518
            close(tmpd);
 
519
            if(!optget(opts, "LeaveTemporaryFiles")->enabled)
 
520
                unlink(tmpname);
 
521
            free(tmpname);
 
522
            return -1;
 
523
        }
 
524
    }
 
525
 
 
526
    switch(retval) {
 
527
        case 0: /* timeout */
 
528
            mdprintf(odesc, "read timeout ERROR%c", term);
 
529
            logg("!ScanStream(%s@%u): read timeout.\n", peer_addr, port);
 
530
            break;
 
531
        case -1:
 
532
            mdprintf(odesc, "read poll ERROR%c", term);
 
533
            logg("!ScanStream(%s@%u): read poll failed.\n", peer_addr, port);
 
534
            break;
 
535
    }
 
536
 
 
537
    if(retval == 1) {
 
538
        lseek(tmpd, 0, SEEK_SET);
 
539
        thrmgr_setactivetask(peer_addr, NULL);
 
540
        context.filename = peer_addr;
 
541
        context.virsize = 0;
 
542
        ret = cl_scandesc_callback(tmpd, &virname, scanned, engine, options, &context);
 
543
        thrmgr_setactivetask(NULL, NULL);
 
544
    } else {
 
545
        ret = -1;
 
546
    }
 
547
    close(tmpd);
 
548
    if(!optget(opts, "LeaveTemporaryFiles")->enabled)
 
549
        unlink(tmpname);
 
550
    free(tmpname);
 
551
 
 
552
    closesocket(acceptd);
 
553
    closesocket(sockfd);
 
554
 
 
555
    if(ret == CL_VIRUS) {
 
556
        if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) {
 
557
            mdprintf(odesc, "stream: %s(%s:%llu) FOUND%c", virname, context.virhash, context.virsize, term);
 
558
            logg("stream(%s@%u): %s(%s:%llu) FOUND\n", peer_addr, port, virname, context.virhash, context.virsize);
 
559
        } else {
 
560
            mdprintf(odesc, "stream: %s FOUND%c", virname, term);
 
561
            logg("stream(%s@%u): %s FOUND\n", peer_addr, port, virname);
 
562
        }
 
563
        virusaction("stream", virname, opts);
 
564
    } else if(ret != CL_CLEAN) {
 
565
        if(retval == 1) {
 
566
            mdprintf(odesc, "stream: %s ERROR%c", cl_strerror(ret), term);
 
567
            logg("stream(%s@%u): %s ERROR\n", peer_addr, port, cl_strerror(ret));
 
568
        }
 
569
    } else {
 
570
        mdprintf(odesc, "stream: OK%c", term);
 
571
        if(logok)
 
572
            logg("stream(%s@%u): OK\n", peer_addr, port); 
 
573
    }
 
574
 
 
575
    return ret;
 
576
}