1 /* $NetBSD: pipequeries.c,v 1.8 2024/02/21 22:51:33 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #include <inttypes.h> 17 #include <stdbool.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 22 #include <isc/app.h> 23 #include <isc/base64.h> 24 #include <isc/commandline.h> 25 #include <isc/hash.h> 26 #include <isc/log.h> 27 #include <isc/managers.h> 28 #include <isc/mem.h> 29 #include <isc/net.h> 30 #include <isc/netmgr.h> 31 #include <isc/parseint.h> 32 #include <isc/print.h> 33 #include <isc/result.h> 34 #include <isc/sockaddr.h> 35 #include <isc/task.h> 36 #include <isc/util.h> 37 38 #include <dns/dispatch.h> 39 #include <dns/events.h> 40 #include <dns/fixedname.h> 41 #include <dns/message.h> 42 #include <dns/name.h> 43 #include <dns/rdataset.h> 44 #include <dns/request.h> 45 #include <dns/resolver.h> 46 #include <dns/result.h> 47 #include <dns/types.h> 48 #include <dns/view.h> 49 50 #define CHECK(str, x) \ 51 { \ 52 if ((x) != ISC_R_SUCCESS) { \ 53 fprintf(stderr, "I:%s: %s\n", (str), \ 54 isc_result_totext(x)); \ 55 exit(-1); \ 56 } \ 57 } 58 59 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) 60 61 #define PORT 5300 62 #define TIMEOUT 30 63 64 static isc_mem_t *mctx = NULL; 65 static dns_requestmgr_t *requestmgr = NULL; 66 static bool have_src = false; 67 static isc_sockaddr_t srcaddr; 68 static isc_sockaddr_t dstaddr; 69 static int onfly; 70 71 static void 72 recvresponse(isc_task_t *task, isc_event_t *event) { 73 dns_requestevent_t *reqev = (dns_requestevent_t *)event; 74 isc_result_t result; 75 dns_message_t *query = NULL; 76 dns_message_t *response = NULL; 77 isc_buffer_t outbuf; 78 char output[1024]; 79 80 UNUSED(task); 81 82 REQUIRE(reqev != NULL); 83 84 if (reqev->result != ISC_R_SUCCESS) { 85 fprintf(stderr, "I:request event result: %s\n", 86 isc_result_totext(reqev->result)); 87 exit(-1); 88 } 89 90 query = reqev->ev_arg; 91 92 dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); 93 94 result = dns_request_getresponse(reqev->request, response, 95 DNS_MESSAGEPARSE_PRESERVEORDER); 96 CHECK("dns_request_getresponse", result); 97 98 if (response->rcode != dns_rcode_noerror) { 99 result = dns_result_fromrcode(response->rcode); 100 fprintf(stderr, "I:response rcode: %s\n", 101 isc_result_totext(result)); 102 exit(-1); 103 } 104 if (response->counts[DNS_SECTION_ANSWER] != 1U) { 105 fprintf(stderr, "I:response answer count (%u!=1)\n", 106 response->counts[DNS_SECTION_ANSWER]); 107 } 108 109 isc_buffer_init(&outbuf, output, sizeof(output)); 110 result = dns_message_sectiontotext( 111 response, DNS_SECTION_ANSWER, &dns_master_style_simple, 112 DNS_MESSAGETEXTFLAG_NOCOMMENTS, &outbuf); 113 CHECK("dns_message_sectiontotext", result); 114 printf("%.*s", (int)isc_buffer_usedlength(&outbuf), 115 (char *)isc_buffer_base(&outbuf)); 116 fflush(stdout); 117 118 dns_message_detach(&query); 119 dns_message_detach(&response); 120 dns_request_destroy(&reqev->request); 121 isc_event_free(&event); 122 123 if (--onfly == 0) { 124 isc_app_shutdown(); 125 } 126 return; 127 } 128 129 static isc_result_t 130 sendquery(isc_task_t *task) { 131 dns_request_t *request = NULL; 132 dns_message_t *message = NULL; 133 dns_name_t *qname = NULL; 134 dns_rdataset_t *qrdataset = NULL; 135 isc_result_t result; 136 dns_fixedname_t queryname; 137 isc_buffer_t buf; 138 static char host[256]; 139 int c; 140 141 c = scanf("%255s", host); 142 if (c == EOF) { 143 return (ISC_R_NOMORE); 144 } 145 146 onfly++; 147 148 dns_fixedname_init(&queryname); 149 isc_buffer_init(&buf, host, strlen(host)); 150 isc_buffer_add(&buf, strlen(host)); 151 result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf, 152 dns_rootname, 0, NULL); 153 CHECK("dns_name_fromtext", result); 154 155 dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message); 156 157 message->opcode = dns_opcode_query; 158 message->flags |= DNS_MESSAGEFLAG_RD; 159 message->rdclass = dns_rdataclass_in; 160 message->id = (unsigned short)(random() & 0xFFFF); 161 162 result = dns_message_gettempname(message, &qname); 163 CHECK("dns_message_gettempname", result); 164 165 result = dns_message_gettemprdataset(message, &qrdataset); 166 CHECK("dns_message_gettemprdataset", result); 167 168 dns_name_clone(dns_fixedname_name(&queryname), qname); 169 dns_rdataset_makequestion(qrdataset, dns_rdataclass_in, 170 dns_rdatatype_a); 171 ISC_LIST_APPEND(qname->list, qrdataset, link); 172 dns_message_addname(message, qname, DNS_SECTION_QUESTION); 173 174 result = dns_request_create(requestmgr, message, 175 have_src ? &srcaddr : NULL, &dstaddr, 176 DNS_REQUESTOPT_TCP, NULL, TIMEOUT, 0, 0, 177 task, recvresponse, message, &request); 178 CHECK("dns_request_create", result); 179 180 return (ISC_R_SUCCESS); 181 } 182 183 static void 184 sendqueries(isc_task_t *task, isc_event_t *event) { 185 isc_result_t result; 186 187 isc_event_free(&event); 188 189 do { 190 result = sendquery(task); 191 } while (result == ISC_R_SUCCESS); 192 193 if (onfly == 0) { 194 isc_app_shutdown(); 195 } 196 return; 197 } 198 199 int 200 main(int argc, char *argv[]) { 201 isc_sockaddr_t bind_any; 202 struct in_addr inaddr; 203 isc_result_t result; 204 isc_log_t *lctx = NULL; 205 isc_logconfig_t *lcfg = NULL; 206 isc_nm_t *netmgr = NULL; 207 isc_taskmgr_t *taskmgr = NULL; 208 isc_task_t *task = NULL; 209 dns_dispatchmgr_t *dispatchmgr = NULL; 210 dns_dispatch_t *dispatchv4 = NULL; 211 dns_view_t *view = NULL; 212 uint16_t port = PORT; 213 int c; 214 215 RUNCHECK(isc_app_start()); 216 217 isc_commandline_errprint = false; 218 while ((c = isc_commandline_parse(argc, argv, "p:r:")) != -1) { 219 switch (c) { 220 case 'p': 221 result = isc_parse_uint16(&port, 222 isc_commandline_argument, 10); 223 if (result != ISC_R_SUCCESS) { 224 fprintf(stderr, "bad port '%s'\n", 225 isc_commandline_argument); 226 exit(1); 227 } 228 break; 229 case 'r': 230 fprintf(stderr, "The -r option has been deprecated.\n"); 231 break; 232 case '?': 233 fprintf(stderr, "%s: invalid argument '%c'", argv[0], 234 c); 235 break; 236 default: 237 break; 238 } 239 } 240 241 argc -= isc_commandline_index; 242 argv += isc_commandline_index; 243 POST(argv); 244 245 if (argc > 0) { 246 have_src = true; 247 } 248 249 isc_sockaddr_any(&bind_any); 250 251 result = ISC_R_FAILURE; 252 if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1) { 253 CHECK("inet_pton", result); 254 } 255 isc_sockaddr_fromin(&srcaddr, &inaddr, 0); 256 257 result = ISC_R_FAILURE; 258 if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1) { 259 CHECK("inet_pton", result); 260 } 261 isc_sockaddr_fromin(&dstaddr, &inaddr, port); 262 263 isc_mem_create(&mctx); 264 265 isc_log_create(mctx, &lctx, &lcfg); 266 267 RUNCHECK(dst_lib_init(mctx, NULL)); 268 269 isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr, NULL); 270 RUNCHECK(isc_task_create(taskmgr, 0, &task)); 271 RUNCHECK(dns_dispatchmgr_create(mctx, netmgr, &dispatchmgr)); 272 273 RUNCHECK(dns_dispatch_createudp( 274 dispatchmgr, have_src ? &srcaddr : &bind_any, &dispatchv4)); 275 RUNCHECK(dns_requestmgr_create(mctx, taskmgr, dispatchmgr, dispatchv4, 276 NULL, &requestmgr)); 277 278 RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); 279 RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL)); 280 281 (void)isc_app_run(); 282 283 dns_view_detach(&view); 284 285 dns_requestmgr_shutdown(requestmgr); 286 dns_requestmgr_detach(&requestmgr); 287 288 dns_dispatch_detach(&dispatchv4); 289 dns_dispatchmgr_detach(&dispatchmgr); 290 291 isc_task_shutdown(task); 292 isc_task_detach(&task); 293 294 isc_managers_destroy(&netmgr, &taskmgr, NULL); 295 296 dst_lib_destroy(); 297 298 isc_log_destroy(&lctx); 299 300 isc_mem_destroy(&mctx); 301 302 isc_app_finish(); 303 304 return (0); 305 } 306