Logo Search packages:      
Sourcecode: wflogs version File versions  Download package

module.cc

/*
 * WallFire -- a comprehensive firewall administration tool.
 * 
 * Copyright (C) 2001 Hervé Eychenne <rv@wallfire.org>
 * 
 * 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 the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 */

using namespace std;

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <unistd.h> /* for getcwd() */

#ifdef USE_DYNAMIC
# ifdef HAVE_DLFCN_H
#  include <dlfcn.h>
# endif
# ifdef HAVE_DL_H
#  include <dl.h>
# endif
#endif

#include "wfinmodule.h"
#include "module-info.cc" /* file generated by mkmodinfo.sh */
#include "defs.h"

/* portability -- HPUX support untested... RV@@0 */
#ifdef HPUX
# ifndef BIND_IMMEDIATE
#  define BIND_IMMEDIATE 0
# endif
# define DLOPEN(file)         ((void *) shl_load((file), BIND_IMMEDIATE, 0))
# define DLCLOSE(handle)            (shl_unload((shl_t) (handle)))
# define DLSYM(handle, name, sym) (shl_findsym((shl_t *) (&(handle)), (name), \
                        TYPE_PROCEDURE, (void *) (&(sym))) == 0 && sym != NULL)
# define DLERROR()            (strerror(errno))
#else /* not HPUX */
# ifndef RTLD_NOW
#  define RTLD_NOW 0
# endif
# define DLOPEN(file)         (dlopen((file), RTLD_NOW))
# define DLCLOSE(handle)            (dlclose((handle)))
# define DLSYM(handle, name, sym) (((sym) = dlsym((handle), (name))) != NULL)
# define DLERROR()            (dlerror())
#endif

/* define path correctly RV@@7 */
static string modulepath = "input_modules/wallfire/.libs:input_modules/netfilter/.libs";

typedef wf_inmodule* (*initfunc)(void);

extern int verbose;


wf_inmodule*
wf_inmodule_init(const string& name) {
  initfunc moduleinit;

  /* Try to instanciate the module if it is built-in (static). */

  /* The function new_module is defined in module-info.cc
     module-info.cc is generated by mkmodinfo.sh */

  /* first have a look in the static modules list */
  int modulesnbr = sizeof(inmodules) / sizeof(wf_inmodulelist);
  int i;
  for (i = 0; i < modulesnbr; i++) {
    if (inmodules[i].name == name) {
      moduleinit = inmodules[i].initfunc;
      return moduleinit();
    }
  }
  
  /* Wanted module is not built-in. Maybe dynamic (if supported)? */

#ifdef USE_DYNAMIC
  unsigned int pos, oldpos = 0;
  string fname = "libwf" + name + ".so";
  void* handle = NULL;
  do {
    pos = modulepath.find(':', oldpos);
    string path = modulepath.substr(oldpos, pos - oldpos);
    oldpos = pos + 1;

    if (path.empty())
      path = fname; /* lookup in LD_LIBRARY_PATH */
    else {
      if (path[0] != '/') {
      char* str = getcwd(NULL, 0);
      path = string(str) + '/' + path;
      free(str);
      }
      path += '/' + fname;
    }

    // cerr << path << endl;
    handle = DLOPEN(path.c_str());
    if (handle != NULL)
      break;
  } while (pos != string::npos);

  if (handle == NULL) {
    fprintf(stderr, _("Error: cannot load module `%s': %s.\n"),
          name.c_str(), DLERROR());
    return NULL;
  }

  string symname = "wf_inmodule_" + name + "_init";
  void* symaddr;
  // cerr << "sym: " << symname << endl;
  if (!DLSYM(handle, symname.c_str(), symaddr)) {
    fprintf(stderr, _("Error: cannot load module `%s': %s.\n"), name.c_str(),
          DLERROR());
    DLCLOSE(handle);
    return NULL;
  }

  moduleinit = (initfunc)symaddr;
  return moduleinit();
#else
  /* Dynamic modules unsupported, and wanted module is not built-in. */
  return NULL;
#endif
}

ostream&
wf_inmodule_available_modules_print(ostream& os) {
  int modulesnbr = sizeof(inmodules) / sizeof(wf_inmodulelist);

  if (modulesnbr) {
    int i;
    for (i = 0; i < modulesnbr; i++)
      os << inmodules[i].name << ' ';
    os << endl;
  }
  else
    os << _("No built-in modules.") << endl;

#ifdef USE_DYNAMIC
  os << _("Dynamic loading of modules supported.") << endl;

#if 0
  os << _("Available dynamic modules: ");
  /*
    Here we should do the following: RV@@4
    Through modulepath directories, try to open files of the desired form
    `libwf*.so'.  If open succeeds, try to load them to see if they are
    functional then unload them.
  */
  os << endl;
#endif

#else
  os << _("Dynamic loading of modules not supported.") << endl;
#endif       

  return os;
}

wf_logentries*
wf_inmodule::parse(FILE* file, const string& filename, unsigned int* lineno,
               enum wf_logentries_parsing_strictness strictness) {
  if (lineno == NULL)
    return NULL;
  wf_logentries* logentries = new wf_logentries();
  if (logentries == NULL)
    return NULL;

  char buf[WF_LOGLINE_MAXLEN];
  while (fgets(buf, sizeof(buf), file)) {
    ++(*lineno);
    wf_logentry* logentry;
    switch (parse(&logentry, buf, *lineno)) {
    case WF_LOGENTRY_PARSING_OK:
      break;
    case WF_LOGENTRY_PARSING_ERROR:
      switch (strictness) {
      case WF_LOGENTRIES_PARSING_STRICTNESS_LOOSE:
      case WF_LOGENTRIES_PARSING_STRICTNESS_NOWARNING:
      continue;
      case WF_LOGENTRIES_PARSING_STRICTNESS_WARNING:
      fprintf(stderr, _("%s:%i: warning: wrong log line.\n"),
            filename.c_str(), *lineno);
      continue;
      case WF_LOGENTRIES_PARSING_STRICTNESS_ERROR:
      delete logentries;
      return NULL;
      }
    case WF_LOGENTRY_PARSING_NOHIT:
      if (strictness == WF_LOGENTRIES_PARSING_STRICTNESS_WARNING)
      fprintf(stderr, _("%s:%i: warning: valid line but not a firewall log line.\n"),
            filename.c_str(), *lineno);
      continue;
    case WF_LOGENTRY_PARSING_NOMATCH: /* this is impossible */
      ;
    }

    if (logentry->check() == false) {
      switch (strictness) {
      case WF_LOGENTRIES_PARSING_STRICTNESS_NOWARNING:
      delete logentry;
      continue;
      case WF_LOGENTRIES_PARSING_STRICTNESS_WARNING:
      fprintf(stderr, _("%s:%i: warning: wrong log entry.\n"),
            filename.c_str(), *lineno);
      delete logentry;
      continue;
      case WF_LOGENTRIES_PARSING_STRICTNESS_ERROR:
      fprintf(stderr, _("%s:%i: wrong log entry.\n"),
            filename.c_str(), *lineno);
      logentry->debugprint(cerr);
      delete logentry;
      delete logentries;
      return NULL;
      case WF_LOGENTRIES_PARSING_STRICTNESS_LOOSE:
      ; /* consider it as valid */
      }
    }

    logentries->add(*logentry);
    // logentry->debugprint(cout);
    // output_module->print(logentry, cout);
  }
  return logentries;
}


static string
input_modules_print(const list<wf_inmodule*>& input_modules) {
  string str;
  list<wf_inmodule*>::const_iterator first = input_modules.begin(),
    last = input_modules.end();
  while (first != last) {
    str += (*first)->name();
    ++first;
    if (first != last)
      str += ", ";
  }
  return str;
}

enum wf_logentry_parsing_result
wf_inmodule_parse(wf_logentry** logentry, const string& line,
              const string& filename, unsigned int lineno,
              const list<wf_inmodule*>& input_modules) {
  list<wf_inmodule*>::const_iterator first = input_modules.begin(),
    last = input_modules.end();
  while (first != last) {
    if ((*first)->match(line))
      break;
    ++first;
  }
  if (first == last)  /* no match */
    return WF_LOGENTRY_PARSING_NOMATCH;
  
  if (verbose > 2)
    fprintf(stderr, _("%s:%i: parsed with `%s' module\n"),
          filename.c_str(), lineno, (*first)->name());
  return (*first)->parse(logentry, line, lineno);
}

/* With strictness! */
enum wf_logentry_parsing_result
wf_inmodule_parse(wf_logentry** logentry, const string& line,
              const string& filename, unsigned int lineno,
              const list<wf_inmodule*>& input_modules,
              enum wf_logentries_parsing_strictness strictness) {
  switch (wf_inmodule_parse(logentry, line, filename, lineno, input_modules)) {
  case WF_LOGENTRY_PARSING_OK:
    break; /* go on with check() */
  case WF_LOGENTRY_PARSING_NOMATCH:
    switch (strictness) {
    case WF_LOGENTRIES_PARSING_STRICTNESS_LOOSE:
    case WF_LOGENTRIES_PARSING_STRICTNESS_NOWARNING:
      return WF_LOGENTRY_PARSING_NOHIT;
    case WF_LOGENTRIES_PARSING_STRICTNESS_WARNING:
      fprintf(stderr, _("%s:%i: warning: line format matches none of the specified module(s): %s\n"),
            filename.c_str(), lineno,
            input_modules_print(input_modules).c_str());
      return WF_LOGENTRY_PARSING_NOHIT;
    case WF_LOGENTRIES_PARSING_STRICTNESS_ERROR:
      fprintf(stderr, _("%s:%i: error: line format matches none of the specified module(s): %s\n"),
            filename.c_str(), lineno,
            input_modules_print(input_modules).c_str());
      return WF_LOGENTRY_PARSING_ERROR;
    }
  case WF_LOGENTRY_PARSING_ERROR:
    switch (strictness) {
    case WF_LOGENTRIES_PARSING_STRICTNESS_LOOSE:
    case WF_LOGENTRIES_PARSING_STRICTNESS_NOWARNING:
      return WF_LOGENTRY_PARSING_NOHIT;
    case WF_LOGENTRIES_PARSING_STRICTNESS_WARNING:
      fprintf(stderr, _("%s:%i: warning: wrong log line.\n"),
            filename.c_str(), lineno);
      return WF_LOGENTRY_PARSING_NOHIT;
    case WF_LOGENTRIES_PARSING_STRICTNESS_ERROR:
      return WF_LOGENTRY_PARSING_ERROR;
    }
  case WF_LOGENTRY_PARSING_NOHIT:
    if (strictness == WF_LOGENTRIES_PARSING_STRICTNESS_WARNING)
      fprintf(stderr, _("%s:%i: warning: valid line but not a firewall log line.\n"),
            filename.c_str(), lineno);
    return WF_LOGENTRY_PARSING_NOHIT;
  }
  
  if ((*logentry)->check() == false) {
    switch (strictness) {
    case WF_LOGENTRIES_PARSING_STRICTNESS_NOWARNING:
      delete *logentry;
      return WF_LOGENTRY_PARSING_NOHIT;
    case WF_LOGENTRIES_PARSING_STRICTNESS_WARNING:
      fprintf(stderr, _("%s:%i: warning: wrong log entry.\n"),
            filename.c_str(), lineno);
      delete *logentry;
      return WF_LOGENTRY_PARSING_NOHIT;
    case WF_LOGENTRIES_PARSING_STRICTNESS_ERROR:
      fprintf(stderr, _("%s:%i: wrong log entry.\n"),
            filename.c_str(), lineno);
      (*logentry)->debugprint(cerr);
      delete *logentry;
      return WF_LOGENTRY_PARSING_ERROR;
    case WF_LOGENTRIES_PARSING_STRICTNESS_LOOSE:
      ; /* consider it as valid */
    }
  }
  return WF_LOGENTRY_PARSING_OK;
}

/* redundant with ::parse implementation RV@@9 */
wf_logentries*
wf_inmodule_parse(FILE* file, const string& filename, unsigned int* lineno,
              const list<wf_inmodule*>& input_modules,
              enum wf_logentries_parsing_strictness strictness) {
  if (lineno == NULL)
    return NULL;
  wf_logentries* logentries = new wf_logentries();
  if (logentries == NULL)
    return NULL;

  char buf[WF_LOGLINE_MAXLEN];
  while (fgets(buf, sizeof(buf), file)) {
    ++(*lineno);
    wf_logentry* logentry;
    switch (wf_inmodule_parse(&logentry, buf, filename, *lineno,
                        input_modules, strictness)) {
    case WF_LOGENTRY_PARSING_OK:
      logentries->add(*logentry);
      // logentry->debugprint(cout);
      // output_module->print(logentry, cout);
      break;
    case WF_LOGENTRY_PARSING_ERROR:
      delete logentries;
      return NULL;
    case WF_LOGENTRY_PARSING_NOHIT:
      continue;
    case WF_LOGENTRY_PARSING_NOMATCH: /* cannot happen */
      WFASSERT(_("WF_LOGENTRY_PARSING_NOMATCH was hit"));
    }
  }
  return logentries;
}

Generated by  Doxygen 1.6.0   Back to index