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