// This function should be used only if you know that the question and
// the resource record belongs to the same set. The main usage is
// in ProcessQuery where we find the question to be part of the same
// set as the resource record, but it needs the AnonData to be
// initialized so that it can walk the cache records to see if they
// answer the question.
mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
{
    if (!q->AnonInfo || !rr->AnonInfo)
    {
        LogMsg("SetAnonData: question %##s(%p), rr %##s(%p), NULL", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
        return;
    }
    
    debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
    if (ForQuestion)
    {
        if (!q->AnonInfo->AnonData)
        {
            q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen);
            if (!q->AnonInfo->AnonData)
                return;
        }
        mDNSPlatformMemCopy(q->AnonInfo->AnonData, rr->AnonInfo->AnonData, rr->AnonInfo->AnonDataLen);
        q->AnonInfo->AnonDataLen = rr->AnonInfo->AnonDataLen;
    }
    else
    {
        if (!rr->AnonInfo->AnonData)
        {
            rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen);
            if (!rr->AnonInfo->AnonData)
                return;
        }
        mDNSPlatformMemCopy(rr->AnonInfo->AnonData, q->AnonInfo->AnonData, q->AnonInfo->AnonDataLen);
        rr->AnonInfo->AnonDataLen = q->AnonInfo->AnonDataLen;
    }
}
Example #2
0
static void DNSSD_API DNSServiceGetAddrInfoResponse(
    DNSServiceRef inRef,
    DNSServiceFlags inFlags,
    uint32_t inInterfaceIndex,
    DNSServiceErrorType inErrorCode,
    const char *        inFullName,
    uint16_t inRRType,
    uint16_t inRRClass,
    uint16_t inRDLen,
    const void *        inRData,
    uint32_t inTTL,
    void *              inContext )
{
    mDNS_DirectOP_GetAddrInfo *     x = (mDNS_DirectOP_GetAddrInfo*)inContext;
    struct sockaddr_in sa4;

    mDNSPlatformMemZero(&sa4, sizeof(sa4));
    if (inErrorCode == kDNSServiceErr_NoError && inRRType == kDNSServiceType_A)
    {
        sa4.sin_family = AF_INET;
        mDNSPlatformMemCopy(&sa4.sin_addr.s_addr, inRData, 4);
    }

    x->callback((DNSServiceRef)x, inFlags, inInterfaceIndex, inErrorCode, inFullName,
                (const struct sockaddr *) &sa4, inTTL, x->context);
}
// When a service is started or a browse is started with the Anonymous data, we allocate a new random
// number and based on that allocate a new NSEC3 resource record whose hash is a function of random number (salt) and
// the anonymous data.
//
// If we receive a packet with the NSEC3 option, we need to cache that along with the resource record so that we can
// check against the question to see whether it answers them or not. In that case, we pass the "rr" that we received.
mDNSexport  AnonymousInfo *AllocateAnonInfo(const domainname *service, const mDNSu8 *data, int len, const ResourceRecord *rr)
{
    AnonymousInfo *ai;
    ai = (AnonymousInfo *)mDNSPlatformMemAllocate(sizeof(AnonymousInfo));
    if (!ai)
    {
        return mDNSNULL;
    }
    mDNSPlatformMemZero(ai, sizeof(AnonymousInfo));
    if (rr)
    {
        if (!CopyNSEC3ResourceRecord(ai, rr))
        {
            mDNSPlatformMemFree(ai);
            return mDNSNULL;
        }
        return ai;
    }
    ai->salt = mDNSRandom(0xFFFFFFFF);
    ai->AnonData = mDNSPlatformMemAllocate(len);
    if (!ai->AnonData)
    {
        mDNSPlatformMemFree(ai);
        return mDNSNULL;
    }
    ai->AnonDataLen = len;
    mDNSPlatformMemCopy(ai->AnonData, data, len);
    ai->nsec3RR = ConstructNSEC3Record(service, data, len, ai->salt);
    if (!ai->nsec3RR)
    {
        mDNSPlatformMemFree(ai);
        return mDNSNULL;
    }
    return ai;
}
mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr)
{
    int len;
    domainname *name;
    ResourceRecord *nsec3rr;

    if (rr->rdlength < MCAST_NSEC3_RDLENGTH)
    {
        LogMsg("CopyNSEC3ResourceRecord: rdlength %d smaller than MCAST_NSEC3_RDLENGTH %d", rr->rdlength, MCAST_NSEC3_RDLENGTH);
        return mDNSNULL;
    }
    // Allocate space for the name and the rdata along with the ResourceRecord
    len = DomainNameLength(rr->name);
    nsec3rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + len + sizeof(RData));
    if (!nsec3rr)
        return mDNSNULL;

    *nsec3rr = *rr;
    name = (domainname *)((mDNSu8 *)nsec3rr + sizeof(ResourceRecord));
    nsec3rr->name = (const domainname *)name;
    AssignDomainName(name, rr->name);

    nsec3rr->rdata = (RData *)((mDNSu8 *)nsec3rr->name + len);
    mDNSPlatformMemCopy(nsec3rr->rdata->u.data, rr->rdata->u.data, rr->rdlength);

    si->nsec3RR = nsec3rr;

    return nsec3rr;
}
mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt)
{
    const mDNSu8 *ptr;
    rdataNSEC3 *nsec3 = (rdataNSEC3 *)rr->rdata->u.data;
    mDNSu8 *tmp, *nxt;
    unsigned short iter = ANON_NSEC3_ITERATIONS;
    int hlen;
    const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];

    // Construct the RDATA first and construct the owner name based on that.
    ptr = (const mDNSu8 *)&salt;
    debugf("InitializeNSEC3Record: %x%x%x%x, name %##s", ptr[0], ptr[1], ptr[2], ptr[3], rr->name->c);

    // Set the RDATA
    nsec3->alg = SHA1_DIGEST_TYPE;
    nsec3->flags = 0;
    nsec3->iterations = swap16(iter);
    nsec3->saltLength = 4;
    tmp = (mDNSu8 *)&nsec3->salt;
    *tmp++ = ptr[0];
    *tmp++ = ptr[1];
    *tmp++ = ptr[2];
    *tmp++ = ptr[3];

    // hashLength, nxt, bitmap
    *tmp++ = SHA1_HASH_LENGTH;    // hash length
    nxt = tmp;
    tmp += SHA1_HASH_LENGTH;
    *tmp++ = 0; // window number
    *tmp++ = NSEC_MCAST_WINDOW_SIZE; // window length
    mDNSPlatformMemZero(tmp, NSEC_MCAST_WINDOW_SIZE);
    tmp[kDNSType_PTR >> 3] |= 128 >> (kDNSType_PTR & 7);

    // Hash the base service name + salt + AnonData
    if (!NSEC3HashName(rr->name, nsec3, AnonData, len, hashName, &hlen))
    {
        LogMsg("InitializeNSEC3Record: NSEC3HashName failed for ##s", rr->name->c);
        return mDNSfalse;
    }
    if (hlen != SHA1_HASH_LENGTH)
    {
        LogMsg("InitializeNSEC3Record: hlen wrong %d", hlen);
        return mDNSfalse;
    }
    mDNSPlatformMemCopy(nxt, hashName, hlen);

    return mDNStrue;
}
Example #6
0
mDNSexport int main(int argc, char **argv)
{
    const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
    int this_arg = 1;
    mStatus status;
    struct in_addr s4;
#if HAVE_IPV6
    struct in6_addr s6;
#endif
    char buffer[256];
    DNSQuestion q;

    if (argc < 2) goto usage;

    // Since this is a special command-line tool, we want LogMsg() errors to go to stderr, not syslog
    mDNS_DebugMode = mDNStrue;

    // Initialise the mDNS core.
    status = mDNS_Init(&mDNSStorage, &PlatformStorage,
                       gRRCache, RR_CACHE_SIZE,
                       mDNS_Init_DontAdvertiseLocalAddresses,
                       mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
    if (status) { fprintf(stderr, "Daemon start: mDNS_Init failed %d\n", (int)status); return(status); }

    signal(SIGINT, HandleSIG);  // SIGINT is what you get for a Ctrl-C
    signal(SIGTERM, HandleSIG);

    while (this_arg < argc)
    {
        char *arg = argv[this_arg++];
        if (this_arg > 2) printf("\n");

        lastid = id = zeroID;
        hostaddr = target = zeroAddr;
        hostname[0] = hardware[0] = software[0] = 0;
        NumAddr = NumAAAA = NumHINFO = 0;

        if (inet_pton(AF_INET, arg, &s4) == 1)
        {
            mDNSu8 *p = (mDNSu8 *)&s4;
            // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code
            mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", p[3], p[2], p[1], p[0]);
            printf("%s\n", buffer);
            target.type = mDNSAddrType_IPv4;
            target.ip.v4.NotAnInteger = s4.s_addr;
            DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
            if (StopNow == 2) break;
        }
#if HAVE_IPV6
        else if (inet_pton(AF_INET6, arg, &s6) == 1)
        {
            int i;
            mDNSu8 *p = (mDNSu8 *)&s6;
            for (i = 0; i < 16; i++)
            {
                static const char hexValues[] = "0123456789ABCDEF";
                buffer[i * 4    ] = hexValues[p[15-i] & 0x0F];
                buffer[i * 4 + 1] = '.';
                buffer[i * 4 + 2] = hexValues[p[15-i] >> 4];
                buffer[i * 4 + 3] = '.';
            }
            mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa.");
            target.type = mDNSAddrType_IPv6;
            mDNSPlatformMemCopy(&target.ip.v6, &s6, sizeof(target.ip.v6));
            DoQuery(&q, buffer, kDNSType_PTR, &target, NameCallback);
            if (StopNow == 2) break;
        }
#endif
        else
        {
            if (strlen(arg) >= sizeof(hostname))