Home | History | Annotate | Line # | Download | only in unittests
      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(void)
     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, const uint8_t *msgbuf, uint32_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, const uint8_t *msgbuf, uint32_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->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->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  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 // The AddDNSServer_ut function adds a dns server to mDNSResponder's list.
    159 mDNSexport mStatus AddDNSServerScoped_ut(mDNSInterfaceID interfaceID, ScopeType scoped)
    160 {
    161     mDNS *m = &mDNSStorage;
    162     m->timenow = 0;
    163     mDNS_Lock(m);
    164     domainname  d;
    165     mDNSAddr    addr;
    166     mDNSIPPort  port;
    167     mDNSs32     serviceID      = 0;
    168     mDNSu32     timeout        = dns_server_timeout;
    169     mDNSBool    cellIntf       = 0;
    170     mDNSBool    isExpensive    = 0;
    171     mDNSBool    isConstrained  = 0;
    172     mDNSBool    isCLAT46       = mDNSfalse;
    173     mDNSu32     resGroupID     = dns_server_resGroupID;
    174     mDNSBool    reqA           = mDNStrue;
    175     mDNSBool    reqAAAA        = mDNStrue;
    176     mDNSBool    reqDO          = mDNSfalse;
    177     d.c[0]                     = 0;
    178     addr.type                  = mDNSAddrType_IPv4;
    179     addr.ip.v4.NotAnInteger    = dns_server_ipv4.NotAnInteger;
    180     port.NotAnInteger          = client_resp_src_port;
    181     mDNS_AddDNSServer(m, &d, interfaceID, serviceID, &addr, port, scoped, timeout,
    182                       cellIntf, isExpensive, isConstrained, isCLAT46, resGroupID,
    183                       reqA, reqAAAA, reqDO);
    184     mDNS_Unlock(m);
    185     return mStatus_NoError;
    186 }
    187 
    188 mDNSexport mStatus AddDNSServer_ut(void)
    189 {
    190     return AddDNSServerScoped_ut(primary_interfaceID, kScopeNone);
    191 }
    192 
    193 mDNSexport mStatus  force_uDNS_SetupDNSConfig_ut(mDNS *const m)
    194 {
    195     m->p->LastConfigGeneration = 0;
    196     return uDNS_SetupDNSConfig(m);
    197 }
    198 
    199 mDNSexport mStatus verify_cache_addr_order_for_domain_ut(mDNS *const m, mDNSu8* octet, mDNSu32 count, const domainname *const name)
    200 {
    201     mStatus result = mStatus_NoError;
    202     const CacheGroup *cg = CacheGroupForName(m, DomainNameHashValue(name), name);
    203     if (cg)
    204     {
    205         mDNSu32 i;
    206         CacheRecord **rp = (CacheRecord **)&cg->members;
    207         for (i = 0 ; *rp && i < count ; i++ )
    208         {
    209             if ((*rp)->resrec.rdata->u.ipv4.b[3] != octet[i])
    210             {
    211                 LogInfo ("Octet %d compare failed %d != %d", i, (*rp)->resrec.rdata->u.ipv4.b[3], octet[i]);
    212                 break;
    213             }
    214             rp = &(*rp)->next;
    215         }
    216         if (i != count) result = mStatus_Invalid;
    217     }
    218     else
    219     {
    220         LogInfo ("Cache group not found");
    221         result = mStatus_Invalid;
    222     }
    223 
    224     return result;
    225 }
    226