int main(int argc, char *argv[]) { plan(TESTS_COUNT + 1); mm_ctx_t mm; mm_ctx_mempool(&mm, MM_DEFAULT_BLKSIZE); conf_remote_t remote; memset(&remote, 0, sizeof(conf_remote_t)); sockaddr_set(&remote.addr, AF_INET, "127.0.0.1", 0); sockaddr_set(&remote.via, AF_INET, "127.0.0.1", 0); /* Create fake server environment. */ server_t server; int ret = create_fake_server(&server, &mm); ok(ret == KNOT_EOK, "requestor: initialize fake server"); /* Initialize requestor. */ struct knot_requestor requestor; knot_requestor_init(&requestor, &mm); knot_requestor_overlay(&requestor, &dummy_module, NULL); /* Test requestor in disconnected environment. */ test_disconnected(&requestor, &remote); /* Bind to random port. */ int origin_fd = net_bound_socket(SOCK_STREAM, &remote.addr, 0); assert(origin_fd > 0); socklen_t addr_len = sockaddr_len((struct sockaddr *)&remote.addr); getsockname(origin_fd, (struct sockaddr *)&remote.addr, &addr_len); ret = listen(origin_fd, 10); assert(ret == 0); /* Responder thread. */ pthread_t thread; pthread_create(&thread, 0, responder_thread, &origin_fd); /* Test requestor in connected environment. */ test_connected(&requestor, &remote); /*! \todo #243 TSIG secured requests test should be implemented. */ /* Terminate responder. */ int responder = net_connected_socket(SOCK_STREAM, &remote.addr, NULL, 0); assert(responder > 0); tcp_send_msg(responder, (const uint8_t *)"", 1, NULL); (void) pthread_join(thread, 0); close(responder); /* Close requestor. */ knot_requestor_clear(&requestor); close(origin_fd); /* Cleanup. */ mp_delete((struct mempool *)mm.ctx); server_deinit(&server); conf_free(conf(), false); return 0; }
/*! \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; }
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; }