Reputation: 4052
I've added a Unix domain socket to a project I'm working on. The socket has a simple function, it simply broadcasts data that the code extracts from another device, the idea is that other applications will be able to read this data from the socket.
I've written a simple server code, and when I run the code on my laptop, using a Ubuntu 10.04 VM, it works perfectly well. However, when I copy the code over onto the embedded device I'm using the code fails, when my application tries to write to the socket the code exits.
In /var/log/messages
I see the following messages:
Dec 2 15:12:17 box local1.info my-app[17338]: Socket Opened
Dec 2 15:12:17 box local1.err my-app[17338]: Socket Failed
Dec 2 15:12:17 box local1.err my-app[17338]: Protocol wrong type for socket
Dec 2 15:12:38 box local1.info ./server[17178]: accept failed: Invalid argument
Here is the server code:
#include <stdio.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include<syslog.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BUF_SIZE 256 //Max length of string listened to
#define BACKLOG 5
int main(int argc, char *argv[]){
struct sockaddr_un addr;
int sfd, cfd; //File Descriptors for the server and the client
ssize_t numRead; //Length of the string read from the client.
u_int8_t buf[BUF_SIZE]; //String that reads messages
char plain[BUF_SIZE]; //Plain string for writing to the log
memset(plain, 0, sizeof plain); //blank out plain string
openlog(argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); //Write the messages to the syslog
//---Declare socket--------------------------------------
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sfd!=0){
syslog(LOG_INFO, "socket success");
}
else{
syslog(LOG_INFO, "socket unsuccessful");
}
//--Test to see if there's already a socket at SV_SOCK_PATH, and remove it if there is.
if (remove(SV_SOCK_PATH) == -1 && errno !=ENOENT){
syslog(LOG_INFO, "error removing socket");
}
//-----------------------------------------------------------
//--blank out the socket address, then write the information to it
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path)-1); //ensure path is null terminated
//----Bind the socket to the address-------------------------------------
if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un))!=0){
syslog(LOG_INFO, "bind unsuccessful");
}
else{
syslog(LOG_INFO, "bind successful");
}
//------------------------------------------------------------------------
//-----Listen on the socket-----------------------------------------------
if (listen(sfd, BACKLOG) != 0){
syslog(LOG_INFO, "listen failed");
}
else{
syslog(LOG_INFO, "listen succeeded");
}
//-------------------------------------------------------------------------
//--------Accept messages on the socket------------------------------------
socklen_t csize;
while(1){
cfd = accept(sfd, (struct sockaddr *)&addr,&csize);
if (cfd < 0) {
syslog(LOG_INFO, "accept failed: %s", strerror(errno));
}
while ( (numRead=read(cfd, buf, BUF_SIZE)) > 0 ){
dump_packet(buf, numRead);
}
}
//-------------------------------------------------------------------------
//---code never gets here but this is how to close the log and the socket--
closelog();
close(cfd);
}
And here's a simple version of the client that connects to this server from my app:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SV_SOCK_PATH "/tmp/rtig.sock" //path to be used by socket
#define BACKLOG 5
int isDaemon = 1;
void etmlog(int level, char *message)
{
isDaemon == 1 ? syslog(level, message) : printf(message);
}
int main(){
struct sockaddr_un addr;
unsigned int sockfd;
ssize_t numRead;
if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) > 0) {
etmlog(LOG_INFO, "Socket Opened\n");
}
else {
etmlog(LOG_ERR, "Socket Failed:\n");
etmlog(LOG_ERR, strerror(errno));
exit(-1);
}
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1); // -1 ensures null terminated string
if (connect
(sockfd, (struct sockaddr *)&addr,
sizeof(struct sockaddr_un)) == -1) {
etmlog(LOG_ERR, "Socket Failed\n");
etmlog(LOG_ERR, strerror(errno));
exit(1);
} else {
etmlog(LOG_INFO, "Socket Connection Successful\n");
}
while (1){
// some data is read into buf up here
if (write(sockfd, buf, rdlen) < 0) {
etmlog(LOG_ERR, "Write to Socket Failed:");
etmlog(LOG_ERR, strerror(errno));
}
}
close(sockfd);
return 0;
}
I appreciate that I've just posted a lot of code to read through, but I'd be very grateful if someone could give me a few pointers on this.
Upvotes: 0
Views: 1278
Reputation: 119847
You are not using accept
correctly. The third argument must be initialized to the size of the second argument, so that accept
won't overflow it. See man accept
.
Upvotes: 5