From: Marek VavruĊĦa Date: Fri, 6 Apr 2018 05:48:51 +0000 (-0700) Subject: add bindings for the checkout layer X-Git-Tag: v2.4.0~53^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=98c8d35364b90a8bf2f3705526c68931917152b6;p=thirdparty%2Fknot-resolver.git add bindings for the checkout layer This one was missing from the current bindings. The checkout layer runs when the worker attempts to send a DNS query to given upstream when the address is already determined. The layer can add EDNS options or update outbound query, or block particular addresses / protocol. --- diff --git a/daemon/ffimodule.c b/daemon/ffimodule.c index 3fb37bee9..496867d70 100644 --- a/daemon/ffimodule.c +++ b/daemon/ffimodule.c @@ -36,6 +36,7 @@ enum { SLOT_finish, SLOT_consume, SLOT_produce, + SLOT_checkout, SLOT_count }; #define SLOT_size sizeof(int) @@ -127,6 +128,7 @@ static int l_ffi_deinit(struct kr_module *module) LAYER_UNREGISTER(L, api, finish); LAYER_UNREGISTER(L, api, consume); LAYER_UNREGISTER(L, api, produce); + LAYER_UNREGISTER(L, api, checkout); LAYER_UNREGISTER(L, api, reset); free(api); } @@ -190,6 +192,19 @@ static int l_ffi_layer_produce(kr_layer_t *ctx, knot_pkt_t *pkt) lua_pushlightuserdata(L, pkt); return l_ffi_call(L, 3); } + +static int l_ffi_layer_checkout(kr_layer_t *ctx, knot_pkt_t *pkt, struct sockaddr *dst, int type) +{ + if (ctx->state & (KR_STATE_FAIL)) { + return ctx->state; /* Already failed or done, skip */ + } + LAYER_FFI_CALL(ctx, checkout); + lua_pushlightuserdata(L, ctx->req); + lua_pushlightuserdata(L, pkt); + lua_pushlightuserdata(L, dst); + lua_pushboolean(L, type == SOCK_STREAM); + return l_ffi_call(L, 5); +} #undef LAYER_FFI_CALL /** @internal Conditionally register layer trampoline @@ -218,6 +233,7 @@ static kr_layer_api_t *l_ffi_layer_create(lua_State *L, struct kr_module *module LAYER_REGISTER(L, api, finish); LAYER_REGISTER(L, api, consume); LAYER_REGISTER(L, api, produce); + LAYER_REGISTER(L, api, checkout); LAYER_REGISTER(L, api, reset); /* Begin is always set, as it initializes layer baton. */ api->begin = l_ffi_layer_begin; diff --git a/lib/layer.h b/lib/layer.h index 2d2e86cda..227ff99aa 100644 --- a/lib/layer.h +++ b/lib/layer.h @@ -78,6 +78,11 @@ struct kr_layer_api { /** Produce either an answer to the request or a query for upstream (or fail). */ int (*produce)(kr_layer_t *ctx, knot_pkt_t *pkt); + /** Finalises the outbound query packet with the knowledge of the IP addresses. + * The checkout layer doesn't persist the state, so canceled subrequests + * don't affect the resolution or rest of the processing. */ + int (*checkout)(kr_layer_t *ctx, knot_pkt_t *packet, struct sockaddr *dst, int type); + /** The module can store anything in here. */ void *data; }; diff --git a/lib/module.h b/lib/module.h index 945283ccc..74acf6015 100644 --- a/lib/module.h +++ b/lib/module.h @@ -35,7 +35,7 @@ struct kr_prop; */ #define KR_MODULE_EXPORT(module) \ KR_EXPORT uint32_t module ## _api() { return KR_MODULE_API; } -#define KR_MODULE_API ((uint32_t) 0x20161108) +#define KR_MODULE_API ((uint32_t) 0x20180401) typedef uint32_t (module_api_cb)(void); diff --git a/lib/resolve.c b/lib/resolve.c index f7b313869..eed3fd902 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -94,6 +94,7 @@ static int begin_yield(kr_layer_t *ctx) { return kr_ok(); } static int reset_yield(kr_layer_t *ctx) { return kr_ok(); } static int finish_yield(kr_layer_t *ctx) { return kr_ok(); } static int produce_yield(kr_layer_t *ctx, knot_pkt_t *pkt) { return kr_ok(); } +static int checkout_yield(kr_layer_t *ctx, knot_pkt_t *packet, struct sockaddr *dst, int type) { return kr_ok(); } /** @internal Macro for iterating module layers. */ #define RESUME_LAYERS(from, r, qry, func, ...) \ @@ -1532,6 +1533,14 @@ int kr_resolve_checkout(struct kr_request *request, struct sockaddr *src, } struct kr_query *qry = array_tail(rplan->pending); + /* Run the checkout layers and cancel on failure. */ + int state = request->state; + ITERATE_LAYERS(request, qry, checkout, packet, dst, type); + if (request->state == KR_STATE_FAIL) { + request->state = state; /* Restore */ + return kr_error(ECANCELED); + } + #if defined(ENABLE_COOKIES) /* Update DNS cookies in request. */ if (type == SOCK_DGRAM) { /* @todo: Add cookies also over TCP? */