static void test_connected(struct knot_requestor *requestor, conf_remote_t *remote) { /* Enqueue packet. */ int ret = knot_requestor_enqueue(requestor, make_query(requestor, remote)); is_int(KNOT_EOK, ret, "requestor: connected/enqueue"); /* Wait for completion. */ struct timeval tv = { 5, 0 }; ret = knot_requestor_exec(requestor, &tv); is_int(KNOT_EOK, ret, "requestor: connected/wait"); /* Enqueue multiple queries. */ ret = KNOT_EOK; for (unsigned i = 0; i < 10; ++i) { ret |= knot_requestor_enqueue(requestor, make_query(requestor, remote)); } is_int(KNOT_EOK, ret, "requestor: multiple enqueue"); /* Wait for multiple queries. */ ret = KNOT_EOK; for (unsigned i = 0; i < 10; ++i) { struct timeval tv = { 5, 0 }; ret |= knot_requestor_exec(requestor, &tv); } is_int(KNOT_EOK, ret, "requestor: multiple wait"); }
static void test_disconnected(struct knot_requestor *requestor, conf_remote_t *remote) { /* Enqueue packet. */ int ret = knot_requestor_enqueue(requestor, make_query(requestor, remote)); is_int(KNOT_EOK, ret, "requestor: disconnected/enqueue"); /* Wait for completion. */ struct timeval tv = { 5, 0 }; ret = knot_requestor_exec(requestor, &tv); is_int(KNOT_ECONN, ret, "requestor: disconnected/wait"); }
static int dnsproxy_fwd(int state, knot_pkt_t *pkt, struct query_data *qdata, void *ctx) { if (pkt == NULL || qdata == NULL || ctx == NULL) { return KNOT_STATE_FAIL; } /* If not already satisfied. */ if (state == KNOT_STATE_DONE) { return state; } struct dnsproxy *proxy = ctx; /* Create a forwarding request. */ struct knot_requestor re; knot_requestor_init(&re, qdata->mm); struct capture_param param; param.sink = pkt; int ret = knot_requestor_overlay(&re, LAYER_CAPTURE, ¶m); if (ret != KNOT_EOK) { return KNOT_STATE_FAIL; } bool is_tcp = net_is_connected(qdata->param->socket); struct knot_request *req; req = knot_request_make(re.mm, (const struct sockaddr *)&proxy->remote, NULL, qdata->query, is_tcp ? 0 : KNOT_RQ_UDP); if (req == NULL) { return state; /* Ignore, not enough memory. */ } /* Forward request. */ ret = knot_requestor_enqueue(&re, req); if (ret == KNOT_EOK) { conf_val_t val = conf_get(conf(), C_SRV, C_TCP_HSHAKE_TIMEOUT); struct timeval tv = { conf_int(&val), 0 }; ret = knot_requestor_exec(&re, &tv); } else { knot_request_free(re.mm, req); } knot_requestor_clear(&re); /* Check result. */ if (ret != KNOT_EOK) { qdata->rcode = KNOT_RCODE_SERVFAIL; return KNOT_STATE_FAIL; /* Forwarding failed, SERVFAIL. */ } return KNOT_STATE_DONE; }
/*! \brief Process query using requestor. */ static int zone_query_request(knot_pkt_t *query, const conf_remote_t *remote, struct process_answer_param *param, knot_mm_t *mm) { /* Create requestor instance. */ struct knot_requestor re; int ret = knot_requestor_init(&re, mm); if (ret != KNOT_EOK) { return ret; } ret = knot_requestor_overlay(&re, KNOT_STATE_ANSWER, param); if (ret != KNOT_EOK) { knot_requestor_clear(&re); return ret; } /* Create a request. */ const struct sockaddr *dst = (const struct sockaddr *)&remote->addr; const struct sockaddr *src = (const struct sockaddr *)&remote->via; struct knot_request *req = knot_request_make(re.mm, dst, src, query, 0); if (req == NULL) { knot_requestor_clear(&re); return KNOT_ENOMEM; } /* Send the queries and process responses. */ ret = knot_requestor_enqueue(&re, req); if (ret == KNOT_EOK) { conf_val_t *val = ¶m->conf->cache.srv_tcp_reply_timeout; int timeout = conf_int(val) * 1000; ret = knot_requestor_exec(&re, timeout); } else { knot_request_free(req, re.mm); } /* Cleanup. */ knot_requestor_clear(&re); return ret; }