1 /* $NetBSD: pipequeries.c,v 1.3 2019/01/09 16:55:03 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 <config.h> 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/mem.h> 28 #include <isc/net.h> 29 #include <isc/parseint.h> 30 #include <isc/platform.h> 31 #include <isc/print.h> 32 #include <isc/sockaddr.h> 33 #include <isc/socket.h> 34 #include <isc/task.h> 35 #include <isc/timer.h> 36 #include <isc/util.h> 37 38 #include <dns/dispatch.h> 39 #include <dns/fixedname.h> 40 #include <dns/message.h> 41 #include <dns/name.h> 42 #include <dns/request.h> 43 #include <dns/result.h> 44 #include <dns/view.h> 45 46 #include <dns/events.h> 47 #include <dns/rdataset.h> 48 #include <dns/resolver.h> 49 #include <dns/types.h> 50 51 #include <dst/result.h> 52 53 #define CHECK(str, x) { \ 54 if ((x) != ISC_R_SUCCESS) { \ 55 fprintf(stderr, "I:%s: %s\n", (str), isc_result_totext(x)); \ 56 exit(-1); \ 57 } \ 58 } 59 60 #define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS) 61 62 #define PORT 5300 63 #define TIMEOUT 30 64 65 static isc_mem_t *mctx; 66 static dns_requestmgr_t *requestmgr; 67 static bool have_src = false; 68 static isc_sockaddr_t srcaddr; 69 static isc_sockaddr_t dstaddr; 70 static int onfly; 71 72 static void 73 recvresponse(isc_task_t *task, isc_event_t *event) { 74 dns_requestevent_t *reqev = (dns_requestevent_t *)event; 75 isc_result_t result; 76 dns_message_t *query, *response; 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 response = NULL; 93 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); 94 CHECK("dns_message_create", result); 95 96 result = dns_request_getresponse(reqev->request, response, 97 DNS_MESSAGEPARSE_PRESERVEORDER); 98 CHECK("dns_request_getresponse", result); 99 100 if (response->rcode != dns_rcode_noerror) { 101 result = ISC_RESULTCLASS_DNSRCODE + response->rcode; 102 fprintf(stderr, "I:response rcode: %s\n", 103 isc_result_totext(result)); 104 exit(-1); 105 } 106 if (response->counts[DNS_SECTION_ANSWER] != 1U) { 107 fprintf(stderr, "I:response answer count (%u!=1)\n", 108 response->counts[DNS_SECTION_ANSWER]); 109 } 110 111 isc_buffer_init(&outbuf, output, sizeof(output)); 112 result = dns_message_sectiontotext(response, DNS_SECTION_ANSWER, 113 &dns_master_style_simple, 114 DNS_MESSAGETEXTFLAG_NOCOMMENTS, 115 &outbuf); 116 CHECK("dns_message_sectiontotext", result); 117 printf("%.*s", (int)isc_buffer_usedlength(&outbuf), 118 (char *)isc_buffer_base(&outbuf)); 119 fflush(stdout); 120 121 dns_message_destroy(&query); 122 dns_message_destroy(&response); 123 dns_request_destroy(&reqev->request); 124 isc_event_free(&event); 125 126 if (--onfly == 0) 127 isc_app_shutdown(); 128 return; 129 } 130 131 static isc_result_t 132 sendquery(isc_task_t *task) { 133 dns_request_t *request; 134 dns_message_t *message; 135 dns_name_t *qname; 136 dns_rdataset_t *qrdataset; 137 isc_result_t result; 138 dns_fixedname_t queryname; 139 isc_buffer_t buf; 140 static char host[256]; 141 int c; 142 143 c = scanf("%255s", host); 144 if (c == EOF) 145 return ISC_R_NOMORE; 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(requestmgr, message, 182 have_src ? &srcaddr : NULL, &dstaddr, 183 -1, 184 DNS_REQUESTOPT_TCP | 185 DNS_REQUESTOPT_SHARE, 186 NULL, TIMEOUT, 0, 0, task, recvresponse, 187 message, &request); 188 CHECK("dns_request_create", result); 189 190 return ISC_R_SUCCESS; 191 } 192 193 static void 194 sendqueries(isc_task_t *task, isc_event_t *event) { 195 isc_result_t result; 196 197 isc_event_free(&event); 198 199 do { 200 result = sendquery(task); 201 } while (result == ISC_R_SUCCESS); 202 203 if (onfly == 0) 204 isc_app_shutdown(); 205 return; 206 } 207 208 int 209 main(int argc, char *argv[]) { 210 isc_sockaddr_t bind_any; 211 struct in_addr inaddr; 212 isc_result_t result; 213 isc_log_t *lctx; 214 isc_logconfig_t *lcfg; 215 isc_taskmgr_t *taskmgr; 216 isc_task_t *task; 217 isc_timermgr_t *timermgr; 218 isc_socketmgr_t *socketmgr; 219 dns_dispatchmgr_t *dispatchmgr; 220 unsigned int attrs, attrmask; 221 dns_dispatch_t *dispatchv4; 222 dns_view_t *view; 223 uint16_t port = PORT; 224 int c; 225 226 RUNCHECK(isc_app_start()); 227 228 isc_commandline_errprint = false; 229 while ((c = isc_commandline_parse(argc, argv, "p:r:")) != -1) { 230 switch (c) { 231 case 'p': 232 result = isc_parse_uint16(&port, 233 isc_commandline_argument, 10); 234 if (result != ISC_R_SUCCESS) { 235 fprintf(stderr, "bad port '%s'\n", 236 isc_commandline_argument); 237 exit(1); 238 } 239 break; 240 case 'r': 241 fprintf(stderr, "The -r option has been deprecated.\n"); 242 break; 243 case '?': 244 fprintf(stderr, "%s: invalid argument '%c'", 245 argv[0], c); 246 break; 247 default: 248 break; 249 } 250 } 251 252 argc -= isc_commandline_index; 253 argv += isc_commandline_index; 254 POST(argv); 255 256 if (argc > 0) { 257 have_src = true; 258 } 259 260 dns_result_register(); 261 262 isc_sockaddr_any(&bind_any); 263 264 result = ISC_R_FAILURE; 265 if (inet_pton(AF_INET, "10.53.0.7", &inaddr) != 1) 266 CHECK("inet_pton", result); 267 isc_sockaddr_fromin(&srcaddr, &inaddr, 0); 268 269 result = ISC_R_FAILURE; 270 if (inet_pton(AF_INET, "10.53.0.4", &inaddr) != 1) 271 CHECK("inet_pton", result); 272 isc_sockaddr_fromin(&dstaddr, &inaddr, port); 273 274 mctx = NULL; 275 RUNCHECK(isc_mem_create(0, 0, &mctx)); 276 277 lctx = NULL; 278 lcfg = NULL; 279 RUNCHECK(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, &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 | 296 DNS_DISPATCHATTR_MAKEQUERY | 297 DNS_DISPATCHATTR_IPV4; 298 attrmask = DNS_DISPATCHATTR_UDP | 299 DNS_DISPATCHATTR_TCP | 300 DNS_DISPATCHATTR_IPV4 | 301 DNS_DISPATCHATTR_IPV6; 302 dispatchv4 = NULL; 303 RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, 304 have_src ? &srcaddr : &bind_any, 305 4096, 4, 2, 3, 5, 306 attrs, attrmask, &dispatchv4)); 307 requestmgr = NULL; 308 RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, 309 dispatchmgr, dispatchv4, NULL, 310 &requestmgr)); 311 312 view = NULL; 313 RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); 314 315 RUNCHECK(isc_app_onrun(mctx, task, sendqueries, NULL)); 316 317 (void)isc_app_run(); 318 319 dns_view_detach(&view); 320 321 dns_requestmgr_shutdown(requestmgr); 322 dns_requestmgr_detach(&requestmgr); 323 324 dns_dispatch_detach(&dispatchv4); 325 dns_dispatchmgr_destroy(&dispatchmgr); 326 327 isc_socketmgr_destroy(&socketmgr); 328 isc_timermgr_destroy(&timermgr); 329 330 isc_task_shutdown(task); 331 isc_task_detach(&task); 332 isc_taskmgr_destroy(&taskmgr); 333 334 dst_lib_destroy(); 335 336 isc_log_destroy(&lctx); 337 338 isc_mem_destroy(&mctx); 339 340 isc_app_finish(); 341 342 return (0); 343 } 344 345