initial support for hardware acceleration

git-svn: trunk@1895
remotes/push_mirror/metadata
Tomasz Kojm 19 years ago
parent a9ecf61922
commit f51e962fc7
  1. 6
      clamav-devel/ChangeLog
  2. 11
      clamav-devel/clamscan/clamscan.c
  3. 5
      clamav-devel/clamscan/manager.c
  4. 3
      clamav-devel/clamscan/options.c
  5. 147
      clamav-devel/configure
  6. 8
      clamav-devel/configure.in
  7. 8
      clamav-devel/libclamav/clamav.h
  8. 2
      clamav-devel/libclamav/filetypes.c
  9. 236
      clamav-devel/libclamav/matcher.c
  10. 6
      clamav-devel/libclamav/others.c
  11. 196
      clamav-devel/libclamav/readdb.c

@ -1,3 +1,9 @@
Fri Apr 7 21:09:25 CEST 2006 (tk)
----------------------------------
* libclamav: initial support for Sensory Network's NodalCore Accelerator
* clamscan: new option --hwaccel (only available on systems with hardware
accelerators)
Fri Apr 7 12:25:20 BST 2006 (njh)
----------------------------------
* libclamav/mbox.c: Better handling of messages with lots of

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
* Copyright (C) 2002 - 2006 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -161,7 +161,10 @@ int clamscan(struct optstruct *opt)
dms += (dms < 0) ? (1000000):(0);
logg("\n----------- SCAN SUMMARY -----------\n");
logg("Known viruses: %d\n", claminfo.signs);
logg("Engine version: %s\n", cl_retver());
if(optl(opt, "hwaccel"))
logg("Engine version: %s [hwaccel]\n", cl_retver());
else
logg("Engine version: %s\n", cl_retver());
logg("Scanned directories: %d\n", claminfo.dirs);
logg("Scanned files: %d\n", claminfo.files);
logg("Infected files: %d\n", claminfo.ifiles);
@ -223,7 +226,9 @@ void help(void)
mprintf(" --include=PATT Only scan file names containing PATT\n");
mprintf(" --include-dir=PATT Only scan directories containing PATT\n");
#endif
#ifdef HAVE_HWACCEL
mprintf("\n --hwaccel Use hardware acceleration\n");
#endif
mprintf("\n");
mprintf(" --no-mail Disable mail file support\n");
mprintf(" --no-phishing Disable phishing detection\n");

@ -85,7 +85,10 @@ int scanmanager(const struct optstruct *opt)
optl(opt, "tar") || optl(opt, "tgz") || optl(opt, "deb"))
compression = 1;
/* now initialize the database */
if(optl(opt, "hwaccel"))
dboptions |= CL_DB_HWACCEL;
if(optl(opt, "no-phishing"))
dboptions |= CL_DB_NOPHISHING;

@ -93,6 +93,9 @@ int main(int argc, char **argv)
{"max-ratio", 1, 0, 0},
{"max-recursion", 1, 0, 0},
{"max-dir-recursion", 1, 0, 0},
#ifdef HWACCEL
{"hwaccel", 0, 0, 0},
#endif
{"disable-archive", 0, 0, 0},
{"no-archive", 0, 0, 0},
{"detect-broken", 0, 0, 0},

@ -10825,13 +10825,160 @@ fi
echo "$as_me:$LINENO: result: $ac_cv_lib_sn_sigscan_sn_sigscan_initdb" >&5
echo "${ECHO_T}$ac_cv_lib_sn_sigscan_sn_sigscan_initdb" >&6
if test $ac_cv_lib_sn_sigscan_sn_sigscan_initdb = yes; then
have_sigscan=yes
fi
if test "$have_sigscan" = "yes"
then
if test "${ac_cv_header_sn_sigscan_sn_sigscan_h+set}" = set; then
echo "$as_me:$LINENO: checking for sn_sigscan/sn_sigscan.h" >&5
echo $ECHO_N "checking for sn_sigscan/sn_sigscan.h... $ECHO_C" >&6
if test "${ac_cv_header_sn_sigscan_sn_sigscan_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
fi
echo "$as_me:$LINENO: result: $ac_cv_header_sn_sigscan_sn_sigscan_h" >&5
echo "${ECHO_T}$ac_cv_header_sn_sigscan_sn_sigscan_h" >&6
else
# Is the header compilable?
echo "$as_me:$LINENO: checking sn_sigscan/sn_sigscan.h usability" >&5
echo $ECHO_N "checking sn_sigscan/sn_sigscan.h usability... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <sn_sigscan/sn_sigscan.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6
# Is the header present?
echo "$as_me:$LINENO: checking sn_sigscan/sn_sigscan.h presence" >&5
echo $ECHO_N "checking sn_sigscan/sn_sigscan.h presence... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <sn_sigscan/sn_sigscan.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
else
ac_cpp_err=
fi
else
ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
yes:no: )
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: present but cannot be compiled" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: present but cannot be compiled" >&2;}
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: check for missing prerequisite headers?" >&2;}
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: see the Autoconf documentation" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: see the Autoconf documentation" >&2;}
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: section \"Present But Cannot Be Compiled\"" >&2;}
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: proceeding with the preprocessor's result" >&2;}
{ echo "$as_me:$LINENO: WARNING: sn_sigscan/sn_sigscan.h: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: sn_sigscan/sn_sigscan.h: in the future, the compiler will take precedence" >&2;}
(
cat <<\_ASBOX
## ------------------------------------------ ##
## Report this to the AC_PACKAGE_NAME lists. ##
## ------------------------------------------ ##
_ASBOX
) |
sed "s/^/$as_me: WARNING: /" >&2
;;
esac
echo "$as_me:$LINENO: checking for sn_sigscan/sn_sigscan.h" >&5
echo $ECHO_N "checking for sn_sigscan/sn_sigscan.h... $ECHO_C" >&6
if test "${ac_cv_header_sn_sigscan_sn_sigscan_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_cv_header_sn_sigscan_sn_sigscan_h=$ac_header_preproc
fi
echo "$as_me:$LINENO: result: $ac_cv_header_sn_sigscan_sn_sigscan_h" >&5
echo "${ECHO_T}$ac_cv_header_sn_sigscan_sn_sigscan_h" >&6
fi
if test $ac_cv_header_sn_sigscan_sn_sigscan_h = yes; then
LIBCLAMAV_LIBS="$LIBCLAMAV_LIBS -lsn_sigscan";
cat >>confdefs.h <<\_ACEOF
#define HAVE_HWACCEL 1
_ACEOF
else
{ echo "$as_me:$LINENO: WARNING: ****** hardware acceleration support disabled -- please install libsigscan-devel " >&5
echo "$as_me: WARNING: ****** hardware acceleration support disabled -- please install libsigscan-devel " >&2;}
fi
fi
fi
# Check whether --enable-dns or --disable-dns was given.

@ -1,5 +1,5 @@
dnl
dnl Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
dnl Copyright (C) 2002 - 2006 Tomasz Kojm <tkojm@clamav.net>
dnl gethostbyname_r and readdir_r checks (c) COPYRIGHT MIT 1995
dnl
dnl This program is free software; you can redistribute it and/or modify
@ -143,7 +143,11 @@ want_hwaccel=$enableval, want_hwaccel="yes")
if test "$want_hwaccel" = "yes"
then
AC_CHECK_LIB(sn_sigscan, sn_sigscan_initdb, AC_DEFINE(HAVE_HWACCEL,1,hardware acceleration),)
AC_CHECK_LIB(sn_sigscan, sn_sigscan_initdb, have_sigscan=yes,)
if test "$have_sigscan" = "yes"
then
AC_CHECK_HEADER(sn_sigscan/sn_sigscan.h,[LIBCLAMAV_LIBS="$LIBCLAMAV_LIBS -lsn_sigscan"; AC_DEFINE(HAVE_HWACCEL,1,hardware acceleration)], AC_MSG_WARN([****** hardware acceleration support disabled -- please install libsigscan-devel ]))
fi
fi
AC_ARG_ENABLE(dns,

@ -34,6 +34,7 @@ extern "C"
/* return codes */
#define CL_CLEAN 0 /* virus not found */
#define CL_VIRUS 1 /* virus found */
#define CL_SUCCESS CL_CLEAN
#define CL_EMAXREC 10 /* recursion level limit exceeded */
#define CL_EMAXSIZE 11 /* size limit exceeded */
@ -63,6 +64,11 @@ extern "C"
#define CL_EIO -12 /* general I/O error */
#define CL_EFORMAT -13 /* bad format or broken file */
#define CL_EHWINIT -14 /* hardware initialization failed */
#define CL_EHWLOAD -15 /* error loading hardware database */
#define CL_EHWIO -16 /* general hardware I/O error */
/* db options */
#define CL_DB_HWACCEL 1
#define CL_DB_NOPHISHING 2
@ -164,6 +170,8 @@ struct cl_engine {
/* RAR metadata */
struct cli_meta_node *rar_mlist;
/* Hardware database handle */
void *hwdb;
};
struct cl_limits {

@ -293,8 +293,10 @@ int cli_addtypesigs(struct cl_engine *engine)
}
if(engine->hwaccel) {
/*
cli_dbgmsg("cli_addtypesigs: AC depth 10 (hwaccel mode)\n");
cli_ac_setdepth(10);
*/
}
root->ac_root = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
* Copyright (C) 2002 - 2006 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -45,16 +45,23 @@ static int targettab[CL_TARGET_TABLE_SIZE] = { 0, CL_TYPE_MSEXE, CL_TYPE_MSOLE2,
extern short cli_debug_flag;
#ifdef CL_THREAD_SAFE
# include <pthread.h>
static pthread_mutex_t cli_ref_mutex = PTHREAD_MUTEX_INITIALIZER;
#ifdef HAVE_HWACCEL
#include <sn_sigscan/sn_sigscan.h>
#define HWBUFFSIZE 32768
#endif
int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype)
{
int ret, i, tid = 0, *partcnt;
int ret = CL_CLEAN, i, tid = 0, *partcnt;
unsigned long int *partoff;
struct cli_matcher *groot, *troot = NULL;
#ifdef HAVE_HWACCEL
void *streamhandle;
void *resulthandle;
uint32_t datamask[2] = { 1, 1 };
int count, hret;
unsigned long long offset;
#endif
if(!engine) {
@ -62,6 +69,49 @@ int cli_scanbuff(const char *buffer, unsigned int length, const char **virname,
return CL_ENULLARG;
}
#ifdef HAVE_HWACCEL
if(engine->hwaccel) {
/* TODO: Setup proper data bitmask (need specs) */
if((hret = sn_sigscan_createstream(engine->hwdb, datamask, 2, &streamhandle)) < 0) {
cli_errmsg("cli_scanbuff: can't create new hardware stream: %d\n", hret);
return CL_EHWIO;
}
if((hret = sn_sigscan_writestream(streamhandle, buffer, length)) < 0) {
cli_errmsg("cli_scanbuff: can't write %u bytes to hardware stream: %d\n", length, hret);
sn_sigscan_closestream(streamhandle, &resulthandle);
return CL_EHWIO;
}
if((hret = sn_sigscan_closestream(streamhandle, &resulthandle)) < 0) {
cli_errmsg("cli_scanbuff: can't close hardware stream: %d\n", hret);
return CL_EHWIO;
}
count = sn_sigscan_resultcount(resulthandle);
cli_dbgmsg("cli_scanbuff: number of results: %d\n", count);
if(count > 0) {
if((hret = sn_sigscan_resultget(resulthandle, 0, virname, &offset)) < 0) {
cli_errmsg("cli_scanbuff: can't get hardware match result: %d\n", hret);
sn_sigscan_resultfree(resulthandle);
return CL_EHWIO;
} else {
cli_dbgmsg("cli_scanbuff: hardware match %s at %u\n", *virname, offset);
ret = CL_VIRUS;
}
}
if((hret = sn_sigscan_resultfree(resulthandle)) < 0) {
cli_errmsg("cli_scanbuff: can't free results: %d\n", ret);
return CL_EHWIO;
}
return ret;
}
#endif /* HAVE_HWACCEL */
groot = engine->root[0]; /* generic signatures */
if(ftype) {
@ -277,13 +327,20 @@ int cli_validatesig(unsigned short target, unsigned short ftype, const char *off
int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short ftype, struct cli_matched_type **ftoffset)
{
char *buffer, *buff, *endbl, *pt;
int ret, *gpartcnt, *tpartcnt, type = CL_CLEAN, i, tid = 0, bytes;
int ret = CL_CLEAN, *gpartcnt, *tpartcnt, type = CL_CLEAN, i, tid = 0, bytes;
unsigned int buffersize, length, maxpatlen, shift = 0;
unsigned long int *gpartoff, *tpartoff, offset = 0;
MD5_CTX md5ctx;
unsigned char digest[16];
struct cli_md5_node *md5_node;
struct cli_matcher *groot, *troot = NULL;
#ifdef HAVE_HWACCEL
void *streamhandle;
void *resulthandle;
unsigned long long hoffset;
uint32_t datamask[2] = { 1, 1 };
int count, hret;
#endif
if(!ctx->engine) {
@ -291,6 +348,61 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
return CL_ENULLARG;
}
#ifdef HAVE_HWACCEL
if(ctx->engine->hwaccel) {
/* TODO: Setup proper data bitmask (need specs) */
if((hret = sn_sigscan_createstream(ctx->engine->hwdb, datamask, 2, &streamhandle)) < 0) {
cli_errmsg("cli_scandesc: can't create new hardware stream: %d\n", hret);
return CL_EHWIO;
}
if(!(buffer = (char *) cli_calloc(HWBUFFSIZE, sizeof(char)))) {
cli_dbgmsg("cli_scandesc: unable to cli_calloc(%u)\n", HWBUFFSIZE);
return CL_EMEM;
}
while((bytes = cli_readn(desc, buffer, HWBUFFSIZE)) > 0) {
if((hret = sn_sigscan_writestream(streamhandle, buffer, bytes)) < 0) {
cli_errmsg("cli_scandesc: can't write to hardware stream: %d\n", hret);
ret = CL_EHWIO;
break;
} else {
if(ctx->scanned)
*ctx->scanned += bytes / CL_COUNT_PRECISION;
}
}
free(buffer);
if((hret = sn_sigscan_closestream(streamhandle, &resulthandle)) < 0) {
cli_errmsg("cli_scandesc: can't close hardware stream: %d\n", hret);
return CL_EHWIO;
}
count = sn_sigscan_resultcount(resulthandle);
cli_dbgmsg("cli_scandesc: number of results: %d\n", count);
if(count > 0) {
if((hret = sn_sigscan_resultget(resulthandle, 0, ctx->virname, &hoffset)) < 0) {
cli_errmsg("cli_scandesc: can't get hardware match result: %d\n", hret);
sn_sigscan_resultfree(resulthandle);
return CL_EHWIO;
} else {
cli_dbgmsg("cli_scandesc: hardware match %s at %u\n", *ctx->virname, hoffset);
ret = CL_VIRUS;
}
}
if((hret = sn_sigscan_resultfree(resulthandle)) < 0) {
cli_errmsg("cli_scandesc: can't free results: %d\n", ret);
return CL_EHWIO;
}
return ret;
}
#endif /* HAVE_HWACCEL */
groot = ctx->engine->root[0]; /* generic signatures */
if(ftype) {
@ -472,115 +584,3 @@ int cli_scandesc(int desc, cli_ctx *ctx, unsigned short otfrec, unsigned short f
return otfrec ? type : CL_CLEAN;
}
int cl_build(struct cl_engine *engine)
{
int i, ret;
struct cli_matcher *root;
if((ret = cli_addtypesigs(engine)))
return ret;
for(i = 0; i < CL_TARGET_TABLE_SIZE; i++)
if((root = engine->root[i]))
cli_ac_buildtrie(root);
/* FIXME: check return values of cli_ac_buildtree */
return 0;
}
struct cl_engine *cl_dup(struct cl_engine *engine)
{
if(!engine) {
cli_errmsg("cl_dup: engine == NULL\n");
return NULL;
}
#ifdef CL_THREAD_SAFE
pthread_mutex_lock(&cli_ref_mutex);
#endif
engine->refcount++;
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif
return engine;
}
void cl_free(struct cl_engine *engine)
{
int i;
struct cli_md5_node *md5pt, *md5h;
struct cli_meta_node *metapt, *metah;
struct cli_matcher *root;
if(!engine) {
cli_errmsg("cl_free: engine == NULL\n");
return;
}
#ifdef CL_THREAD_SAFE
pthread_mutex_lock(&cli_ref_mutex);
#endif
engine->refcount--;
if(engine->refcount) {
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif
return;
}
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif
for(i = 0; i < CL_TARGET_TABLE_SIZE; i++) {
if((root = engine->root[i])) {
cli_ac_free(root);
if(!engine->root[i]->ac_only)
cli_bm_free(root);
}
}
if(engine->md5_hlist) {
for(i = 0; i < 256; i++) {
md5pt = engine->md5_hlist[i];
while(md5pt) {
md5h = md5pt;
md5pt = md5pt->next;
free(md5h->md5);
free(md5h->virname);
if(md5h->viralias)
free(md5h->viralias);
free(md5h);
}
}
free(engine->md5_hlist);
}
metapt = engine->zip_mlist;
while(metapt) {
metah = metapt;
metapt = metapt->next;
free(metah->virname);
if(metah->filename)
free(metah->filename);
free(metah);
}
metapt = engine->rar_mlist;
while(metapt) {
metah = metapt;
metapt = metapt->next;
free(metah->virname);
if(metah->filename)
free(metah->filename);
free(metah);
}
free(engine);
}

@ -195,6 +195,12 @@ const char *cl_strerror(int clerror)
return "Input/Output error";
case CL_EFORMAT:
return "Bad format or broken data";
case CL_EHWINIT:
return "Hardware initialization failure";
case CL_EHWLOAD:
return "Error loading hardware database";
case CL_EHWIO:
return "Hardware accelerator Input/Output error";
default:
return "Unknown error code";
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
* Copyright (C) 2002 - 2006 Tomasz Kojm <tkojm@clamav.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -58,6 +58,16 @@
# endif
#endif
#ifdef CL_THREAD_SAFE
# include <pthread.h>
static pthread_mutex_t cli_ref_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
#ifdef HAVE_HWACCEL
#include <sn_sigscan/sn_sigscan.h>
#endif
/* TODO: clean up the code */
static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, int sigid, int parts, int partno, unsigned short type, unsigned int mindist, unsigned int maxdist, char *offset, unsigned short target)
@ -962,14 +972,56 @@ static int cli_loadmd(FILE *fd, struct cl_engine **engine, unsigned int *signo,
return 0;
}
#ifdef HAVE_HWACCEL
static int cli_loadhw(const char *filename, struct cl_engine **engine, unsigned int *signo, unsigned int options)
{
int ret = 0;
if((ret = cli_initengine(engine, options))) {
cl_free(*engine);
return ret;
}
if((ret = sn_sigscan_initdb(&(*engine)->hwdb)) < 0) {
cli_errmsg("hwaccel: error initializing the matcher: %d\n", ret);
cl_free(*engine);
return CL_EHWINIT;
}
(*engine)->hwaccel = 1;
if((ret = sn_sigscan_loaddb((*engine)->hwdb, filename, 0, signo)) < 0) {
cli_errmsg("hwaccel: can't load hardware database: %d\n", ret);
cl_free(*engine);
return CL_EHWLOAD;
}
return CL_SUCCESS;
}
#endif /* HAVE_HWACCEL */
static int cli_load(const char *filename, struct cl_engine **engine, unsigned int *signo, unsigned int options)
{
FILE *fd;
int ret;
int ret = CL_SUCCESS;
#ifdef HAVE_HWACCEL
if(options & CL_DB_HWACCEL) {
if(cli_strbcasestr(filename, ".hw")) {
cli_dbgmsg("Loading %s\n", filename);
ret = cli_loadhw(filename, engine, signo, options);
} else {
cli_dbgmsg("Ignoring %s\n", filename);
}
return ret;
}
#endif /* HAVE_HWACCEL */
if((fd = fopen(filename, "rb")) == NULL) {
cli_errmsg("cli_loaddb(): Can't open file %s\n", filename);
cli_errmsg("cli_load(): Can't open file %s\n", filename);
return CL_EOPEN;
}
@ -1005,7 +1057,7 @@ static int cli_load(const char *filename, struct cl_engine **engine, unsigned in
ret = cli_loadmd(fd, engine, signo, 2, options);
} else {
cli_dbgmsg("cli_loaddb: unknown extension - assuming old database format\n");
cli_dbgmsg("cli_load: unknown extension - assuming old database format\n");
ret = cli_loaddb(fd, engine, signo, options);
}
@ -1062,6 +1114,7 @@ static int cli_loaddbdir(const char *dirname, struct cl_engine **engine, unsigne
cli_strbcasestr(dent->d_name, ".sdb") ||
cli_strbcasestr(dent->d_name, ".zmd") ||
cli_strbcasestr(dent->d_name, ".rmd") ||
cli_strbcasestr(dent->d_name, ".hw") ||
cli_strbcasestr(dent->d_name, ".cvd"))) {
dbfile = (char *) cli_calloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char));
@ -1107,14 +1160,7 @@ int cl_load(const char *path, struct cl_engine **engine, unsigned int *signo, un
return ret;
}
if(options & CL_DB_HWACCEL) {
(*engine)->hwaccel = 1;
/* load hw db */
return 0;
} else switch(sb.st_mode & S_IFMT) {
switch(sb.st_mode & S_IFMT) {
case S_IFREG:
return cli_load(path, engine, signo, options);
@ -1178,11 +1224,12 @@ int cl_statinidir(const char *dirname, struct cl_stat *dbstat)
cli_strbcasestr(dent->d_name, ".db2") ||
cli_strbcasestr(dent->d_name, ".db3") ||
cli_strbcasestr(dent->d_name, ".hdb") ||
cli_strbcasestr(dent->d_name, ".fp") ||
cli_strbcasestr(dent->d_name, ".fp") ||
cli_strbcasestr(dent->d_name, ".ndb") ||
cli_strbcasestr(dent->d_name, ".sdb") ||
cli_strbcasestr(dent->d_name, ".zmd") ||
cli_strbcasestr(dent->d_name, ".rmd") ||
cli_strbcasestr(dent->d_name, ".hw") ||
cli_strbcasestr(dent->d_name, ".cvd"))) {
dbstat->no++;
@ -1250,11 +1297,12 @@ int cl_statchkdir(const struct cl_stat *dbstat)
cli_strbcasestr(dent->d_name, ".db2") ||
cli_strbcasestr(dent->d_name, ".db3") ||
cli_strbcasestr(dent->d_name, ".hdb") ||
cli_strbcasestr(dent->d_name, ".fp") ||
cli_strbcasestr(dent->d_name, ".fp") ||
cli_strbcasestr(dent->d_name, ".ndb") ||
cli_strbcasestr(dent->d_name, ".sdb") ||
cli_strbcasestr(dent->d_name, ".zmd") ||
cli_strbcasestr(dent->d_name, ".rmd") ||
cli_strbcasestr(dent->d_name, ".hw") ||
cli_strbcasestr(dent->d_name, ".cvd"))) {
fname = cli_calloc(strlen(dbstat->dir) + strlen(dent->d_name) + 2, sizeof(char));
@ -1318,3 +1366,123 @@ int cl_statfree(struct cl_stat *dbstat)
return 0;
}
void cl_free(struct cl_engine *engine)
{
int i, ret;
struct cli_md5_node *md5pt, *md5h;
struct cli_meta_node *metapt, *metah;
struct cli_matcher *root;
if(!engine) {
cli_errmsg("cl_free: engine == NULL\n");
return;
}
#ifdef CL_THREAD_SAFE
pthread_mutex_lock(&cli_ref_mutex);
#endif
engine->refcount--;
if(engine->refcount) {
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif
return;
}
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif
#ifdef HAVE_HWACCEL
if(engine->hwaccel) {
if((ret = sn_sigscan_closedb(engine->hwdb)) < 0) {
cli_errmsg("cl_free: can't close hardware database: %d\n", ret);
}
}
#endif
for(i = 0; i < CL_TARGET_TABLE_SIZE; i++) {
if((root = engine->root[i])) {
cli_ac_free(root);
if(!engine->root[i]->ac_only)
cli_bm_free(root);
}
}
if(engine->md5_hlist) {
for(i = 0; i < 256; i++) {
md5pt = engine->md5_hlist[i];
while(md5pt) {
md5h = md5pt;
md5pt = md5pt->next;
free(md5h->md5);
free(md5h->virname);
if(md5h->viralias)
free(md5h->viralias);
free(md5h);
}
}
free(engine->md5_hlist);
}
metapt = engine->zip_mlist;
while(metapt) {
metah = metapt;
metapt = metapt->next;
free(metah->virname);
if(metah->filename)
free(metah->filename);
free(metah);
}
metapt = engine->rar_mlist;
while(metapt) {
metah = metapt;
metapt = metapt->next;
free(metah->virname);
if(metah->filename)
free(metah->filename);
free(metah);
}
free(engine);
}
int cl_build(struct cl_engine *engine)
{
int i, ret;
struct cli_matcher *root;
if((ret = cli_addtypesigs(engine)))
return ret;
for(i = 0; i < CL_TARGET_TABLE_SIZE; i++)
if((root = engine->root[i]))
cli_ac_buildtrie(root);
/* FIXME: check return values of cli_ac_buildtree */
return 0;
}
struct cl_engine *cl_dup(struct cl_engine *engine)
{
if(!engine) {
cli_errmsg("cl_dup: engine == NULL\n");
return NULL;
}
#ifdef CL_THREAD_SAFE
pthread_mutex_lock(&cli_ref_mutex);
#endif
engine->refcount++;
#ifdef CL_THREAD_SAFE
pthread_mutex_unlock(&cli_ref_mutex);
#endif
return engine;
}

Loading…
Cancel
Save