static int upnp_device_advlist_init(UPNP_CONTEXT *context) { int i; int size; UPNP_INTERFACE *ifp = context->focus_ifp; UPNP_ADVERTISE *src, *dst; char new_uuid[64]; char old_uuid[64]; /* Count advertise_table size */ for (i = 0; ifp->device->advertise_table[i].name; i++) ; size = (i + 1) * sizeof(UPNP_ADVERTISE); ifp->advlist = (UPNP_ADVERTISE *)malloc(size); if (ifp->advlist == NULL) return -1; memcpy(ifp->advlist, ifp->device->advertise_table, size); /* Renew UUIDs of this ifp */ for (src = ifp->advlist; src->name; src++) { if (src->type != ADVERTISE_ROOTDEVICE && src->type != ADVERTISE_DEVICE) continue; /* Generate interface uuid for this device */ strcpy(old_uuid, src->uuid); upnp_gen_uuid(new_uuid, src->name, (unsigned char *)ifp->mac); /* Sync to device/services with this UUID */ for (dst = ifp->advlist; dst->name; dst++) { if (strcmp(dst->uuid, old_uuid) == 0) { strncpy(dst->uuid, new_uuid, sizeof(dst->uuid)); dst->uuid[sizeof(dst->uuid)-1] = '\0'; } } } return 0; }
/* Give a unique uuid to this rootdevice */ int upnp_device_renew_uuid(UPNP_CONTEXT *context, UPNP_DEVICE *device) { char *s, *p; char deviceType[256]; char serviceType[256]; char new_uuid[64]; UPNP_DESCRIPTION *desc; /* Find root device */ for (desc = device->description_table; desc; desc++) { if (strcmp(device->root_device_xml, desc->name+1) == 0) break; } if (desc == 0) { upnp_syslog(LOG_ERR, "Root device can not find it's xml."); return -1; } /* * Update UUID of the root device xml * for each AP/router. By using the MAC address * and the value between <deviceType>...</deviceType>, we can * generate a unique UUID. */ for (p = desc->xml; *p != 0; p++) { /* Search for <deviceType> */ if (strncmp(p, DEVICE_BTAG, strlen(DEVICE_BTAG)) == 0) { p += strlen(DEVICE_BTAG); /* Find the balanced </deviceType> */ s = strstr(p, DEVICE_ETAG); if (s == 0 || (s-p) > sizeof(deviceType)-1) { upnp_syslog(LOG_ERR, "Parse format:<deviceType>...</deviceType> error.\n"); return -1; } /* Save deviceType */ memcpy(deviceType, p, s-p); deviceType[s-p] = '\0'; p = s + strlen(DEVICE_ETAG); } /* * For example, * <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1</deviceType> * the value between <UDN>...</UDN> is the UUID we have to replace. * The UUID format is such as, uuid:eb9ab5b2-981c-4401-a20e-b7bcde359dbb. * By generate the same UUID size, we don't have to do memory ajustment. */ if (strncmp(p, UDN_BTAG, strlen(UDN_BTAG)) == 0) { p += strlen(UDN_BTAG); /* Find the balanced </UDN> */ s = strstr(p, UDN_ETAG); if (s == 0 || (s-p) > sizeof(deviceType)-1) { upnp_syslog(LOG_ERR, "Parse format:<UDN>...</UDN> error.\n"); return -1; } p += 5; /* "uuid:" is 5 char */ if ((s-p) != 36) { upnp_syslog(LOG_ERR, "UUID length is not 36.\n"); return -1; } /* Replace uuid */ upnp_gen_uuid(new_uuid, deviceType); memcpy(p, new_uuid, 36); /* uuid is 36 characters. */ p = p + 36; /* 46 = 10 + 36 */ /* * Afert the UUID of device in description XML is changed, * we have to sync this new UUID to the advertisement table. */ sync_advertise_uuid(device, new_uuid, deviceType); } /* * The SSDP broadcasts not only the device information but * also all the services of this device, which shares the * UUID of that device. * As a result, we have to find out all the <serviceType>'s * of this <deviceType>, and sync the device UUID to the * advertisement table */ if (strncmp(p, SERVICE_BTAG, strlen(SERVICE_BTAG)) == 0) { p += strlen(SERVICE_BTAG); /* Find the balanced </serviceType> */ s = strstr(p, SERVICE_ETAG); if (s == 0 || (s-p) > sizeof(serviceType)-1) { upnp_syslog(LOG_ERR, "Parse format:<serviceType>...</serviceType> error.\n"); return -1; } /* Save serviceType */ strncpy(serviceType, p, s-p); serviceType[s-p] = '\0'; p = s + strlen(SERVICE_ETAG); /* * Found a <serviceType>...</serviceType>. * For example, * <serviceType>urn:schemas-upnp-org:service:Layer3Forwarding:1 * </serviceType> * is the service of * <deviceType>urn:schemas-upnp-org:device:InternetGatewayDevice:1 * </deviceType>. * We have to search the * "urn:schemas-upnp-org:service:Layer3Forwarding:1" * in the advertisement table, and replace its UUID with the UUID of * "urn:schemas-upnp-org:device:InternetGatewayDevice:1". */ sync_advertise_uuid(device, new_uuid, serviceType); } } return 0; }