void ProcessSSDPData(int s, const char *bufr, int n, const struct sockaddr * sender, unsigned short port) { int i, l; struct lan_addr_s * lan_addr = NULL; const char * st = NULL; int st_len = 0; char sender_str[64]; const char * announced_host = NULL; #ifdef UPNP_STRICT char announced_host_buf[64]; #endif /* get the string representation of the sender address */ sockaddr_to_string(sender, sender_str, sizeof(sender_str)); if(memcmp(bufr, "NOTIFY", 6) == 0) { /* ignore NOTIFY packets. We could log the sender and device type */ return; } else if(memcmp(bufr, "M-SEARCH", 8) == 0) { i = 0; while(i < n) { while((i < n - 1) && (bufr[i] != '\r' || bufr[i+1] != '\n')) i++; i += 2; if((i < n - 3) && (strncasecmp(bufr+i, "st:", 3) == 0)) { st = bufr+i+3; st_len = 0; while((*st == ' ' || *st == '\t') && (st < bufr + n)) st++; while(st[st_len]!='\r' && st[st_len]!='\n' && (st + st_len < bufr + n)) st_len++; /*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/ /*j = 0;*/ /*while(bufr[i+j]!='\r') j++;*/ /*syslog(LOG_INFO, "%.*s", j, bufr+i);*/ } } /*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s", sender_str );*/ if(st && (st_len > 0)) { /* TODO : doesnt answer at once but wait for a random time */ syslog(LOG_INFO, "SSDP M-SEARCH from %s ST: %.*s", sender_str, st_len, st); /* find in which sub network the client is */ if(sender->sa_family == AF_INET) { for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) { if( (((const struct sockaddr_in *)sender)->sin_addr.s_addr & lan_addr->mask.s_addr) == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) break; } if (lan_addr == NULL) { syslog(LOG_ERR, "Can't find in which sub network the client is"); return; } announced_host = lan_addr->str; } #ifdef ENABLE_IPV6 else { /* IPv6 address with brackets */ #ifdef UPNP_STRICT struct in6_addr addr6; size_t addr6_len = sizeof(addr6); /* retrieve the IPv6 address which * will be used locally to reach sender */ memset(&addr6, 0, sizeof(addr6)); if(get_src_for_route_to (sender, &addr6, &addr6_len) < 0) { syslog(LOG_WARNING, "get_src_for_route_to() failed, using %s", ipv6_addr_for_http_with_brackets); announced_host = ipv6_addr_for_http_with_brackets; } else { if(inet_ntop(AF_INET6, &addr6, announced_host_buf+1, sizeof(announced_host_buf) - 2)) { announced_host_buf[0] = '['; i = strlen(announced_host_buf); if(i < (int)sizeof(announced_host_buf) - 1) { announced_host_buf[i] = ']'; announced_host_buf[i+1] = '\0'; } else { syslog(LOG_NOTICE, "cannot suffix %s with ']'", announced_host_buf); } announced_host = announced_host_buf; } else { syslog(LOG_NOTICE, "inet_ntop() failed %m"); announced_host = ipv6_addr_for_http_with_brackets; } } #else announced_host = ipv6_addr_for_http_with_brackets; #endif } #endif /* Responds to request with a device as ST header */ for(i = 0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); if(l<=st_len && (0 == memcmp(st, known_service_types[i], l))) { syslog(LOG_INFO, "Single search found"); SendSSDPAnnounce2(s, sender, st, st_len, "", announced_host, port); break; } } /* Responds to request with ST: ssdp:all */ /* strlen("ssdp:all") == 8 */ if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8))) { syslog(LOG_INFO, "ssdp:all found"); for(i=0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); SendSSDPAnnounce2(s, sender, known_service_types[i], l, i==0?"":"1", announced_host, port); } } /* responds to request by UUID value */ l = (int)strlen(uuidvalue); if(l==st_len && (0 == memcmp(st, uuidvalue, l))) { syslog(LOG_INFO, "ssdp:uuid found"); SendSSDPAnnounce2(s, sender, st, st_len, "", announced_host, port); } } else { syslog(LOG_INFO, "Invalid SSDP M-SEARCH from %s", sender_str); } } else { syslog(LOG_NOTICE, "Unknown udp packet received from %s", sender_str); } }
void ProcessSSDPData(int s, char *bufr, struct sockaddr_in sendername, int n, unsigned short port) { int i, l; int lan_addr_index = 0; char * st = 0; int st_len = 0; if(memcmp(bufr, "NOTIFY", 6) == 0) { /* ignore NOTIFY packets. We could log the sender and device type */ return; } else if(memcmp(bufr, "M-SEARCH", 8) == 0) { i = 0; while(i < n) { while((i < n - 1) && (bufr[i] != '\r' || bufr[i+1] != '\n')) i++; i += 2; if((i < n - 3) && (strncasecmp(bufr+i, "st:", 3) == 0)) { st = bufr+i+3; st_len = 0; while((*st == ' ' || *st == '\t') && (st < bufr + n)) st++; while(st[st_len]!='\r' && st[st_len]!='\n' && (st + st_len < bufr + n)) st_len++; /*syslog(LOG_INFO, "ST: %.*s", st_len, st);*/ /*j = 0;*/ /*while(bufr[i+j]!='\r') j++;*/ /*syslog(LOG_INFO, "%.*s", j, bufr+i);*/ } } /*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s:%d", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port) );*/ if(st && (st_len > 0)) { /* TODO : doesnt answer at once but wait for a random time */ syslog(LOG_INFO, "SSDP M-SEARCH from %s:%d ST: %.*s", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port), st_len, st); /* find in which sub network the client is */ for(i = 0; i<n_lan_addr; i++) { if( (sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr) == (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr)) { lan_addr_index = i; break; } } /* Responds to request with a device as ST header */ for(i = 0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); if(l<=st_len && (0 == memcmp(st, known_service_types[i], l))) { syslog(LOG_INFO, "Single search found"); SendSSDPAnnounce2(s, sendername, st, st_len, "", lan_addr[lan_addr_index].str, port); break; } } /* Responds to request with ST: ssdp:all */ /* strlen("ssdp:all") == 8 */ if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8))) { syslog(LOG_INFO, "ssdp:all found"); for(i=0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); SendSSDPAnnounce2(s, sendername, known_service_types[i], l, i==0?"":"1", lan_addr[lan_addr_index].str, port); } } /* responds to request by UUID value */ l = (int)strlen(uuidvalue); if(l==st_len && (0 == memcmp(st, uuidvalue, l))) { syslog(LOG_INFO, "ssdp:uuid found"); SendSSDPAnnounce2(s, sendername, st, st_len, "", lan_addr[lan_addr_index].str, port); } } else { syslog(LOG_INFO, "Invalid SSDP M-SEARCH from %s:%d", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); } } else { syslog(LOG_NOTICE, "Unknown udp packet received from %s:%d", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); } }
void ProcessSSDPData(int s, const char *bufr, int n, const struct sockaddr * sender, unsigned short port) { int i, l; struct lan_addr_s * lan_addr = NULL; const char * st = NULL; int st_len = 0; char sender_str[64]; const char * announced_host = NULL; /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 added */ char has_mx = 0; /* END 2082304944 zhoujianchun 00203875 2012.8.29 added */ /* get the string representation of the sender address */ sockaddr_to_string(sender, sender_str, sizeof(sender_str)); if(memcmp(bufr, "NOTIFY", 6) == 0) { /* ignore NOTIFY packets. We could log the sender and device type */ return; } else if(memcmp(bufr, "M-SEARCH", 8) == 0) { i = 0; while(i < n) { while((i < n - 1) && (bufr[i] != '\r' || bufr[i+1] != '\n')) i++; i += 2; /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 added */ if((i < n - 3) && (0 == strncasecmp(bufr+i, "mx:", 3))) { has_mx = 1; } /* END 2082304944 zhoujianchun 00203875 2012.8.29 added */ if((i < n - 3) && (strncasecmp(bufr+i, "st:", 3) == 0)) { st = bufr+i+3; st_len = 0; while((*st == ' ' || *st == '\t') && (st < bufr + n)) st++; while(st[st_len]!='\r' && st[st_len]!='\n' && (st + st_len < bufr + n)) st_len++; } } /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 added */ if(0 == has_mx) { NP_UPNP_DEBUG("M-SEARCH, NO MX: RETURN.\n"); return; } /* END 2082304944 zhoujianchun 00203875 2012.8.29 added */ if(st && (st_len > 0)) { /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 added */ if(strncmp("upnp:rootdevice", st, st_len) && strncmp("ssdp:all", st, st_len) && strncmp("urn:schemas-upnp-org:device:InternetGatewayDevice:1", st, st_len) && strncmp("urn:schemas-upnp-org:device:WANConnectionDevice:1", st, st_len) && strncmp("urn:schemas-upnp-org:device:WANDevice:1", st, st_len) && strncmp("urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1", st, st_len) && strncmp("urn:schemas-upnp-org:service:WANIPConnection:1", st, st_len) && strncmp("urn:schemas-upnp-org:service:Layer3Forwarding:1", st, st_len) && strncmp("urn:schemas-upnp-org:service:WANIPv6FirewallControl:1", st, st_len) && strncmp(uuidvalue_root, st, st_len) && strncmp(uuidvalue_wan, st, st_len) && strncmp(uuidvalue_wan_conn, st, st_len) ) { NP_UPNP_DEBUG("ST IS NOT CORRECT, RETURN.\n"); return; } /* END 2082304944 zhoujianchun 00203875 2012.8.29 added */ /* TODO : doesnt answer at once but wait for a random time */ NP_UPNP_DEBUG("SSDP M-SEARCH from %s ST: %.*s\n", sender_str, st_len, st); /* find in which sub network the client is */ if(sender->sa_family == AF_INET) { for(lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next) { if( (((const struct sockaddr_in *)sender)->sin_addr.s_addr & lan_addr->mask.s_addr) == (lan_addr->addr.s_addr & lan_addr->mask.s_addr)) break; } if (lan_addr == NULL) { NP_UPNP_ERROR("Can't find in which sub network the client is\n"); return; } announced_host = lan_addr->str; } #ifdef ENABLE_IPV6 else { /* IPv6 address with brackets */ announced_host = ipv6_addr_for_http_with_brackets; } #endif /* Responds to request with a device as ST header */ for(i = 0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); if(l<=st_len && (0 == memcmp(st, known_service_types[i], l))) { NP_UPNP_DEBUG("Single search found\n"); SendSSDPAnnounce2(s, sender, st, st_len, "", /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 modified */ announced_host, port, i); /* END 2082304944 zhoujianchun 00203875 2012.8.29 modified */ break; } } /* Responds to request with ST: ssdp:all */ /* strlen("ssdp:all") == 8 */ if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8))) { NP_UPNP_DEBUG("ssdp:all found\n"); for(i=0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); SendSSDPAnnounce2(s, sender, /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 modified */ known_service_types[i], l, i==0 ? "" : "1", announced_host, port, i); /* END 2082304944 zhoujianchun 00203875 2012.8.29 modified */ } /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 added */ for(i = 0; i < DEV_NUM; i++) { SendSSDPAnnounce2(s, sender, uuid_value[i], st_len, "", announced_host, port, -1); } /* END 2082304944 zhoujianchun 00203875 2012.8.29 added */ } /* responds to request by UUID value */ l = (int)strlen(uuidvalue); /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 modified */ if(l==st_len && 0 == memcmp(st, uuidvalue_root, l)) { NP_UPNP_DEBUG("ssdp:uuid found\n"); SendSSDPAnnounce2(s, sender, uuidvalue_root, st_len, "", announced_host, port, -1); } /* END 2082304944 zhoujianchun 00203875 2012.8.29 modified */ /* BEGIN 2082304944 zhoujianchun 00203875 2012.8.29 added */ else if(l==st_len && 0 == memcmp(st, uuidvalue_wan, l)) { NP_UPNP_DEBUG("ssdp:uuid found\n"); SendSSDPAnnounce2(s, sender, uuidvalue_wan, st_len, "", announced_host, port, -1); } else if(l==st_len && 0 == memcmp(st, uuidvalue_wan_conn, l)) { NP_UPNP_DEBUG("ssdp:uuid found\n"); SendSSDPAnnounce2(s, sender, uuidvalue_wan_conn, st_len, "", announced_host, port, -1); } /* END 2082304944 zhoujianchun 00203875 2012.8.29 added */ } else { NP_UPNP_DEBUG("Invalid SSDP M-SEARCH from %s\n", sender_str); } } else { NP_UPNP_DEBUG("Unknown udp packet received from %s\n", sender_str); } }
/* ProcessSSDPRequest() * process SSDP M-SEARCH requests and responds to them */ void ProcessSSDPRequest(int s, unsigned short port) { int n; char bufr[1500]; socklen_t len_r; struct sockaddr_in sendername; int i; char *st = NULL, *mx = NULL, *man = NULL, *mx_end = NULL; int man_len = 0; len_r = sizeof(struct sockaddr_in); n = recvfrom(s, bufr, sizeof(bufr)-1, 0, (struct sockaddr *)&sendername, &len_r); if (n < 0) { DPRINTF(E_ERROR, L_SSDP, "recvfrom(udp): %s\n", strerror(errno)); return; } bufr[n] = '\0'; n -= 2; if (memcmp(bufr, "NOTIFY", 6) == 0) { char *loc = NULL, *srv = NULL, *nts = NULL, *nt = NULL; int loc_len = 0; //DEBUG DPRINTF(E_DEBUG, L_SSDP, "Received SSDP notify:\n%.*s", n, bufr); for (i = 0; i < n; i++) { if( bufr[i] == '*' ) break; } if (strcasestrc(bufr+i, "HTTP/1.1", '\r') == NULL) return; while (i < n) { while ((i < n) && (bufr[i] != '\r' || bufr[i+1] != '\n')) i++; i += 2; if (strncasecmp(bufr+i, "SERVER:", 7) == 0) { srv = bufr+i+7; while (*srv == ' ' || *srv == '\t') srv++; } else if (strncasecmp(bufr+i, "LOCATION:", 9) == 0) { loc = bufr+i+9; while (*loc == ' ' || *loc == '\t') loc++; while (loc[loc_len]!='\r' && loc[loc_len]!='\n') loc_len++; } else if (strncasecmp(bufr+i, "NTS:", 4) == 0) { nts = bufr+i+4; while (*nts == ' ' || *nts == '\t') nts++; } else if (strncasecmp(bufr+i, "NT:", 3) == 0) { nt = bufr+i+3; while(*nt == ' ' || *nt == '\t') nt++; } } if (!loc || !srv || !nt || !nts || (strncmp(nts, "ssdp:alive", 10) != 0) || (strncmp(nt, "urn:schemas-upnp-org:device:MediaRenderer", 41) != 0)) return; loc[loc_len] = '\0'; if ((strncmp(srv, "Allegro-Software-RomPlug", 24) == 0) || /* Roku */ (strstr(loc, "SamsungMRDesc.xml") != NULL) || /* Samsung TV */ (strstrc(srv, "DigiOn DiXiM", '\r') != NULL)) /* Marantz Receiver */ { /* Check if the client is already in cache */ i = SearchClientCache(sendername.sin_addr, 1); if (i >= 0) { if (clients[i].type < EStandardDLNA150 && clients[i].type != ESamsungSeriesA) { clients[i].age = time(NULL); return; } } ParseUPnPClient(loc); } } else if (memcmp(bufr, "M-SEARCH", 8) == 0) { int st_len = 0, mx_len = 0, mx_val = 0; //DPRINTF(E_DEBUG, L_SSDP, "Received SSDP request:\n%.*s\n", n, bufr); for (i = 0; i < n; i++) { if (bufr[i] == '*') break; } if (strcasestrc(bufr+i, "HTTP/1.1", '\r') == NULL) return; while (i < n) { while ((i < n) && (bufr[i] != '\r' || bufr[i+1] != '\n')) i++; i += 2; if (strncasecmp(bufr+i, "ST:", 3) == 0) { st = bufr+i+3; st_len = 0; while (*st == ' ' || *st == '\t') st++; while (st[st_len]!='\r' && st[st_len]!='\n') st_len++; } else if (strncasecmp(bufr+i, "MX:", 3) == 0) { mx = bufr+i+3; mx_len = 0; while (*mx == ' ' || *mx == '\t') mx++; while (mx[mx_len]!='\r' && mx[mx_len]!='\n') mx_len++; mx_val = strtol(mx, &mx_end, 10); } else if (strncasecmp(bufr+i, "MAN:", 4) == 0) { man = bufr+i+4; man_len = 0; while (*man == ' ' || *man == '\t') man++; while (man[man_len]!='\r' && man[man_len]!='\n') man_len++; } } /*DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH packet received from %s:%d\n", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port) );*/ if (GETFLAG(DLNA_STRICT_MASK) && (ntohs(sendername.sin_port) <= 1024 || ntohs(sendername.sin_port) == 1900)) { DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad source port %d]\n", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); } else if (!man || (strncmp(man, "\"ssdp:discover\"", 15) != 0)) { DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad %s header '%.*s']\n", inet_ntoa(sendername.sin_addr), "MAN", man_len, man); } else if (!mx || mx == mx_end || mx_val < 0) { DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad %s header '%.*s']\n", inet_ntoa(sendername.sin_addr), "MX", mx_len, mx); } else if (st && (st_len > 0)) { int l; int lan_addr_index = 0; /* find in which sub network the client is */ for (i = 0; i < n_lan_addr; i++) { if((sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr) == (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr)) { lan_addr_index = i; break; } } if (n_lan_addr == i) { DPRINTF(E_DEBUG, L_SSDP, "Ignoring SSDP M-SEARCH on other interface [%s]\n", inet_ntoa(sendername.sin_addr)); return; } DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH from %s:%d ST: %.*s, MX: %.*s, MAN: %.*s\n", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port), st_len, st, mx_len, mx, man_len, man); /* Responds to request with a device as ST header */ for (i = 0; known_service_types[i]; i++) { l = strlen(known_service_types[i]); if ((l <= st_len) && (memcmp(st, known_service_types[i], l) == 0)) { if (st_len != l) { /* Check version number - must always be 1 currently. */ if ((st[l-1] == ':') && (st[l] == '1')) l++; while (l < st_len) { if (!isspace(st[l])) { DPRINTF(E_DEBUG, L_SSDP, "Ignoring SSDP M-SEARCH with bad extra data [%s]\n", inet_ntoa(sendername.sin_addr)); break; } l++; } if (l != st_len) break; } _usleep(random()>>20); SendSSDPAnnounce2(s, sendername, i, lan_addr[lan_addr_index].str, port); break; } } /* Responds to request with ST: ssdp:all */ /* strlen("ssdp:all") == 8 */ if ((st_len == 8) && (memcmp(st, "ssdp:all", 8) == 0)) { for (i=0; known_service_types[i]; i++) { l = strlen(known_service_types[i]); SendSSDPAnnounce2(s, sendername, i, lan_addr[lan_addr_index].str, port); } } }
/* ProcessSSDPRequest() * process SSDP M-SEARCH requests and responds to them */ void ProcessSSDPRequest(int s, unsigned short port) /*ProcessSSDPRequest(int s, struct lan_addr_s * lan_addr, int n_lan_addr, unsigned short port)*/ { int n; char bufr[1500]; socklen_t len_r; struct sockaddr_in sendername; int i, l; int lan_addr_index = 0; char * st = NULL, * mx = NULL, * man = NULL, * mx_end = NULL; int st_len = 0, mx_len = 0, man_len = 0, mx_val = 0; len_r = sizeof(struct sockaddr_in); n = recvfrom(s, bufr, sizeof(bufr), 0, (struct sockaddr *)&sendername, &len_r); if(n < 0) { DPRINTF(E_ERROR, L_SSDP, "recvfrom(udp): %s\n", strerror(errno)); return; } if(memcmp(bufr, "NOTIFY", 6) == 0) { /* ignore NOTIFY packets. We could log the sender and device type */ return; } else if(memcmp(bufr, "M-SEARCH", 8) == 0) { //DEBUG DPRINTF(E_DEBUG, L_SSDP, "Received SSDP request:\n%.*s", n, bufr); for(i=0; i < n; i++) { if( bufr[i] == '*' ) break; } if( !strcasestr(bufr+i, "HTTP/1.1") ) { return; } while(i < n) { while((i < n - 1) && (bufr[i] != '\r' || bufr[i+1] != '\n')) i++; i += 2; if((i < n - 3) && (strncasecmp(bufr+i, "ST:", 3) == 0)) { st = bufr+i+3; st_len = 0; while(*st == ' ' || *st == '\t') st++; while(st[st_len]!='\r' && st[st_len]!='\n') st_len++; } else if(strncasecmp(bufr+i, "MX:", 3) == 0) { mx = bufr+i+3; mx_len = 0; while(*mx == ' ' || *mx == '\t') mx++; while(mx[mx_len]!='\r' && mx[mx_len]!='\n') mx_len++; mx_val = strtol(mx, &mx_end, 10); } else if(strncasecmp(bufr+i, "MAN:", 4) == 0) { man = bufr+i+4; man_len = 0; while(*man == ' ' || *man == '\t') man++; while(man[man_len]!='\r' && man[man_len]!='\n') man_len++; } } /*DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH packet received from %s:%d\n", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port) );*/ if( ntohs(sendername.sin_port) <= 1024 || ntohs(sendername.sin_port) == 1900 ) { DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad source port %d]\n", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port)); } else if( !man || (strncmp(man, "\"ssdp:discover\"", 15) != 0) ) { DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad MAN header %.*s]\n", inet_ntoa(sendername.sin_addr), man_len, man); } else if( !mx || mx == mx_end || mx_val < 0 ) { DPRINTF(E_INFO, L_SSDP, "WARNING: Ignoring invalid SSDP M-SEARCH from %s [bad MX header %.*s]\n", inet_ntoa(sendername.sin_addr), mx_len, mx); } else if( st && (st_len > 0) ) { DPRINTF(E_INFO, L_SSDP, "SSDP M-SEARCH from %s:%d ST: %.*s, MX: %.*s, MAN: %.*s\n", inet_ntoa(sendername.sin_addr), ntohs(sendername.sin_port), st_len, st, mx_len, mx, man_len, man); /* find in which sub network the client is */ for(i = 0; i<n_lan_addr; i++) { if( (sendername.sin_addr.s_addr & lan_addr[i].mask.s_addr) == (lan_addr[i].addr.s_addr & lan_addr[i].mask.s_addr)) { lan_addr_index = i; break; } } /* Responds to request with a device as ST header */ for(i = 0; known_service_types[i]; i++) { l = strlen(known_service_types[i]); if(l<=st_len && (0 == memcmp(st, known_service_types[i], l))) { /* Check version number - must always be 1 currently. */ if( (st[st_len-2] == ':') && (atoi(st+st_len-1) != 1) ) break; usleep(random()>>20); SendSSDPAnnounce2(s, sendername, i, lan_addr[lan_addr_index].str, port); break; } } /* Responds to request with ST: ssdp:all */ /* strlen("ssdp:all") == 8 */ if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8))) { for(i=0; known_service_types[i]; i++) { l = (int)strlen(known_service_types[i]); SendSSDPAnnounce2(s, sendername, i, lan_addr[lan_addr_index].str, port); } } } else {