I'm brand new to working with networking, protocols, and sockets but this issue has been bothering me for a few days and I just cannot seem to find a solution. I am using Seagull, an open source multi-protocol traffic generator (source code), to create a client with a custom UDP. The unfortunate thing is that no one really keeps up with this software anymore and other people have had this problem but there are no solutions and it may be a bug in the generator software. I was able to write the XML scripts needed to run the traffic generator and when I ran the client on the local loopback (127.0.0.1) the generator worked fine and I was able to collect the packets and analyze them with Wireshark and they contained the correct data.
I'm now trying to use this client to send messages to a server on my local network (192.x.x.x) but Seagull keeps failing to send the messages. It's not a network issue because I've been able to ping the address with no packet loss. I've traced the source of the error back to the sendto()
function, which keeps failing due to an invalid argument. I've stepped through the code using GDB when the destination was set to both the local loopback and the other IP and the arguments passed to the sendto() function were the exact same with the exception of different IP addresses in the sockaddr
struct, which is of course expected. However, when I look at the registers after the system call in sendto()
for the the one that contains the value for the length of the message length turns negative partway through the call and that is the value that is returned from the function call- this does not happen with the local loopback network. Here is the section of code that calls sendto()
and fails:
size_t C_SocketWithData::send_buffer(unsigned char *P_data,
size_t P_size){
// T_SockAddrStorage *P_remote_sockaddr,
// tool_socklen_t *P_len_remote_sockaddr) {
size_t L_size = 0 ;
int L_rc ;
if (m_write_buf_size != 0) {
// Try to send pending data
if (m_type == E_SOCKET_TCP_MODE) {
L_rc = _call_write(m_write_buf, m_write_buf_size) ;
} else {
L_rc = _write(m_write_buf, m_write_buf_size) ;
}
if (L_rc < 0) {
SOCKET_ERROR(0,
"send failed [" << L_rc << "] [" << strerror(errno) << "]");
switch (errno) {
case EAGAIN:
SOCKET_ERROR(0, "Flow control not implemented");
break ;
case ECONNRESET:
break ;
default:
SOCKET_ERROR(0, "process error [" << errno << "] not implemented");
break ;
}
return(0);
where _write()
is a wrapper for sendto()
.
I'm not really sure what is going on that causes it to do this and I've spent hours looking through the source code and tracing what is going on but everything seems normal up until the buffer length is modified in the system call. I've looked at the socket()
initialization, binding, and other functions but everything seems fine. If anyone has any experience with Seagull or this problem, please let me know if you have had any suggestions. I've looked through almost every sendto()
related question on this website and have not found a solution.
I am running the client on Ubuntu v 14.04 through a VM (Virtualbox) on a Windows 10 host, where I'm trying to send the messages. Thanks in advance!
I figured out the answer to this after days of debugging and looking through source code and I want to update this in case any poor soul in the future has the same problem. The original Seagull implementation always tries to bind the socket before calling send
/sendto
. In this case, since sendto
automatically binds the socket I was able to remove the binding for this case.
Original implementation in C_SocketClient::_open (C_Socket.cpp Line 666):
} else {
L_rc = call_bind(m_socket_id,
(sockaddr *)(void *)&(m_remote_addr_info->m_addr_src),
SOCKADDR_IN_SIZE(&(m_remote_addr_info->m_addr_src)));
Edited Version:
} else {
L_rc = call_bind(m_socket_id,
/* UDP Does not need to bind first */
if(m_type != E_SOCKET_UDP_MODE) {
L_rc = call_bind(m_socket_id,
(sockaddr *)(void *)&(m_remote_addr_info->m_addr_src),
SOCKADDR_IN_SIZE(&(m_remote_addr_info->m_addr_src)));
} else {
L_rc = 0;
}
Now Seagull works and I am able to send my custom protocol! I opened a pull request for the original source code so that this can possibly be fixed.