]> git.saurik.com Git - apple/mdnsresponder.git/blob - unittests/unittest_common.c
mDNSResponder-1096.40.7.tar.gz
[apple/mdnsresponder.git] / unittests / unittest_common.c
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.op.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.op.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 void receive_suspicious_response_ut(const request_state* req, DNSMessage *msg, size_t msgSize, mDNSOpaque16 suspiciousqid, mDNSBool goodLastQID)
121 {
122 mDNS *m = &mDNSStorage;
123 mDNSAddr srcaddr;
124 mDNSIPPort srcport, dstport;
125 const mDNSu8 * end;
126 DNSQuestion *q = (DNSQuestion *)&req->u.queryrecord.op.q;
127 UInt8* data = (UInt8*)msg;
128
129 // Used same values for DNS server as specified during init of unit test
130 srcaddr.type = mDNSAddrType_IPv4;
131 srcaddr.ip.v4.NotAnInteger = dns_server_ipv4.NotAnInteger;
132 srcport.NotAnInteger = client_resp_src_port;
133
134 // Used random value for dstport
135 dstport.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
136
137 // Set DNS message (that was copied from a WireShark packet)
138 end = (const mDNSu8 *)msg + msgSize;
139
140 // Set socket info that mDNSCoreReceive uses to verify socket context
141 q->LocalSocket->ss.port.NotAnInteger = swap16((mDNSu16)client_resp_dst_port);
142 if (suspiciousqid.NotAnInteger)
143 {
144 q->TargetQID.NotAnInteger = swap16(suspiciousqid.NotAnInteger);
145 if (goodLastQID)
146 {
147 q->LastTargetQID.b[0] = data[0];
148 q->LastTargetQID.b[1] = data[1];
149 }
150 else q->LastTargetQID.NotAnInteger = 0;
151 }
152 else
153 {
154 q->TargetQID.b[0] = data[0];
155 q->TargetQID.b[1] = data[1];
156 }
157
158 // Execute mDNSCoreReceive which copies two DNS records into the cache
159 mDNSCoreReceive(m, msg, end, &srcaddr, srcport, &primary_v4, dstport, primary_interfaceID);
160 }
161
162 mDNSexport size_t get_reply_len(char* name, uint16_t rdlen)
163 {
164 size_t len = sizeof(DNSServiceFlags);
165 len += sizeof(mDNSu32); // interface index
166 len += sizeof(DNSServiceErrorType);
167 len += strlen(name) + 1;
168 len += 3 * sizeof(mDNSu16); // type, class, rdlen
169 len += rdlen;
170 len += sizeof(mDNSu32); // TTL
171 return len;
172 }
173
174
175 void free_req(request_state* req)
176 {
177 // Cleanup request's memory usage
178 while (req->replies)
179 {
180 reply_state *reply = req->replies;
181 req->replies = req->replies->next;
182 mDNSPlatformMemFree(reply);
183 }
184 req->replies = NULL;
185 mDNSPlatformMemFree(req);
186 }
187
188 // Unit test support functions follow
189 #define SA_LEN(addr) (((addr)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
190
191 mDNSexport void get_ip(const char *const name, struct sockaddr_storage *result)
192 {
193 struct addrinfo* aiList;
194 int err = getaddrinfo(name, NULL, NULL, &aiList);
195 if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name);
196 else memcpy(result, aiList->ai_addr, SA_LEN(aiList->ai_addr));
197 if (aiList) freeaddrinfo(aiList);
198 }
199
200 // The AddDNSServer_ut function adds a dns server to mDNSResponder's list.
201 mDNSexport mStatus AddDNSServerScoped_ut(mDNSInterfaceID interfaceID, ScopeType scoped)
202 {
203 mDNS *m = &mDNSStorage;
204 m->timenow = 0;
205 mDNS_Lock(m);
206 domainname d;
207 mDNSAddr addr;
208 mDNSIPPort port;
209 mDNSs32 serviceID = 0;
210 mDNSu32 timeout = dns_server_timeout;
211 mDNSBool cellIntf = 0;
212 mDNSBool isExpensive = 0;
213 mDNSBool isConstrained = 0;
214 mDNSBool isCLAT46 = mDNSfalse;
215 mDNSu32 resGroupID = dns_server_resGroupID;
216 mDNSBool reqA = mDNStrue;
217 mDNSBool reqAAAA = mDNStrue;
218 mDNSBool reqDO = mDNSfalse;
219 d.c[0] = 0;
220 addr.type = mDNSAddrType_IPv4;
221 addr.ip.v4.NotAnInteger = dns_server_ipv4.NotAnInteger;
222 port.NotAnInteger = client_resp_src_port;
223 mDNS_AddDNSServer(m, &d, interfaceID, serviceID, &addr, port, scoped, timeout,
224 cellIntf, isExpensive, isConstrained, isCLAT46, resGroupID,
225 reqA, reqAAAA, reqDO);
226 mDNS_Unlock(m);
227 return mStatus_NoError;
228 }
229
230 mDNSexport mStatus AddDNSServer_ut(void)
231 {
232 return AddDNSServerScoped_ut(primary_interfaceID, kScopeNone);
233 }
234
235 mDNSexport mStatus force_uDNS_SetupDNSConfig_ut(mDNS *const m)
236 {
237 m->p->LastConfigGeneration = 0;
238 return uDNS_SetupDNSConfig(m);
239 }
240
241 mDNSexport mStatus verify_cache_addr_order_for_domain_ut(mDNS *const m, mDNSu8* octet, mDNSu32 count, const domainname *const name)
242 {
243 mStatus result = mStatus_NoError;
244 const CacheGroup *cg = CacheGroupForName(m, DomainNameHashValue(name), name);
245 if (cg)
246 {
247 mDNSu32 i;
248 CacheRecord **rp = (CacheRecord **)&cg->members;
249 for (i = 0 ; *rp && i < count ; i++ )
250 {
251 if ((*rp)->resrec.rdata->u.ipv4.b[3] != octet[i])
252 {
253 LogInfo ("Octet %d compare failed %d != %d", i, (*rp)->resrec.rdata->u.ipv4.b[3], octet[i]);
254 break;
255 }
256 rp = &(*rp)->next;
257 }
258 if (i != count) result = mStatus_Invalid;
259 }
260 else
261 {
262 LogInfo ("Cache group not found");
263 result = mStatus_Invalid;
264 }
265
266 return result;
267 }