我正在尝试实现 SSDP 协议,但我不确定它是如何工作的。SSDP 通过 udp 发送数据,这很清楚。如果控制器连接到网络,它可以搜索带有 MSEARCH 消息的设备,该消息可以发送到多播地址 239.255.255.250:1900。每个设备都必须监听这个地址并做出响应。但我不知道他们是如何回应的。我在wireshark中看到他们用单播响应,但我不知道如何确定接收响应的端口。
编辑 - - - - - - - -
我正在尝试使用尖峰模糊测试框架编写 ssdp 模糊测试。正如我所说,我能够发送正确的数据,但无法接收响应。我将尝试粘贴一些带有简要说明的尖峰代码。有 Spike 结构,它表示要发送的数据(它存储实际数据、大小、协议信息......)。我删除了一些变量以使其更清晰。
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;
};
现在我正在通过 udp 发送数据,并希望通过以下功能接收一些响应
spike_connect_udp(target,port);
spike_send();
s_read_packet();
功能实现:
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;
}
这工作正常并通过 udp 发送数据。现在我想通过打开的套接字 current_spike->fd 接收一些响应。函数 s_read_packet 无效
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);
}
}
}
但是函数 s_read_packet 不会产生任何数据...