]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
add bindings for the checkout layer
authorMarek Vavruša <mvavrusa@cloudflare.com>
Fri, 6 Apr 2018 05:48:51 +0000 (22:48 -0700)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 23 Apr 2018 15:49:33 +0000 (17:49 +0200)
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.

daemon/ffimodule.c
lib/layer.h
lib/module.h
lib/resolve.c

index 3fb37bee98e5417e568b19f367608398dccce156..496867d70efec48ea409a39c844e32f1b677c051 100644 (file)
@@ -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;
index 2d2e86cda7d7c6fc8f9bc25c809ff8e0f76b0f0d..227ff99aabd7a56feeff34448fbf1d6c25278260 100644 (file)
@@ -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;
 };
index 945283ccc0631476f643a473da06b595c4a00d01..74acf60158f28d013136ee1de1ced86638f5649c 100644 (file)
@@ -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);
 
index f7b313869449010c1d7cfe4e35882b88ddd6113e..eed3fd90247dd090c351426cdfafddb7f2d60428 100644 (file)
@@ -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? */