xref: /netbsd-src/external/apache2/mDNSResponder/dist/unittests/unittest_common.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 #include "unittest_common.h"
2 #include "dns_sd.h"
3 #include "mDNSEmbeddedAPI.h"
4 #include "mDNSMacOSX.h"
5 
6 static mDNS_PlatformSupport PlatformStorage;
7 #define RR_CACHE_SIZE ((32*1024) / sizeof(CacheRecord))
8 static CacheEntity gRrcachestorage[RR_CACHE_SIZE];
9 
10 // Primary interface info that is used when simulating the receive of the response packet
11 mDNSInterfaceID primary_interfaceID;
12 mDNSAddr primary_v4;
13 mDNSAddr primary_v6;
14 mDNSAddr primary_router;
15 
16 // This function sets up the minimum environement to run a unit test. It
17 // initializes logging, interfaces, and timenow.
18 mDNSexport mStatus init_mdns_environment(mDNSBool enableLogging)
19 {
20 	mDNS *m = &mDNSStorage;
21 
22 	init_logging_ut();
23 	mDNS_LoggingEnabled = enableLogging;
24 	mDNS_PacketLoggingEnabled = enableLogging;
25 
26 	mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL);
27 	if (result != mStatus_NoError)
28 		return result;
29 
30 	primary_v4 = primary_v6 = primary_router = zeroAddr;
31 	SetInterfaces_ut(&primary_interfaceID, &primary_v4, &primary_v6, &primary_router);
32 
33 	m->timenow = mDNS_TimeNow_NoLock(m);
34 	return mStatus_NoError;
35 }
36 
37 // This function sets up the minimum environement to run a unit test. It
38 // initializes logging and timenow.  This is the call to use if your
39 // unit test does not use interfaces.
40 mDNSexport mStatus init_mdns_storage()
41 {
42 	mDNS *m = &mDNSStorage;
43 
44 	init_logging_ut();
45 	mDNS_LoggingEnabled = 1;
46 	mDNS_PacketLoggingEnabled = 1;
47 
48 	mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL);
49 	if (result != mStatus_NoError)
50 		return result;
51 
52 	return mStatus_NoError;
53 }
54 
55 mDNSlocal void init_client_request(request_state* req, char *msgbuf, size_t msgSize, uint32_t op)
56 {
57 	// Simulate read_msg behavior since unit test does not open a socket
58 	memset(req, 0, sizeof(request_state));
59 
60 	req->ts = t_complete;
61 	req->msgbuf = mDNSNULL;
62 	req->msgptr = msgbuf;
63 	req->msgend = msgbuf + msgSize;
64 
65 	// The rest of the request values are set in order to simulate a request
66 	req->sd             = client_req_sd;
67 	req->uid            = client_req_uid;
68 	req->hdr_bytes      = client_req_hdr_bytes;
69 	req->hdr.version    = client_req_hdr_version;
70 	req->hdr.op         = op; // query_request
71 	req->hdr.datalen    = msgSize;
72 	req->data_bytes     = msgSize;
73 	req->process_id     = client_req_process_id;
74 	memcpy(req->pid_name, client_req_pid_name, strlen(client_req_pid_name));
75 }
76 
77 // This function calls the mDNSResponder handle_client_request() API.  It initializes
78 // the request and query data structures.
79 mDNSexport mStatus start_client_request(request_state* req, char *msgbuf, size_t msgsz, uint32_t op, UDPSocket* socket)
80 {
81 	// Process the unit test's client request
82 	init_client_request(req, msgbuf, msgsz, op);
83 
84 	mStatus result = handle_client_request_ut((void*)req);
85 	DNSQuestion* q = &req->u.queryrecord.q;
86 	q->LocalSocket = socket;
87 	return result;
88 }
89 
90 // This function calls the mDNSResponder mDNSCoreReceive() API.
91 mDNSexport void receive_response(const request_state* req, DNSMessage *msg, size_t msgSize)
92 {
93 	mDNS *m = &mDNSStorage;
94 	mDNSAddr srcaddr;
95 	mDNSIPPort srcport, dstport;
96 	const mDNSu8 * end;
97 	DNSQuestion *q = (DNSQuestion *)&req->u.queryrecord.q;
98 	UInt8* data = (UInt8*)msg;
99 
100 	// Used same values for DNS server as specified during init of unit test
101 	srcaddr.type				= mDNSAddrType_IPv4;
102 	srcaddr.ip.v4.NotAnInteger	= dns_server_ipv4.NotAnInteger;
103 	srcport.NotAnInteger		= client_resp_src_port;
104 
105 	// Used random value for dstport
106 	dstport.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
107 
108 	// Set DNS message (that was copied from a WireShark packet)
109 	end = (const mDNSu8 *)msg + msgSize;
110 
111 	// Set socket info that mDNSCoreReceive uses to verify socket context
112 	q->LocalSocket->ss.port.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
113 	q->TargetQID.b[0] = data[0];
114 	q->TargetQID.b[1] = data[1];
115 
116 	// Execute mDNSCoreReceive which copies two DNS records into the cache
117 	mDNSCoreReceive(m, msg, end, &srcaddr, srcport, &primary_v4, dstport, primary_interfaceID);
118 }
119 
120 mDNSexport  size_t get_reply_len(char* name, uint16_t rdlen)
121 {
122 	size_t len = sizeof(DNSServiceFlags);
123 	len += sizeof(mDNSu32);     // interface index
124 	len += sizeof(DNSServiceErrorType);
125 	len += strlen(name) + 1;
126 	len += 3 * sizeof(mDNSu16); // type, class, rdlen
127 	len += rdlen;
128 	len += sizeof(mDNSu32);     // TTL
129 	return len;
130 }
131 
132 
133 void free_req(request_state* req)
134 {
135 	// Cleanup request's memory usage
136 	while (req->replies)
137 	{
138 		reply_state *reply = req->replies;
139 		req->replies = req->replies->next;
140 		mDNSPlatformMemFree(reply);
141 	}
142 	req->replies = NULL;
143 	mDNSPlatformMemFree(req);
144 }
145 
146 // Unit test support functions follow
147 #define SA_LEN(addr) (((addr)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
148 
149 mDNSexport void get_ip(const char *const name, struct sockaddr_storage *result)
150 {
151 	struct addrinfo* aiList;
152 	int err = getaddrinfo(name, NULL, NULL, &aiList);
153 	if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name);
154 	else memcpy(result, aiList->ai_addr, SA_LEN(aiList->ai_addr));
155 	if (aiList) freeaddrinfo(aiList);
156 }
157 
158