req, struct dns_cli_request_state);
DATA_BLOB reply;
enum ndr_err_code ndr_err;
+ uint16_t reply_id, operation;
int ret;
ret = dns_udp_request_recv(subreq, state, &reply.data, &reply.length);
return;
}
- state->reply = talloc(state, struct dns_name_packet);
- if (tevent_req_nomem(state->reply, req)) {
- return;
- }
-
- ndr_err = ndr_pull_struct_blob(
- &reply, state->reply, state->reply,
- (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- tevent_req_error(req, ndr_map_error2errno(ndr_err));
+ if (reply.length < 4) {
+ DBG_DEBUG("Short DNS packet: length=%zu\n", reply.length);
+ tevent_req_error(req, EINVAL);
return;
}
- TALLOC_FREE(reply.data);
- if (state->reply->id != state->req_id) {
+ reply_id = PULL_BE_U16(reply.data, 0);
+ if (reply_id != state->req_id) {
DBG_DEBUG("Got id %"PRIu16", expected %"PRIu16"\n",
state->reply->id, state->req_id);
tevent_req_error(req, ENOMSG);
return;
}
- if ((state->reply->operation & DNS_FLAG_TRUNCATION) == 0) {
- DBG_DEBUG("Got op=%x %"PRIu16"/%"PRIu16"/%"PRIu16"/%"PRIu16
- " recs\n", (int)state->reply->operation,
- state->reply->qdcount, state->reply->ancount,
- state->reply->nscount, state->reply->nscount);
- tevent_req_done(req);
+ operation = PULL_BE_U16(reply.data, 2);
+ if ((operation & DNS_FLAG_TRUNCATION) != 0) {
+ DBG_DEBUG("Reply was truncated, retrying TCP\n");
+ subreq = dns_tcp_request_send(
+ state,
+ state->ev,
+ state->nameserver,
+ state->query.data,
+ state->query.length);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, dns_cli_request_tcp_done, req);
return;
}
- DBG_DEBUG("Reply was truncated, retrying TCP\n");
-
- TALLOC_FREE(state->reply);
+ state->reply = talloc(state, struct dns_name_packet);
+ if (tevent_req_nomem(state->reply, req)) {
+ return;
+ }
- subreq = dns_tcp_request_send(state, state->ev, state->nameserver,
- state->query.data, state->query.length);
- if (tevent_req_nomem(subreq, req)) {
+ ndr_err = ndr_pull_struct_blob(
+ &reply, state->reply, state->reply,
+ (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ tevent_req_error(req, ndr_map_error2errno(ndr_err));
return;
}
- tevent_req_set_callback(subreq, dns_cli_request_tcp_done, req);
+ TALLOC_FREE(reply.data);
+
+ tevent_req_done(req);
}
static void dns_cli_request_tcp_done(struct tevent_req *subreq)