Reputation: 924
I am attempting to monitor a long running daemon using a monitoring application which creates a UNIX socket and listens. In testing, however, I have found that calls I am making to the system on other threads within the application are showing up in this socket.
// Output from Server Test Application (just echoing from recv buffer)
# serverTest /tmp/receiver-programmer-socket
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: PING 192.168.1.51 (192.168.1.51): 56 data bytes
--- 192.168.1.51 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: PING 192.168.1.52 (192.168.1.52): 56 data bytes
--- 192.168.1.52 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: PING 192.168.1.51 (192.168.1.51): 56 data bytes
--- 192.168.1.51 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: PING 192.168.1.52 (192.168.1.52): 56 data bytes
--- 192.168.1.52 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
MESSAGE FROM CLIENT: test
The long running daemon is already created and outputs to a socket if available. At the moment it is just writting "test" to the socket every second.
// Long Running Daemon Snippet
int Monitor::write_to_socket(){
std::string string = "test";
char buffer[1024];
bzero(buffer, sizeof(buffer));
strcpy(buffer, string.c_str());
if (send(sockfd, buffer, strlen(buffer), MSG_NOSIGNAL) < 0)
{
syslog(LOG_INFO, "Error sending to socket");
close(sockfd);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
I have pasted together a quick server application to test that everything was working correctly, so the code is very rough.
/* a server in the unix domain. The pathname of
the socket address is passed as an argument */
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/un.h>
#include <stdio.h>
void error(const char *);
int connection_handler(int);
int main(int argc, char *argv[])
{
// File descriptors
int sockfd, newsockfd;
// Length of address string
int servlen;
//
int n;
// Size of client address
socklen_t clilen;
// Client socket address
struct sockaddr_un cli_addr;
// Server socket address
struct sockaddr_un serv_addr;
// Character buffer
char buf[80];
// Create socket
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
error("creating socket");
// Sets server address area to all zeros
bzero((char *)&serv_addr, sizeof(serv_addr));
// Sets server address family to local interprocess
serv_addr.sun_family = AF_UNIX;
// Sets server address path to passed in argument
strcpy(serv_addr.sun_path, argv[1]);
// Sets length of full server address
servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);
// Bind socket at address and port (sortof)
if (bind(sockfd, (struct sockaddr *)&serv_addr, servlen) < 0)
error("binding socket");
// Start listening for requests
listen(sockfd, 5);
pid_t child;
int connection_fd;
socklen_t address_length;
while((connection_fd = accept(sockfd, (struct sockaddr *) &serv_addr, &address_length)) > -1)
{
child = fork();
if(child == 0)
{
/* now inside newly created connection handling process */
return connection_handler(connection_fd);
}
/* still inside server process */
close(connection_fd);
}
return 0;
}
int connection_handler(int connection_fd)
{
int nbytes;
char buffer[256];
while(1) {
bzero((char *)&buffer, sizeof(buffer));
// Corrected to test for correct return and buffer size
if((nbytes = recv(connection_fd, buffer, 256, 0)) > 0)
{
buffer[nbytes] = 0;
printf("MESSAGE FROM CLIENT: %s\n", buffer);
}
}
close(connection_fd);
return 0;
}
void error(const char *msg)
{
perror(msg);
exit(0);
}
I'm not certain how the calls are being introduced to the socket. There are no sockets used anywhere else in this application. Is there a buffer that I should be clearing before writting or reading from the socket?
Portion from strace
output.
[pid 15286] close(4) = 0
[pid 15286] accept(3, <unfinished ...>
[pid 15296] recv(4, "test", 256, 0) = 4
[pid 15296] fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
[pid 15296] mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40001000
[pid 15296] write(1, "MESSAGE FROM CLIENT: test\n", 26MESSAGE FROM CLIENT: test
) = 26
[pid 15296] recv(4, "PING 192.168.1.50 (192.168.1.50)"..., 256, 0) = 103
[pid 15296] write(1, "MESSAGE FROM CLIENT: PING 192.16"..., 124MESSAGE FROM CLIENT: PING 192.168.1.50 (192.168.1.50): 56 data bytes
64 bytes from 192.168.1.50: seq=0 ttl=64 time=2.156 ms
) = 124
[pid 15296] write(1, "\n", 1
) = 1
[pid 15296] recv(4, "\n--- 192.168.1.50 ping statistic"..., 256, 0) = 142
[pid 15296] write(1, "MESSAGE FROM CLIENT: \n--- 192.16"..., 163MESSAGE FROM CLIENT:
--- 192.168.1.50 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 2.156/2.156/2.156 ms
) = 163
[pid 15296] write(1, "\n", 1
) = 1
[pid 15296] recv(4, "PING 192.168.1.50 (192.168.1.50)"..., 256, 0) = 103
[pid 15296] write(1, "MESSAGE FROM CLIENT: PING 192.16"..., 124MESSAGE FROM CLIENT: PING 192.168.1.50 (192.168.1.50): 56 data bytes
64 bytes from 192.168.1.50: seq=0 ttl=64 time=2.063 ms
) = 124
It appears to be like the message is being read in correctly. I will work on parsing the output from the daemon's strace to see if it uncovers anything.
UPDATE
I was not able to determine the source of this issue. I rewrote all system calls to output to /dev/null
and still received the warning and error messages in the socket. I attempted to switch to a TCP socket but encountered the same issue. strace
didn't reveal any send or write calls on the socket that would lead to these calls appearing.
Eventual solution was to use telnet and ANSI controls to constantly rewrite telnet output to mask warning messages.
Upvotes: 1
Views: 1987
Reputation: 443
The problem is not with the buffer and the chance is minimal that some other part of the program is writing to your buffer, since the buffer is allocated on stack. It seems that the message is received on the socket, but is strange for a normal Linux that the socket fd=3, you don't have any open files?
For example:
nbytes = recv(connection_fd, buffer, 256, 0)
buffer[nbytes] = \0;
When nbytes is 256 you are writing outside the buffer, which can cause even segmentation faults.
connection_fd = accept(sockfd, (struct sockaddr *) &serv_addr, &address_length)
Overwriting server address, it should be cli_addr probably
Upvotes: 1