return 1;
}
+/** Select HTTP headers to subscribe to for incoming DoH requests. */
+static int net_doh_headers_in(lua_State *L)
+{
+ doh_headerlist_t *headers = &the_worker->doh_headers_in;
+ int i;
+ const char *name;
+
+ /* Only return current configuration. */
+ if (lua_gettop(L) == 0) {
+ lua_newtable(L);
+ for (i = 0; i < headers->len; i++) {
+ lua_pushinteger(L, i + 1);
+ name = headers->at[i];
+ lua_pushlstring(L, name, strlen(name));
+ lua_settable(L, -3);
+ }
+ return 1;
+ }
+
+ if (lua_gettop(L) != 1)
+ lua_error_p(L, "net.doh_headers_in() takes one parameter (string or table)");
+
+ if (!lua_istable(L, 1) && !lua_isstring(L, 1))
+ lua_error_p(L, "net.doh_headers_in() argument must be string or table");
+
+ /* Clear existing headers. */
+ for (i = 0; i < headers->len; i++)
+ free(headers->at[i]);
+ array_clear(*headers);
+
+ if (lua_istable(L, 1)) {
+ for (i = 1; !lua_isnil(L, -1); i++) {
+ lua_pushinteger(L, i);
+ lua_gettable(L, 1);
+ if (lua_isnil(L, -1)) /* missing value - end iteration */
+ break;
+ if (!lua_isstring(L, -1))
+ lua_error_p(L, "net.doh_headers_in() argument table can only contain strings");
+ name = lua_tostring(L, -1);
+ array_push(*headers, strdup(name));
+ }
+ } else if (lua_isstring(L, 1)) {
+ name = lua_tostring(L, 1);
+ array_push(*headers, strdup(name));
+ }
+
+ return 0;
+}
+
/** Return a lua table with TLS authentication parameters.
* The format is the same as passed to policy.TLS_FORWARD();
* more precisely, it's in a compatible canonical form. */
{ "bpf_set", net_bpf_set },
{ "bpf_clear", net_bpf_clear },
{ "register_endpoint_kind", net_register_endpoint_kind },
+ { "doh_headers_in", net_doh_headers_in },
{ NULL, NULL }
};
luaL_register(L, "net", lib);
trie_free(worker->subreq_out);
worker->subreq_out = NULL;
+ for (int i = 0; i < worker->doh_headers_in.len; i++)
+ free(worker->doh_headers_in.at[i]);
+ array_clear(worker->doh_headers_in);
+
reclaim_mp_freelist(&worker->pool_mp);
mp_delete(worker->pkt_pool.ctx);
worker->pkt_pool.ctx = NULL;
worker->out_addr4.sin_family = AF_UNSPEC;
worker->out_addr6.sin6_family = AF_UNSPEC;
+ array_init(worker->doh_headers_in);
+
int ret = worker_reserve(worker, MP_FREELIST_SIZE);
if (ret) return ret;
worker->next_request_uid = UINT16_MAX + 1;
/** List of query resolution tasks. */
typedef array_t(struct qr_task *) qr_tasklist_t;
+/** List of HTTP header names. */
+typedef array_t(const char *) doh_headerlist_t;
+
/** \details Worker state is meant to persist during the whole life of daemon. */
struct worker_ctx {
struct engine *engine;
mp_freelist_t pool_mp;
knot_mm_t pkt_pool;
unsigned int next_request_uid;
+
+ /* HTTP Headers for DoH. */
+ doh_headerlist_t doh_headers_in;
};
/** @endcond */