static void control_close(struct ctl_conn *c) { TAILQ_REMOVE(&ctl_conns, c, entry); event_del(&c->iev.ev); close(c->iev.ibuf.fd); imsg_clear(&c->iev.ibuf); free(c); stat_backend->decrement("control.session", 1); if (available_fds(CONTROL_FD_RESERVE)) return; if (!event_pending(&control_state.ev, EV_READ, NULL)) { log_warnx("re-enabling ctl connections"); event_add(&control_state.ev, NULL); } }
static void chld_sighdlr(evutil_socket_t sig, short events, void *args) { struct event_base *evbase = args; char *name = "unknow"; (void)events; switch (sig) { case SIGTERM: name = "sigterm"; break; case SIGINT: name = "sigint"; break; } log_warnx("received signal %s(%d), stopping", name, sig); event_base_loopbreak(evbase); }
static int on_rcpt(uint64_t id, const char *rcpt) { char s_id[20]; memset(s_id, 0, 20); sprintf(s_id, "%lu", id); lua_getglobal(L, "on_rcpt"); lua_pushstring(L, s_id); lua_pushstring(L, rcpt); if (lua_pcall(L, 2, 0, 0)) { log_warnx("warn: filter-lua: on_rcpt() failed: %s", lua_tostring(L, -1)); exit(1); } return (1); }
/* Initial state. */ int fetch_mbox_state_init(struct account *a, struct fetch_ctx *fctx) { struct fetch_mbox_data *data = a->data; if (fetch_mbox_make(a) != 0) return (FETCH_ERROR); if (ARRAY_EMPTY(&data->fmboxes)) { log_warnx("%s: no mboxes found", a->name); return (-1); } data->index = 0; TAILQ_INIT(&data->kept); fctx->state = fetch_mbox_state_open; return (FETCH_AGAIN); }
void xml_finish(struct writer * w) { struct xml_writer_private * p = w->priv; int failed = 0; if (xmlTextWriterEndDocument(p->xw) < 0 ) { log_warnx("lldpctl", "cannot finish document"); failed = 1; } xmlFreeTextWriter(p->xw); if ( ! failed ) xmlSaveFileEnc("-", p->doc, MY_ENCODING); xmlFreeDoc(p->doc); free( w->priv ); free( w ); }
static void filter_register_query(uint64_t id, uint64_t qid, int type) { struct filter_session *s; log_trace(TRACE_FILTERS, "filter-api:%s %016"PRIx64" %s", filter_name, id, query_to_str(type)); s = tree_xget(&sessions, id); if (s->qid) { log_warnx("warn: filter-api:%s query already in progess", filter_name); fatalx("filter-api: exiting"); } s->qid = qid; s->qtype = type; s->response.ready = 0; tree_xset(&queries, qid, s); }
/* Sleep for lock. */ int locksleep(const char *hdr, const char *path, long long *used) { useconds_t us; if (*used == 0) srandom((u_int) getpid()); us = LOCKSLEEPTIME + (random() % LOCKSLEEPTIME); log_debug3("%s: %s: " "sleeping %.3f seconds for lock", hdr, path, us / 1000000.0); usleep(us); *used += us; if (*used < LOCKTOTALTIME) return (0); log_warnx("%s: %s: " "couldn't get lock in %.3f seconds", hdr, path, *used / 1000000.0); return (-1); }
static int queue_ram_envelope_load(uint64_t evpid, char *buf, size_t len) { struct qr_envelope *evp; struct qr_message *msg; if ((msg = get_message(evpid_to_msgid(evpid))) == NULL) return (0); if ((evp = tree_get(&msg->envelopes, evpid)) == NULL) { log_warn("warn: queue-ram: not found"); return (0); } if (len < evp->len) { log_warnx("warn: queue-ram: buffer too small"); return (0); } memmove(buf, evp->buf, evp->len); return (evp->len); }
int check_http_digest(struct ctl_tcp_event *cte) { char *head; u_char *b; char digest[SHA1_DIGEST_STRING_LENGTH]; struct host *host; /* * ensure string is nul-terminated. */ b = ibuf_reserve(cte->buf, 1); if (b == NULL) fatal("out of memory"); *b = '\0'; head = cte->buf->buf; host = cte->host; host->he = HCE_HTTP_DIGEST_ERROR; if ((head = strstr(head, "\r\n\r\n")) == NULL) { log_debug("%s: %s failed (no end of headers)", __func__, host->conf.name); host->up = HOST_DOWN; return (1); } head += strlen("\r\n\r\n"); digeststr(cte->table->conf.digest_type, head, strlen(head), digest); if (strcmp(cte->table->conf.digest, digest)) { log_warnx("%s: %s failed (wrong digest)", __func__, host->conf.name); host->he = HCE_HTTP_DIGEST_FAIL; host->up = HOST_DOWN; } else { host->he = HCE_HTTP_DIGEST_OK; host->up = HOST_UP; } return (!(host->up == HOST_UP)); }
/* ARGSUSED */ static void control_accept(int listenfd, short event, void *arg) { int connfd; socklen_t len; struct sockaddr_un sun; struct ctl_conn *c; if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE) goto pause; len = sizeof(sun); if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) { if (errno == ENFILE || errno == EMFILE) goto pause; if (errno == EINTR || errno == EWOULDBLOCK || errno == ECONNABORTED) return; fatal("control_accept: accept"); } session_socket_blockmode(connfd, BM_NONBLOCK); c = xcalloc(1, sizeof(*c), "control_accept"); if (getpeereid(connfd, &c->euid, &c->egid) == -1) fatal("getpeereid"); c->id = ++connid; c->mproc.proc = PROC_CLIENT; c->mproc.handler = control_dispatch_ext; c->mproc.data = c; mproc_init(&c->mproc, connfd); mproc_enable(&c->mproc); tree_xset(&ctl_conns, c->id, c); stat_backend->increment("control.session", 1); return; pause: log_warnx("warn: ctl client limit hit, disabling new connections"); event_del(&control_state.ev); }
int main(int argc, char **argv) { int ch, d = 0, v = 0; log_init(1); while ((ch = getopt(argc, argv, "dv")) != -1) { switch (ch) { case 'd': d = 1; break; case 'v': v |= TRACE_DEBUG; break; default: log_warnx("warn: bad option"); return (1); /* NOTREACHED */ } } argc -= optind; argv += optind; log_init(d); log_verbose(v); log_debug("debug: starting..."); filter_api_on_data(clamav_on_data); filter_api_on_dataline(clamav_on_dataline); filter_api_on_eom(clamav_on_eom); filter_api_on_reset(clamav_on_reset); filter_api_on_disconnect(clamav_on_disconnect); filter_api_on_rollback(clamav_on_rollback); filter_api_loop(); log_debug("debug: exiting"); return (1); }
static int queue_proc_envelope_load(uint64_t evpid, char *buf, size_t len) { int r; imsg_compose(&ibuf, PROC_QUEUE_ENVELOPE_LOAD, 0, 0, -1, &evpid, sizeof(evpid)); queue_proc_call(); if (rlen > len) { log_warnx("warn: queue-proc: buf too small"); fatalx("queue-proc: exiting"); } r = rlen; queue_proc_read(buf, rlen); queue_proc_end(); return (r); }
static int on_data(uint64_t id) { PyObject *py_args; PyObject *py_ret; PyObject *py_id; py_args = PyTuple_New(1); py_id = PyLong_FromUnsignedLongLong(id); PyTuple_SetItem(py_args, 0, py_id); py_ret = PyObject_CallObject(py_on_data, py_args); Py_DECREF(py_args); if (py_ret == NULL) { PyErr_Print(); log_warnx("warn: filter-python: call to on_datra handler failed"); exit(1); } return (1); }
static int on_connect(uint64_t id, struct filter_connect *conn) { char s_id[20]; memset(s_id, 0, 20); sprintf(s_id, "%lu", id); lua_getglobal(L, "on_connect"); lua_pushstring(L, s_id); lua_pushstring(L, filter_api_sockaddr_to_text((struct sockaddr *)&conn->local)); lua_pushstring(L, filter_api_sockaddr_to_text((struct sockaddr *)&conn->remote)); lua_pushstring(L, conn->hostname); if (lua_pcall(L, 4, 0, 0)) { log_warnx("warn: filter-lua: on_connect() failed: %s", lua_tostring(L, -1)); exit(1); } return (1); }
static int queue_ram_message_delete(uint32_t msgid) { struct qr_message *msg; struct qr_envelope *evp; uint64_t evpid; if ((msg = tree_pop(&messages, msgid)) == NULL) { log_warnx("warn: queue-ram: not found"); return (0); } while (tree_poproot(&messages, &evpid, (void**)&evp)) { stat_decrement("queue.ram.envelope.size", evp->len); free(evp->buf); free(evp); } stat_decrement("queue.ram.message.size", msg->len); free(msg->buf); free(msg); return (0); }
void control_close(int fd) { struct ctl_conn *c; if ((c = control_connbyfd(fd)) == NULL) { log_warn("control_close: fd %d: not found", fd); return; } TAILQ_REMOVE(&ctl_conns, c, entry); event_del(&c->iev.ev); imsg_clear(&c->iev.ibuf); close(fd); free(c); if (stat_decrement(STATS_CONTROL_SESSION) < env->sc_maxconn && !event_pending(&control_state.ev, EV_READ, NULL)) { log_warnx("re-enabling ctl connections"); event_add(&control_state.ev, NULL); } }
/** * Read an anoubis protocol message from a client connected to the session * engine. A client message on the wire consists of a 32 bit length in * network byte order followed by the actual message data. The length * given includes the 32 length itself and the 32 bit checksum at the * end of the message. * * @param fd The file descriptor to read from. * @param msgp A complete message (if any) is stored here. This value * must never be NULL. The pointer pointed to by msgp is either set * to NULL or is set to point to the result message. The result message * is allocated using anoubis_msg_new and must be freed by the caller * with anoubis_msg_free. * @return Zero if EOF is encountered. A negative error code if an error * occured or a positive value in case of success. * NOTE: Success does not mean that there is a complete message * available. The message may still be incomplete. In this case * NULL is stored in *msgp. */ int get_client_msg(int fd, struct anoubis_msg **msgp) { struct msg_buf *mbp; u_int32_t len; struct anoubis_msg *m; *msgp = NULL; if ((mbp = _get_mbp(fd)) == NULL) return 0; if (mbp->rmsg) { log_warnx("get_client_msg: Bad buffer state"); return 0; } if ((unsigned int)(mbp->rtailp - mbp->rheadp) < sizeof(len)) if (!_fill_buf(mbp)) return 0; if ((unsigned int)(mbp->rtailp - mbp->rheadp) < sizeof(len)) return 1; len = ntohl(*(u_int32_t*)mbp->rheadp); if ((unsigned int)(mbp->rtailp - mbp->rheadp) < len) if (!_fill_buf(mbp)) return 0; if ((unsigned int)(mbp->rtailp - mbp->rheadp) < len) return 1; /* * anoubis_msg_new expects the size of the message without * the message length and without the trainling checksum (i.e. * payload data only). However, m->length of the resulting * message includes the checksum but not the message length. * This is the reason for the somewhat surprising length calculations. */ m = anoubis_msg_new(len - sizeof(len) - CSUM_LEN); if (!m) return -ENOMEM; memcpy(m->u.buf, mbp->rheadp+sizeof(len), m->length); mbp->rheadp += len; *msgp = m; return 1; }
static int chap_b642bin(const char *b64, void **binp, size_t *bin_lenp) { char *bin; int b64_len, bin_len; b64_len = strlen(b64); bin_len = (b64_len + 3) / 4 * 3; bin = calloc(bin_len, 1); if (bin == NULL) log_err(1, "calloc"); bin_len = b64_pton(b64, bin, bin_len); if (bin_len < 0) { log_warnx("malformed base64 variable"); free(bin); return (-1); } *binp = bin; *bin_lenp = bin_len; return (0); }
/* * Copy 'src' to 'dst' until 'marker' is found while unescaping '\' * characters. The return value tells the caller where to continue * parsing (might be the end of the string) or NULL on error. */ static char * ca_x509_name_unescape(char *src, char *dst, char marker) { while (*src) { if (*src == marker) { src++; break; } if (*src == '\\') { src++; if (!*src) { log_warnx("%s: '\\' at end of string", __func__); *dst = '\0'; return (NULL); } } *dst++ = *src++; } *dst = '\0'; return (src); }
int host(const char *s, struct bgpd_addr *h, u_int8_t *len) { int done = 0; int mask; char *p, *ps; const char *errstr; if ((p = strrchr(s, '/')) != NULL) { mask = strtonum(p + 1, 0, 128, &errstr); if (errstr) { log_warnx("prefixlen is %s: %s", errstr, p + 1); return (0); } if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) fatal("host: malloc"); strlcpy(ps, s, strlen(s) - strlen(p) + 1); } else { if ((ps = strdup(s)) == NULL) fatal("host: strdup"); mask = 128; } bzero(h, sizeof(struct bgpd_addr)); /* IPv4 address? */ if (!done) done = host_v4(s, h, len); /* IPv6 address? */ if (!done) { done = host_v6(ps, h); *len = mask; } free(ps); return (done); }
static int clamav_on_eom(uint64_t id, size_t size) { struct clamav *cl; int r; if ((cl = filter_api_get_udata(id)) == NULL) return filter_api_accept(id); if (clamav_response(cl) == -1) { clamav_clear(cl); filter_api_set_udata(id, NULL); return filter_api_reject_code(id, FILTER_FAIL, 451, "4.7.1 Virus filter failed"); } r = cl->r; clamav_clear(cl); filter_api_set_udata(id, NULL); if (r) { log_warnx("warn: session %016"PRIx64": on_eom: REJECT virus", id); return filter_api_reject_code(id, FILTER_CLOSE, 554, "5.7.1 Virus found"); } return filter_api_accept(id); }
void tcp_send_req(int s, short event, void *arg) { struct ctl_tcp_event *cte = arg; int bs; int len; if (event == EV_TIMEOUT) { cte->host->up = HOST_DOWN; close(cte->s); hce_notify_done(cte->host, HCE_TCP_WRITE_TIMEOUT); return; } len = strlen(cte->req); do { bs = write(s, cte->req, len); if (bs == -1) { if (errno == EAGAIN || errno == EINTR) goto retry; log_warnx("%s: cannot send request", __func__); cte->host->up = HOST_DOWN; close(cte->s); hce_notify_done(cte->host, HCE_TCP_WRITE_FAIL); return; } cte->req += bs; len -= bs; } while (len > 0); if ((cte->buf = ibuf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL) fatalx("tcp_send_req: cannot create dynamic buffer"); event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf, &cte->tv_start, &cte->table->conf.timeout, cte); return; retry: event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_send_req, &cte->tv_start, &cte->table->conf.timeout, cte); }
/* Capability state 1. Parse capabilities and set flags. */ int imap_state_capability1(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; char *line, *ptr; if (imap_getln(a, fctx, IMAP_UNTAGGED, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); /* Convert to uppercase. */ for (ptr = line; *ptr != '\0'; ptr++) *ptr = toupper((u_char) *ptr); if (strstr(line, "IMAP4REV1") == NULL) { log_warnx("%s: no IMAP4rev1 capability: %s", a->name, line); return (FETCH_ERROR); } data->capa = 0; if (strstr(line, "AUTH=CRAM-MD5") != NULL) data->capa |= IMAP_CAPA_AUTH_CRAM_MD5; /* Use XYZZY to detect Google brokenness. */ if (strstr(line, "XYZZY") != NULL) data->capa |= IMAP_CAPA_XYZZY; /* GMail IMAP extensions. */ if (strstr(line, "X-GM-EXT-1") != NULL) data->capa |= IMAP_CAPA_GMEXT; if (strstr(line, "STARTTLS") != NULL) data->capa |= IMAP_CAPA_STARTTLS; fctx->state = imap_state_capability2; return (FETCH_AGAIN); }
int up_generate(struct rde_peer *peer, struct rde_aspath *asp, struct bgpd_addr *addr, u_int8_t prefixlen) { struct update_attr *ua = NULL; struct update_prefix *up; if (asp) { ua = calloc(1, sizeof(struct update_attr)); if (ua == NULL) fatal("up_generate"); if (up_generate_attr(peer, ua, asp, addr->aid) == -1) { log_warnx("generation of bgp path attributes failed"); free(ua); return (-1); } /* * use aspath_hash as attr_hash, this may be unoptimal * but currently I don't care. */ ua->attr_hash = hash32_buf(ua->attr, ua->attr_len, HASHINIT); if (ua->mpattr) ua->attr_hash = hash32_buf(ua->mpattr, ua->mpattr_len, ua->attr_hash); } up = calloc(1, sizeof(struct update_prefix)); if (up == NULL) fatal("up_generate"); up->prefix = *addr; up->prefixlen = prefixlen; if (up_add(peer, up, ua) == -1) return (-1); return (0); }
/* ARGSUSED */ static void control_accept(int listenfd, short event, void *arg) { int connfd; socklen_t len; struct sockaddr_un sun; struct ctl_conn *c; if (available_fds(CONTROL_FD_RESERVE)) goto pause; len = sizeof(sun); if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) { if (errno == ENFILE || errno == EMFILE) goto pause; if (errno == EINTR || errno == ECONNABORTED) return; fatal("control_accept: accept"); } session_socket_blockmode(connfd, BM_NONBLOCK); c = xcalloc(1, sizeof(*c), "control_accept"); imsg_init(&c->iev.ibuf, connfd); c->iev.handler = control_dispatch_ext; c->iev.events = EV_READ; event_set(&c->iev.ev, c->iev.ibuf.fd, c->iev.events, c->iev.handler, NULL); event_add(&c->iev.ev, NULL); TAILQ_INSERT_TAIL(&ctl_conns, c, entry); stat_backend->increment("control.session", 1); return; pause: log_warnx("ctl client limit hit, disabling new connections"); event_del(&control_state.ev); }
static char * table_postgres_prepare_stmt(PGconn *_db, const char *query, int nparams, unsigned int nfields) { static unsigned int n = 0; PGresult *res; char *stmt; if (asprintf(&stmt, "stmt%u", n++) == -1) { log_warn("warn: asprintf"); return NULL; } res = PQprepare(_db, stmt, query, nparams, NULL); if (PQresultStatus(res) != PGRES_COMMAND_OK) { log_warnx("warn: PQprepare: %s", PQerrorMessage(_db)); free(stmt); stmt = NULL; } PQclear(res); return stmt; }
int main(int argc, char **argv) { int ch; log_init(1); while ((ch = getopt(argc, argv, "")) != -1) { switch (ch) { default: log_warnx("warn: queue-null: bad option"); return (1); /* NOTREACHED */ } } argc -= optind; argv += optind; queue_null_init(1); queue_api_dispatch(); return (0); }
/* STARTTLS state. */ int imap_state_starttls(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; char *line, *cause; if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); if (!imap_okay(line)) return (imap_bad(a, line)); data->io->ssl = makessl(&data->server, data->io->fd, conf.verify_certs && data->server.verify, conf.timeout, &cause); if (data->io->ssl == NULL) { log_warnx("%s: STARTTLS failed: %s", a->name, cause); xfree(cause); return (FETCH_ERROR); } return (imap_pick_auth(a, fctx)); }
static int process_stdin(void) { char *s = &stdin_cmdline_buf[0]; int size; int status = 0; while(fgets(s, STDIN_CMDLINE_BUF_SIZE, stdin) != NULL) { size = strlen(s); if(s[size - 1] != '\n') { status = 1; log_warnx("%s", "Line too long"); break; } s[size - 1] = '\0'; --size; g.strp = strsplit_recreate(s, g.opt_strsplit_delim, STRSPLIT_FLAG_IGNEMPTY, g.strp); if(g.strp == NULL) { status = -1; log_err(0, "%s", "strsplit_create returned an error."); break; } status = process_stdin_entry(); if(status != 0) break; } if(g.strp != NULL) { strsplit_delete(g.strp); g.strp = NULL; } return(status != 0 ? 1 : 0); }
void filter_api_loop(void) { if (register_done) { log_warnx("warn: filter-api:%s filter_api_loop() already called", filter_name); fatalx("filter-api: exiting"); } filter_api_init(); register_done = 1; mproc_enable(&fi.p); if (fi.rootpath) { if (chroot(fi.rootpath) == -1) { log_warn("warn: filter-api:%s chroot", filter_name); fatalx("filter-api: exiting"); } if (chdir("/") == -1) { log_warn("warn: filter-api:%s chdir", filter_name); fatalx("filter-api: exiting"); } } if (setgroups(1, &fi.gid) || setresgid(fi.gid, fi.gid, fi.gid) || setresuid(fi.uid, fi.uid, fi.uid)) { log_warn("warn: filter-api:%s cannot drop privileges", filter_name); fatalx("filter-api: exiting"); } if (event_dispatch() < 0) { log_warn("warn: filter-api:%s event_dispatch", filter_name); fatalx("filter-api: exiting"); } }