1 /**
2  * \file
3  * unit tests for getdns_dict helper routines, these should be used to
4  * perform regression tests, output must be unchanged from canonical output
5  * stored with the sources
6  */
7 
8 /*
9  * Copyright (c) 2013, NLNet Labs, Verisign, Inc.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  * * Redistributions of source code must retain the above copyright
15  *   notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above copyright
17  *   notice, this list of conditions and the following disclaimer in the
18  *   documentation and/or other materials provided with the distribution.
19  * * Neither the names of the copyright holders nor the
20  *   names of its contributors may be used to endorse or promote products
21  *   derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "config.h"
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "testmessages.h"
40 #include "getdns/getdns.h"
41 #include "getdns/getdns_extra.h"
42 #include <sys/time.h>
43 
44 #define TRANSPORT_UDP "udp"
45 #define TRANSPORT_UDP_TCP "udp_tcp"
46 #define TRANSPORT_TCP "tcp"
47 #define TRANSPORT_PIPELINE "pipeline"
48 #define TRANSPORT_TLS_KEEPOPEN "tls"
49 #define TRANSPORT_TLS_TCP_KEEPOPEN "dns-over-tls"
50 #define RESOLUTION_STUB "stub"
51 #define RESOLUTION_REC "rec"
52 
53 /* Set up the callback function, which will also do the processing of the results */
54 void
this_callbackfn(struct getdns_context * this_context,getdns_callback_type_t this_callback_type,struct getdns_dict * this_response,void * this_userarg,getdns_transaction_t this_transaction_id)55 this_callbackfn(struct getdns_context *this_context,
56 	getdns_callback_type_t this_callback_type,
57 	struct getdns_dict *this_response,
58 	void *this_userarg, getdns_transaction_t this_transaction_id)
59 {
60 	(void)this_context; (void)this_userarg;
61 
62 	if (this_callback_type == GETDNS_CALLBACK_COMPLETE) {	/* This is a callback with data */
63 		char *res = getdns_pretty_print_dict(this_response);
64 		fprintf(stdout, "%s\n", res);
65 		free(res);
66 
67 	} else if (this_callback_type == GETDNS_CALLBACK_CANCEL)
68 		fprintf(stderr,
69 			"The callback with ID %llu was cancelled. Exiting.\n",
70 			(unsigned long long)this_transaction_id);
71 	else
72 		fprintf(stderr,
73 			"The callback got a callback_type of %d. Exiting.\n",
74 			this_callback_type);
75 	getdns_dict_destroy(this_response);
76 }
77 
78 int
main(int argc,char ** argv)79 main(int argc, char** argv)
80 {
81 
82 	const char *transport = argc > 2 ? argv[2] : "udp_tcp";
83 	const char *resolution = argc > 3 ? argv[3] : "stub";
84 
85 	/* Create the DNS context for this call */
86 	struct getdns_context *this_context = NULL;
87 	getdns_return_t return_value =
88 		getdns_context_create(&this_context, 1);
89 	if (return_value != GETDNS_RETURN_GOOD) {
90 		fprintf(stderr, "Trying to create the context failed: %d",
91 			return_value);
92 		return (GETDNS_RETURN_GENERIC_ERROR);
93 	}
94 
95 	if (strncmp(resolution, RESOLUTION_STUB, 4) == 0)
96 		getdns_context_set_resolution_type(this_context, GETDNS_RESOLUTION_STUB);
97 	else if (strncmp(resolution, RESOLUTION_REC, 4) != 0) {
98 		fprintf(stderr, "Invalid resolution %s, must be one of stub or rec\n", transport);
99 		exit(EXIT_FAILURE);
100 	}
101 
102 	/* Order matters*/
103 	if (strncmp(transport, TRANSPORT_TCP, 3) == 0)
104 		getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY);
105 	else if (strncmp(transport, TRANSPORT_UDP_TCP, 7) == 0)
106 		getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP);
107 	else if (strncmp(transport, TRANSPORT_UDP, 3) == 0)
108 		getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_UDP_ONLY);
109 	else if (strncmp(transport, TRANSPORT_PIPELINE, 8) == 0)
110 		getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN);
111 	else if (strncmp(transport, TRANSPORT_TLS_KEEPOPEN, 3) == 0)
112 		getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN);
113 	else if (strncmp(transport, TRANSPORT_TLS_TCP_KEEPOPEN, 12) == 0)
114 		getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN);
115 	else if (strncmp(transport, TRANSPORT_UDP_TCP, 3) != 0) {
116 		fprintf(stderr, "Invalid transport %s, must be one of udp, udp_tcp, tcp or pipeline\n", transport);
117 		exit(EXIT_FAILURE);
118 	}
119 
120 	getdns_context_set_timeout(this_context, 5000);
121 	/* Create an event base and put it in the context using the unknown function name */
122 	/* Set up the getdns call */
123 	const char *this_name = argc > 1 ? argv[1] : "getdnsapi.net";
124 	char *this_userarg = "somestring";	// Could add things here to help identify this call
125 	getdns_transaction_t this_transaction_id = 0;
126 
127 	/* Make the call */
128 	getdns_return_t dns_request_return =
129 		getdns_address(this_context, this_name,
130 		NULL, this_userarg, &this_transaction_id, this_callbackfn);
131 	if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME) {
132 		fprintf(stderr, "A bad domain name was used: %s. Exiting.",
133 			this_name);
134 		getdns_context_destroy(this_context);
135 		return (GETDNS_RETURN_GENERIC_ERROR);
136 	}
137 	else {
138 		getdns_context_run(this_context);
139 	}
140 
141 	getdns_transport_t get_transport;
142 	return_value = getdns_context_get_dns_transport(this_context, &get_transport);
143 	if (return_value != GETDNS_RETURN_GOOD) {
144 		fprintf(stderr, "Trying to get transport type failed: %d\n",
145 			return_value);
146 		return (GETDNS_RETURN_GENERIC_ERROR);
147 	}
148 	fprintf(stderr, "Transport type is %d\n", get_transport);
149 
150 	size_t transport_count = 0;
151 	getdns_transport_list_t *get_transport_list;
152 	return_value = getdns_context_get_dns_transport_list(this_context, &transport_count, &get_transport_list);
153 	if (return_value != GETDNS_RETURN_GOOD) {
154 		fprintf(stderr, "Trying to get transport type failed: %d\n",
155 			return_value);
156 		return (GETDNS_RETURN_GENERIC_ERROR);
157 	}
158 	size_t i;
159 	for (i = 0; i < transport_count; i++) {
160 		fprintf(stderr, "Transport %d is %d\n", (int)i, get_transport_list[i]);
161 	}
162 	free(get_transport_list);
163 
164 	/* Clean up */
165 	getdns_context_destroy(this_context);
166 	/* Assuming we get here, leave gracefully */
167 	exit(EXIT_SUCCESS);
168 }				/* main */
169 
170 /* tests_stub_async.c */
171