Imported Upstream version 878.70.2
[platform/upstream/mdnsresponder.git] / unittests / CNameRecordTests.c
1 #include "CNameRecordTests.h"
2 #include "unittest_common.h"
3
4 mDNSlocal int InitThisUnitTest(void);
5 mDNSlocal int StartClientQueryRequest(void);
6 mDNSlocal int PopulateCacheWithClientResponseRecords(void);
7 mDNSlocal int SimulateNetworkChangeAndVerifyTest(void);
8 mDNSlocal int FinalizeUnitTest(void);
9 mDNSlocal mStatus AddDNSServer(void);
10
11 // This unit test's variables
12 static UDPSocket* local_socket;
13 static request_state* client_request_message;
14
15 struct UDPSocket_struct
16 {
17         mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
18 };
19 typedef struct UDPSocket_struct UDPSocket;
20
21 // This client request was generated using the following command: "dns-sd -Q 123server.dotbennu.com. A".
22 uint8_t query_client_msgbuf[35] = {
23         0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x32, 0x33, 0x73, 0x65, 0x72, 0x76, 0x65,
24         0x72, 0x2e, 0x64, 0x6f, 0x74, 0x62, 0x65, 0x6e, 0x6e, 0x75, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x00,
25         0x01, 0x00, 0x01
26 };
27
28 // This uDNS message is a canned response that was originally captured by wireshark.
29 uint8_t query_response_msgbuf[108] = {
30     0x69, 0x41, // transaction id
31         0x85, 0x80, // flags
32         0x00, 0x01, // 1 question for 123server.dotbennu.com. Addr
33         0x00, 0x02,     // 2 anwsers: 123server.dotbennu.com. CNAME test212.dotbennu.com., test212.dotbennu.com. Addr 10.100.0.1,
34         0x00, 0x01,     // 1 authorities anwser: dotbennu.com. NS cardinal2.apple.com.
35         0x00, 0x00, 0x09, 0x31, 0x32, 0x33,
36     0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x08, 0x64, 0x6f, 0x74, 0x62, 0x65, 0x6e, 0x6e, 0x75, 0x03,
37     0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00,
38     0x02, 0x56, 0x00, 0x0a, 0x07, 0x74, 0x65, 0x73, 0x74, 0x32, 0x31, 0x32, 0xc0, 0x16, 0xc0, 0x34,
39     0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x0a, 0x64, 0x00, 0x01, 0xc0, 0x16,
40     0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x51, 0x80, 0x00, 0x12, 0x09, 0x63, 0x61, 0x72, 0x64, 0x69,
41     0x6e, 0x61, 0x6c, 0x32, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x65, 0xc0, 0x1f
42 };
43
44 // Variables associated with contents of the above uDNS message
45 #define uDNS_TargetQID 16745
46 char udns_original_domainname_cstr[] = "123server.dotbennu.com.";
47 char udns_cname_domainname_cstr[] = "test212.dotbennu.com.";
48 static const mDNSv4Addr dns_response_ipv4 = {{ 10, 100, 0, 1 }};
49
50 UNITTEST_HEADER(CNameRecordTests)
51         UNITTEST_TEST(InitThisUnitTest)
52         UNITTEST_TEST(StartClientQueryRequest)
53     UNITTEST_TEST(PopulateCacheWithClientResponseRecords)
54     UNITTEST_TEST(SimulateNetworkChangeAndVerifyTest)
55     UNITTEST_TEST(FinalizeUnitTest)
56 UNITTEST_FOOTER
57
58 // The InitThisUnitTest() initializes the mDNSResponder environment as well as
59 // a DNSServer. It also allocates memory for a local_socket and client request.
60 // Note: This unit test does not send packets on the wire and it does not open sockets.
61 UNITTEST_HEADER(InitThisUnitTest)
62         // Init unit test environment and verify no error occurred.
63         mStatus result = init_mdns_environment(mDNStrue);
64         UNITTEST_ASSERT(result == mStatus_NoError);
65
66         // Add one DNS server and verify it was added.
67         AddDNSServer();
68         UNITTEST_ASSERT(NumUnicastDNSServers == 1);
69
70         // Create memory for a socket that is never used or opened.
71         local_socket = mDNSPlatformMemAllocate(sizeof(UDPSocket));
72         mDNSPlatformMemZero(local_socket, sizeof(UDPSocket));
73
74         // Create memory for a request that is used to make this unit test's client request.
75         client_request_message = calloc(1, sizeof(request_state));
76 UNITTEST_FOOTER
77
78 // This test simulates a uds client request by setting up a client request and then
79 // calling mDNSResponder's handle_client_request.  The handle_client_request function
80 // processes the request and starts a query.  This unit test verifies
81 // the client request and query were setup as expected.  This unit test also calls
82 // mDNS_execute which determines the cache does not contain the new question's
83 // answer.
84 UNITTEST_HEADER(StartClientQueryRequest)
85     mDNS *const m = &mDNSStorage;
86     request_state* req = client_request_message;
87         char *msgptr = (char *)query_client_msgbuf;
88         size_t msgsz = sizeof(query_client_msgbuf);
89         mDNSs32 min_size = sizeof(DNSServiceFlags) + sizeof(mDNSu32) + 4;
90     DNSQuestion *q;
91     mStatus err = mStatus_NoError;
92         char qname_cstr[MAX_ESCAPED_DOMAIN_NAME];
93
94     // Process the unit test's client request
95         start_client_request(req, msgptr, msgsz, query_request, local_socket);
96     UNITTEST_ASSERT(err == mStatus_NoError);
97
98         // Verify the request fields were set as expected
99         UNITTEST_ASSERT(req->next == mDNSNULL);
100         UNITTEST_ASSERT(req->primary == mDNSNULL);
101         UNITTEST_ASSERT(req->sd == client_req_sd);
102         UNITTEST_ASSERT(req->process_id == client_req_process_id);
103         UNITTEST_ASSERT(!strcmp(req->pid_name, client_req_pid_name));
104         UNITTEST_ASSERT(req->validUUID == mDNSfalse);
105         UNITTEST_ASSERT(req->errsd == 0);
106         UNITTEST_ASSERT(req->uid == client_req_uid);
107         UNITTEST_ASSERT(req->ts == t_complete);
108         UNITTEST_ASSERT((mDNSs32)req->data_bytes > min_size);
109         UNITTEST_ASSERT(req->msgend == msgptr+msgsz);
110         UNITTEST_ASSERT(req->msgbuf == mDNSNULL);
111     UNITTEST_ASSERT(req->hdr.version == VERSION);
112     UNITTEST_ASSERT(req->replies == mDNSNULL);
113     UNITTEST_ASSERT(req->terminate != mDNSNULL);
114         UNITTEST_ASSERT(req->flags == kDNSServiceFlagsReturnIntermediates);
115     UNITTEST_ASSERT(req->interfaceIndex == kDNSServiceInterfaceIndexAny);
116
117         // Verify the query fields were set as expected
118         q = &req->u.queryrecord.q;
119     UNITTEST_ASSERT(q != mDNSNULL);
120     UNITTEST_ASSERT(q == m->Questions);
121     UNITTEST_ASSERT(q == m->NewQuestions);
122     UNITTEST_ASSERT(q->SuppressUnusable == mDNSfalse);
123     UNITTEST_ASSERT(q->ReturnIntermed == mDNStrue);
124     UNITTEST_ASSERT(q->SuppressQuery == mDNSfalse);
125
126         UNITTEST_ASSERT(q->qnameOrig == mDNSNULL);
127         ConvertDomainNameToCString(&q->qname, qname_cstr);
128         UNITTEST_ASSERT(!strcmp(qname_cstr, udns_original_domainname_cstr));
129         UNITTEST_ASSERT(q->qnamehash == DomainNameHashValue(&q->qname));
130
131         UNITTEST_ASSERT(q->InterfaceID == mDNSInterface_Any);
132     UNITTEST_ASSERT(q->flags == req->flags);
133     UNITTEST_ASSERT(q->qtype == 1);
134     UNITTEST_ASSERT(q->qclass == 1);
135     UNITTEST_ASSERT(q->LongLived == 0);
136     UNITTEST_ASSERT(q->ExpectUnique == mDNSfalse);
137     UNITTEST_ASSERT(q->ForceMCast == 0);
138     UNITTEST_ASSERT(q->TimeoutQuestion == 0);
139     UNITTEST_ASSERT(q->WakeOnResolve == 0);
140     UNITTEST_ASSERT(q->UseBackgroundTrafficClass == 0);
141     UNITTEST_ASSERT(q->ValidationRequired == 0);
142     UNITTEST_ASSERT(q->ValidatingResponse == 0);
143     UNITTEST_ASSERT(q->ProxyQuestion == 0);
144     UNITTEST_ASSERT(q->AnonInfo == mDNSNULL);
145     UNITTEST_ASSERT(q->QuestionCallback != mDNSNULL);
146     UNITTEST_ASSERT(q->QuestionContext == req);
147     UNITTEST_ASSERT(q->SearchListIndex == 0);
148     UNITTEST_ASSERT(q->DNSSECAuthInfo == mDNSNULL);
149     UNITTEST_ASSERT(q->DAIFreeCallback == mDNSNULL);
150     UNITTEST_ASSERT(q->RetryWithSearchDomains == 0);
151     UNITTEST_ASSERT(q->AppendSearchDomains == 0);
152     UNITTEST_ASSERT(q->AppendLocalSearchDomains == 0);
153     UNITTEST_ASSERT(q->DuplicateOf == mDNSNULL);
154
155     // Call mDNS_Execute to see if the new question, q, has an answer in the cache.
156         // It won't be yet because the cache is empty.
157         m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
158     mDNS_Execute(m);
159
160     // Verify mDNS_Execute processed the new question.
161         UNITTEST_ASSERT(m->NewQuestions == mDNSNULL);
162
163         // Verify the cache is empty and the request got no reply.
164         UNITTEST_ASSERT(m->rrcache_totalused == 0);
165     UNITTEST_ASSERT(req->replies == mDNSNULL);
166
167 UNITTEST_FOOTER
168
169 // This unit test receives a canned uDNS response message by calling the mDNSCoreReceive() function.
170 // It then verifies cache entries were added for the CNAME and A records that were contained in the
171 // answers of the canned response, query_response_msgbuf.  This unit test also verifies that
172 // 2 add events were generated for the client.
173 UNITTEST_HEADER(PopulateCacheWithClientResponseRecords)
174     mDNS *const m = &mDNSStorage;
175         DNSMessage *msgptr = (DNSMessage *)query_response_msgbuf;
176         size_t msgsz = sizeof(query_response_msgbuf);
177     struct reply_state *reply;
178     request_state* req = client_request_message;
179     DNSQuestion *q = &req->u.queryrecord.q;
180     const char *data;
181         const char *end;
182     char name[kDNSServiceMaxDomainName];
183     uint16_t rrtype, rrclass, rdlen;
184     const char *rdata;
185     size_t len;
186     char domainname_cstr[MAX_ESCAPED_DOMAIN_NAME];
187
188         // Receive and populate the cache with canned response
189     receive_response(req, msgptr, msgsz);
190
191     // Verify 2 cache entries for CName and A record are present
192     mDNSu32 CacheUsed =0, notUsed =0;
193     LogCacheRecords_ut(mDNS_TimeNow(m), &CacheUsed, &notUsed);
194     UNITTEST_ASSERT(CacheUsed == m->rrcache_totalused);
195     UNITTEST_ASSERT(CacheUsed  == 4); // 2 for the CacheGroup object plus 2 for the A and CNAME records
196     UNITTEST_ASSERT(m->PktNum  == 1); // one packet was received
197
198         // Verify question's qname is now set with the A record's domainname
199         UNITTEST_ASSERT(q->qnameOrig == mDNSNULL);
200         ConvertDomainNameToCString(&q->qname, domainname_cstr);
201         UNITTEST_ASSERT(q->qnamehash == DomainNameHashValue(&q->qname));
202         UNITTEST_ASSERT(!strcmp(domainname_cstr, udns_cname_domainname_cstr));
203
204         // Verify client's add event for CNAME is properly formed
205     reply = req->replies;
206     UNITTEST_ASSERT(reply != mDNSNULL);
207     UNITTEST_ASSERT(reply->next == mDNSNULL);
208
209     data    = (char *)&reply->rhdr[1];
210     end     = data+reply->totallen;
211     get_string(&data, data+reply->totallen, name, kDNSServiceMaxDomainName);
212     rrtype  = get_uint16(&data, end);
213     rrclass = get_uint16(&data, end);
214     rdlen   = get_uint16(&data, end);
215     rdata   = get_rdata(&data, end, rdlen);
216         len     = get_reply_len(name, rdlen);
217
218     UNITTEST_ASSERT(reply->totallen == len + sizeof(ipc_msg_hdr));
219     UNITTEST_ASSERT(reply->mhdr->version == VERSION);
220     UNITTEST_ASSERT(reply->mhdr->datalen == len);
221     UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
222     UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
223
224     UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
225     UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexAny);
226     UNITTEST_ASSERT(reply->rhdr->error == kDNSServiceErr_NoError);
227
228     UNITTEST_ASSERT(rrtype == kDNSType_CNAME);
229     UNITTEST_ASSERT(rrclass == kDNSClass_IN);
230     ConvertDomainNameToCString((const domainname *const)rdata, domainname_cstr);
231     UNITTEST_ASSERT(!strcmp(domainname_cstr, "test212.dotbennu.com."));
232
233     // The mDNS_Execute call generates an add event for the A record
234     m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
235     mDNS_Execute(m);
236
237     // Verify the client's reply contains a properly formed add event for the A record.
238     reply = req->replies;
239     UNITTEST_ASSERT(reply != mDNSNULL);
240     UNITTEST_ASSERT(reply->next != mDNSNULL);
241     reply = reply->next;
242
243     data    = (char *)&reply->rhdr[1];
244     end     = data+reply->totallen;
245     get_string(&data, data+reply->totallen, name, kDNSServiceMaxDomainName);
246     rrtype  = get_uint16(&data, end);
247     rrclass = get_uint16(&data, end);
248     rdlen   = get_uint16(&data, end);
249     rdata   = get_rdata(&data, end, rdlen);
250         len     = get_reply_len(name, rdlen);
251
252     UNITTEST_ASSERT(reply->totallen == len + sizeof(ipc_msg_hdr));
253     UNITTEST_ASSERT(reply->mhdr->version == VERSION);
254     UNITTEST_ASSERT(reply->mhdr->datalen == len);
255
256     UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
257     UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
258
259     UNITTEST_ASSERT(reply->rhdr->flags == htonl(kDNSServiceFlagsAdd));
260     UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexAny);
261     UNITTEST_ASSERT(reply->rhdr->error == kDNSServiceErr_NoError);
262
263     UNITTEST_ASSERT(rrtype == kDNSType_A);
264     UNITTEST_ASSERT(rrclass == kDNSClass_IN);
265         UNITTEST_ASSERT(rdata[0] == dns_response_ipv4.b[0]);
266         UNITTEST_ASSERT(rdata[1] == dns_response_ipv4.b[1]);
267         UNITTEST_ASSERT(rdata[2] == dns_response_ipv4.b[2]);
268         UNITTEST_ASSERT(rdata[3] == dns_response_ipv4.b[3]);
269
270 UNITTEST_FOOTER
271
272 // This function verifies the cache and event handling occurred as expected when a network change happened.
273 // The uDNS_SetupDNSConfig is called to simulate a network change and two outcomes occur. First the A record
274 // query is restarted and sent to a new DNS server. Second the cache records are purged. Then mDNS_Execute
275 // is called and it removes the purged cache records and generates a remove event for the A record.
276 // The following are verified:
277 //      1.) The restart of query for A record.
278 //      2.) The cache is empty after mDNS_Execute removes the cache entres.
279 //  3.) The remove event is verified by examining the request's reply data.
280 UNITTEST_HEADER(SimulateNetworkChangeAndVerifyTest)
281     mDNS *const m = &mDNSStorage;
282     request_state*  req = client_request_message;
283     DNSQuestion*    q = &req->u.queryrecord.q;
284     mDNSu32 CacheUsed =0, notUsed =0;
285     const char *data;   const char *end;
286     char name[kDNSServiceMaxDomainName];
287     uint16_t rrtype, rrclass, rdlen;
288     const char *rdata;
289     size_t len;
290
291     // The uDNS_SetupDNSConfig reconfigures the resolvers so the A record query is restarted and
292     // both the CNAME and A record are purged.
293     uDNS_SetupDNSConfig(m);
294
295     // Verify the A record query was restarted.  This is done indirectly by noticing the transaction id and interval have changed.
296     UNITTEST_ASSERT(q->ThisQInterval == InitialQuestionInterval);
297     UNITTEST_ASSERT(q->TargetQID.NotAnInteger != uDNS_TargetQID);
298
299     // Then mDNS_Execute removes both records from the cache and calls the client back with a remove event for A record.
300     m->NextScheduledEvent = mDNS_TimeNow_NoLock(m);
301     mDNS_Execute(m);
302
303     // Verify the cache entries are removed
304     LogCacheRecords_ut(mDNS_TimeNow(m), &CacheUsed, &notUsed);
305     UNITTEST_ASSERT(CacheUsed == m->rrcache_totalused);
306     UNITTEST_ASSERT(CacheUsed == 0);
307
308     // Verify the A record's remove event is setup as expected in the reply data
309     struct reply_state *reply;
310     reply = req->replies;
311     UNITTEST_ASSERT(reply != mDNSNULL);
312
313     UNITTEST_ASSERT(reply != mDNSNULL);
314     UNITTEST_ASSERT(reply->next != mDNSNULL);
315     UNITTEST_ASSERT(reply->next->next != mDNSNULL);
316
317     reply = reply->next->next; // Get to last event to verify remove event
318     data    = (char *)&reply->rhdr[1];
319     end     = data+reply->totallen;
320     get_string(&data, data+reply->totallen, name, kDNSServiceMaxDomainName);
321     rrtype  = get_uint16(&data, end);
322     rrclass = get_uint16(&data, end);
323     rdlen   = get_uint16(&data, end);
324     rdata   = get_rdata(&data, end, rdlen);
325         len     = get_reply_len(name, rdlen);
326
327     UNITTEST_ASSERT(reply->totallen == reply->mhdr->datalen + sizeof(ipc_msg_hdr));
328     UNITTEST_ASSERT(reply->mhdr->version == VERSION);
329     UNITTEST_ASSERT(reply->mhdr->datalen == len);
330     UNITTEST_ASSERT(reply->mhdr->ipc_flags == 0);
331     UNITTEST_ASSERT(reply->mhdr->op == query_reply_op);
332
333     UNITTEST_ASSERT(reply->rhdr->flags != htonl(kDNSServiceFlagsAdd));
334     UNITTEST_ASSERT(reply->rhdr->ifi == kDNSServiceInterfaceIndexAny);
335     UNITTEST_ASSERT(reply->rhdr->error == kDNSServiceErr_NoError);
336
337     UNITTEST_ASSERT(rrtype == kDNSType_A);
338     UNITTEST_ASSERT(rrclass == kDNSClass_IN);
339         UNITTEST_ASSERT(rdata[0] == dns_response_ipv4.b[0]);
340         UNITTEST_ASSERT(rdata[1] == dns_response_ipv4.b[1]);
341         UNITTEST_ASSERT(rdata[2] == dns_response_ipv4.b[2]);
342         UNITTEST_ASSERT(rdata[3] == dns_response_ipv4.b[3]);
343
344 UNITTEST_FOOTER
345
346 // This function does memory cleanup and no verification.
347 UNITTEST_HEADER(FinalizeUnitTest)
348     mDNS *m = &mDNSStorage;
349     request_state* req = client_request_message;
350     DNSServer   *ptr, **p = &m->DNSServers;
351
352     while (req->replies)
353     {
354         reply_state *reply = req->replies;
355         req->replies = req->replies->next;
356                 mDNSPlatformMemFree(reply);
357     }
358     mDNSPlatformMemFree(req);
359
360     mDNSPlatformMemFree(local_socket);
361
362     while (*p)
363     {
364         ptr = *p;
365         *p = (*p)->next;
366         LogInfo("FinalizeUnitTest: Deleting server %p %#a:%d (%##s)", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c);
367         mDNSPlatformMemFree(ptr);
368     }
369 UNITTEST_FOOTER
370
371 // The mDNS_AddDNSServer function adds a dns server to mDNSResponder's list.
372 mDNSlocal mStatus AddDNSServer(void)
373 {
374     mDNS *m = &mDNSStorage;
375     m->timenow = 0;
376     mDNS_Lock(m);
377     domainname  d;
378     mDNSAddr    addr;
379     mDNSIPPort  port;
380     mDNSs32             serviceID               = 0;
381     mDNSu32             scoped                  = 0;
382     mDNSu32             timeout                 = dns_server_timeout;
383     mDNSBool    cellIntf                = 0;
384     mDNSBool    isExpensive             = 0;
385     mDNSu16             resGroupID              = dns_server_resGroupID;
386     mDNSBool    reqA                    = mDNStrue;
387     mDNSBool    reqAAAA                 = mDNStrue;
388     mDNSBool    reqDO                   = mDNSfalse;
389     d.c[0]                                              = 0;
390     addr.type                                   = mDNSAddrType_IPv4;
391     addr.ip.v4.NotAnInteger             = dns_server_ipv4.NotAnInteger;
392     port.NotAnInteger                   = client_resp_src_port;
393         mDNS_AddDNSServer(m, &d, primary_interfaceID, serviceID, &addr, port, scoped, timeout,
394                       cellIntf, isExpensive, resGroupID,
395                                           reqA, reqAAAA, reqDO);
396         mDNS_Unlock(m);
397         return mStatus_NoError;
398 }
399
400