Beispiel #1
0
mDNSlocal void FoundInstance(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
	{
	DNSServiceFlags flags = AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0;
	domainlabel name;
	domainname type, domain;
	char cname[MAX_DOMAIN_LABEL+1];			// Unescaped name: up to 63 bytes plus C-string terminating NULL.
	char ctype[MAX_ESCAPED_DOMAIN_NAME];
	char cdom [MAX_ESCAPED_DOMAIN_NAME];
	mDNS_DirectOP_Browse *x = (mDNS_DirectOP_Browse*)question->QuestionContext;
	(void)m;		// Unused
	
	if (answer->rrtype != kDNSType_PTR)
		{ LogMsg("FoundInstance: Should not be called with rrtype %d (not a PTR record)", answer->rrtype); return; }
	
	if (!DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain))
		{
		LogMsg("FoundInstance: %##s PTR %##s received from network is not valid DNS-SD service pointer",
			answer->name->c, answer->rdata->u.name.c);
		return;
		}

	ConvertDomainLabelToCString_unescaped(&name, cname);
	ConvertDomainNameToCString(&type, ctype);
	ConvertDomainNameToCString(&domain, cdom);
	if (x->callback)
		x->callback((DNSServiceRef)x, flags, 0, 0, cname, ctype, cdom, x->context);
	}
Beispiel #2
0
static void BrowseCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
// A callback from the core mDNS code that indicates that we've received a
// response to our query.  Note that this code runs on the main thread
// (in fact, there is only one thread!), so we can safely printf the results.
{
    domainlabel name;
    domainname  type;
    domainname  domain;
    char nameC  [MAX_DOMAIN_LABEL+1];			// Unescaped name: up to 63 bytes plus C-string terminating NULL.
    char typeC  [MAX_ESCAPED_DOMAIN_NAME];
    char domainC[MAX_ESCAPED_DOMAIN_NAME];
    const char *state;

    (void)m;		// Unused
    (void)question;	// Unused

    assert(answer->rrtype == kDNSType_PTR);

    DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain);

    ConvertDomainLabelToCString_unescaped(&name, nameC);
    ConvertDomainNameToCString(&type, typeC);
    ConvertDomainNameToCString(&domain, domainC);

    // If the TTL has hit 0, the service is no longer available.
    if (!AddRecord) {
        state = "Lost ";
    } else {
        state = "Found";
    }
    fprintf(stderr, "*** %s name = '%s', type = '%s', domain = '%s'\n", state, nameC, typeC, domainC);
}
// This sample ServiceCallback just calls mDNS_RenameAndReregisterService to automatically pick a new
// unique name for the service. For a device such as a printer, this may be appropriate.
// For a device with a user interface, and a screen, and a keyboard, the appropriate
// response may be to prompt the user and ask them to choose a new name for the service.
mDNSlocal void ServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
{
    switch (result)
    {
    case mStatus_NoError:      debugf("Callback: %##s Name Registered",    sr->RR_SRV.resrec.name->c); break;
    case mStatus_NameConflict: debugf("Callback: %##s Name Conflict",      sr->RR_SRV.resrec.name->c); break;
    case mStatus_MemFree:      debugf("Callback: %##s Memory Free",        sr->RR_SRV.resrec.name->c); break;
    default:                   debugf("Callback: %##s Unknown Result %ld", sr->RR_SRV.resrec.name->c, result); break;
    }

    if (result == mStatus_NoError)
    {
        char buffer[MAX_ESCAPED_DOMAIN_NAME];
        ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer);
        printf("Service %s now registered and active\n", buffer);
    }

    if (result == mStatus_NameConflict)
    {
        char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME];
        ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer1);
        mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
        ConvertDomainNameToCString(sr->RR_SRV.resrec.name, buffer2);
        printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2);
    }
}
mDNSlocal void NoSuchServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
{
    const domainname *proxyhostname = (const domainname *)rr->RecordContext;
    switch (result)
    {
    case mStatus_NoError:      debugf("Callback: %##s Name Registered",    rr->resrec.name->c); break;
    case mStatus_NameConflict: debugf("Callback: %##s Name Conflict",      rr->resrec.name->c); break;
    case mStatus_MemFree:      debugf("Callback: %##s Memory Free",        rr->resrec.name->c); break;
    default:                   debugf("Callback: %##s Unknown Result %ld", rr->resrec.name->c, result); break;
    }

    if (result == mStatus_NoError)
    {
        char buffer[MAX_ESCAPED_DOMAIN_NAME];
        ConvertDomainNameToCString(rr->resrec.name, buffer);
        printf("Non-existence assertion %s now registered and active\n", buffer);
    }

    if (result == mStatus_NameConflict)
    {
        domainlabel n;
        domainname t, d;
        char buffer1[MAX_ESCAPED_DOMAIN_NAME], buffer2[MAX_ESCAPED_DOMAIN_NAME];
        ConvertDomainNameToCString(rr->resrec.name, buffer1);
        DeconstructServiceName(rr->resrec.name, &n, &t, &d);
        IncrementLabelSuffix(&n, mDNStrue);
        mDNS_RegisterNoSuchService(m, rr, &n, &t, &d, proxyhostname, mDNSInterface_Any, NoSuchServiceCallback, mDNSNULL, 0);
        ConvertDomainNameToCString(rr->resrec.name, buffer2);
        printf("Name Conflict! %s renamed as %s\n", buffer1, buffer2);
    }
}
Beispiel #5
0
static void BrowseCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
    // A callback from the core mDNS code that indicates that we've received a 
    // response to our query.  Note that this code runs on the main thread 
    // (in fact, there is only one thread!), so we can safely printf the results.
{
return;
    domainlabel name;
    domainname  type;
    domainname  domain;
    char nameC  [MAX_DOMAIN_LABEL+1];	// Unescaped name: up to 63 bytes plus C-string terminating NULL.
    char typeC  [MAX_ESCAPED_DOMAIN_NAME];
    char domainC[MAX_ESCAPED_DOMAIN_NAME];
    const char *state;
    (void)m;        // Unused
    (void)question; // Unused

    assert(answer->rrtype == kDNSType_PTR);

    DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain);

    ConvertDomainLabelToCString_unescaped(&name, nameC);
    ConvertDomainNameToCString(&type, typeC);
    ConvertDomainNameToCString(&domain, domainC);
    callback++;
    // If the TTL has hit 0, the service is no longer available.
    if (AddRecord) {
    	fprintf(stderr, "*** Found name = '%s', type = '%s', domain = '%s'\n", nameC, typeC, domainC);
	//fprintf(stderr, "=== call back count: %d ===\n", callback);
	if(Service_list == NULL) {
		Service_list = (struct Queried_Service *)malloc(sizeof(struct Queried_Service));
		strcpy(Service_list->service, nameC);
		strcpy(Service_list->type, typeC);
		Service_list->sup_device = NULL;
		Service_cur = Service_list;
		Service_cur->next = NULL;
	}
	else {
                Service_tmp = (struct Queried_Service *)malloc(sizeof(struct Queried_Service));
                strcpy(Service_tmp->service, nameC);
                strcpy(Service_tmp->type, typeC);
		Service_tmp->sup_device = NULL;
		Service_tmp->next = NULL;
                Service_cur->next = Service_tmp;
                Service_cur = Service_tmp;
	}
        callback = 0;
        event = 0;
    }
}
// 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);
	}
Beispiel #8
0
mDNSlocal void DNSServiceQueryRecordResponse(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
	{
	mDNS_DirectOP_QueryRecord *x = (mDNS_DirectOP_QueryRecord*)question->QuestionContext;
	char fullname[MAX_ESCAPED_DOMAIN_NAME];
	(void)m;	// Unused
	ConvertDomainNameToCString(answer->name, fullname);
	x->callback((DNSServiceRef)x, AddRecord ? kDNSServiceFlagsAdd : (DNSServiceFlags)0, 0, kDNSServiceErr_NoError,
		fullname, answer->rrtype, answer->rrclass, answer->rdlength, answer->rdata->u.data, answer->rroriginalttl, x->context);
	}
// PrintServiceInfo prints the service information to standard out
// A real application might want to do something else with the information
static void PrintServiceInfo(SearcherServices *services)
	{
	OTLink *link = OTReverseList(OTLIFOStealList(&services->serviceinfolist));
	
	while (link)
		{
		linkedServiceInfo *ls = OTGetLinkObject(link, linkedServiceInfo, link);
		ServiceInfo *s = &ls->i;

		if (!services->headerPrinted)
			{
			printf("%-55s Type             Domain         IP Address       Port Info\n", "Name");
			services->headerPrinted = true;
			}

		if (ls->dom)
			{
			char c_dom[MAX_ESCAPED_DOMAIN_NAME];
			ConvertDomainNameToCString(&s->name, c_dom);
			if (ls->add) printf("%-55s available for browsing\n", c_dom);
			else         printf("%-55s no longer available for browsing\n", c_dom);
			}
		else
			{
			domainlabel name;
			domainname type, domain;
			char c_name[MAX_DOMAIN_LABEL+1], c_type[MAX_ESCAPED_DOMAIN_NAME], c_dom[MAX_ESCAPED_DOMAIN_NAME], c_ip[20];
			DeconstructServiceName(&s->name, &name, &type, &domain);
			ConvertDomainLabelToCString_unescaped(&name, c_name);
			ConvertDomainNameToCString(&type, c_type);
			ConvertDomainNameToCString(&domain, c_dom);
			sprintf(c_ip, "%d.%d.%d.%d", s->ip.ip.v4.b[0], s->ip.ip.v4.b[1], s->ip.ip.v4.b[2], s->ip.ip.v4.b[3]);

			printf("%-55s %-16s %-14s ", c_name, c_type, c_dom);
			if (ls->add) printf("%-15s %5d %#s\n", c_ip, mDNSVal16(s->port), s->TXTinfo);
			else         printf("Removed\n");
			}

		link = link->fNext;
		OTFreeMem(ls);
		}
	}
mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
	{
	mDNS_DirectOP_Register *x = (mDNS_DirectOP_Register*)sr->ServiceContext;

    domainlabel name;
    domainname type, dom;
	char namestr[MAX_DOMAIN_LABEL+1];		// Unescaped name: up to 63 bytes plus C-string terminating NULL.
	char typestr[MAX_ESCAPED_DOMAIN_NAME];
	char domstr [MAX_ESCAPED_DOMAIN_NAME];
    if (!DeconstructServiceName(sr->RR_SRV.resrec.name, &name, &type, &dom)) return;
    if (!ConvertDomainLabelToCString_unescaped(&name, namestr)) return;
    if (!ConvertDomainNameToCString(&type, typestr)) return;
    if (!ConvertDomainNameToCString(&dom, domstr)) return;

	if (result == mStatus_NoError)
		{
		if (x->callback)
			x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context);
		}
	else if (result == mStatus_NameConflict)
		{
			if (x->autoname) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
			else if (x->autorename) {
				IncrementLabelSuffix(&x->name, mDNStrue);
				mDNS_RenameAndReregisterService(m, &x->s, &x->name);
			}
			else if (x->callback)
				x->callback((DNSServiceRef)x, 0, result, namestr, typestr, domstr, x->context);
		}
	else if (result == mStatus_MemFree)
		{
		if (x->autorename)
			{
			x->autorename = mDNSfalse;
			x->name = mDNSStorage.nicelabel;
			mDNS_RenameAndReregisterService(m, &x->s, &x->name);
			}
		else
			FreeDNSServiceRegistration(x);
		}
	}
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);
}
Beispiel #12
0
mDNSlocal void NameCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
    (void)m;        // Unused
    (void)question; // Unused
    (void)AddRecord; // Unused
    if (!id.NotAnInteger) id = lastid;
    if (answer->rrtype == kDNSType_PTR || answer->rrtype == kDNSType_CNAME)
    {
        ConvertDomainNameToCString(&answer->rdata->u.name, hostname);
        StopNow = 1;
        mprintf("%##s %s %##s\n", answer->name->c, DNSTypeName(answer->rrtype), answer->rdata->u.name.c);
    }
}
Beispiel #13
0
mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
	{
	mDNS_DirectOP_Resolve *x = (mDNS_DirectOP_Resolve*)question->QuestionContext;
	(void)m;	// Unused
	if (!AddRecord)
		{
		if (answer->rrtype == kDNSType_SRV && x->SRV == answer) x->SRV = mDNSNULL;
		if (answer->rrtype == kDNSType_TXT && x->TXT == answer) x->TXT = mDNSNULL;
		}
	else
		{
		if (answer->rrtype == kDNSType_SRV) x->SRV = answer;
		if (answer->rrtype == kDNSType_TXT) x->TXT = answer;
		if (x->SRV && x->TXT && x->callback)
			{
			char fullname[MAX_ESCAPED_DOMAIN_NAME], targethost[MAX_ESCAPED_DOMAIN_NAME];
		    ConvertDomainNameToCString(answer->name, fullname);
		    ConvertDomainNameToCString(&x->SRV->rdata->u.srv.target, targethost);
			x->callback((DNSServiceRef)x, 0, 0, kDNSServiceErr_NoError, fullname, targethost,
				x->SRV->rdata->u.srv.port.NotAnInteger, x->TXT->rdlength, (char*)x->TXT->rdata->u.txt.c, x->context);
			}
		}
	}
Beispiel #14
0
static mDNSBool
eval_service_name(const domainname *fqdn, domainlabel *name)
{
	domainname type;
	domainname domain;
	mDNSBool ok = DeconstructServiceName(fqdn, name, &type, &domain);

	if (ok) {
		char name_str[MAX_DOMAIN_LABEL + 1];
		char type_str[MAX_ESCAPED_DOMAIN_NAME];
		char domain_str[MAX_ESCAPED_DOMAIN_NAME];

		ConvertDomainLabelToCString_unescaped(name, name_str);
		ConvertDomainNameToCString(&type, type_str);
		ConvertDomainNameToCString(&domain, domain_str);

		printf("name = '%s', type = '%s', domain = '%s'",
		    name_str, type_str, domain_str);
	} else {
		printf("?");
	}

	return ok;
}
// Done once on startup, and then again every time our address changes
mDNSlocal OSStatus mDNSResponderTestSetup(mDNS *m)
	{
	char buffer[MAX_ESCAPED_DOMAIN_NAME];
	mDNSv4Addr ip = m->HostInterfaces->ip.ip.v4;
	
	ConvertDomainNameToCString(&m->MulticastHostname, buffer);
	printf("Name %s\n", buffer);
	printf("IP   %d.%d.%d.%d\n", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);

	printf("\n");
	printf("Registering Service Records\n");
	// Create example printer discovery records
	//static ServiceRecordSet p1, p2;

	RegisterFakeServiceForTesting(m, &p1, "", "One", "_raop._tcp.", "local.");
	RegisterFakeServiceForTesting(m, &p2, "", "Two", "_raop._tcp.", "local.");

	return(kOTNoError);
	}
// Done once on startup, and then again every time our address changes
mDNSlocal OSStatus mDNSResponderTestSetup(mDNS *m)
	{
	char buffer[MAX_ESCAPED_DOMAIN_NAME];
	mDNSv4Addr ip = m->HostInterfaces->ip.ip.v4;
	
	ConvertDomainNameToCString(&m->MulticastHostname, buffer);
	printf("Name %s\n", buffer);
	printf("IP   %d.%d.%d.%d\n", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);

	printf("\n");
	printf("Registering Service Records\n");
	// Create example printer discovery records
	//static ServiceRecordSet p1, p2;

#define SRSET 0
#if SRSET==0
	RegisterFakeServiceForTesting(m, &p1, "path=/index.html", "Web Server One", "_http._tcp.", "local.");
	RegisterFakeServiceForTesting(m, &p2, "path=/path.html",  "Web Server Two", "_http._tcp.", "local.");
#elif SRSET==1
	RegisterFakeServiceForTesting(m, &p1, "rn=lpq1", "Epson Stylus 900N", "_printer._tcp.", "local.");
	RegisterFakeServiceForTesting(m, &p2, "rn=lpq2", "HP LaserJet",       "_printer._tcp.", "local.");
#else
	RegisterFakeServiceForTesting(m, &p1, "rn=lpq3", "My Printer",        "_printer._tcp.", "local.");
	RegisterFakeServiceForTesting(m, &p2, "lrn=pq4", "My Other Printer",  "_printer._tcp.", "local.");
#endif

	// If AFP Server is running, register a record for it
	CreateProxyRegistrationForRealService(m, 548, "", "_afpovertcp._tcp.", &afp);

	// If Web Server is running, register a record for it
	CreateProxyRegistrationForRealService(m, 80, "", "_http._tcp.", &http);

	// And pretend we always have an NJP server running on port 80 too
	//RegisterService(m, &njp, 80, "NJP/", &m->nicelabel, "_njp._tcp.", "local.");

	// Advertise that apple.com. is available for browsing
	mDNS_AdvertiseDomains(m, &browsedomain1, mDNS_DomainTypeBrowse, mDNSInterface_Any, "apple.com.");
	mDNS_AdvertiseDomains(m, &browsedomain2, mDNS_DomainTypeBrowse, mDNSInterface_Any, "IL 2\\4th Floor.apple.com.");

	return(kOTNoError);
	}
Beispiel #17
0
static void QueryCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord)
{
    domainlabel name;
    domainname  type;
    domainname  domain;
    char nameC  [MAX_DOMAIN_LABEL+1];   // Unescaped name: up to 63 bytes plus C-string terminating NULL.
    char typeC  [MAX_ESCAPED_DOMAIN_NAME];
    char domainC[MAX_ESCAPED_DOMAIN_NAME];
    const char *state;
    (void)m;        // Unused
    (void)question; // Unused

    assert(answer->rrtype == kDNSType_PTR);

    DeconstructServiceName(&answer->rdata->u.name, &name, &type, &domain);

    ConvertDomainLabelToCString_unescaped(&name, nameC);
    ConvertDomainNameToCString(&type, typeC);
    ConvertDomainNameToCString(&domain, domainC);
    callback++;
    // If the TTL has hit 0, the service is no longer available.
    if (AddRecord) {
        fprintf(stderr, "*** Found device = '%s', service = '%s', domain = '%s'\n", nameC, typeC, domainC);
        //fprintf(stderr, "=== call back count: %d ===\n", callback);
        if(Device_list == NULL) {
                Device_list = (struct Device *)malloc(sizeof(struct Device));
                QueriedNameParse(Service_tmp->service, nameC, Device_list);
printf("1.    Get %s, %s\n", Device_list->name, Device_list->MACAddr);
		Device_list->sup_service = (struct Support_Service *)malloc(sizeof(struct Support_Service));
		strcpy(Device_list->sup_service->name, Service_tmp->service);
		Device_list->sup_service->next = NULL;
                Device_cur = Device_list;
                Device_cur->next = NULL;
		service_count++;
        }
        else {
		Device_found = (struct Device *)malloc(sizeof(struct Device));
		QueriedNameParse(Service_tmp->service, nameC, Device_found);
printf("2.    Get %s, %s\n", Device_found->name, Device_found->MACAddr);

		Device_cmp = Device_list;
		while(Device_cmp != NULL) {
printf("%s ? %s\n",Device_found->name, Device_cmp->name);
			if(!strcmp(Device_found->name, Device_cmp->name)) { //the device already exist, add service to list.
printf("Device name the same!\n");
				Sup_service_cur = Device_cmp->sup_service;
				while(Sup_service_cur->next!=NULL)
					Sup_service_cur = Sup_service_cur->next;

				Sup_service_tmp = (struct Support_Service *)malloc(sizeof(struct Support_Service));
				strcpy(Sup_service_tmp->name, Service_tmp->service);
				Sup_service_tmp->next = NULL;
				Sup_service_cur->next = Sup_service_tmp;
				Sup_service_cur = Sup_service_tmp;				
				service_count++;

				return;
			}
			Device_cmp = Device_cmp->next;
		}

printf("New Device name!\n");
		Device_found->sup_service = (struct Support_Service *)malloc(sizeof(struct Support_Service));
		strcpy(Device_found->sup_service->name, Service_tmp->service);
		Device_found->sup_service->next = NULL;
                Device_found->next = NULL;
       	        Device_cur->next = Device_found;
               	Device_cur = Device_found;
		Device_cur->next = NULL;
        }

printf("device= %s\n", Device_cur->name);
	device_count++;
        callback = 0;
        event = 0;
    }
}