13 #include <arpa/inet.h>
35 int header_string_length = 0;
36 char *header_lower = NULL;
37 const char *header_strings[] = {
38 SSDP_HEADER_UNKNOWN_STR,
43 SSDP_HEADER_CACHE_STR,
44 SSDP_HEADER_LOCATION_STR,
47 SSDP_HEADER_01NLS_STR,
50 SSDP_HEADER_SERVER_STR,
51 SSDP_HEADER_XUSERAGENT_STR,
54 headers_size =
sizeof(header_strings)/
sizeof(
char *);
56 header_string_length = strlen(header_string);
57 if(header_string_length < 1) {
58 PRINT_ERROR(
"Erroneous header string detected");
59 return (
unsigned char)SSDP_HEADER_UNKNOWN;
61 header_lower = (
char *)malloc(
sizeof(
char) * (header_string_length + 1));
63 memset(header_lower,
'\0',
sizeof(
char) * (header_string_length + 1));
66 for(i = 0; header_string[i] !=
'\0'; i++){
67 header_lower[i] = tolower(header_string[i]);
70 for(i = 0; i < headers_size; i++) {
71 if(strcmp(header_lower, header_strings[i]) == 0) {
73 return (
unsigned char)i;
77 return (
unsigned char)SSDP_HEADER_UNKNOWN;
102 int header_name_length = -1, header_contents_length = -1;
103 int raw_header_length = 0;
106 header_name_length =
strpos(raw_header,
":");
107 if(header_name_length < 1) {
110 header_name = (
char *)malloc(header_name_length + 1);
111 memset(header_name,
'\0', header_name_length + 1);
112 strncpy(header_name, raw_header, header_name_length);
115 if(header->
type == SSDP_HEADER_UNKNOWN) {
117 memset(header->
unknown_type,
'\0', header_name_length + 1);
124 raw_header_length = strlen(raw_header);
125 header_contents_length = raw_header_length - header_name_length + 2;
126 header->
contents = (
char *)malloc(header_contents_length);
127 memset(header->
contents,
'\0', header_contents_length);
129 strcpy(header->
contents, &raw_header[header_name_length + 1 +
130 (raw_header[header_name_length + 2] ==
' ' ? 1 : 0)]);
135 const char *custom_field) {
138 if(ssdp_message && custom_field) {
145 if(0 == strcmp(custom_field, cf->
name)) {
158 int bytes_received = 0;
159 char *location_header = NULL;
163 PRINT_DEBUG(
"Custom info has already been fetched for this device");
168 PRINT_ERROR(
"Missing headers, cannot fetch custom info");
172 while(ssdp_headers) {
173 if(ssdp_headers->
type == SSDP_HEADER_LOCATION) {
174 location_header = ssdp_headers->
contents;
177 PRINT_DEBUG(
"found header_location: %s", location_header);
179 ssdp_headers = ssdp_headers->
next;
183 if(location_header != NULL) {
186 PRINT_DEBUG(
"allocating for URL parsing");
189 char *rest = (
char *)malloc(
sizeof(
char) * 256);
190 char *request = (
char *)malloc(
sizeof(
char) * 1024);
193 memset(rest,
'\0', 256);
194 memset(request,
'\0', 1024);
198 PRINT_DEBUG(
"trying to parse URL");
202 PRINT_DEBUG(
"creating socket");
222 PRINT_ERROR(
"fetch_custom_fields(); setup_socket(): (%d) %s", errno, strerror(errno));
241 PRINT_DEBUG(
"setting up socket addresses");
242 struct sockaddr_storage *da = (
struct sockaddr_storage *)malloc(
sizeof(
struct sockaddr_storage));
243 memset(da, 0,
sizeof(
struct sockaddr_storage));
244 da->ss_family = conf->
use_ipv6 ? AF_INET6 : AF_INET;
245 if(!inet_pton(da->ss_family, ip, (da->ss_family == AF_INET ? (
void *)&((
struct sockaddr_in *)da)->sin_addr : (
void *)&((
struct sockaddr_in6 *)da)->sin6_addr))) {
246 int ip_length = strlen(ip);
248 PRINT_ERROR(
"The destination IP address could be determined (%s)\n", (ip_length < 1 ?
"empty" : ip));
259 if(da->ss_family == AF_INET) {
260 struct sockaddr_in *da_ipv4 = (
struct sockaddr_in *)da;
261 da_ipv4->sin_port = htons(port);
264 struct sockaddr_in6 *da_ipv6 = (
struct sockaddr_in6 *)da;
265 da_ipv6->sin6_port = htons(port);
272 inet_ntop(da->ss_family, (da->ss_family == AF_INET ? (
void *)&((
struct sockaddr_in *)da)->sin_addr : (
void *)&((
struct sockaddr_in6 *)da)->sin6_addr), tmp_ip,
IPv6_STR_MAX_SIZE);
273 PRINT_DEBUG(
"connecting to destination (%s; ss_family = %s [%d])", tmp_ip, (da->ss_family == AF_INET ?
"AF_INET" :
"AF_INET6"), da->ss_family);
277 if(connect(fetch_sock, (
struct sockaddr*)da,
sizeof(
struct sockaddr)) ==
SOCKET_ERROR) {
278 PRINT_ERROR(
"fetch_custom_fields(); connect(): (%d) %s", errno, strerror(errno));
296 used_length += snprintf(request + used_length, 1024 - used_length,
"GET %s HTTP/1.0\r\n", rest);
297 used_length += snprintf(request + used_length, 1024 - used_length,
"Host: %s\r\n", ip);
298 snprintf(request + used_length, 1024 - used_length,
"User-Agent: abused-%s\r\n\r\n",
ABUSED_VERSION);
299 PRINT_DEBUG(
"sending string:\n%s", request);
300 int bytes = send(fetch_sock, request, strlen(request), 0);
301 PRINT_DEBUG(
"sent %d bytes", bytes);
304 bytes = recv(fetch_sock, response + bytes_received,
DEVICE_INFO_SIZE - bytes_received, 0);
305 bytes_received += bytes;
307 PRINT_DEBUG(
"received %d bytes", bytes_received);
308 PRINT_DEBUG(
"%s", response);
309 PRINT_DEBUG(
"closing socket");
317 char *tmp_pointer = NULL;
320 const char *field[] = {
329 int fields_size =
sizeof(field) /
sizeof(
char *);
330 PRINT_DEBUG(
"fields_size: %d", fields_size);
332 for(i = 0; i < fields_size; i++) {
335 int field_length = strlen(field[i]);
337 char needle[field_length + 4];
338 sprintf(needle,
"<%s>", field[i]);
339 tmp_pointer = strstr(response, needle);
348 cf->
name = (
char *)malloc(
sizeof(
char) * field_length + 1);
349 strcpy(cf->
name, field[i]);
352 sprintf(needle,
"</%s>", field[i]);
353 buffer_size = (int)(strstr(response, needle) - (tmp_pointer + field_length + 2) + 1);
354 cf->
contents = (
char *)malloc(
sizeof(
char) * buffer_size);
355 memset(cf->
contents,
'\0', buffer_size);
356 strncpy(cf->
contents, (tmp_pointer + field_length + 2), buffer_size - 1);
358 PRINT_DEBUG(
"Found expected custom field (%d) '%s' with value '%s'",
364 PRINT_DEBUG(
"Expected custom field '%s' is missing", field[i]);
399 return bytes_received;
404 const char *header_strings[] = {
405 SSDP_HEADER_UNKNOWN_STR,
406 SSDP_HEADER_HOST_STR,
410 SSDP_HEADER_CACHE_STR,
411 SSDP_HEADER_LOCATION_STR,
412 SSDP_HEADER_HOST_STR,
414 SSDP_HEADER_01NLS_STR,
417 SSDP_HEADER_SERVER_STR,
418 SSDP_HEADER_XUSERAGENT_STR,
422 if((header_type == 0 ||
423 (header_type > (
sizeof(header_strings)/
sizeof(
char *) - 1))) &&
428 return header_strings[header_type];
432 if(NULL == *message_pointer) {
434 if(!*message_pointer) {
441 if(NULL == message->
mac) {
447 if(NULL == message->
ip) {
453 message->
datetime = (
char *)malloc(
sizeof(
char) * 20);
460 memset(message->
datetime,
'\0', 20);
461 message->
request = (
char *)malloc(
sizeof(
char) * 1024);
469 memset(message->
request,
'\0', 1024);
470 message->
protocol = (
char *)malloc(
sizeof(
char) * 48);
479 memset(message->
protocol,
'\0',
sizeof(
char) * 48);
480 message->
answer = (
char *)malloc(
sizeof(
char) * 1024);
481 if(NULL == message->
answer) {
490 memset(message->
answer,
'\0',
sizeof(
char) * 1024);
491 message->
info = NULL;
499 int message_length,
const char *raw_message) {
501 int newline = 0, last_newline = 0;
502 int raw_message_left = strlen(raw_message);
506 strftime(message->
datetime, 20,
"%Y-%m-%d %H:%M:%S", localtime(&t));
518 last_newline =
strpos(raw_message,
"\r\n");
519 if(last_newline < 0) {
520 PRINT_DEBUG(
"build_ssdp_message() failed: last_newline < 0");
534 newline =
strpos(raw_message,
"HTTP");
537 PRINT_DEBUG(
"build_ssdp_message() failed: newline < 0");
540 strncpy(message->
request, raw_message, (!newline? newline : newline - 1));
541 strncpy(message->
protocol, &raw_message[newline], last_newline - 2 - newline);
553 pos =
strpos(&raw_message[last_newline],
"\r\n");
556 PRINT_DEBUG(
"build_ssdp_message() failed: pos < 0");
559 newline = last_newline + pos;
561 raw_header = (
char *)malloc(
sizeof(
char) * (newline - last_newline + 1));
563 memset(raw_header,
'\0', (newline - last_newline + 1));
564 strncpy(raw_header, &raw_message[last_newline], newline - last_newline);
574 raw_message_left = strlen(&raw_message[newline]);
575 if(raw_message_left < 4 || (raw_message[newline] ==
'\r' && raw_message[newline + 1] ==
'\n' &&
576 raw_message[newline + 2] ==
'\r' && raw_message[newline + 3] ==
'\n')) {
577 has_next_header =
FALSE;
581 if(has_next_header) {
583 last_newline = newline + 2;
599 }
while(has_next_header);
612 if(!message_pointer || !*message_pointer) {
613 PRINT_ERROR(
"Message was empty, nothing to free");
618 *message_pointer = NULL;
620 if(message->
mac != NULL) {
625 if(message->
ip != NULL) {
645 if(message->
answer != NULL) {
650 if(message->
info != NULL) {
652 message->
info = NULL;
669 message->
headers = next_header;
689 next_custom_field = NULL;
#define IPv6_STR_MAX_SIZE
SOCKET setup_socket(socket_conf_s *conf)
int fetch_custom_fields(configuration_s *conf, ssdp_message_s *ssdp_message)
char ip[IPv6_STR_MAX_SIZE]
BOOL parse_url(const char *url, char *ip, int ip_size, int *port, char *rest, int rest_size)
unsigned char header_count
struct ssdp_custom_field_struct * custom_fields
static void build_ssdp_header(ssdp_header_s *header, const char *raw_header)
char interface[IPv6_STR_MAX_SIZE]
BOOL build_ssdp_message(ssdp_message_s *message, char *ip, char *mac, int message_length, const char *raw_message)
static unsigned char get_header_type(const char *header_string)
struct ssdp_header_struct * headers
void free_ssdp_message(ssdp_message_s **message_pointer)
unsigned char custom_field_count
int set_receive_timeout(SOCKET sock, int timeout)
const char * get_header_string(const unsigned int header_type, const ssdp_header_s *header)
ssdp_custom_field_s * get_custom_field(const ssdp_message_s *ssdp_message, const char *custom_field)
struct ssdp_custom_field_struct * first
int strpos(const char *haystack, const char *needle)
int set_send_timeout(SOCKET sock, int timeout)
static configuration_s conf
BOOL init_ssdp_message(ssdp_message_s **message_pointer)
struct ssdp_custom_field_struct * next