示例#1
0
int
allocate_pty(int *master, int *slave) {
#if defined(HAVE_OPENPTY) || (defined(HAVE_DECL_OPENPTY) && HAVE_DECL_OPENPTY != 0)
  if(openpty(master, slave, NULL, NULL, NULL)) return -1;
#else
  /* STREAMS... sigh */
  char   *slavename;
  extern char *ptsname();

  *master = open("/dev/ptmx", O_RDWR);  /* open master */
  if(*master < 0) return -1;
  grantpt(*master);                     /* change permission of   slave */
  unlockpt(*master);                    /* unlock slave */
  slavename = ptsname(*master);         /* get name of slave */
  *slave = open(slavename, O_RDWR);    /* open slave */
  if(*slave < 0) {
    close(*master);
    *master = -1;
    return -1;
  }
  /* This is a bit backwards as we using the PTY backwards.
   * We want to make the master a tty instead of the slave... odd, I know.
   */
  ioctl(*master, I_PUSH, "ptem");       /* push ptem */
  ioctl(*master, I_PUSH, "ldterm");     /* push ldterm*/
#endif
  if(eventer_set_fd_nonblocking(*master)) return -1;
  noitL(noit_debug, "allocate_pty -> %d,%d\n", *master, *slave);
  return 0;
}
示例#2
0
static int
child_main() {
  int log_flags;
  mtev_conf_section_t section;
  char *err = NULL;

  cli_stdout = mtev_log_stream_new_on_fd("stdout", 1, NULL);

  log_flags = mtev_log_stream_get_flags(mtev_stderr);
  log_flags &= ~(MTEV_LOG_STREAM_FACILITY|MTEV_LOG_STREAM_TIMESTAMPS);
  mtev_log_stream_set_flags(mtev_stderr, log_flags);

  /* reload our config, to make sure we have the most current */
  if(mtev_conf_load(NULL) == -1) {
    mtevL(mtev_error, "Cannot load config: '%s'\n", config_file);
    if(needs_unlink) unlink(config_file);
    exit(2);
  }

  mtev_conf_security_init(APPNAME, droptouser, droptogroup, NULL);

  if(mtev_conf_write_file(&err) != 0) {
    if(err) {
      mtevL(mtev_stderr, "Error: '%s'\n", err);
      free(err);
    }
    mtevL(mtev_stderr, "Permissions issue, are you running as the right user?\n");
    exit(2);
  }
  if(needs_unlink) unlink(config_file);

  /* update the lua module */
  section = mtev_conf_get_section(NULL, "/cli/modules/generic[@name=\"lua_general\"]/config");
  if(!section || !mtev_conf_set_string(section, "lua_module", lua_file)) {
    mtevL(mtev_stderr, "Cannot set target lua module, invalid config.\n");
    exit(2);
  }

  eventer_init();
  mtev_dso_init();
  mtev_dso_post_init();
  if(mtev_dso_load_failures() > 0) {
    mtevL(mtev_stderr, "Failed to initialize.\n");
    exit(2);
  }

  if(interactive) {
    mtev_console_init(APPNAME);
    mtev_console_conf_init(APPNAME);
    eventer_set_fd_nonblocking(STDIN_FILENO);
    if(mtev_console_std_init(STDIN_FILENO, STDOUT_FILENO)) {
      mtevL(mtev_stderr, "Failed to initialize IO\n");
      exit(2);
    }
  }
  /* Lastly, spin up the event loop */
  eventer_loop();
  return 0;
}
示例#3
0
static int external_init(noit_module_t *self) {
  external_data_t *data;

  data = noit_module_get_userdata(self);
  if(!data) data = malloc(sizeof(*data));
  data->nlerr = noit_log_stream_find("error/external");
  data->nldeb = noit_log_stream_find("debug/external");

  data->jobq = calloc(1, sizeof(*data->jobq));
  eventer_jobq_init(data->jobq, "external");
  data->jobq->backq = eventer_default_backq();
  eventer_jobq_increase_concurrency(data->jobq);

  if(socketpair(AF_UNIX, SOCK_STREAM, 0, data->pipe_n2e) != 0 ||
     socketpair(AF_UNIX, SOCK_STREAM, 0, data->pipe_e2n) != 0) {
    noitL(noit_error, "external: pipe() failed: %s\n", strerror(errno));
    return -1;
  }

  data->child = fork();
  if(data->child == -1) {
    /* No child, bail. */
    noitL(noit_error, "external: fork() failed: %s\n", strerror(errno));
    return -1;
  }

  /* parent must close the read side of n2e and the write side of e2n */
  /* The child must do the opposite */
  close(data->pipe_n2e[(data->child == 0) ? 1 : 0]);
  close(data->pipe_e2n[(data->child == 0) ? 0 : 1]);

  /* Now the parent must set its bits non-blocking, the child need not */
  if(data->child != 0) {
    /* in the parent */
    if(eventer_set_fd_nonblocking(data->pipe_e2n[0]) == -1) {
      close(data->pipe_n2e[1]);
      close(data->pipe_e2n[0]);
      noitL(noit_error,
            "external: could not set pipe non-blocking: %s\n",
            strerror(errno));
      return -1;
    }
    eventer_t newe;
    newe = eventer_alloc();
    newe->fd = data->pipe_e2n[0];
    newe->mask = EVENTER_READ | EVENTER_EXCEPTION;
    newe->callback = external_handler;
    newe->closure = self;
    eventer_add(newe);
  }
  else {
    const char *user = NULL, *group = NULL;
    if(data->options) {
      noit_hash_retr_str(data->options, "user", 4, &user);
      noit_hash_retr_str(data->options, "group", 4, &group);
    }
    noit_security_usergroup(user, group, noit_false);
    exit(external_child(data));
  }
  noit_module_set_userdata(self, data);
  return 0;
}
示例#4
0
static int noit_statsd_init(noit_module_t *self) {
  unsigned short port = 8125;
  int packets_per_cycle = 100;
  int payload_len = 256*1024;
  struct sockaddr_in skaddr;
  int sockaddr_len;
  const char *config_val;
  statsd_mod_config_t *conf;
  conf = noit_module_get_userdata(self);

  eventer_name_callback("statsd/statsd_handler", statsd_handler);

  if(noit_hash_retr_str(conf->options, "check", strlen("check"),
                        (const char **)&config_val)) {
    if(uuid_parse((char *)config_val, conf->primary) != 0)
      noitL(noit_error, "statsd check isn't a UUID\n");
    conf->primary_active = 1;
    conf->check = NULL;
  }
  if(noit_hash_retr_str(conf->options, "port", strlen("port"),
                        (const char **)&config_val)) {
    port = atoi(config_val);
  }
  conf->port = port;

  if(noit_hash_retr_str(conf->options, "packets_per_cycle",
                        strlen("packets_per_cycle"),
                        (const char **)&config_val)) {
    packets_per_cycle = atoi(config_val);
  }
  conf->packets_per_cycle = packets_per_cycle;

  conf->payload_len = payload_len;
  conf->payload = malloc(conf->payload_len);
  if(!conf->payload) {
    noitL(noit_error, "statsd malloc() failed\n");
    return -1;
  }

  conf->ipv4_fd = socket(PF_INET, NE_SOCK_CLOEXEC|SOCK_DGRAM, IPPROTO_UDP);
  if(conf->ipv4_fd < 0) {
    noitL(noit_error, "statsd: socket failed: %s\n", strerror(errno));
    return -1;
  }
  else {
    if(eventer_set_fd_nonblocking(conf->ipv4_fd)) {
      close(conf->ipv4_fd);
      conf->ipv4_fd = -1;
      noitL(noit_error,
            "collectd: could not set socket non-blocking: %s\n",
            strerror(errno));
      return -1;
    }
  }
  memset(&skaddr, 0, sizeof(skaddr));
  skaddr.sin_family = AF_INET;
  skaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  skaddr.sin_port = htons(conf->port);
  sockaddr_len = sizeof(skaddr);
  if(bind(conf->ipv4_fd, (struct sockaddr *)&skaddr, sockaddr_len) < 0) {
    noitL(noit_error, "bind failed[%d]: %s\n", conf->port, strerror(errno));
    close(conf->ipv4_fd);
    return -1;
  }

  if(conf->ipv4_fd >= 0) {
    eventer_t newe;
    newe = eventer_alloc();
    newe->fd = conf->ipv4_fd;
    newe->mask = EVENTER_READ | EVENTER_EXCEPTION;
    newe->callback = statsd_handler;
    newe->closure = self;
    eventer_add(newe);
  }

  conf->ipv6_fd = socket(AF_INET6, NE_SOCK_CLOEXEC|SOCK_DGRAM, IPPROTO_UDP);
  if(conf->ipv6_fd < 0) {
    noitL(noit_error, "statsd: IPv6 socket failed: %s\n",
          strerror(errno));
  }
  else {
    if(eventer_set_fd_nonblocking(conf->ipv6_fd)) {
      close(conf->ipv6_fd);
      conf->ipv6_fd = -1;
      noitL(noit_error,
            "statsd: could not set socket non-blocking: %s\n",
            strerror(errno));
    }
    else {
      struct sockaddr_in6 skaddr6;
      struct in6_addr in6addr_any;
      sockaddr_len = sizeof(skaddr6);
      memset(&skaddr6, 0, sizeof(skaddr6));
      skaddr6.sin6_family = AF_INET6;
      memset(&in6addr_any, 0, sizeof(in6addr_any));
      skaddr6.sin6_addr = in6addr_any;
      skaddr6.sin6_port = htons(conf->port);

      if(bind(conf->ipv6_fd, (struct sockaddr *)&skaddr6, sockaddr_len) < 0) {
        noitL(noit_error, "bind(IPv6) failed[%d]: %s\n",
              conf->port, strerror(errno));
        close(conf->ipv6_fd);
        conf->ipv6_fd = -1;
      }
    }
  }

  if(conf->ipv6_fd >= 0) {
    eventer_t newe;
    newe = eventer_alloc();
    newe->fd = conf->ipv6_fd;
    newe->mask = EVENTER_READ | EVENTER_EXCEPTION;
    newe->callback = statsd_handler;
    newe->closure = self;
    eventer_add(newe);
  }

  noit_module_set_userdata(self, conf);
  return 0;
}
示例#5
0
int
noit_listener(char *host, unsigned short port, int type,
              int backlog, noit_hash_table *sslconfig,
              noit_hash_table *config,
              eventer_func_t handler, void *service_ctx) {
  int rv, fd;
  int8_t family;
  int sockaddr_len;
  socklen_t reuse;
  listener_closure_t listener_closure;
  eventer_t event;
  union {
    struct in_addr addr4;
    struct in6_addr addr6;
  } a;
  union {
    struct sockaddr_in addr4;
    struct sockaddr_in6 addr6;
    struct sockaddr_un addru;
  } s;
  const char *event_name;

  noitL(nldeb, "noit_listener(%s, %d, %d, %d, %s, %p)\n",
        host, port, type, backlog,
        (event_name = eventer_name_for_callback(handler))?event_name:"??",
        service_ctx);
  if(host[0] == '/') {
    family = AF_UNIX;
  }
  else {
    family = AF_INET;
    rv = inet_pton(family, host, &a);
    if(rv != 1) {
      family = AF_INET6;
      rv = inet_pton(family, host, &a);
      if(rv != 1) {
        if(!strcmp(host, "*")) {
          family = AF_INET;
          a.addr4.s_addr = INADDR_ANY;
        } else {
          noitL(noit_error, "Cannot translate '%s' to IP\n", host);
          return -1;
        }
      }
    }
  }

  fd = socket(family, NE_SOCK_CLOEXEC|type, 0);
  if(fd < 0) {
    noitL(noit_error, "Cannot create socket: %s\n", strerror(errno));
    return -1;
  }

  if(eventer_set_fd_nonblocking(fd)) {
    close(fd);
    noitL(noit_error, "Cannot make socket non-blocking: %s\n",
          strerror(errno));
    return -1;
  }

  reuse = 1;
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
                 (void*)&reuse, sizeof(reuse)) != 0) {
    close(fd);
    noitL(noit_error, "Cannot set SO_REUSEADDR: %s\n", strerror(errno));
    return -1;
  }

  memset(&s, 0, sizeof(s));
  if(family == AF_UNIX) {
    struct stat sb;
    /* unlink the path if it is a socket */
    /* coverity[fs_check_call] */
    if(stat(host, &sb) == -1) {
      if(errno != ENOENT) {
        noitL(noit_error, "%s: %s\n", host, strerror(errno));
        close(fd);
        return -1;
      }
    }
    else {
      if(sb.st_mode & S_IFSOCK) {
        /* coverity[toctou] */
        unlink(host);
      }
      else {
        noitL(noit_error, "unlink %s failed: %s\n", host, strerror(errno));
        close(fd);
        return -1;
      }
    }
    s.addru.sun_family = AF_UNIX;
    strncpy(s.addru.sun_path, host, sizeof(s.addru.sun_path)-1);
    sockaddr_len = sizeof(s.addru);
  }
  else {
    if(family == AF_INET6) {
      s.addr6.sin6_family = family;
      s.addr6.sin6_port = htons(port);
      memcpy(&s.addr6.sin6_addr, &a.addr6, sizeof(a.addr6));
    }
    else {
      s.addr4.sin_family = family;
      s.addr4.sin_port = htons(port);
      memcpy(&s.addr4.sin_addr, &a.addr4, sizeof(a.addr4));
    }
    sockaddr_len = (family == AF_INET) ?  sizeof(s.addr4) : sizeof(s.addr6);
  }
  if(bind(fd, (struct sockaddr *)&s, sockaddr_len) < 0) {
    noitL(noit_error, "bind failed[%s]: %s\n", host, strerror(errno));
    close(fd);
    return -1;
  }

  if(type == SOCK_STREAM) {
    if(listen(fd, backlog) < 0) {
      close(fd);
      return -1;
    }
  }

  listener_closure = calloc(1, sizeof(*listener_closure));
  listener_closure->family = family;
  listener_closure->port = htons(port);
  listener_closure->sslconfig = calloc(1, sizeof(noit_hash_table));
  noit_hash_merge_as_dict(listener_closure->sslconfig, sslconfig);
  listener_closure->dispatch_callback = handler;

  listener_closure->dispatch_closure =
    calloc(1, sizeof(*listener_closure->dispatch_closure));
  listener_closure->dispatch_closure->config = config;
  listener_closure->dispatch_closure->dispatch = handler;
  listener_closure->dispatch_closure->service_ctx = service_ctx;

  event = eventer_alloc();
  event->fd = fd;
  event->mask = EVENTER_READ | EVENTER_EXCEPTION;
  event->callback = noit_listener_acceptor;
  event->closure = listener_closure;

  eventer_add(event);
  return 0;
}
示例#6
0
static int
noit_listener_acceptor(eventer_t e, int mask,
                       void *closure, struct timeval *tv) {
  int conn, newmask = EVENTER_READ;
  socklen_t salen;
  listener_closure_t listener_closure = (listener_closure_t)closure;
  acceptor_closure_t *ac = NULL;

  if(mask & EVENTER_EXCEPTION) {
 socketfail:
    if(ac) acceptor_closure_free(ac);
    /* We don't shut down the socket, it's out listener! */
    return EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
  }

  do {
    ac = malloc(sizeof(*ac));
    memcpy(ac, listener_closure->dispatch_closure, sizeof(*ac));
    salen = sizeof(ac->remote);
    conn = e->opset->accept(e->fd, &ac->remote.remote_addr, &salen, &newmask, e);
    if(conn >= 0) {
      eventer_t newe;
      noitL(nldeb, "noit_listener[%s] accepted fd %d\n",
            eventer_name_for_callback(listener_closure->dispatch_callback),
            conn);
      if(eventer_set_fd_nonblocking(conn)) {
        close(conn);
        free(ac);
        goto accept_bail;
      }
      newe = eventer_alloc();
      newe->fd = conn;
      newe->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
  
      if(listener_closure->sslconfig->size) {
        const char *layer, *cert, *key, *ca, *ciphers, *crl;
        eventer_ssl_ctx_t *ctx;
        /* We have an SSL configuration.  While our socket accept is
         * complete, we now have to SSL_accept, which could require
         * several reads and writes and needs its own event callback.
         */
  #define SSLCONFGET(var,name) do { \
    if(!noit_hash_retr_str(listener_closure->sslconfig, name, strlen(name), \
                           &var)) var = NULL; } while(0)
        SSLCONFGET(layer, "layer");
        SSLCONFGET(cert, "certificate_file");
        SSLCONFGET(key, "key_file");
        SSLCONFGET(ca, "ca_chain");
        SSLCONFGET(ciphers, "ciphers");
        ctx = eventer_ssl_ctx_new(SSL_SERVER, layer, cert, key, ca, ciphers);
        if(!ctx) {
          newe->opset->close(newe->fd, &newmask, e);
          eventer_free(newe);
          goto socketfail;
        }
        SSLCONFGET(crl, "crl");
        if(crl) {
          if(!eventer_ssl_use_crl(ctx, crl)) {
            noitL(noit_error, "Failed to load CRL from %s\n", crl);
            eventer_ssl_ctx_free(ctx);
            newe->opset->close(newe->fd, &newmask, e);
            eventer_free(newe);
            goto socketfail;
          }
        }

        eventer_ssl_ctx_set_verify(ctx, eventer_ssl_verify_cert,
                                   listener_closure->sslconfig);
        EVENTER_ATTACH_SSL(newe, ctx);
        newe->callback = noit_listener_accept_ssl;
        newe->closure = malloc(sizeof(*listener_closure));
        memcpy(newe->closure, listener_closure, sizeof(*listener_closure));
        ((listener_closure_t)newe->closure)->dispatch_closure = ac;
      }
      else {
        newe->callback = listener_closure->dispatch_callback;
        /* We must make a copy of the acceptor_closure_t for each new
         * connection.
         */
        newe->closure = ac;
      }
      eventer_add(newe);
    }
    else {
      if(errno == EAGAIN) {
        if(ac) acceptor_closure_free(ac);
      }
      else if(errno != EINTR) {
        noitL(noit_error, "accept socket error: %s\n", strerror(errno));
        goto socketfail;
      }
    }
  } while(conn >= 0);
 accept_bail:
  return newmask | EVENTER_EXCEPTION;
}
示例#7
0
static int ssh2_initiate(noit_module_t *self, noit_check_t *check,
                         noit_check_t *cause) {
  ssh2_check_info_t *ci = check->closure;
  struct timeval p_int, __now;
  int fd = -1, rv = -1;
  eventer_t e;
  union {
    struct sockaddr_in sin;
    struct sockaddr_in6 sin6;
  } sockaddr;
  socklen_t sockaddr_len;
  unsigned short ssh_port = DEFAULT_SSH_PORT;
  const char *port_str = NULL;

  /* We cannot be running */
  BAIL_ON_RUNNING_CHECK(check);
  check->flags |= NP_RUNNING;

  ci->self = self;
  ci->check = check;

  ci->timed_out = 1;
  if(ci->timeout_event) {
    eventer_remove(ci->timeout_event);
    free(ci->timeout_event->closure);
    eventer_free(ci->timeout_event);
    ci->timeout_event = NULL;
  }
  gettimeofday(&__now, NULL);
  memcpy(&check->last_fire_time, &__now, sizeof(__now));

  if(check->target_ip[0] == '\0') {
    ci->error = strdup("name resolution failure");
    goto fail;
  }
  /* Open a socket */
  fd = socket(check->target_family, NE_SOCK_CLOEXEC|SOCK_STREAM, 0);
  if(fd < 0) goto fail;

  /* Make it non-blocking */
  if(eventer_set_fd_nonblocking(fd)) goto fail;

  if(noit_hash_retr_str(check->config, "port", strlen("port"),
                        &port_str)) {
    ssh_port = (unsigned short)atoi(port_str);
  }
#define config_method(a) do { \
  const char *v; \
  if(noit_hash_retr_str(check->config, "method_" #a, strlen("method_" #a), \
                        &v)) \
    ci->methods.a = strdup(v); \
} while(0)
  config_method(kex);
  config_method(hostkey);
  config_method(crypt_cs);
  config_method(crypt_sc);
  config_method(mac_cs);
  config_method(mac_sc);
  config_method(comp_cs);
  config_method(comp_sc);
  memset(&sockaddr, 0, sizeof(sockaddr));
  sockaddr.sin6.sin6_family = check->target_family;
  if(check->target_family == AF_INET) {
    memcpy(&sockaddr.sin.sin_addr,
           &check->target_addr.addr, sizeof(sockaddr.sin.sin_addr));
    sockaddr.sin.sin_port = htons(ssh_port);
    sockaddr_len = sizeof(sockaddr.sin);
  }
  else {
    memcpy(&sockaddr.sin6.sin6_addr,
           &check->target_addr.addr6, sizeof(sockaddr.sin6.sin6_addr));
    sockaddr.sin6.sin6_port = htons(ssh_port);
    sockaddr_len = sizeof(sockaddr.sin6);
  }

  /* Initiate a connection */
  rv = connect(fd, (struct sockaddr *)&sockaddr, sockaddr_len);
  if(rv == -1 && errno != EINPROGRESS) goto fail;

  /* Register a handler for connection completion */
  e = eventer_alloc();
  e->fd = fd;
  e->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION;
  e->callback = ssh2_connect_complete;
  e->closure =  ci;
  ci->synch_fd_event = e;
  eventer_add(e);

  e = eventer_alloc();
  e->mask = EVENTER_TIMER;
  e->callback = ssh2_connect_timeout;
  e->closure = ci;
  memcpy(&e->whence, &__now, sizeof(__now));
  p_int.tv_sec = check->timeout / 1000;
  p_int.tv_usec = (check->timeout % 1000) * 1000;
  add_timeval(e->whence, p_int, &e->whence);
  ci->timeout_event = e;
  eventer_add(e);
  return 0;

 fail:
  if(fd >= 0) close(fd);
  ssh2_log_results(ci->self, ci->check);
  ssh2_cleanup(ci->self, ci->check);
  check->flags &= ~NP_RUNNING;
  return -1;
}