// RegisterService() is a simple wrapper function which takes C string // parameters, converts them to domainname parameters, and calls mDNS_RegisterService() mDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset, const char name[], const char type[], const char domain[], const domainname *host, mDNSu16 PortAsNumber, int argc, char **argv) { domainlabel n; domainname t, d; unsigned char txtbuffer[1024], *bptr = txtbuffer; char buffer[MAX_ESCAPED_DOMAIN_NAME]; MakeDomainLabelFromLiteralString(&n, name); MakeDomainNameFromDNSNameString(&t, type); MakeDomainNameFromDNSNameString(&d, domain); while (argc) { int len = strlen(argv[0]); if (len > 255 || bptr + 1 + len >= txtbuffer + sizeof(txtbuffer)) break; printf("STR: %s\n", argv[0]); bptr[0] = len; strcpy((char*)(bptr+1), argv[0]); bptr += 1 + len; argc--; argv++; } mDNS_RegisterService(m, recordset, &n, &t, &d, // Name, type, domain host, mDNSOpaque16fromIntVal(PortAsNumber), txtbuffer, bptr-txtbuffer, // TXT data, length mDNSNULL, 0, // Subtypes mDNSInterface_Any, // Interface ID ServiceCallback, mDNSNULL, 0); // Callback, context, flags ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer); printf("Made Service Records for %s\n", buffer); }
// RegisterService() is a simple wrapper function which takes C string // parameters, converts them to domainname parameters, and calls mDNS_RegisterService() mDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset, UInt16 PortAsNumber, const char txtinfo[], const domainlabel *const n, const char type[], const char domain[]) { domainname t; domainname d; char buffer[MAX_ESCAPED_DOMAIN_NAME]; UInt8 txtbuffer[512]; MakeDomainNameFromDNSNameString(&t, type); MakeDomainNameFromDNSNameString(&d, domain); if (txtinfo) { strncpy((char*)txtbuffer+1, txtinfo, sizeof(txtbuffer)-1); txtbuffer[0] = (UInt8)strlen(txtinfo); } else txtbuffer[0] = 0; mDNS_RegisterService(m, recordset, n, &t, &d, // Name, type, domain mDNSNULL, mDNSOpaque16fromIntVal(PortAsNumber), txtbuffer, (mDNSu16)(1+txtbuffer[0]), // TXT data, length mDNSNULL, 0, // Subtypes (none) mDNSInterface_Any, // Interface ID Callback, mDNSNULL); // Callback and context ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer); printf("Made Service Records for %s\n", buffer); }
static mStatus RegisterOneService(const char * richTextHostName, const char * serviceType, const char * serviceDomain, const mDNSu8 text[], mDNSu16 textLen, long portNumber) { mStatus status; PosixService * thisServ; mDNSOpaque16 port; domainlabel name; domainname type; domainname domain; status = mStatus_NoError; thisServ = (PosixService *) malloc(sizeof(*thisServ)); if (thisServ == NULL) { status = mStatus_NoMemoryErr; } if (status == mStatus_NoError) { MakeDomainLabelFromLiteralString(&name, richTextHostName); MakeDomainNameFromDNSNameString(&type, serviceType); MakeDomainNameFromDNSNameString(&domain, serviceDomain); port.b[0] = (portNumber >> 8) & 0x0FF; port.b[1] = (portNumber >> 0) & 0x0FF;; status = mDNS_RegisterService(&mDNSStorage, &thisServ->coreServ, &name, &type, &domain, NULL, port, text, textLen, NULL, 0, mDNSInterface_Any, RegistrationCallback, thisServ); }
static mStatus RegisterOneService(const char * richTextName, const char * serviceType, const char * serviceDomain, const mDNSu8 text[], mDNSu16 textLen, long portNumber) { mStatus status; PosixService * thisServ; domainlabel name; domainname type; domainname domain; status = mStatus_NoError; thisServ = (PosixService *) malloc(sizeof(*thisServ)); if (thisServ == NULL) { status = mStatus_NoMemoryErr; } if (status == mStatus_NoError) { MakeDomainLabelFromLiteralString(&name, richTextName); MakeDomainNameFromDNSNameString(&type, serviceType); MakeDomainNameFromDNSNameString(&domain, serviceDomain); status = mDNS_RegisterService(&mDNSStorage, &thisServ->coreServ, &name, &type, &domain, // Name, type, domain NULL, mDNSOpaque16fromIntVal(portNumber), text, textLen, // TXT data, length NULL, 0, // Subtypes mDNSInterface_Any, // Interface ID RegistrationCallback, thisServ); // Callback and context } if (status == mStatus_NoError) { thisServ->serviceID = gServiceID; gServiceID += 1; thisServ->next = gServiceList; gServiceList = thisServ; if (gMDNSPlatformPosixVerboseLevel > 0) { fprintf(stderr, "%s: Registered service %d, name '%s', type '%s', port %ld\n", gProgramName, thisServ->serviceID, richTextName, serviceType, portNumber); } } else { if (thisServ != NULL) { free(thisServ); } } return status; }
mDNSlocal void RegisterNoSuchService(mDNS *m, AuthRecord *const rr, domainname *proxyhostname, const char name[], const char type[], const char domain[]) { domainlabel n; domainname t, d; char buffer[MAX_ESCAPED_DOMAIN_NAME]; MakeDomainLabelFromLiteralString(&n, name); MakeDomainNameFromDNSNameString(&t, type); MakeDomainNameFromDNSNameString(&d, domain); mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, proxyhostname, 0); ConvertDomainNameToCString(rr->resrec.name, buffer); printf("Made Non-existence Record for %s\n", buffer); }
mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const filename, domainname *const hostname, domainname *const domain, mDNSBool *DomainDiscoveryDisabled) { char buf[MAX_ESCAPED_DOMAIN_NAME] = ""; char knn[MAX_ESCAPED_DOMAIN_NAME] = ""; domainname keyName; mDNSIPPort port; keyName.c[0] = knn[0] = 0; mStatus err; FILE *f = fopen(filename, "r"); if (hostname) hostname->c[0] = 0; if (domain) domain->c[0] = 0; if (DomainDiscoveryDisabled) *DomainDiscoveryDisabled = mDNSfalse; port = UnicastDNSPort; if (f) { if (DomainDiscoveryDisabled && GetConfigOption(buf, "DomainDiscoveryDisabled", f) && !strcasecmp(buf, "true")) *DomainDiscoveryDisabled = mDNStrue; if (hostname && GetConfigOption(buf, "hostname", f) && !MakeDomainNameFromDNSNameString(hostname, buf)) goto badf; if (domain && GetConfigOption(buf, "zone", f) && !MakeDomainNameFromDNSNameString(domain, buf)) goto badf; if (GetConfigOption(buf, "port", f)) { port = mDNSOpaque16fromIntVal(strtol(buf, (char **)NULL, 10)); } buf[0] = 0; GetConfigOption(buf, "secret-64", f); // failure means no authentication if (GetConfigOption(knn, "secret-name", f)) MakeDomainNameFromDNSNameString(&keyName, knn); fclose(f); f = NULL; } else { if (errno != ENOENT) LogMsg("ERROR: Config file exists, but cannot be opened."); return; } if (domain && domain->c[0] && buf[0]) { DomainAuthInfo *info = (DomainAuthInfo*)mDNSPlatformMemAllocate(sizeof(*info)); // for now we assume keyname = service reg domain and we use same key for service and hostname registration err = mDNS_SetSecretForDomain(m, info, domain, (keyName.c[0] ? &keyName : domain), buf, hostname, &port, NULL); if (err) LogMsg("ERROR: mDNS_SetSecretForDomain returned %d for domain %##s", err, domain->c); } return; badf: LogMsg("ERROR: malformatted config file"); if (f) fclose(f); }
int main(int argc, char **argv) // The program's main entry point. The program does a trivial // mDNS query, looking for all AFP servers in the local domain. { int result; mStatus status; DNSQuestion question; domainname type; domainname domain; // Parse our command line arguments. This won't come back if there's an error. ParseArguments(argc, argv); // Initialise the mDNS core. status = mDNS_Init(&mDNSStorage, &PlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); if (status == mStatus_NoError) { // Construct and start the query. MakeDomainNameFromDNSNameString(&type, gServiceType); MakeDomainNameFromDNSNameString(&domain, gServiceDomain); status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, BrowseCallback, NULL); // Run the platform main event loop until the user types ^C. // The BrowseCallback routine is responsible for printing // any results that we find. if (status == mStatus_NoError) { fprintf(stderr, "Hit ^C when you're bored waiting for responses.\n"); ExampleClientEventLoop(&mDNSStorage); mDNS_StopQuery(&mDNSStorage, &question); mDNS_Close(&mDNSStorage); } } if (status == mStatus_NoError) { result = 0; } else { result = 2; } if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) { fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result); } return 0; }
static void foobar_register(DNSQuestion *question) { mStatus status; domainname type; domainname domain; MakeDomainNameFromDNSNameString(&type, "_foobar._tcp"); MakeDomainNameFromDNSNameString(&domain, "local."); status = mDNS_StartBrowse(&mDNSStorage, question, &type, &domain, mDNSNULL, mDNSInterface_Any, 0, mDNSfalse, mDNSfalse, foobar_browse, NULL); assert(status == mStatus_NoError); }
mDNSlocal mStatus mDNS_RegisterProxyHost(mDNS *m, ProxyHost *p) { char buffer[32]; mDNS_SetupResourceRecord(&p->RR_A, mDNSNULL, mDNSInterface_Any, kDNSType_A, 60, kDNSRecordTypeUnique, AuthRecordAny, HostNameCallback, p); mDNS_SetupResourceRecord(&p->RR_PTR, mDNSNULL, mDNSInterface_Any, kDNSType_PTR, 60, kDNSRecordTypeKnownUnique, AuthRecordAny, HostNameCallback, p); p->RR_A.namestorage.c[0] = 0; AppendDomainLabel(&p->RR_A.namestorage, &p->hostlabel); AppendLiteralLabelString(&p->RR_A.namestorage, "local"); // 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->ip.b[3], p->ip.b[2], p->ip.b[1], p->ip.b[0]); MakeDomainNameFromDNSNameString(&p->RR_PTR.namestorage, buffer); p->RR_PTR.ForceMCast = mDNStrue; // This PTR points to our dot-local name, so don't ever try to write it into a uDNS server p->RR_A.resrec.rdata->u.ipv4 = p->ip; AssignDomainName(&p->RR_PTR.resrec.rdata->u.name, p->RR_A.resrec.name); mDNS_Register(m, &p->RR_A); mDNS_Register(m, &p->RR_PTR); debugf("Made Proxy Host Records for %##s", p->RR_A.resrec.name->c); return(mStatus_NoError); }
mDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const mDNSAddr *target, mDNSQuestionCallback callback) { lastsrc = zeroAddr; if (qname) MakeDomainNameFromDNSNameString(&q->qname, qname); q->InterfaceID = mDNSInterface_Any; q->flags = 0; q->Target = target ? *target : zeroAddr; q->TargetPort = MulticastDNSPort; q->TargetQID = zeroID; q->qtype = qtype; q->qclass = kDNSClass_IN; q->LongLived = mDNSfalse; q->ExpectUnique = mDNSfalse; // Don't want to stop after the first response packet q->ForceMCast = mDNStrue; // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa. q->ReturnIntermed = mDNStrue; q->SuppressUnusable = mDNSfalse; q->SearchListIndex = 0; q->AppendSearchDomains = 0; q->RetryWithSearchDomains = mDNSfalse; q->TimeoutQuestion = 0; q->ValidationRequired = 0; q->ValidatingResponse = 0; q->WakeOnResolve = 0; q->UseBackgroundTrafficClass = mDNSfalse; q->ProxyQuestion = 0; q->qnameOrig = mDNSNULL; q->AnonInfo = mDNSNULL; q->pid = mDNSPlatformGetPID(); q->QuestionCallback = callback; q->QuestionContext = NULL; //mprintf("%##s %s ?\n", q->qname.c, DNSTypeName(qtype)); return(mDNS_StartQuery(&mDNSStorage, q)); }
DNSServiceErrorType DNSServiceBrowse ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *regtype, const char *domain, /* may be NULL */ DNSServiceBrowseReply callback, void *context /* may be NULL */ ) { mStatus err = mStatus_NoError; const char *errormsg = "Unknown"; domainname t, d; mDNS_DirectOP_Browse *x; (void)flags; // Unused (void)interfaceIndex; // Unused // Check parameters if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; } if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Illegal domain"; goto badparam; } // Allocate memory, and handle failure x = (mDNS_DirectOP_Browse *)mDNSPlatformMemAllocate(sizeof(*x)); if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } // Set up object x->disposefn = DNSServiceBrowseDispose; x->callback = callback; x->context = context; x->q.QuestionContext = x; // Do the operation err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, (flags & kDNSServiceFlagsForceMulticast) != 0, FoundInstance, x); if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_StartBrowse"; goto fail; } // Succeeded: Wrap up and return *sdRef = (DNSServiceRef)x; return(mStatus_NoError); badparam: err = mStatus_BadParamErr; fail: LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err); return(err); }
DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *fullname, uint16_t rrtype, uint16_t rrclass, DNSServiceQueryRecordReply callback, void *context /* may be NULL */ ) { mStatus err = mStatus_NoError; const char *errormsg = "Unknown"; mDNS_DirectOP_QueryRecord *x; (void)flags; // Unused (void)interfaceIndex; // Unused // Allocate memory, and handle failure x = (mDNS_DirectOP_QueryRecord *)mDNSPlatformMemAllocate(sizeof(*x)); if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } // Set up object x->disposefn = DNSServiceQueryRecordDispose; x->callback = callback; x->context = context; x->q.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question x->q.InterfaceID = mDNSInterface_Any; x->q.Target = zeroAddr; MakeDomainNameFromDNSNameString(&x->q.qname, fullname); x->q.qtype = rrtype; x->q.qclass = rrclass; x->q.LongLived = (flags & kDNSServiceFlagsLongLivedQuery) != 0; x->q.ExpectUnique = mDNSfalse; x->q.ForceMCast = (flags & kDNSServiceFlagsForceMulticast) != 0; x->q.ReturnIntermed = (flags & kDNSServiceFlagsReturnIntermediates) != 0; x->q.SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable) != 0; x->q.SearchListIndex = 0; x->q.AppendSearchDomains = 0; x->q.RetryWithSearchDomains = mDNSfalse; x->q.WakeOnResolve = 0; x->q.qnameOrig = mDNSNULL; x->q.QuestionCallback = DNSServiceQueryRecordResponse; x->q.QuestionContext = x; err = mDNS_StartQuery(&mDNSStorage, &x->q); if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery"; goto fail; } // Succeeded: Wrap up and return *sdRef = (DNSServiceRef)x; return(mStatus_NoError); fail: LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err); return(err); }
mDNSlocal OSStatus mDNSResponderSetAvail(mDNS *m, AuthRecord *rr, ServiceRecordSet *sr) { // 1. Initialize required fields of AuthRecord // 2. Set name of subtype PTR record to our special subtype name denoting "available" instances // 3. Set target of subtype PTR record to point to our SRV record (exactly the same as the main service PTR record) // 4. And register it mDNS_SetupResourceRecord(rr, mDNSNULL, mDNSInterface_Any, kDNSType_PTR, 2*3600, kDNSRecordTypeShared, AvailCallback, &availRec2Active); MakeDomainNameFromDNSNameString(rr->resrec.name, "a._sub._raop._tcp.local."); AssignDomainName(&rr->resrec.rdata->u.name, sr->RR_SRV.resrec.name); return(mDNS_Register(m, rr)); }
static ServiceRecordSet * foobar_register(mDNSu16 port) { ServiceRecordSet *srs; mStatus status; domainlabel name; domainname type; domainname domain; srs = calloc(1, sizeof(*srs)); assert(srs != NULL); MakeDomainLabelFromLiteralString(&name, "foobar"); MakeDomainNameFromDNSNameString(&type, "_foobar._tcp"); MakeDomainNameFromDNSNameString(&domain, "local."); status = mDNS_RegisterService(&mDNSStorage, srs, &name, &type, &domain, NULL, mDNSOpaque16fromIntVal(port), NULL, 0, NULL, 0, mDNSInterface_Any, foobar_callback, srs, 0); assert(status == mStatus_NoError); return srs; }
mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p) { AuthRecord *st = mDNSNULL; if (NumSubTypes) { mDNSs32 i; st = mDNSPlatformMemAllocate(NumSubTypes * sizeof(AuthRecord)); if (!st) return(mDNSNULL); for (i = 0; i < NumSubTypes; i++) { mDNS_SetupResourceRecord(&st[i], mDNSNULL, mDNSInterface_Any, kDNSQType_ANY, kStandardTTL, 0, AuthRecordAny, mDNSNULL, mDNSNULL); while (*p) p++; p++; if (!MakeDomainNameFromDNSNameString(&st[i].namestorage, p)) { mDNSPlatformMemFree(st); return(mDNSNULL); } } } return(st); }
// All the children are in a linked list // // <TrustAnchor> has two children: <Zone> and <KeyDigest> // <KeyDigest> has four children <KeyTag> <Algorithm> <DigestType> <Digest> // // Returns false if failed to parse the element i.e., malformed xml document. // Validity of the actual values itself is done outside the function. mDNSlocal mDNSBool ParseElementChildren(xmlDocPtr tadoc, xmlNode *node, TrustAnchor *ta) { xmlNode *cur_node; xmlChar *val1, *val2, *val; char *invalid = NULL; val = val1 = val2 = NULL; for (cur_node = node; cur_node; cur_node = cur_node->next) { invalid = NULL; val1 = val2 = NULL; val = xmlNodeListGetString(tadoc, cur_node->xmlChildrenNode, 1); if (!val) { LogInfo("ParseElementChildren: NULL value for %s", cur_node->name); continue; } if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Zone")) { // MaeDomainNameFromDNSNameString does not work for "." if (!xmlStrcmp(val, (const xmlChar *)".")) { ta->zone.c[0] = 0; } else if (!MakeDomainNameFromDNSNameString(&ta->zone, (char *)val)) { LogMsg("ParseElementChildren: Cannot parse Zone %s", val); goto error; } else { LogInfo("ParseElementChildren: Element %s, value %##s", cur_node->name, ta->zone.c); } } else if (!xmlStrcmp(cur_node->name, (const xmlChar *)"KeyTag")) { ta->rds.keyTag = strtol((const char *)val, &invalid, 10); if (*invalid != '\0') { LogMsg("ParseElementChildren: KeyTag invalid character %d", *invalid); goto error; } else { LogInfo("ParseElementChildren: Element %s, value %d", cur_node->name, ta->rds.keyTag); } } else if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Algorithm")) { ta->rds.alg = strtol((const char *)val, &invalid, 10); if (*invalid != '\0') { LogMsg("ParseElementChildren: Algorithm invalid character %c", *invalid); goto error; } else { LogInfo("ParseElementChildren: Element %s, value %d", cur_node->name, ta->rds.alg); } } else if (!xmlStrcmp(cur_node->name, (const xmlChar *)"DigestType")) { ta->rds.digestType = strtol((const char *)val, &invalid, 10); if (*invalid != '\0') { LogMsg("ParseElementChildren: Algorithm invalid character %c", *invalid); goto error; } else { LogInfo("ParseElementChildren: Element %s, value %d", cur_node->name, ta->rds.digestType); } } else if (!xmlStrcmp(cur_node->name, (const xmlChar *)"Digest")) { int diglen; mDNSu8 *dig = ConvertDigest((char *)val, ta->rds.digestType, &diglen); if (dig) { LogInfo("ParseElementChildren: Element %s, digest %s", cur_node->name, val); ta->digestLen = diglen; ta->rds.digest = dig; } else { LogMsg("ParseElementChildren: Element %s, NULL digest", cur_node->name); goto error; } } else if (!xmlStrcmp(cur_node->name, (const xmlChar *)"KeyDigest")) { struct tm tm; val1 = xmlGetProp(cur_node, (const xmlChar *)"validFrom"); if (val1) { char *s = strptime((const char *)val1, "%Y-%m-%dT%H:%M:%S", &tm); if (!s) { LogMsg("ParseElementChildren: Parsing ValidFrom failed %s", val1); goto error; } else { ta->validFrom = (mDNSu32)timegm(&tm); } } val2 = xmlGetProp(cur_node, (const xmlChar *)"validUntil"); if (val2) { char *s = strptime((const char *)val2, "%Y-%m-%dT%H:%M:%S", &tm); if (!s) { LogMsg("ParseElementChildren: Parsing ValidFrom failed %s", val2); goto error; } else { ta->validUntil = (mDNSu32)timegm(&tm); } } else { // If there is no validUntil, set it to the next probing interval mDNSu32 t = (mDNSu32) time(NULL); ta->validUntil = t + ROOT_TA_UPDATE_INTERVAL; } LogInfo("ParseElementChildren: ValidFrom time %u, validUntil %u", (unsigned)ta->validFrom, (unsigned)ta->validUntil); } if (val1) xmlFree(val1); if (val2) xmlFree(val2); if (val) xmlFree(val); } return mDNStrue; error: if (val1) xmlFree(val1); if (val2) xmlFree(val2); if (val) xmlFree(val); return mDNSfalse; }
int main() { mStatus err; Boolean DoneSetup = false; void *tempmem; SIOUXSettings.asktosaveonclose = false; SIOUXSettings.userwindowtitle = "\pMulticast DNS Searcher"; SIOUXSettings.rows = 40; SIOUXSettings.columns = 132; printf("Multicast DNS Searcher\n\n"); printf("This software reports errors using MacsBug breaks,\n"); printf("so if you don't have MacsBug installed your Mac may crash.\n\n"); printf("******************************************************************************\n"); err = InitOpenTransport(); if (err) { debugf("InitOpenTransport failed %d", err); return(err); } err = mDNS_Init(&mDNSStorage, &PlatformSupportStorage, rrcachestorage, RR_CACHE_SIZE, mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); if (err) return(err); // Make sure OT has a large enough memory pool for us to draw from at OTNotifier (interrupt) time tempmem = OTAllocMem(0x10000); if (tempmem) OTFreeMem(tempmem); else printf("**** Warning: OTAllocMem couldn't pre-allocate 64K for us.\n"); services.serviceinfolist.fHead = NULL; services.headerPrinted = false; services.lostRecords = false; while (!YieldSomeTime(35)) { #if MDNS_ONLYSYSTEMTASK // For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically. // For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle() extern void mDNSPlatformIdle(mDNS *const m); mDNSPlatformIdle(&mDNSStorage); // Only needed for debugging version #endif if (mDNSStorage.mDNSPlatformStatus == mStatus_NoError && !DoneSetup) { domainname srvtype, srvdom; DoneSetup = true; printf("\nSending mDNS service lookup queries and waiting for responses...\n\n"); MakeDomainNameFromDNSNameString(&srvtype, "_http._tcp."); MakeDomainNameFromDNSNameString(&srvdom, "local."); err = mDNS_StartBrowse(&mDNSStorage, &browsequestion, &srvtype, &srvdom, mDNSInterface_Any, mDNSfalse, FoundInstance, &services); if (err) break; err = mDNS_GetDomains(&mDNSStorage, &domainquestion, mDNS_DomainTypeBrowse, NULL, mDNSInterface_Any, FoundDomain, &services); if (err) break; } if (services.serviceinfolist.fHead) PrintServiceInfo(&services); if (services.lostRecords) { services.lostRecords = false; printf("**** Warning: Out of memory: Records have been missed.\n"); } } mDNS_StopBrowse(&mDNSStorage, &browsequestion); mDNS_Close(&mDNSStorage); return(0); }
int main(void) // The program's main entry point. The program does a trivial // mDNS query, looking for mDNS service & device in the local domain. { int result; mStatus status; DNSQuestion question; domainname type; domainname domain; char DeviceName[64]; // Initialise the mDNS core. status = mDNS_Init(&mDNSStorage, &PlatformStorage, gRRCache, RR_CACHE_SIZE, mDNS_Init_DontAdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext); if (status == mStatus_NoError) { #if 1 /* Query service type */ // Construct and start the query. MakeDomainNameFromDNSNameString(&type, gServiceType); MakeDomainNameFromDNSNameString(&domain, gServiceDomain); status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, BrowseCallback, NULL); //return; // Run the platform main event loop. // The BrowseCallback routine is responsible for printing // any results that we find. if (status == mStatus_NoError) { fprintf(stderr, "* Query: %s\n", gServiceType); EventLoop(&mDNSStorage); mDNS_StopQuery(&mDNSStorage, &question); //Parse all service type and query detail //fprintf(stderr, "===== Parse all service type and query detail...\n"); callback = 0; event = 0; StopNow = 0; } return 0; #endif #if 0 /* Query device name */ Service_tmp = Service_list; while(Service_tmp!=NULL) { printf("\n======= Queried Service: %s.%s\n", Service_tmp->service, Service_tmp->type); sprintf(Query_type, "%s.%s", Service_tmp->service, Service_tmp->type); //Device_found = Service_tmp->sup_device; gServiceType = Query_type; MakeDomainNameFromDNSNameString(&type, gServiceType); status = mDNS_StartBrowse(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, QueryCallback, NULL); if (status == mStatus_NoError) { EventLoop(&mDNSStorage); mDNS_StopQuery(&mDNSStorage, &question); } callback = 0; event = 0; StopNow = 0; Service_tmp = Service_tmp->next; } printf("===============\n\n"); #endif #if 0 /* Query IP of device */ DeviceIP_cur = Device_list; printf("%d,%d,%d ", callback, event, StopNow); printf("QUERY DEVICE: %s/%s\n", Device_cur->name, Device_cur->IPv4Addr); char *cc = Device_cur->IPv4Addr; int x =0; for(; x<16; x++) { printf("%",*cc); cc++; } printf("\n"); //if(DeviceIP_cur->IPv4Addr == NULL) if(!strcmp(DeviceIP_cur->IPv4Addr, "")) printf(" DeviceIP_cur->IPv4Addr == NULL\n"); while(DeviceIP_cur && (!strcmp(DeviceIP_cur->IPv4Addr, ""))) { memset(DeviceName, 0, 64); strcpy(DeviceName, DeviceIP_cur->name); HostnameParse(DeviceName); gServiceType = DeviceName; printf("Query IP of %s\n", gServiceType); // Construct and start the query. MakeDomainNameFromDNSNameString(&type, gServiceType); status = mDNS_GetAddrInfo(&mDNSStorage, &question, &type, &domain, mDNSInterface_Any, mDNSfalse, IPInfoCallback, NULL); if (status == mStatus_NoError) { EventLoop(&mDNSStorage); mDNS_StopQuery(&mDNSStorage, &question); } else { printf("Error= %ld\n", status); } DeviceIP_cur = DeviceIP_cur->next; callback = 0; event = 0; StopNow = 0; } printf("===============\n"); #endif int nvram_size, i = 0; char *nvram_info; char device_name_ascii[256], service_type_list[512]; struct mDNS_service_handler *handler; nvram_size = device_count*64 + service_count*4; nvram_info = malloc(nvram_size); memset(nvram_info, 0, nvram_size); printf("nvram_size= %d\n", nvram_size); //Print all info Service_tmp = Service_list; while(Service_tmp!=NULL) { printf("\n=== %s.%s ===\n", Service_tmp->service, Service_tmp->type); Service_tmp = Service_tmp->next; } printf("\n===== Print device ========\n"); Device_tmp = Device_list; while(Device_tmp!=NULL) { //printf(" %s:%s->", Device_tmp->name, Device_tmp->IPv4Addr); memset(device_name_ascii, 0, 256); char_to_ascii(device_name_ascii, Device_tmp->name); strcat(nvram_info, "<"); sprintf(nvram_info, "%s%s>%s>", nvram_info, Device_tmp->IPv4Addr, device_name_ascii); printf(" %s\n", nvram_info); Sup_service_tmp = Device_tmp->sup_service; memset(service_type_list, 0, 512); while(Sup_service_tmp!=NULL) { for(handler = &service_handler[0], i=0; handler->service; handler++, i++) { if(strstr(Sup_service_tmp->name, handler->service)) { sprintf(service_type_list, "%s#%d", service_type_list, i); break; } } printf("%s ", Sup_service_tmp->name); Sup_service_tmp = Sup_service_tmp->next; } printf("\n"); printf("Service_type= %s\n", service_type_list); sprintf(nvram_info, "%s%s", nvram_info, service_type_list); printf("-> %s\n", nvram_info); Device_tmp = Device_tmp->next; } printf("\n==> %s\n", nvram_info); free(nvram_info); mDNS_Close(&mDNSStorage); }//Endof Initialise the mDNS core. if (status == mStatus_NoError) { result = 0; } else { result = 2; } if ( (result != 0) || (gMDNSPlatformPosixVerboseLevel > 0) ) { fprintf(stderr, "%s: Finished with status %d, result %d\n", gProgramName, (int)status, result); } return 0; }
DNSServiceErrorType DNSServiceResolve ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, DNSServiceResolveReply callback, void *context /* may be NULL */ ) { mStatus err = mStatus_NoError; const char *errormsg = "Unknown"; domainlabel n; domainname t, d, srv; mDNS_DirectOP_Resolve *x; (void)flags; // Unused (void)interfaceIndex; // Unused // Check parameters if (!name[0] || !MakeDomainLabelFromLiteralString(&n, name )) { errormsg = "Bad Instance Name"; goto badparam; } if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; } if (!domain[0] || !MakeDomainNameFromDNSNameString(&d, domain )) { errormsg = "Bad Domain"; goto badparam; } if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; } // Allocate memory, and handle failure x = (mDNS_DirectOP_Resolve *)mDNSPlatformMemAllocate(sizeof(*x)); if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } // Set up object x->disposefn = DNSServiceResolveDispose; x->callback = callback; x->context = context; x->SRV = mDNSNULL; x->TXT = mDNSNULL; x->qSRV.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question x->qSRV.InterfaceID = mDNSInterface_Any; x->qSRV.Target = zeroAddr; AssignDomainName(&x->qSRV.qname, &srv); x->qSRV.qtype = kDNSType_SRV; x->qSRV.qclass = kDNSClass_IN; x->qSRV.LongLived = mDNSfalse; x->qSRV.ExpectUnique = mDNStrue; x->qSRV.ForceMCast = mDNSfalse; x->qSRV.QuestionCallback = FoundServiceInfo; x->qSRV.QuestionContext = x; x->qTXT.ThisQInterval = -1; // So that DNSServiceResolveDispose() knows whether to cancel this question x->qTXT.InterfaceID = mDNSInterface_Any; x->qTXT.Target = zeroAddr; AssignDomainName(&x->qTXT.qname, &srv); x->qTXT.qtype = kDNSType_TXT; x->qTXT.qclass = kDNSClass_IN; x->qTXT.LongLived = mDNSfalse; x->qTXT.ExpectUnique = mDNStrue; x->qTXT.ForceMCast = mDNSfalse; x->qTXT.QuestionCallback = FoundServiceInfo; x->qTXT.QuestionContext = x; err = mDNS_StartQuery(&mDNSStorage, &x->qSRV); if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qSRV"; goto fail; } err = mDNS_StartQuery(&mDNSStorage, &x->qTXT); if (err) { DNSServiceResolveDispose((mDNS_DirectOP*)x); errormsg = "mDNS_StartQuery qTXT"; goto fail; } // Succeeded: Wrap up and return *sdRef = (DNSServiceRef)x; return(mStatus_NoError); badparam: err = mStatus_BadParamErr; fail: LogMsg("DNSServiceResolve(\"%s\", \"%s\", \"%s\") failed: %s (%ld)", name, regtype, domain, errormsg, err); return(err); }
DNSServiceErrorType DNSServiceRegister ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, /* may be NULL */ const char *regtype, const char *domain, /* may be NULL */ const char *host, /* may be NULL */ uint16_t notAnIntPort, uint16_t txtLen, const void *txtRecord, /* may be NULL */ DNSServiceRegisterReply callback, /* may be NULL */ void *context /* may be NULL */ ) { mStatus err = mStatus_NoError; const char *errormsg = "Unknown"; domainlabel n; domainname t, d, h, srv; mDNSIPPort port; unsigned int size = sizeof(RDataBody); AuthRecord *SubTypes = mDNSNULL; mDNSu32 NumSubTypes = 0; mDNS_DirectOP_Register *x; (void)flags; // Unused (void)interfaceIndex; // Unused // Check parameters if (!name[0]) n = mDNSStorage.nicelabel; else if (!MakeDomainLabelFromLiteralString(&n, name)) { errormsg = "Bad Instance Name"; goto badparam; } if (!regtype || !*regtype || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Bad Service Type"; goto badparam; } if (!MakeDomainNameFromDNSNameString(&d, (domain && *domain) ? domain : "local.")) { errormsg = "Bad Domain"; goto badparam; } if (!MakeDomainNameFromDNSNameString(&h, (host && *host ) ? host : "")) { errormsg = "Bad Target Host"; goto badparam; } if (!ConstructServiceName(&srv, &n, &t, &d)) { errormsg = "Bad Name"; goto badparam; } port.NotAnInteger = notAnIntPort; // Allocate memory, and handle failure if (size < txtLen) size = txtLen; x = (mDNS_DirectOP_Register *)mDNSPlatformMemAllocate(sizeof(*x) - sizeof(RDataBody) + size); if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } // Set up object x->disposefn = DNSServiceRegisterDispose; x->callback = callback; x->context = context; x->autoname = (!name[0]); x->autorename = mDNSfalse; x->name = n; // Do the operation err = mDNS_RegisterService(&mDNSStorage, &x->s, &x->name, &t, &d, // Name, type, domain &h, port, // Host and port txtRecord, txtLen, // TXT data, length SubTypes, NumSubTypes, // Subtypes mDNSInterface_Any, // Interface ID RegCallback, x); // Callback and context if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_RegisterService"; goto fail; } // Succeeded: Wrap up and return *sdRef = (DNSServiceRef)x; return(mStatus_NoError); badparam: err = mStatus_BadParamErr; fail: LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err); return(err); }
DNSServiceErrorType DNSSD_API DNSServiceBrowse ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *regtype, const char *domain, /* may be NULL */ DNSServiceBrowseReply callback, void *context /* may be NULL */ ) { mStatus err = mStatus_NoError; const char *errormsg = "Unknown"; domainname t, d; mDNS_DirectOP_Browse *x; mDNSs32 NumSubTypes; char regTypeBuf[MAX_ESCAPED_DOMAIN_NAME]; (void)flags; // Unused (void)interfaceIndex; // Unused if (!regtype || !*regtype) { goto badregtype; } mDNSPlatformStrCopy(regTypeBuf, regtype); // Check parameters t.c[0] = 0; NumSubTypes = ChopSubTypes(regTypeBuf); // Note: Modifies regtype string to remove trailing subtypes if (NumSubTypes < 0 || NumSubTypes > 1) { goto badregtype; } if (NumSubTypes == 1 && !AppendDNSNameString(&t, regTypeBuf + mDNSPlatformStrLen(regTypeBuf) + 1)) { goto badregtype; } if (!regTypeBuf[0] || !AppendDNSNameString(&t, regTypeBuf)) { goto badregtype; } if (!MakeDomainNameFromDNSNameString(&d, (domain && *domain) ? domain : "local.")) { errormsg = "Illegal domain"; goto badparam; } // Allocate memory, and handle failure x = (mDNS_DirectOP_Browse *)mDNSPlatformMemAllocate(sizeof(*x)); if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } // Set up object x->disposefn = DNSServiceBrowseDispose; x->callback = callback; x->context = context; x->q.QuestionContext = x; // Do the operation err = mDNS_StartBrowse(&mDNSStorage, &x->q, &t, &d, mDNSInterface_Any, (flags & kDNSServiceFlagsForceMulticast) != 0, FoundInstance, x); if (err) { mDNSPlatformMemFree(x); errormsg = "mDNS_StartBrowse"; goto fail; } // Succeeded: Wrap up and return *sdRef = (DNSServiceRef)x; return(mStatus_NoError); badregtype: errormsg = "Illegal regtype"; badparam: err = mStatus_BadParamErr; fail: LogMsg("DNSServiceBrowse(\"%s\", \"%s\") failed: %s (%ld)", regtype, domain, errormsg, err); return(err); }