I am trying to implement SSDP protocol, but I am not sure how exactly it works. SSDP sends data over udp, that is clear. If controller connects to network it can search for devices with MSEARCH message, which can be send to multicast address 239.255.255.250:1900. Every device has to listen to this address and respond. But I don't know how they responds. I see in wireshark that they responds with unicast but I don't know how to determine port which receives responds.
EDIT---------------
I am trying to write ssdp fuzzer with spike fuzzing framework. As I said, I am able to send correct data, but unable to receive responses. I ll try to paste some spike code with brief explanation. There is Spike struct, which represents data to be send (it stores actual data, sizes, protocol info...). I removed some variables to make it more clear.
struct spike {
/*total size of all data*/
unsigned long datasize;
unsigned char *databuf;
unsigned char *endbuf;
int fd; /*for holding socket or file information*/
int proto; /*1 for tcp, 2 for udp*/
struct sockaddr_in *destsockaddr;
};
Now i am sending data via udp and want to receive some responds with following functions
spike_connect_udp(target,port);
spike_send();
s_read_packet();
Function implementations:
int
spike_connect_udp(char * host, int port)
{
int fd;
/*ahh, having udpstuff.c makes this stuff easy*/
fd=udpconnect(host,port);
if (fd==-1)
{
fprintf(stderr,"Couldn't udp connect to target\n");
return (0);
}
current_spike->fd=fd;
current_spike->proto=2; /*UDP*/
return 1;
}
int
udpconnect(const char * host, const unsigned short port )
{
int sfd = -1;
struct sockaddr_in addr;
/* Translate hostname from DNS or IP-address form */
memset(&addr, 0, sizeof(addr));
if (!getHostAddress(host, &addr))
{
hdebug("can't resolve host or address.\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_port = ntohs(port);
if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
hdebug("Could not create socket!\n");
return -1;
}
/* Now connect! */
if (connect(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
close(sfd);
return -1;
}
return sfd;
}
int
spike_send()
{
int retval;
switch (current_spike->proto)
{
case 1: /*TCP*/
//deleted, doesnt matter, i am sending via udp
case 2: /*UDP*/
//udp_write_data is function from framework
retval=udp_write_data(current_spike->fd, current_spike->destsockaddr, s_get_size(), s_get_databuf());
break;
}
fflush(0);
return retval;
}
This works fine and send data via udp. Now i would like to receive some responses via open socket current_spike->fd. Function s_read_packet void
s_read_packet()
{
unsigned char buffer[5000];
int i;
int size;
s_fd_wait();
printf("Reading packet\n");
memset(buffer,0x00,sizeof(buffer));
/what alarm and fcntl does?
alarm(1);
fcntl(current_spike->fd, F_SETFL, O_NONBLOCK);
//this read return error -1 and sets errno to 11 service temporarily unavailable
size=read(current_spike->fd,buffer,1500);
fcntl(current_spike->fd, F_SETFL, 0);
alarm(0);
for (i=0; i<size; i++)
{
if (isprint(buffer[i]))
printf("%c",buffer[i]);
else
printf("[%2.2x]",buffer[i]);
}
printf("\nDone with read\n");
}
int
s_fd_wait()
{
/*this function does a select to wait for
input on the fd, and if there
is, returns 1, else 0 */
int fd;
fd_set rfds;
struct timeval tv;
int retval;
fd=current_spike->fd;
/* Watch server_fd (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
/* Wait up to zero seconds . will this wait forever? not on linux.*/
/* from man page: timeout is an upper bound on the amount of time
elapsed before select returns. It may be zero, causing select
to return immediately. If timeout is NULL (no timeout), select
can block indefinitely. */
/*wait 2 seconds only*/
tv.tv_sec = TIMEINSECONDS;
tv.tv_usec = TIMEINUSECONDS;
//printf("Before select %d:%d\n",TIMEINSECONDS,TIMEINUSECONDS);
retval = select(fd+1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
//printf("After select retval=%d.\n",retval);
switch (retval)
{
case 0:
/*Timeout - no packet or keypress*/
return(0);
break;
case -1:
/* ignore interrupted system calls */
if (errno != EINTR)
{
/*some kind of weird select error. Die. */
exit(-1);
}
/*otherwise we got interrupted, so just return false*/
return (0);
break;
default:
{
if (FD_ISSET(fd,&rfds))
return (1);
else
return (0);
}
}
}
But function s_read_packet produces no data...