예제 #1
0
void
control_connection_wait_for_output(ControlConnection *self)
{
  if (self->output_buffer->len == 0)
    self->waiting_for_output = TRUE;
  control_connection_update_watches(self);
}
예제 #2
0
static void
control_connection_io_output(gpointer s)
{
  ControlConnection *self = (ControlConnection *) s;
  gint rc;
  
  rc = write(self->control_io.fd, self->output_buffer->str + self->pos, self->output_buffer->len - self->pos);
  if (rc < 0)
    {
      if (errno != EAGAIN)
        {
          msg_error("Error writing control channel",
                    evt_tag_errno("error", errno),
                    NULL);
          control_connection_stop_watches(self);
          control_connection_free(self);
          return;
        }
    }
  else
    {
      self->pos += rc;
    }
  control_connection_update_watches(self);
}
예제 #3
0
static void
control_connection_start_watches(ControlConnection *self, gint sock)
{
  IV_FD_INIT(&self->control_io);
  self->control_io.cookie = self;
  self->control_io.fd = sock;
  iv_fd_register_try(&self->control_io);

  control_connection_update_watches(self);
}
예제 #4
0
void
control_connection_start_watches(ControlConnection *s)
{
  ControlConnectionUnix *self = (ControlConnectionUnix *)s;
  IV_FD_INIT(&self->control_io);
  self->control_io.cookie = self;
  self->control_io.fd = self->fd;
  iv_fd_register(&self->control_io);

  control_connection_update_watches(s);
}
예제 #5
0
static void
control_connection_send_reply(ControlConnection *self, gchar *reply, gboolean free_reply)
{
  g_string_assign(self->output_buffer, reply);
  if (free_reply)
    g_free(reply);

  self->pos = 0;

  if (self->output_buffer->str[self->output_buffer->len - 1] != '\n')
    g_string_append_c(self->output_buffer, '\n');
  g_string_append(self->output_buffer, ".\n");

  control_connection_update_watches(self);
}
예제 #6
0
void
control_connection_send_reply(ControlConnection *self, GString *reply)
{
  g_string_assign(self->output_buffer, reply->str);
  g_string_free(reply, TRUE);

  self->pos = 0;
  self->waiting_for_output = FALSE;
  if (self->output_buffer->str[self->output_buffer->len - 1] != '\n')
    {
      g_string_append_c(self->output_buffer, '\n');
    }
  g_string_append(self->output_buffer, ".\n");

  control_connection_update_watches(self);
}
예제 #7
0
static void
control_connection_io_output(gpointer s)
{
  ControlConnection *self = (ControlConnection *) s;
  gint rc;

  rc = self->write(self, self->output_buffer->str + self->pos, self->output_buffer->len - self->pos);
  if (rc < 0)
    {
      if (errno != EAGAIN)
        {
          msg_error("Error writing control channel",
                    evt_tag_error("error"));
          control_server_connection_closed(self->server, self);
          return;
        }
    }
  else
    {
      self->pos += rc;
    }
  control_connection_update_watches(self);
}
예제 #8
0
static void
control_connection_io_input(void *s)
{
  ControlConnection *self = (ControlConnection *) s;
  GString *command = NULL;
  gchar *nl;
  gint rc;
  gint orig_len;
  GList *iter;

  if (self->input_buffer->len > MAX_CONTROL_LINE_LENGTH)
    {
      /* too much data in input, drop the connection */
      msg_error("Too much data in the control socket input buffer");
      control_server_connection_closed(self->server, self);
      return;
    }

  orig_len = self->input_buffer->len;

  /* NOTE: plus one for the terminating NUL */
  g_string_set_size(self->input_buffer, self->input_buffer->len + 128 + 1);
  rc = self->read(self, self->input_buffer->str + orig_len, 128);
  if (rc < 0)
    {
      if (errno != EAGAIN)
        {
          msg_error("Error reading command on control channel, closing control channel",
                    evt_tag_error("error"));
          goto destroy_connection;
        }
      /* EAGAIN, should try again when data comes */
      control_connection_update_watches(self);
      return;
    }
  else if (rc == 0)
    {
      msg_debug("EOF on control channel, closing connection");
      goto destroy_connection;
    }
  else
    {
      self->input_buffer->len = orig_len + rc;
      self->input_buffer->str[self->input_buffer->len] = 0;
    }

  /* here we have finished reading the input, check if there's a newline somewhere */
  nl = strchr(self->input_buffer->str, '\n');
  if (nl)
    {
      command = g_string_sized_new(128);
      /* command doesn't contain NL */
      g_string_assign_len(command, self->input_buffer->str, nl - self->input_buffer->str);
      secret_storage_wipe(self->input_buffer->str, nl - self->input_buffer->str);
      /* strip NL */
      /*g_string_erase(self->input_buffer, 0, command->len + 1);*/
      g_string_truncate(self->input_buffer, 0);
    }
  else
    {
      /* no EOL in the input buffer, wait for more data */
      control_connection_update_watches(self);
      return;
    }

  iter = g_list_find_custom(get_control_command_list(), command->str,
                            (GCompareFunc)control_command_start_with_command);
  if (iter == NULL)
    {
      msg_error("Unknown command read on control channel, closing control channel",
                evt_tag_str("command", command->str));
      g_string_free(command, TRUE);
      goto destroy_connection;
    }
  ControlCommand *cmd_desc = (ControlCommand *) iter->data;

  cmd_desc->func(self, command, cmd_desc->user_data);
  control_connection_wait_for_output(self);

  secret_storage_wipe(command->str, command->len);
  g_string_free(command, TRUE);
  return;
destroy_connection:
  control_server_connection_closed(self->server, self);
}
예제 #9
0
/*
 * NOTE: the channel is not in nonblocking mode, thus the control channel
 * may block syslog-ng completely.
 */
static void
control_connection_io_input(void *s)
{
  ControlConnection *self = (ControlConnection *) s;
  GString *command = NULL;
  gchar *nl;
  gint rc;
  gint cmd;
  gint orig_len;
  
  if (self->input_buffer->len > MAX_CONTROL_LINE_LENGTH)
    {
      /* too much data in input, drop the connection */
      msg_error("Too much data in the control socket input buffer",
                NULL);
      control_connection_stop_watches(self);
      control_connection_free(self);
      return;
    }

  orig_len = self->input_buffer->len;

  /* NOTE: plus one for the terminating NUL */
  g_string_set_size(self->input_buffer, self->input_buffer->len + 128 + 1);
  rc = read(self->control_io.fd, self->input_buffer->str + orig_len, 128);
  if (rc < 0)
    {
      if (errno != EAGAIN)
        {
          msg_error("Error reading command on control channel, closing control channel",
                    evt_tag_errno("error", errno),
                    NULL);
          goto destroy_connection;
        }
      /* EAGAIN, should try again when data comes */
      control_connection_update_watches(self);
      return;
    }
  else if (rc == 0)
    {
      msg_error("EOF on control channel, closing connection",
                NULL);
      goto destroy_connection;
    }
  else
    {
      self->input_buffer->len = orig_len + rc;
      self->input_buffer->str[self->input_buffer->len] = 0;
    }

  /* here we have finished reading the input, check if there's a newline somewhere */
  nl = strchr(self->input_buffer->str, '\n');
  if (nl)
    {
      command = g_string_sized_new(128);
      /* command doesn't contain NL */
      g_string_assign_len(command, self->input_buffer->str, nl - self->input_buffer->str);
      /* strip NL */
      g_string_erase(self->input_buffer, 0, command->len + 1);
    }
  else
    {
      /* no EOL in the input buffer, wait for more data */
      control_connection_update_watches(self);
      return;
    }

  for (cmd = 0; commands[cmd].func; cmd++)
    {
      if (strncmp(commands[cmd].command, command->str, strlen(commands[cmd].command)) == 0)
        {
          commands[cmd].func(self, command);
          break;
        }
    }
  if (!commands[cmd].func)
    {
      msg_error("Unknown command read on control channel, closing control channel",
                evt_tag_str("command", command->str), NULL);
      goto destroy_connection;
    }
  control_connection_update_watches(self);
  g_string_free(command, TRUE);
  return;
 destroy_connection:
  control_connection_stop_watches(self);
  control_connection_free(self);

}