conf_remote_t conf_remote_txn( conf_t *conf, knot_db_txn_t *txn, conf_val_t *id, size_t index) { assert(id != NULL && id->item != NULL); assert(id->item->type == YP_TSTR || (id->item->type == YP_TREF && id->item->var.r.ref->var.g.id->type == YP_TSTR)); conf_remote_t out = { { AF_UNSPEC } }; conf_val_t rundir_val = conf_get_txn(conf, txn, C_SRV, C_RUNDIR); char *rundir = conf_abs_path(&rundir_val, NULL); // Get indexed remote address. conf_val_t val = conf_id_get_txn(conf, txn, C_RMT, C_ADDR, id); for (size_t i = 0; val.code == KNOT_EOK && i < index; i++) { if (i == 0) { conf_val(&val); } conf_val_next(&val); } // Index overflow causes empty socket. out.addr = conf_addr(&val, rundir); // Get outgoing address if family matches (optional). val = conf_id_get_txn(conf, txn, C_RMT, C_VIA, id); while (val.code == KNOT_EOK) { struct sockaddr_storage via = conf_addr(&val, rundir); if (via.ss_family == out.addr.ss_family) { out.via = conf_addr(&val, rundir); break; } conf_val_next(&val); } // Get TSIG key (optional). conf_val_t key_id = conf_id_get_txn(conf, txn, C_RMT, C_KEY, id); if (key_id.code == KNOT_EOK) { out.key.name = (knot_dname_t *)conf_dname(&key_id); val = conf_id_get_txn(conf, txn, C_KEY, C_ALG, &key_id); out.key.algorithm = conf_opt(&val); val = conf_id_get_txn(conf, txn, C_KEY, C_SECRET, &key_id); out.key.secret.data = (uint8_t *)conf_bin(&val, &out.key.secret.size); } free(rundir); return out; }
int dnsproxy_load(struct query_plan *plan, struct query_module *self) { if (plan == NULL || self == NULL) { return KNOT_EINVAL; } struct dnsproxy *proxy = mm_alloc(self->mm, sizeof(struct dnsproxy)); if (proxy == NULL) { MODULE_ERR("not enough memory"); return KNOT_ENOMEM; } memset(proxy, 0, sizeof(struct dnsproxy)); conf_val_t val = conf_mod_get(self->config, MOD_REMOTE, self->id); if (val.code != KNOT_EOK) { if (val.code == KNOT_EINVAL) { MODULE_ERR("no remote proxy address for '%s'", self->id->data); } mm_free(self->mm, proxy); return val.code; } proxy->remote = conf_addr(&val, NULL); self->ctx = proxy; return query_plan_step(plan, QPLAN_BEGIN, dnsproxy_fwd, self->ctx); }
/*! \brief Event loop listening for signals and remote commands. */ static void event_loop(server_t *server) { uint8_t buf[KNOT_WIRE_MAX_PKTSIZE]; size_t buflen = sizeof(buf); /* Read control socket configuration. */ conf_val_t listen_val = conf_get(conf(), C_CTL, C_LISTEN); conf_val_t rundir_val = conf_get(conf(), C_SRV, C_RUNDIR); char *rundir = conf_abs_path(&rundir_val, NULL); struct sockaddr_storage addr = conf_addr(&listen_val, rundir); free(rundir); /* Bind to control interface (error logging is inside the function. */ int remote = remote_bind(&addr); sigset_t empty; (void)sigemptyset(&empty); /* Run event loop. */ for (;;) { int ret = remote_poll(remote, &empty); /* Events. */ if (ret > 0) { ret = remote_process(server, &addr, remote, buf, buflen); if (ret == KNOT_CTL_STOP) { break; } } /* Interrupts. */ if (sig_req_stop) { break; } if (sig_req_reload) { sig_req_reload = false; server_reload(server, conf()->filename); } } server_stop(server); /* Close remote control interface. */ remote_unbind(&addr, remote); /* Wait for server to finish. */ server_wait(server); }