diff options
Diffstat (limited to 'mDNSResponder/unittests/unittest_common.c')
-rw-r--r-- | mDNSResponder/unittests/unittest_common.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/mDNSResponder/unittests/unittest_common.c b/mDNSResponder/unittests/unittest_common.c new file mode 100644 index 00000000..39718059 --- /dev/null +++ b/mDNSResponder/unittests/unittest_common.c @@ -0,0 +1,157 @@ +#include "unittest_common.h" +#include "dns_sd.h" +#include "mDNSEmbeddedAPI.h" +#include "mDNSMacOSX.h" + +static mDNS_PlatformSupport PlatformStorage; +#define RR_CACHE_SIZE ((32*1024) / sizeof(CacheRecord)) +static CacheEntity gRrcachestorage[RR_CACHE_SIZE]; + +// Primary interface info that is used when simulating the receive of the response packet +mDNSInterfaceID primary_interfaceID; +mDNSAddr primary_v4; +mDNSAddr primary_v6; +mDNSAddr primary_router; + +// This function sets up the minimum environement to run a unit test. It +// initializes logging, interfaces, and timenow. +mDNSexport mStatus init_mdns_environment(mDNSBool enableLogging) +{ + mDNS *m = &mDNSStorage; + + init_logging_ut(); + mDNS_LoggingEnabled = enableLogging; + mDNS_PacketLoggingEnabled = enableLogging; + + mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL); + if (result != mStatus_NoError) + return result; + + primary_v4 = primary_v6 = primary_router = zeroAddr; + SetInterfaces_ut(&primary_interfaceID, &primary_v4, &primary_v6, &primary_router); + + m->timenow = mDNS_TimeNow_NoLock(m); + return mStatus_NoError; +} + +// This function sets up the minimum environement to run a unit test. It +// initializes logging and timenow. This is the call to use if your +// unit test does not use interfaces. +mDNSexport mStatus init_mdns_storage() +{ + mDNS *m = &mDNSStorage; + + init_logging_ut(); + mDNS_LoggingEnabled = 1; + mDNS_PacketLoggingEnabled = 1; + + mStatus result = mDNS_InitStorage_ut(m, &PlatformStorage, gRrcachestorage, RR_CACHE_SIZE, mDNSfalse, mDNSNULL, mDNSNULL); + if (result != mStatus_NoError) + return result; + + return mStatus_NoError; +} + +mDNSlocal void init_client_request(request_state* req, char *msgbuf, size_t msgSize, uint32_t op) +{ + // Simulate read_msg behavior since unit test does not open a socket + memset(req, 0, sizeof(request_state)); + + req->ts = t_complete; + req->msgbuf = mDNSNULL; + req->msgptr = msgbuf; + req->msgend = msgbuf + msgSize; + + // The rest of the request values are set in order to simulate a request + req->sd = client_req_sd; + req->uid = client_req_uid; + req->hdr_bytes = client_req_hdr_bytes; + req->hdr.version = client_req_hdr_version; + req->hdr.op = op; // query_request + req->hdr.datalen = msgSize; + req->data_bytes = msgSize; + req->process_id = client_req_process_id; + memcpy(req->pid_name, client_req_pid_name, strlen(client_req_pid_name)); +} + +// This function calls the mDNSResponder handle_client_request() API. It initializes +// the request and query data structures. +mDNSexport mStatus start_client_request(request_state* req, char *msgbuf, size_t msgsz, uint32_t op, UDPSocket* socket) +{ + // Process the unit test's client request + init_client_request(req, msgbuf, msgsz, op); + + mStatus result = handle_client_request_ut((void*)req); + DNSQuestion* q = &req->u.queryrecord.q; + q->LocalSocket = socket; + return result; +} + +// This function calls the mDNSResponder mDNSCoreReceive() API. +mDNSexport void receive_response(const request_state* req, DNSMessage *msg, size_t msgSize) +{ + mDNS *m = &mDNSStorage; + mDNSAddr srcaddr; + mDNSIPPort srcport, dstport; + const mDNSu8 * end; + DNSQuestion *q = (DNSQuestion *)&req->u.queryrecord.q; + UInt8* data = (UInt8*)msg; + + // Used same values for DNS server as specified during init of unit test + srcaddr.type = mDNSAddrType_IPv4; + srcaddr.ip.v4.NotAnInteger = dns_server_ipv4.NotAnInteger; + srcport.NotAnInteger = client_resp_src_port; + + // Used random value for dstport + dstport.NotAnInteger = swap16((mDNSu16)client_resp_dst_port); + + // Set DNS message (that was copied from a WireShark packet) + end = (const mDNSu8 *)msg + msgSize; + + // Set socket info that mDNSCoreReceive uses to verify socket context + q->LocalSocket->ss.port.NotAnInteger = swap16((mDNSu16)client_resp_dst_port); + q->TargetQID.b[0] = data[0]; + q->TargetQID.b[1] = data[1]; + + // Execute mDNSCoreReceive which copies two DNS records into the cache + mDNSCoreReceive(m, msg, end, &srcaddr, srcport, &primary_v4, dstport, primary_interfaceID); +} + +mDNSexport size_t get_reply_len(char* name, uint16_t rdlen) +{ + size_t len = sizeof(DNSServiceFlags); + len += sizeof(mDNSu32); // interface index + len += sizeof(DNSServiceErrorType); + len += strlen(name) + 1; + len += 3 * sizeof(mDNSu16); // type, class, rdlen + len += rdlen; + len += sizeof(mDNSu32); // TTL + return len; +} + + +void free_req(request_state* req) +{ + // Cleanup request's memory usage + while (req->replies) + { + reply_state *reply = req->replies; + req->replies = req->replies->next; + mDNSPlatformMemFree(reply); + } + req->replies = NULL; + mDNSPlatformMemFree(req); +} + +// Unit test support functions follow +#define SA_LEN(addr) (((addr)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) + +mDNSexport void get_ip(const char *const name, struct sockaddr_storage *result) +{ + struct addrinfo* aiList; + int err = getaddrinfo(name, NULL, NULL, &aiList); + if (err) fprintf(stderr, "getaddrinfo error %d for %s", err, name); + else memcpy(result, aiList->ai_addr, SA_LEN(aiList->ai_addr)); + if (aiList) freeaddrinfo(aiList); +} + |