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; }
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; }
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; }
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; }
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; }
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; }
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; }