示例#1
0
/**
 * afsql_dd_begin_txn:
 *
 * Commit SQL transaction.
 *
 * NOTE: This function can only be called from the database thread.
 **/
static gboolean
afsql_dd_commit_txn(AFSqlDestDriver *self, gboolean lock)
{
  gboolean success;

  success = afsql_dd_run_query(self, "COMMIT", FALSE, NULL);
  if (lock)
    g_mutex_lock(self->db_thread_mutex);

  /* FIXME: this is a workaround because of the non-proper locking semantics
   * of the LogQueue.  It might happen that the _queue() method sees 0
   * elements in the queue, while the thread is still busy processing the
   * previous message.  In that case arming the parallel push callback is
   * not needed and will cause assertions to fail.  This is ugly and should
   * be fixed by properly defining the "blocking" semantics of the LogQueue
   * object w/o having to rely on user-code messing with parallel push
   * callbacks. */

  log_queue_reset_parallel_push(self->queue);
  if (success)
    {
      log_queue_ack_backlog(self->queue, self->flush_lines_queued);
    }
  else
    {
      msg_notice("SQL transaction commit failed, rewinding backlog and starting again",
                 NULL);
      log_queue_rewind_backlog(self->queue);
    }
  if (lock)
    g_mutex_unlock(self->db_thread_mutex);
  self->flush_lines_queued = 0;
  return success;
}
示例#2
0
static gssize
log_transport_device_read_method(LogTransport *s, gpointer buf, gsize buflen, GSockAddr **sa)
{
  LogTransportDevice *self = (LogTransportDevice *) s;
  gint rc;

  if (sa)
    *sa = NULL;

  do
    {
      if (self->timeout)
        alarm_set(self->timeout);
      rc = read(self->super.fd, buf, buflen);

      if (self->timeout > 0 && rc == -1 && errno == EINTR && alarm_has_fired())
        {
          msg_notice("Nonblocking read has blocked, returning with an error",
                     evt_tag_int("fd", self->super.fd),
                     evt_tag_int("timeout", self->timeout),
                     NULL);
          alarm_cancel();
          break;
        }
      if (self->timeout)
        alarm_cancel();
    }
  while (rc == -1 && errno == EINTR);
  return rc;
}
示例#3
0
static void
log_db_parser_reload_database(LogDBParser *self)
{
  struct stat st;

  if (stat(self->db_file, &st) < 0)
    {
      msg_error("Error stating pattern database file, no automatic reload will be performed",
                evt_tag_str("error", g_strerror(errno)),
                NULL);
      return;
    }
  if ((self->db_file_inode == st.st_ino && self->db_file_mtime == st.st_mtime))
    {
      return;
    }

  self->db_file_inode = st.st_ino;
  self->db_file_mtime = st.st_mtime;

  if (!pattern_db_reload_ruleset(self->db, self->cfg, self->db_file))
    {
      msg_error("Error reloading pattern database, no automatic reload will be performed", NULL);
    }
  else
    {
      /* free the old database if the new was loaded successfully */
      msg_notice("Log pattern database reloaded",
                 evt_tag_str("file", self->db_file),
                 evt_tag_str("version", pattern_db_get_ruleset_version(self->db)),
                 evt_tag_str("pub_date", pattern_db_get_ruleset_pub_date(self->db)),
                 NULL);
    }

}
示例#4
0
static gssize
log_transport_plain_write_method(LogTransport *s, const gpointer buf, gsize buflen)
{
  LogTransportPlain *self = (LogTransportPlain *) s;
  gint rc;
  
  do
    {
      if (self->super.timeout)
        alarm_set(self->super.timeout);
      if (self->super.flags & LTF_APPEND)
        lseek(self->super.fd, 0, SEEK_END);
      rc = write(self->super.fd, buf, buflen);
      if (self->super.timeout > 0 && rc == -1 && errno == EINTR && alarm_has_fired())
        {
          msg_notice("Nonblocking write has blocked, returning with an error",
                     evt_tag_int("fd", self->super.fd),
                     evt_tag_int("timeout", self->super.timeout),
                     NULL);
          alarm_cancel();
          break;
        }
      if (self->super.timeout)
        alarm_cancel();
      if (self->super.flags & LTF_FSYNC)
        fsync(self->super.fd);
    }
  while (rc == -1 && errno == EINTR);
  return rc;
}
示例#5
0
static void
afsocket_dd_notify(LogPipe *s, LogPipe *sender, gint notify_code, gpointer user_data)
{
  AFSocketDestDriver *self = (AFSocketDestDriver *) s;
  gchar buf[MAX_SOCKADDR_STRING];

  switch (notify_code)
    {
    case NC_CLOSE:
    case NC_WRITE_ERROR:
      log_writer_reopen(self->writer, NULL);

      msg_notice("Syslog connection broken",
                 evt_tag_int("fd", self->fd),
                 evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf, sizeof(buf), GSA_FULL)),
                 evt_tag_int("time_reopen", self->time_reopen),
                 NULL);
      if (self->reconnect_timer)
        {
          g_source_remove(self->reconnect_timer);
          self->reconnect_timer = 0;
        }
      self->reconnect_timer = g_timeout_add(self->time_reopen * 1000, afsocket_dd_reconnect_timer, self);
      break;
    }
}
示例#6
0
static void
afsocket_sd_accept(gpointer s)
{
  AFSocketSourceDriver *self = (AFSocketSourceDriver *) s;
  GSockAddr *peer_addr;
  gchar buf1[256], buf2[256];
  gint new_fd;
  gboolean res;
  int accepts = 0;

  while (accepts < MAX_ACCEPTS_AT_A_TIME)
    {
      GIOStatus status;

      status = g_accept(self->fd, &new_fd, &peer_addr);
      if (status == G_IO_STATUS_AGAIN)
        {
          /* no more connections to accept */
          break;
        }
      else if (status != G_IO_STATUS_NORMAL)
        {
          msg_error("Error accepting new connection",
                    evt_tag_errno(EVT_TAG_OSERROR, errno),
                    NULL);
          return;
        }

      g_fd_set_nonblock(new_fd, TRUE);
      g_fd_set_cloexec(new_fd, TRUE);

      res = afsocket_sd_process_connection(self, peer_addr, self->bind_addr, new_fd);

      if (res)
        {
          if (peer_addr->sa.sa_family != AF_UNIX)
            msg_notice("Syslog connection accepted",
                        evt_tag_int("fd", new_fd),
                        evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)),
                        evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)),
                        NULL);
          else
            msg_verbose("Syslog connection accepted",
                        evt_tag_int("fd", new_fd),
                        evt_tag_str("client", g_sockaddr_format(peer_addr, buf1, sizeof(buf1), GSA_FULL)),
                        evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)),
                        NULL);
        }
      else
        {
          close(new_fd);
        }

      g_sockaddr_unref(peer_addr);
      accepts++;
    }
  return;
}
示例#7
0
static gboolean
afsocket_dd_connected(AFSocketDestDriver *self)
{
  gchar buf1[256], buf2[256];
  int error = 0;
  socklen_t errorlen = sizeof(error);
  LogTransport *transport;
  LogProtoClient *proto;

  main_loop_assert_main_thread();

  if (iv_fd_registered(&self->connect_fd))
    iv_fd_unregister(&self->connect_fd);

  if (self->transport_mapper->sock_type == SOCK_STREAM)
    {
      if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &error, &errorlen) == -1)
        {
          msg_error("getsockopt(SOL_SOCKET, SO_ERROR) failed for connecting socket",
                    evt_tag_int("fd", self->fd),
                    evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)),
                    evt_tag_errno(EVT_TAG_OSERROR, errno),
                    evt_tag_int("time_reopen", self->time_reopen),
                    NULL);
          goto error_reconnect;
        }
      if (error)
        {
          msg_error("Syslog connection failed",
                    evt_tag_int("fd", self->fd),
                    evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)),
                    evt_tag_errno(EVT_TAG_OSERROR, error),
                    evt_tag_int("time_reopen", self->time_reopen),
                    NULL);
          goto error_reconnect;
        }
    }
  msg_notice("Syslog connection established",
              evt_tag_int("fd", self->fd),
              evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)),
              evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf1, sizeof(buf1), GSA_FULL)),
              NULL);

  transport = afsocket_dd_construct_transport(self, self->fd);
  if (!transport)
    goto error_reconnect;

  proto = log_proto_client_factory_construct(self->proto_factory, transport, &self->writer_options.proto_options.super);

  log_writer_reopen(self->writer, proto);
  return TRUE;
 error_reconnect:
  close(self->fd);
  self->fd = -1;
  afsocket_dd_start_reconnect_timer(self);
  return FALSE;
}
示例#8
0
/* called to apply the new configuration once all I/O worker threads have finished */
static void
main_loop_reload_config_apply(void)
{
  if (main_loop_is_terminating())
    {
      if (main_loop_new_config)
        {
          cfg_free(main_loop_new_config);
          main_loop_new_config = NULL;
        }
      return;
    }
  main_loop_old_config->persist = persist_config_new();
  cfg_deinit(main_loop_old_config);
  cfg_persist_config_move(main_loop_old_config, main_loop_new_config);

  if (cfg_init(main_loop_new_config))
    {
      msg_verbose("New configuration initialized");
      persist_config_free(main_loop_new_config->persist);
      main_loop_new_config->persist = NULL;
      cfg_free(main_loop_old_config);
      current_configuration = main_loop_new_config;
      service_management_clear_status();
    }
  else
    {
      msg_error("Error initializing new configuration, reverting to old config");
      service_management_publish_status("Error initializing new configuration, using the old config");
      cfg_persist_config_move(main_loop_new_config, main_loop_old_config);
      cfg_deinit(main_loop_new_config);
      if (!cfg_init(main_loop_old_config))
        {
          /* hmm. hmmm, error reinitializing old configuration, we're hosed.
           * Best is to kill ourselves in the hope that the supervisor
           * restarts us.
           */
          kill(getpid(), SIGQUIT);
          g_assert_not_reached();
        }
      persist_config_free(main_loop_old_config->persist);
      main_loop_old_config->persist = NULL;
      cfg_free(main_loop_new_config);
      current_configuration = main_loop_old_config;
      goto finish;
    }

  /* this is already running with the new config in place */
  app_post_config_loaded();
  msg_notice("Configuration reload request received, reloading configuration");

 finish:
  main_loop_new_config = NULL;
  main_loop_old_config = NULL;

  return;
}
示例#9
0
static void
log_reader_idle_timeout(void *cookie)
{
  LogReader *self = (LogReader *) cookie;

  msg_notice("Source timeout has elapsed, closing connection",
             evt_tag_int("fd", log_proto_server_get_fd(self->proto)));

  log_pipe_notify(self->control, NC_CLOSE, self);
}
示例#10
0
static void
log_writer_error_suspend_elapsed(gpointer s)
{
  LogWriter *self = (LogWriter *) s;

  self->suspended = FALSE;
  msg_notice("Error suspend timeout has elapsed, attempting to write again",
             evt_tag_int("fd", log_proto_client_get_fd(self->proto)));
  log_writer_start_watches(self);
}
示例#11
0
int
tls_session_verify(TLSSession *self, int ok, X509_STORE_CTX *ctx)
{
  /* untrusted means that we have to accept the certificate even if it is untrusted */
  if (self->ctx->verify_mode & TVM_UNTRUSTED)
    return 1;

  /* accept certificate if its fingerprint matches, again regardless whether x509 certificate validation was successful */
  if (ok && ctx->error_depth == 0 && !tls_session_verify_fingerprint(ctx))
    {
      msg_notice("Certificate valid, but fingerprint constraints were not met, rejecting", NULL);
      return 0;
    }

  if (ok && ctx->error_depth != 0 && (ctx->current_cert->ex_flags & EXFLAG_CA) == 0)
    {
      msg_notice("Invalid certificate found in chain, basicConstraints.ca is unset in non-leaf certificate", NULL);
      ctx->error = X509_V_ERR_INVALID_CA;
      return 0;
    }

  /* reject certificate if it is valid, but its DN is not trusted */
  if (ok && ctx->error_depth == 0 && !tls_session_verify_dn(ctx))
    {
      msg_notice("Certificate valid, but DN constraints were not met, rejecting", NULL);
      ctx->error = X509_V_ERR_CERT_UNTRUSTED;
      return 0;
    }
  /* if the crl_dir is set in the configuration file but the directory is empty ignore this error */
  if (!ok && ctx->error == X509_V_ERR_UNABLE_TO_GET_CRL)
    {
      msg_notice("CRL directory is set but no CRLs found", NULL);
      return 1;
    }

  if (!ok && ctx->error == X509_V_ERR_INVALID_PURPOSE)
    {
      msg_warning("Certificate valid, but purpose is invalid", NULL);
      return 1;
    }
  return ok;
}
示例#12
0
static gssize
log_transport_plain_read_method(LogTransport *s, gpointer buf, gsize buflen, GSockAddr **sa)
{
  LogTransportPlain *self = (LogTransportPlain *) s;
  gint rc;
  
  if ((self->super.flags & LTF_RECV) == 0)
    {
      if (sa)
        *sa = NULL;

      do
        {
          if (self->super.timeout)
            alarm_set(self->super.timeout);
          rc = read(self->super.fd, buf, buflen);
          
          if (self->super.timeout > 0 && rc == -1 && errno == EINTR && alarm_has_fired())
            {
              msg_notice("Nonblocking read has blocked, returning with an error",
                         evt_tag_int("fd", self->super.fd),
                         evt_tag_int("timeout", self->super.timeout),
                         NULL);
              alarm_cancel();
              break;
            }
          if (self->super.timeout)
            alarm_cancel();
        }
      while (rc == -1 && errno == EINTR);
    }
  else 
    {
      union
      {
#if HAVE_STRUCT_SOCKADDR_STORAGE
        struct sockaddr_storage __sas;
#endif
        struct sockaddr __sa;
      } sas;
      
      socklen_t salen = sizeof(sas);

      do
        {
          rc = recvfrom(self->super.fd, buf, buflen, 0, 
                        (struct sockaddr *) &sas, &salen);
        }
      while (rc == -1 && errno == EINTR);
      if (rc != -1 && salen && sa)
        (*sa) = g_sockaddr_new((struct sockaddr *) &sas, salen);
    }
  return rc;
}
示例#13
0
static void
dummy_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
{
  DummyDestDriver *self = (DummyDestDriver *) s;
  msg_notice("Dummy plugin received a message",
             evt_tag_str("msg", log_msg_get_value(msg, LM_V_MESSAGE, NULL)),
             evt_tag_int("opt", self->opt),
             NULL);

  log_msg_ack(msg, path_options);
  log_msg_unref(msg);
}
示例#14
0
static void
log_writer_work_finished(gpointer s)
{
  LogWriter *self = (LogWriter *) s;

  main_loop_assert_main_thread();
  self->flush_waiting_for_timeout = FALSE;

  if (self->pending_proto_present)
    {
      /* pending proto is only set in the main thread, so no need to
       * lock it before coming here. After we're syncing with the
       * log_writer_reopen() call, quite possibly coming from a
       * non-main thread. */

      g_static_mutex_lock(&self->pending_proto_lock);
      if (self->proto)
        log_proto_free(self->proto);

      self->proto = self->pending_proto;
      self->pending_proto = NULL;
      self->pending_proto_present = FALSE;

      g_cond_signal(self->pending_proto_cond);
      g_static_mutex_unlock(&self->pending_proto_lock);
    }

  if (!self->work_result)
    {
      log_writer_broken(self, NC_WRITE_ERROR);
      if (self->proto)
        {
          log_writer_suspend(self);
          msg_notice("Suspending write operation because of an I/O error",
                     evt_tag_int("fd", log_proto_get_fd(self->proto)),
                     evt_tag_int("time_reopen", self->options->time_reopen),
                     NULL);
        }
      goto exit;
    }

  if ((self->super.flags & PIF_INITIALIZED) && self->proto)
    {
      /* reenable polling the source, but only if we're still initialized */
      log_writer_start_watches(self);
    }

exit:
  log_pipe_unref(&self->super);
}
示例#15
0
void
main_loop_run(void)
{
  msg_notice("syslog-ng starting up",
             evt_tag_str("version", SYSLOG_NG_VERSION));

  /* main loop */
  service_management_indicate_readiness();
  service_management_clear_status();
  if (interactive_mode)
    {
      plugin_load_module("python", current_configuration, NULL);
      debugger_start(current_configuration);
    }
  iv_main();
  service_management_publish_status("Shutting down...");
}
示例#16
0
static void
main_loop_exit_initiate(void)
{
  if (main_loop_is_terminating())
    return;

  msg_notice("syslog-ng shutting down",
             evt_tag_str("version", SYSLOG_NG_VERSION));

  IV_TIMER_INIT(&main_loop_exit_timer);
  iv_validate_now();
  main_loop_exit_timer.expires = iv_now;
  main_loop_exit_timer.handler = main_loop_exit_timer_elapsed;
  timespec_add_msec(&main_loop_exit_timer.expires, 100);
  iv_timer_register(&main_loop_exit_timer);
  __main_loop_is_terminating = TRUE;
}
示例#17
0
  static gboolean
log_writer_fd_dispatch(GSource *source,
    GSourceFunc callback,
    gpointer user_data)
{
  LogWriterWatch *self = (LogWriterWatch *) source;
  gint64 num_elements = log_queue_get_length(self->writer->queue);

  if (self->pollfd.revents & (G_IO_HUP | G_IO_IN) && self->input_means_connection_broken)
  {
    msg_error("EOF occurred while idle",
        evt_tag_int("fd", log_proto_get_fd(self->proto)),
        NULL);
    log_writer_broken(self->writer, NC_CLOSE);
    return FALSE;
  }
  else if (self->pollfd.revents & (G_IO_ERR) && num_elements == 0)
  {
    msg_error("POLLERR occurred while idle",
        evt_tag_int("fd", log_proto_get_fd(self->proto)),
        NULL);
    log_writer_broken(self->writer, NC_WRITE_ERROR);
  }
  else if (num_elements)
  {
    if (!log_writer_flush_log(self->writer, self->proto))
    {
      self->error_suspend = TRUE;
      g_source_get_current_time(source, &self->error_suspend_target);
      g_time_val_add(&self->error_suspend_target, self->writer->options->time_reopen * 1e6);

      log_writer_broken(self->writer, NC_WRITE_ERROR);

      if (self->writer->source == (GSource *) self)
      {
        msg_notice("Suspending write operation because of an I/O error",
            evt_tag_int("fd", log_proto_get_fd(self->proto)),
            evt_tag_int("time_reopen", self->writer->options->time_reopen),
            NULL);
      }
      return TRUE;
    }
  }
  return TRUE;
}
示例#18
0
/**
 * afsql_dd_begin_txn:
 *
 * Commit SQL transaction.
 *
 * NOTE: This function can only be called from the database thread.
 **/
static gboolean
afsql_dd_commit_txn(AFSqlDestDriver *self)
{
  gboolean success;

  success = afsql_dd_run_query(self, "COMMIT", FALSE, NULL);
  if (success)
    {
      log_queue_ack_backlog(self->queue, self->flush_lines_queued);
    }
  else
    {
      msg_notice("SQL transaction commit failed, rewinding backlog and starting again",
                 NULL);
      log_queue_rewind_backlog(self->queue);
    }
  self->flush_lines_queued = 0;
  return success;
}
示例#19
0
gboolean
cfg_allow_config_dups(GlobalConfig *self)
{
  const gchar *s;

  if (cfg_is_config_version_older(self, 0x0303))
    return TRUE;

  s = cfg_args_get(self->lexer->globals, "allow-config-dups");
  if (s && atoi(s))
    {
      return TRUE;
    }
  else
    {
      /* duplicate found, but allow-config-dups is not enabled, hint the user that he might want to use allow-config-dups */
      msg_notice("WARNING: Duplicate configuration objects (sources, destinations, ...) are not allowed by default starting with syslog-ng 3.3, add \"@define allow-config-dups 1\" to your configuration to reenable", NULL);
      return FALSE;
    }
}
示例#20
0
static void
afsocket_sd_close_connection(AFSocketSourceDriver *self, AFSocketSourceConnection *sc)
{
  gchar buf1[MAX_SOCKADDR_STRING], buf2[MAX_SOCKADDR_STRING];
  
  if (sc->peer_addr->sa.sa_family != AF_UNIX)
    msg_notice("Syslog connection closed",
               evt_tag_int("fd", sc->sock),
               evt_tag_str("client", g_sockaddr_format(sc->peer_addr, buf1, sizeof(buf1), GSA_FULL)),
               evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)),
               NULL);
  else
    msg_verbose("Syslog connection closed",
               evt_tag_int("fd", sc->sock),
               evt_tag_str("client", g_sockaddr_format(sc->peer_addr, buf1, sizeof(buf1), GSA_FULL)),
               evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf2, sizeof(buf2), GSA_FULL)),
               NULL);
  log_pipe_deinit(&sc->super);
  log_pipe_unref(&sc->super);
  self->num_connections--;
}
示例#21
0
int
tls_session_verify_callback(int ok, X509_STORE_CTX *ctx)
{
  SSL *ssl = X509_STORE_CTX_get_app_data(ctx);
  TLSSession *self = SSL_get_app_data(ssl);
  /* NOTE: Sometimes libssl calls this function
     with no current_cert. This happens when
     some global error is happen. At this situation
     we do not need to call any other check and callback
   */
  if (X509_STORE_CTX_get_current_cert(ctx) == NULL)
    {
    switch (ctx->error)
      {
      case X509_V_ERR_NO_EXPLICIT_POLICY:
        /* NOTE: Because we set the CHECK_POLICY_FLAG if the
           certificate contains ExplicitPolicy constraint
           we would get this error. But this error is because
           we do not set the policy what we want to check for.
         */
        ok = 1;
        break;
      default:
        msg_notice("Error occured during certificate validation",
                    evt_tag_int("error", ctx->error),
                    NULL);
        break;
      }
    }
  else
    {
      ok = tls_session_verify(self, ok, ctx);

      tls_log_certificate_validation_progress(ok, ctx);

      if (self->verify_func)
        return self->verify_func(ok, ctx, self->verify_data);
    }
  return ok;
}
示例#22
0
/*
 * log_transport_fd_is_locked:
 * @fd: file descriptor
 *
 * This function checks if a file lock is associated with a @fd.
 *
 * return code:
 * 1 - file is locked;
 * 0 - file is unlocked or fcntl() is failed.
 **/
static gboolean
log_transport_fd_is_locked(int fd)
{
  gint rc;
  struct flock lock;
  memset(&lock, 0, sizeof(lock));
  errno = 0;
  rc = fcntl(fd, F_GETLK, &lock);
  if (rc != 0)
    {
      msg_notice("Check locking fd is failed"
          , evt_tag_int("fd", fd)
          , evt_tag_str("error", strerror(errno))
          , NULL);
      return 0;
    }
  if (lock.l_type != F_UNLCK && lock.l_pid != 0)
    {
      return 1;
    }
  return 0;
}
示例#23
0
gboolean
plugin_load_module(const gchar *module_name, GlobalConfig *cfg, CfgArgs *args)
{
  GModule *mod;
  static GModule *main_module_handle;
  gboolean (*init_func)(GlobalConfig *cfg, CfgArgs *args);
  gchar *module_init_func;
  const gchar *mp;
  gchar *p;
  gboolean result;

  if (!main_module_handle)
    main_module_handle = g_module_open(NULL, 0);
  module_init_func = g_strdup_printf("%s_module_init", module_name);
  for (p = module_init_func; *p; p++)
    {
      if ((*p) == '-')
        *p = '_';
    }

  if (g_module_symbol(main_module_handle, module_init_func, (gpointer *) &init_func))
    {
      /* already linked in, no need to load explicitly */
      goto call_init;
    }

  if (cfg->lexer)
    mp = cfg_args_get(cfg->lexer->globals, "module-path");
  else
    mp = NULL;

  if (!mp)
    mp = module_path;

  mod = plugin_dlopen_module(module_name, mp);
  if (!mod)
    {
      g_free(module_init_func);
      return FALSE;
    }
  g_module_make_resident(mod);

  if (!g_module_symbol(mod, module_init_func, (gpointer *) &init_func))
    {
      msg_error("Error finding init function in module",
                evt_tag_str("module", module_name),
                evt_tag_str("symbol", module_init_func),
                evt_tag_str("error", g_module_error()),
                NULL);
      g_free(module_init_func);
      return FALSE;
    }
 call_init:
  g_free(module_init_func);
  result = (*init_func)(cfg, args);
  if (result)
    msg_notice("Module loaded and initialized successfully",
               evt_tag_str("module", module_name),
               NULL);
  else
    msg_error("Module initialization failed",
               evt_tag_str("module", module_name),
               NULL);
  return result;
}
示例#24
0
static void
afuser_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options)
{
  AFUserDestDriver *self = (AFUserDestDriver *) s;
  gchar buf[8192];
  struct utmp *ut;
  GString *timestamp;
  time_t now;
  
  now = msg->timestamps[LM_TS_RECVD].time.tv_sec;
  if (self->disable_until && self->disable_until > now)
    goto finish;
  
  timestamp = g_string_sized_new(0);
  log_stamp_format(&msg->timestamps[LM_TS_STAMP], timestamp, TS_FMT_FULL, -1, 0);
  g_snprintf(buf, sizeof(buf), "%s %s %s\n",
             timestamp->str,
             log_msg_get_value(msg, LM_V_HOST, NULL),
             log_msg_get_value(msg, LM_V_MESSAGE, NULL));
  g_string_free(timestamp, TRUE);
  
  /* NOTE: there's a private implementations of getutent in utils.c on Systems which do not provide one. */
  while ((ut = getutent())) 
    {
#if HAVE_MODERN_UTMP
      if (ut->ut_type == USER_PROCESS &&
          ((self->username->len == 1 &&
            self->username->str[0] == '*') ||
           (self->username->len <= sizeof(ut->ut_user) &&
            memcmp(self->username->str, ut->ut_user, self->username->len) == 0))) 
#else
      if ((self->username->len == 1 &&
           self->username->str[0] == '*') ||
          (self->username->len <= sizeof(ut->ut_name) &&
           memcmp(self->username->str, ut->ut_name, self->username->len) == 0)) 
#endif
        {
          gchar line[128];
          gchar *p = line;
          int fd;

          if (ut->ut_line[0] != '/')
            {
              strcpy(line, "/dev/");
              p = line + 5;
            }
          else
            line[0] = 0;
          strncpy(p, ut->ut_line, sizeof(line) - (p - line));
          fd = open(line, O_NOCTTY | O_APPEND | O_WRONLY | O_NONBLOCK);
          if (fd != -1) 
            {
              alarm_set(10);
              if (write(fd, buf, strlen(buf)) < 0 && errno == EINTR && alarm_has_fired())
                {
                  msg_notice("Writing to the user terminal has blocked for 10 seconds, disabling for 10 minutes",
                            evt_tag_str("user", self->username->str),
                            NULL);
                  self->disable_until = now + 600;
                }
              alarm_cancel();
              close(fd);
            }
        }
    }
  endutent();
finish:
  log_msg_ack(msg, path_options);
  log_msg_unref(msg);
}
示例#25
0
static gboolean
afsocket_dd_connected(AFSocketDestDriver *self)
{
  gchar buf1[256], buf2[256];
  int error = 0;
  socklen_t errorlen = sizeof(error);
  LogTransport *transport;
  LogProto *proto;
  guint32 transport_flags = 0;

  main_loop_assert_main_thread();

  if (iv_fd_registered(&self->connect_fd))
    iv_fd_unregister(&self->connect_fd);

  if (self->flags & AFSOCKET_STREAM)
    {
      transport_flags |= LTF_SHUTDOWN;
      if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &error, &errorlen) == -1)
        {
          msg_error("getsockopt(SOL_SOCKET, SO_ERROR) failed for connecting socket",
                    evt_tag_int("fd", self->fd),
                    evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)),
                    evt_tag_errno(EVT_TAG_OSERROR, errno),
                    evt_tag_int("time_reopen", self->time_reopen),
                    NULL);
          goto error_reconnect;
        }
      if (error)
        {
          msg_error("Syslog connection failed",
                    evt_tag_int("fd", self->fd),
                    evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)),
                    evt_tag_errno(EVT_TAG_OSERROR, error),
                    evt_tag_int("time_reopen", self->time_reopen),
                    NULL);
          goto error_reconnect;
        }
    }
  msg_notice("Syslog connection established",
              evt_tag_int("fd", self->fd),
              evt_tag_str("server", g_sockaddr_format(self->dest_addr, buf2, sizeof(buf2), GSA_FULL)),
              evt_tag_str("local", g_sockaddr_format(self->bind_addr, buf1, sizeof(buf1), GSA_FULL)),
              NULL);


#if ENABLE_SSL
  if (self->tls_context)
    {
      TLSSession *tls_session;

      tls_session = tls_context_setup_session(self->tls_context);
      if (!tls_session)
        {
          goto error_reconnect;
        }

      tls_session_set_verify(tls_session, afsocket_dd_tls_verify_callback, self, NULL);
      transport = log_transport_tls_new(tls_session, self->fd, transport_flags);
    }
  else
#endif
    transport = log_transport_plain_new(self->fd, transport_flags);

  if (self->flags & AFSOCKET_SYSLOG_PROTOCOL)
    {
      if (self->flags & AFSOCKET_STREAM)
        proto = log_proto_framed_client_new(transport);
      else
        proto = log_proto_text_client_new(transport);
    }
  else
    {
      proto = log_proto_text_client_new(transport);
    }

  log_writer_reopen(self->writer, proto);
  return TRUE;
 error_reconnect:
  close(self->fd);
  self->fd = -1;
  afsocket_dd_start_reconnect_timer(self);
  return FALSE;
}
示例#26
0
  static gboolean
log_writer_fd_prepare(GSource *source,
    gint *timeout)
{
  LogWriterWatch *self = (LogWriterWatch *) source;
  gint64 num_elements = log_queue_get_length(self->writer->queue);
  GTimeVal now;
  GIOCondition proto_cond;

  self->pollfd.events = G_IO_ERR;
  self->pollfd.revents = 0;

  g_source_get_current_time(source, &now);
  if (log_proto_prepare(self->proto, &self->pollfd.fd, &proto_cond, timeout))
    return TRUE;

  /* recalculate buckets */

  if (self->writer->options->throttle > 0)
  {
    gint64 diff;
    gint new_buckets;

    /* throttling is enabled, calculate new buckets */
    if (self->last_throttle_check.tv_sec != 0)
    {
      diff = g_time_val_diff(&now, &self->last_throttle_check);
    }
    else
    {
      diff = 0;
      self->last_throttle_check = now;
    }
    new_buckets = (self->writer->options->throttle * diff) / G_USEC_PER_SEC;
    if (new_buckets)
    {

      /* if new_buckets is zero, we don't save the current time as
       * last_throttle_check. The reason is that new_buckets could be
       * rounded to zero when only a minimal interval passes between
       * poll iterations.
       */
      self->writer->throttle_buckets = MIN(self->writer->options->throttle, self->writer->throttle_buckets + new_buckets);
      self->last_throttle_check = now;
    }
  }

  if (G_UNLIKELY(self->error_suspend))
  {
    *timeout = g_time_val_diff(&self->error_suspend_target, &now) / 1000;
    if (*timeout <= 0)
    {
      msg_notice("Error suspend timeout has elapsed, attempting to write again",
          evt_tag_int("fd", log_proto_get_fd(self->proto)),
          NULL);
      self->error_suspend = FALSE;
      *timeout = -1;
    }
    else
    {
      return FALSE;
    }
  }

  if ((self->writer->options->flush_lines == 0 && (!log_writer_throttling(self->writer) && num_elements != 0)) ||
      (self->writer->options->flush_lines > 0  && (!log_writer_throttling(self->writer) && num_elements >= self->writer->options->flush_lines)))
  {
    /* we need to flush our buffers */
    self->pollfd.events |= proto_cond;
  }
  else if (num_elements && !log_writer_throttling(self->writer))
  {
    /* our buffer does not contain enough elements to flush, but we do not
     * want to wait more than flush_timeout time */

    if (!self->flush_waiting_for_timeout)
    {
      /* start waiting */

      *timeout = self->writer->options->flush_timeout;
      g_source_get_current_time(source, &self->flush_target);
      g_time_val_add(&self->flush_target, *timeout * 1000);
      self->flush_waiting_for_timeout = TRUE;
    }
    else
    {
      glong to = g_time_val_diff(&self->flush_target, &now) / 1000;
      if (to <= 0)
      {
        /* timeout elapsed, start polling again */
        if (self->writer->flags & LW_ALWAYS_WRITABLE)
          return TRUE;
        self->pollfd.events = proto_cond;
      }
      else
      {
        *timeout = to;
      }
    }
    return FALSE;
  }
  else
  {
    if (num_elements && log_writer_throttling(self->writer))
    {
      /* we are unable to send because of throttling, make sure that we
       * wake up when the rate limits lets us send at least 1 message */
      *timeout = (1000 / self->writer->options->throttle) + 1;
      msg_debug("Throttling output", 
          evt_tag_int("wait", *timeout), 
          NULL);
    }
  }

  if (self->writer->flags & LW_DETECT_EOF && (self->pollfd.events & G_IO_IN) == 0)
  {
    self->pollfd.events |= G_IO_HUP | G_IO_IN;
    self->input_means_connection_broken = TRUE;
  }
  else
  {
    self->input_means_connection_broken = FALSE;
  }

  self->flush_waiting_for_timeout = FALSE;

  if ((self->pollfd.events & G_IO_OUT) && (self->writer->flags & LW_ALWAYS_WRITABLE))
  {
    self->pollfd.revents = G_IO_OUT;
    return TRUE;
  }
  return FALSE;
}
示例#27
0
文件: stat_hdd.c 项目: kinpro/ussd-1
/*****************************************************************************
 * Processes HDD and SMART commands.
 *****************************************************************************/
void stat_hdd() {
	time_t tm;
	int channels_n, channel, device, i;
	int f_ata_request_supported, f_smart_supported, f_smart_enabled;
	struct ata_device dev[2];
	u_llong sectors;
	struct dev_match_result matches[100];
	union ccb ccb;

	msg_debug(1, "Processing of HDD/HDD_LIST/SMART command started");

	/* check byte order */
#if BYTE_ORDER != LITTLE_ENDIAN
	msg_err(0, "%s: ussd supports only LITTLE_ENDIAN byte order", __FUNCTION__);
	stat_hdd_finish();
	return;
#endif

	/* get statistics of all devices from devstat library */
	if ((f_stat_hdd_command_hdd || f_stat_hdd_command_hdd_list) && !stat_hdd_get_devstat()) {
		stat_hdd_finish();
		return;
	}

	/* check if [IOC]ATAREQUEST ioctl request supported by system */
	f_ata_request_supported = stat_hdd_is_ata_request_supported();
	if (f_stat_hdd_command_hdd || f_stat_hdd_command_smart) {
		tm = get_remote_tm();
		printf("%lu ata_request_supported %d\n", (u_long)tm, f_ata_request_supported);
	}

	/* determine number of ATA channels */
	if (stat_hdd_get_ata_channels_n(&channels_n)) {

		/* process all channels */
			for (channel = 0; channels_n < 0 || channel < channels_n; channel++) {
			msg_debug(2, "%s: Processing ATA channel %d", __FUNCTION__, channel);

			/* get channel devices */
			bzero(dev, sizeof(dev));
			if (!stat_hdd_get_ata_channel_devices(channel, dev)) {
				if (channels_n < 0)
					break;
				else
					continue;
			}
	
			/* check if channel has at least one device */
			if (!*dev[0].name && !*dev[1].name) {
				msg_debug(2, "%s: No devices found", __FUNCTION__);
				continue;
			}

			/* Process all devices within channel */
			for (device = 0; device < 2; device++) {
				/* skip if there is no device */
				if (!*dev[device].name)
					continue;
				msg_debug(2, "%s: Found device %s", __FUNCTION__, dev[device].name);
	
				if (!stat_hdd_is_device_ata(&dev[device])) {
					msg_debug(2, "%s: Device is not ATA device", __FUNCTION__);
					continue;
				}

				/* process HDD_LIST command */
				if (f_stat_hdd_command_hdd_list) {
					tm = get_remote_tm();
					printf("%lu hdd_exists:%s 1\n", (u_long)tm, dev[device].name);
				}
	
				/* go to the next device if no HDD or SMART command given */
				if (!f_stat_hdd_command_hdd && !f_stat_hdd_command_smart) {
					stat_hdd_fake_devstat(dev[device].name);
					continue;
				}
	
				/* refresh device parameters because they can be
				   cached by system */
				stat_hdd_refresh_ata_device_params(&dev[device]);
	
				/* process HDD command */
				if (f_stat_hdd_command_hdd) {
					/* get device size */
					sectors = stat_hdd_get_device_size(&dev[device]);
	
					tm = get_remote_tm();
					printf("%lu hdd_model:%s %s\n",
					    (u_long)tm, dev[device].name, dev[device].model);
					printf("%lu hdd_serno:%s %s\n",
					    (u_long)tm, dev[device].name, dev[device].serial);
					printf("%lu hdd_revision:%s %s\n",
					    (u_long)tm, dev[device].name, dev[device].revision);
					printf("%lu hdd_size_sectors:%s %llu\n",
					    (u_long)tm, dev[device].name, sectors);
					printf("%lu hdd_size_mbytes:%s %llu\n",
					    (u_long)tm, dev[device].name, sectors >> 11);
	
					/* print devstat statistics of device */
					stat_hdd_print_devstat(dev[device].name);
				}
				stat_hdd_fake_devstat(dev[device].name);
	
				/* process SMART command in remaining code */
				if (!f_stat_hdd_command_smart)
					continue;
	
				/* check if SMART supported by device */
				f_smart_supported = stat_hdd_is_smart_supported(&dev[device]);
	
				/* check if SMART enabled on device */
				f_smart_enabled = stat_hdd_is_smart_enabled(&dev[device]);
	
				/* enable SMART if requested */
				if (conf.f_enable_smart && f_ata_request_supported &&
				    f_smart_supported && !f_smart_enabled &&
				    stat_hdd_ata_command_interface(&dev[device],
				    SMART_ENABLE_OPERATIONS, NULL)) {
					f_smart_enabled = 1;
					msg_notice("SMART has been successfully enabled "
					    "on device %s", dev[device].name);
				}
	
				tm = get_remote_tm();
				printf("%lu smart_supported:%s %d\n",
				    (u_long)tm, dev[device].name, f_smart_supported);
				printf("%lu smart_enabled:%s %d\n",
				    (u_long)tm, dev[device].name, f_smart_enabled);
	
				/* don't try to get SMART if no attributes requested */
				if (!f_stat_hdd_smart_attrs_requested) {
					msg_debug(2, "%s: No SMART attributes requested",
					    __FUNCTION__);
					continue;
				}
	
				/* don't try to get SMART if system doesn't support
				   [IOC]ATAREQUEST ioctl request */
				if (!f_ata_request_supported) {
					msg_debug(2, "%s: Can't get SMART because system doesn't "
					    "support [IOC]ATAREQUEST ioctl request", __FUNCTION__);
					continue;
				}
	
				/* don't try to get SMART if it is not supported by device */
				if (!f_smart_supported) {
					msg_debug(2, "%s: SMART is not supported by device",
					    __FUNCTION__);
					continue;
				}
	
				/* don't try to get SMART if it is not enabled on device */
				if (!f_smart_enabled) {
					msg_debug(2, "%s: SMART is not enabled on device",
					    __FUNCTION__);
					continue;
				}
	
				/* get SMART values */
				if (!stat_hdd_ata_command_interface(&dev[device],
				    SMART_READ_VALUES, (char *)&dev[device].smart_values))
					continue;
				msg_debug(2, "%s: Got SMART values", __FUNCTION__);
	
				/* get SMART thresholds */
				if (!stat_hdd_ata_command_interface(&dev[device],
				    SMART_READ_THRESHOLDS, (char *)&dev[device].smart_thresholds))
					continue;
				msg_debug(2, "%s: Got SMART thresholds", __FUNCTION__);
	
				/* process SMART attributes */
				stat_hdd_process_smart_attributes(&dev[device]);
			}
		}
	
		msg_debug(2, "%s: All ATA channels processed", __FUNCTION__);
	}

	/* processing SCSI bus
	 * now we're not support SMART on SCSI, sad but true */

	msg_debug(2, "%s: Processing SCSI bus", __FUNCTION__);
	if ((channel = open(XPT_DEVICE, O_RDWR)) == -1) {
		msg_debug(1, "%s: open(%s) error %d (%s)", __FUNCTION__, XPT_DEVICE, errno, strerror(errno));
		stat_hdd_finish();
		return;
	}
	bzero(&ccb, sizeof(ccb));
	ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
	ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
	ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
	ccb.ccb_h.func_code = XPT_DEV_MATCH;
	ccb.cdm.match_buf_len = sizeof(matches);
	ccb.cdm.matches = &matches[0];
	if (ioctl(channel, CAMIOCOMMAND, &ccb) == -1) {
		msg_debug(1, "%s: ioctl(CAMIOCOMMAND) error %d (%s)", __FUNCTION__, errno, strerror(errno));
		stat_hdd_finish();
		return;
	}
	if ((ccb.ccb_h.status != CAM_REQ_CMP)
		|| ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
		&& (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
		msg_debug(1, "%s: CAM return error %#x, CDM error %d\n",
			__FUNCTION__, ccb.ccb_h.status, ccb.cdm.status);
		stat_hdd_finish();
		return;
	}

	/* walking CAM hierarchy */
	for(device = 0; (unsigned) device < ccb.cdm.num_matches; device++) {
		if (ccb.cdm.matches[device].type == DEV_MATCH_DEVICE) {
			if (ccb.cdm.matches[device].result.device_result.flags
				& DEV_RESULT_UNCONFIGURED)
				continue;
#if __FreeBSD_version > 800100
			/* new atacam devices - see ada(4) */
			if (ccb.cdm.matches[device].result.device_result.protocol == PROTO_ATA) {
				cam_strvis((void *) dev[0].model,
					ccb.cdm.matches[device].result.device_result.ident_data.model,
					sizeof(ccb.cdm.matches[device].result.device_result.ident_data.model),
					sizeof(dev[0].model));
				cam_strvis((void *) dev[0].serial,
					ccb.cdm.matches[device].result.device_result.ident_data.serial,
					sizeof(ccb.cdm.matches[device].result.device_result.ident_data.serial),
					sizeof(dev[0].serial));
				cam_strvis((void *) dev[0].revision,
					ccb.cdm.matches[device].result.device_result.ident_data.revision,
					sizeof(ccb.cdm.matches[device].result.device_result.ident_data.revision),
					sizeof(dev[0].revision));
				memcpy(&dev[0].params,
					&ccb.cdm.matches[device].result.device_result.ident_data,
					sizeof(dev[0].params));
				/* fake 3'rd device on IDE channel is atacam */
				dev[0].device = 2;
			}
			else if (ccb.cdm.matches[device].result.device_result.protocol == PROTO_SCSI) {
#endif
				cam_strvis((u_int8_t *) dev[0].model,
					(u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.vendor,
					sizeof(ccb.cdm.matches[device].result.device_result.inq_data.vendor),
					sizeof(dev[0].model));
				if (strlen(dev[0].model) < sizeof(dev[0].model)+2)
					strlcat(dev[0].model, " ", sizeof(dev[0].model));
				cam_strvis((u_int8_t *) dev[0].model+strlen(dev[0].model),
					(u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.product,
					sizeof(ccb.cdm.matches[device].result.device_result.inq_data.product),
					sizeof(dev[0].model)-strlen(dev[0].model));
				cam_strvis((u_int8_t *) dev[0].revision,
					(u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.revision,
					sizeof(ccb.cdm.matches[device].result.device_result.inq_data.revision),
					sizeof(dev[0].revision));
				/* fake 4'th device on IDE channel is SCSI disk */
				dev[0].device = 3;
				msg_debug(2, "%s: found SCSI device, model is %s",
					__FUNCTION__, dev[0].model);
#if __FreeBSD_version > 800100
			}
#endif
		}
		if (ccb.cdm.matches[device].type == DEV_MATCH_PERIPH) {
			for (i=0; i < dinfo.numdevs; i++) {
				if (((dinfo.devices[i].device_type & DEVSTAT_TYPE_MASK) != DEVSTAT_TYPE_DIRECT)
					|| (dinfo.devices[i].device_type & DEVSTAT_TYPE_PASS))
					continue;
				if (!strcmp(dinfo.devices[i].device_name,
					ccb.cdm.matches[device].result.periph_result.periph_name)
					&& (unsigned) dinfo.devices[i].unit_number == ccb.cdm.matches[device].result.periph_result.unit_number) {
					snprintf(dev[0].name, sizeof(dev[0].name),
						"%s%d",
						ccb.cdm.matches[device].result.periph_result.periph_name,
						ccb.cdm.matches[device].result.periph_result.unit_number);
					msg_debug(2, "%s: periph %s have stat", __FUNCTION__, dev[0].name);
					if (dev[0].device == 2)
						stat_hdd_refresh_ata_device_params(&dev[0]);
					if (dev[0].device == 3)
						stat_hdd_refresh_cam_device_params(&dev[0]);

					if (f_stat_hdd_command_hdd_list) {
						tm = get_remote_tm();
						printf("%lu hdd_exists:%s 1\n",
							(u_long)tm, dev[0].name);
					}
					if (f_stat_hdd_command_hdd) {
						sectors = stat_hdd_get_device_size(&dev[0]);
						tm = get_remote_tm();
						printf("%lu hdd_model:%s %s\n",
							(u_long)tm, dev[0].name, dev[0].model);
						printf("%lu hdd_serno:%s %s\n",
							(u_long)tm, dev[0].name, dev[0].serial);
						printf("%lu hdd_revision:%s %s\n",
							(u_long)tm, dev[0].name, dev[0].revision);
						printf("%lu hdd_size_sectors:%s %llu\n",
							(u_long)tm, dev[0].name, sectors);
						printf("%lu hdd_size_mbytes:%s %llu\n",
							(u_long)tm, dev[0].name, sectors >> 11);
						stat_hdd_print_devstat(dev[0].name);
					}
					stat_hdd_fake_devstat(dev[0].name);
					if (!f_stat_hdd_command_smart)
						break;
					/* Now i don't know how to read SMART from SCSI */
					if (dev[0].device == 3) {
						break;
					}
			
					f_smart_supported = stat_hdd_is_smart_supported(&dev[0]);
					f_smart_enabled = stat_hdd_is_smart_enabled(&dev[0]);
					if (conf.f_enable_smart
						&& f_ata_request_supported
						&& f_smart_supported
						&& !f_smart_enabled
						&& stat_hdd_ata_command_interface(&dev[0], SMART_ENABLE_OPERATIONS, NULL)) {
						f_smart_enabled = 1;
						msg_notice("SMART has been successfully enabled on device %s", dev[0].name);
					}
					tm = get_remote_tm();
					printf("%lu smart_supported:%s %d\n", (u_long)tm, dev[0].name, f_smart_supported);
					printf("%lu smart_enabled:%s %d\n", (u_long)tm, dev[0].name, f_smart_enabled);
					if (!f_stat_hdd_smart_attrs_requested) {
						msg_debug(2, "%s: No SMART attributes requested", __FUNCTION__);
						break;
					}
					if (!f_smart_supported) {
						msg_debug(2, "%s: SMART is not supported by device", __FUNCTION__);
						break;
					}
					if (!f_smart_enabled) {
						msg_debug(2, "%s: SMART is not enabled on device", __FUNCTION__);
						break;
					}
					if (!stat_hdd_ata_command_interface(&dev[0], SMART_READ_VALUES, (char *)&dev[0].smart_values))
						break;
					msg_debug(2, "%s: Got SMART values", __FUNCTION__);
					if (!stat_hdd_ata_command_interface(&dev[0], SMART_READ_THRESHOLDS, (char *)&dev[0].smart_thresholds))
						break;
					msg_debug(2, "%s: Got SMART thresholds", __FUNCTION__);
					stat_hdd_process_smart_attributes(&dev[0]);

					break;
				}
			}
		}
	}
static gboolean
log_proto_buffered_server_convert_from_raw(LogProtoBufferedServer *self, const guchar *raw_buffer, gsize raw_buffer_len)
{
  /* some data was read */
  gsize avail_in = raw_buffer_len;
  gsize avail_out;
  gchar *out;
  gint  ret = -1;
  gboolean success = FALSE;
  LogProtoBufferedServerState *state = log_proto_buffered_server_get_state(self);

  do
    {
      avail_out = state->buffer_size - state->pending_buffer_end;
      out = (gchar *) self->buffer + state->pending_buffer_end;

      ret = g_iconv(self->convert, (gchar **) &raw_buffer, &avail_in, (gchar **) &out, &avail_out);
      if (ret == (gsize) -1)
        {
          switch (errno)
            {
            case EINVAL:
              if (self->stream_based)
                {
                  /* Incomplete text, do not report an error, rather try to read again */
                  state->pending_buffer_end = state->buffer_size - avail_out;

                  if (avail_in > 0)
                    {
                      if (avail_in > sizeof(state->raw_buffer_leftover))
                        {
                          msg_error("Invalid byte sequence, the remaining raw buffer is larger than the supported leftover size",
                                    evt_tag_str("encoding", self->super.options->encoding),
                                    evt_tag_int("avail_in", avail_in),
                                    evt_tag_int("leftover_size", sizeof(state->raw_buffer_leftover)));
                          goto error;
                        }
                      memcpy(state->raw_buffer_leftover, raw_buffer, avail_in);
                      state->raw_buffer_leftover_size = avail_in;
                      state->raw_buffer_size -= avail_in;
                      msg_trace("Leftover characters remained after conversion, delaying message until another chunk arrives",
                                evt_tag_str("encoding", self->super.options->encoding),
                                evt_tag_int("avail_in", avail_in));
                      goto success;
                    }
                }
              else
                {
                  msg_error("Byte sequence too short, cannot convert an individual frame in its entirety",
                            evt_tag_str("encoding", self->super.options->encoding),
                            evt_tag_int("avail_in", avail_in));
                  goto error;
                }
              break;
            case E2BIG:
              state->pending_buffer_end = state->buffer_size - avail_out;
              /* extend the buffer */

              if (state->buffer_size < self->super.options->max_buffer_size)
                {
                  state->buffer_size *= 2;
                  if (state->buffer_size > self->super.options->max_buffer_size)
                    state->buffer_size = self->super.options->max_buffer_size;

                  self->buffer = g_realloc(self->buffer, state->buffer_size);

                  /* recalculate the out pointer, and add what we have now */
                  ret = -1;
                }
              else
                {
                  msg_error("Incoming byte stream requires a too large conversion buffer, probably invalid character sequence",
                            evt_tag_str("encoding", self->super.options->encoding),
                            evt_tag_printf("buffer", "%.*s", (gint) state->pending_buffer_end, self->buffer));
                  goto error;
                }
              break;
            case EILSEQ:
            default:
              msg_notice("Invalid byte sequence or other error while converting input, skipping character",
                         evt_tag_str("encoding", self->super.options->encoding),
                         evt_tag_printf("char", "0x%02x", *(guchar *) raw_buffer));
              goto error;
            }
        }
      else
        {
          state->pending_buffer_end = state->buffer_size - avail_out;
        }
    }
  while (avail_in > 0);

 success:
  success = TRUE;
 error:
  log_proto_buffered_server_put_state(self);
  return success;
}
static void
log_proto_buffered_server_apply_state(LogProtoBufferedServer *self, PersistEntryHandle handle, const gchar *persist_name)
{
  struct stat st;
  gint64 ofs = 0;
  LogProtoBufferedServerState *state;
  gint fd;

  fd = self->super.transport->fd;
  self->persist_handle = handle;

  if (fstat(fd, &st) < 0)
    return;

  state = log_proto_buffered_server_get_state(self);

  if (!self->buffer)
    {
      self->buffer = g_malloc(state->buffer_size);
    }
  state->pending_buffer_end = 0;

  if (state->file_inode &&
      state->file_inode == st.st_ino &&
      state->file_size <= st.st_size &&
      state->raw_stream_pos <= st.st_size)
    {
      ofs = state->raw_stream_pos;

      lseek(fd, ofs, SEEK_SET);
    }
  else
    {
      if (state->file_inode)
        {
          /* the stored state does not match the current file */
          msg_notice("The current log file has a mismatching size/inode information, restarting from the beginning",
                     evt_tag_str("state", persist_name),
                     evt_tag_int("stored_inode", state->file_inode),
                     evt_tag_int("cur_file_inode", st.st_ino),
                     evt_tag_int("stored_size", state->file_size),
                     evt_tag_int("cur_file_size", st.st_size),
                     evt_tag_int("raw_stream_pos", state->raw_stream_pos));
        }
      goto error;
    }
  if (state->raw_buffer_size)
    {
      gssize rc;
      guchar *raw_buffer;

      if (!self->super.options->encoding)
        {
          /* no conversion, we read directly into our buffer */
          if (state->raw_buffer_size > state->buffer_size)
            {
              msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than buffer_size and no encoding is set, restarting from the beginning",
                         evt_tag_str("state", persist_name),
                         evt_tag_int("raw_buffer_size", state->raw_buffer_size),
                         evt_tag_int("buffer_size", state->buffer_size),
                         evt_tag_int("init_buffer_size", self->super.options->init_buffer_size));
              goto error;
            }
          raw_buffer = self->buffer;
        }
      else
        {
          if (state->raw_buffer_size > self->super.options->max_buffer_size)
            {
              msg_notice("Invalid LogProtoBufferedServerState.raw_buffer_size, larger than max_buffer_size, restarting from the beginning",
                         evt_tag_str("state", persist_name),
                         evt_tag_int("raw_buffer_size", state->raw_buffer_size),
                         evt_tag_int("init_buffer_size", self->super.options->init_buffer_size),
                         evt_tag_int("max_buffer_size", self->super.options->max_buffer_size));
              goto error;
            }
          raw_buffer = g_alloca(state->raw_buffer_size);
        }

      rc = log_transport_read(self->super.transport, raw_buffer, state->raw_buffer_size, NULL);
      if (rc != state->raw_buffer_size)
        {
          msg_notice("Error re-reading buffer contents of the file to be continued, restarting from the beginning",
                     evt_tag_str("state", persist_name));
          goto error;
        }

      state->pending_buffer_end = 0;
      if (self->super.options->encoding)
        {
          if (!log_proto_buffered_server_convert_from_raw(self, raw_buffer, rc))
            {
              msg_notice("Error re-converting buffer contents of the file to be continued, restarting from the beginning",
                         evt_tag_str("state", persist_name));
              goto error;
            }
        }
      else
        {
          state->pending_buffer_end += rc;
        }

      if (state->buffer_pos > state->pending_buffer_end)
        {
          msg_notice("Converted buffer contents is smaller than the current buffer position, starting from the beginning of the buffer, some lines may be duplicated",
                     evt_tag_str("state", persist_name));
          state->buffer_pos = state->pending_buffer_pos = 0;
        }
    }
  else
    {
      /* although we do have buffer position information, but the
       * complete contents of the buffer is already processed, instead
       * of reading and then dropping it, position the file after the
       * indicated block */

      state->raw_stream_pos += state->raw_buffer_size;
      ofs = state->raw_stream_pos;
      state->raw_buffer_size = 0;
      state->buffer_pos = state->pending_buffer_end = 0;

      lseek(fd, state->raw_stream_pos, SEEK_SET);
    }
  goto exit;

 error:
  ofs = 0;
  state->buffer_pos = 0;
  state->pending_buffer_end = 0;
  state->__deprecated_buffer_cached_eol = 0;
  state->raw_stream_pos = 0;
  state->raw_buffer_size = 0;
  state->raw_buffer_leftover_size = 0;
  lseek(fd, 0, SEEK_SET);

 exit:
  state->file_inode = st.st_ino;
  state->file_size = st.st_size;
  state->raw_stream_pos = ofs;
  state->pending_buffer_pos = state->buffer_pos;
  state->pending_raw_stream_pos = state->raw_stream_pos;
  state->pending_raw_buffer_size = state->raw_buffer_size;
  state->__deprecated_buffer_cached_eol = 0;

  state = NULL;
  log_proto_buffered_server_put_state(self);
}