Reusing linux abstract namespace socket - c

I would like to reuse one abstract socket adress during one server session. I tried to close sockets and bind them again, but it isn't working.
server.c:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int main()
{
struct sockaddr_un workmanaddr;
workmanaddr.sun_family=AF_UNIX;
strcpy(workmanaddr.sun_path+1,"name");
workmanaddr.sun_path[0]='0';
char buf[255];
int sd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(sd <0)
{
perror("socket() error");
exit(2);
}
if((bind(sd , (struct sockaddr *)&workmanaddr,sizeof(workmanaddr)))<0)
{
perror("bind() error");
exit(3);
}
while(true)
{
recv(sd, buf, sizeof(buf), 0);
printf("%s\n",buf);
close(sd);
sd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(sd <0)
{
perror("socket() error");
exit(2);
}
if((bind(sd , (struct sockaddr*)&workmanaddr,sizeof(workmanaddr)))<0)
{
perror("bind() error");
exit(3);
}
}
return 0;
}
client.c:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int main(int argc, char *argv[])
{
char _path[108]="name";
struct sockaddr_un tempadres = {0};
int tmpsock;
tmpsock = socket(AF_UNIX, SOCK_DGRAM, 0);
if(tmpsock<0)
{
perror("socket() error");
exit(2);
}
tempadres.sun_family=AF_UNIX;
strcpy(tempadres.sun_path+1,_path);
tempadres.sun_path[0]='0';
if((connect(tmpsock, (struct sockaddr *)&tempadres,sizeof(tempadres)))<0)
{
perror("connect() error");
exit(3);
}
char buf[255];
scanf("%s",buf);
if(send(tmpsock, buf, sizeof(buf), 0)<0)
{
perror("send() error");
exit(4);
}
return 0;
}
What should I do to make it possible to reuse it many times? Any advices?

In this line: tempadres.sun_path[0]='0','0' is not null byte what abstract socket requires for the first byte of the sun_path field. So it wouldn't be regarded as abstract socket. Change it to tempadres.sun_path[0]=0 or tempadres.sun_path[0]='\0'.
PS: there is another problem in your server.c, you didn't zero out workmanaddr, so the sun_path is very likely to contain garbage value as it's allocated on the stack even though you called strcpy(workmanaddr.sun_path+1,"name"); and a null byte is appended because all the remaining bytes in sun_path define the "name" of the socket. it would lead to different socket names with the client, resulting in connection refused on client side.

Related

Why bind function is returning -1

So i am following the book of UNIX network programming, and tried to write a simple daytime server from chapter 1 and client but the bind function is always returning an error, what I'm doing wrong can anyone help??
server.c
/*
* Daytime Server
*/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h>
void printError(char *str)
{
printf("%s", str);
exit(0);
}
int main(int argc, char **argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[4096];
time_t ticks;
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printError("Error at line 32 socket fuct.");
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13);
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printError("Error at bind function");
}
if (listen(listenfd, 1024) < 0)
{
printError("Error at listen fuct.");
}
while (1)
{
if ((connfd = accept(listenfd, (struct sockaddr *)NULL, NULL)) < 0)
{
printError("Error at accept fuct.");
}
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
if (write(connfd, buff, strlen(buff)) < 0)
{
printError("Error at write fuct.");
}
close(connfd);
}
return EXIT_SUCCESS;
}
client.c
/*
* Daytime Client
*/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
void printError(char *str)
{
printf("%s", str);
exit(0);
}
int main(int argc, char **argv)
{
int socketfd, n;
char recvline[4097];
struct sockaddr_in servaddr;
if (argc != 2)
{
printError("Requires ip address of the server");
}
if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printError("Unable to create a Connection");
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_port = htons(13);
servaddr.sin_family = AF_INET;
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
{
printError("Not valid IP");
}
if (connect(socketfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printError("Connection Error");
}
while ((n = read(socketfd, recvline, 4096)) > 0)
{
recvline[n] = 0;
if (fputs(recvline, stdout) == EOF)
{
printError("Fputs Error");
}
}
if (n < 0)
{
printError("Not readable");
}
return EXIT_SUCCESS;
}
Running server is always returning -1 on bind function. and running client always prints connection error.
Thank you in advance for help.
You should check with errno to find out WHY bind() is failing when it returns -1. You can use perror() to print a human-readable description of errno to the console, or at least strerror() to get that description in a string buffer that you can then do whatever you want with.
But the most likely reason for WHY bind() is failing is that you are trying to bind() your server to port 13. On most systems, ports 0-1023 are reserved for system services, so you would need to run your app with admin rights to listen on those ports.

Connect() function in C, invalid argument

I'm coding a client/server, the client simply sends a message to the server that he will print the message.
To do this I used sockets and localhost. Here is the code:
server:
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/un.h>
#include <sys/socket.h>
#include"thpool.h"
#include"functions.h"
#define N 7
#define SERVER_PATH "/tmp/server"
int main(void){
unlink(SERVER_PATH);
struct sockaddr_un stru;
int sock_serv, new_sock;
int opt = 1;
struct sockaddr* cliaddr;
char buff[N];
cliaddr = malloc(sizeof(struct sockaddr));
socklen_t addrlen = strlen((char* )cliaddr);
if((sock_serv = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
printf("socket creation error");
exit(-1);
}
bzero(&stru, sizeof(struct sockaddr_in));
stru.sun_family = AF_UNIX ;
strncpy (stru.sun_path, SERVER_PATH, sizeof(stru.sun_path));
if((bind(sock_serv, (struct sockaddr*) &stru , sizeof(struct sockaddr_un ))) < 0){
perror("bind failed");
exit(EXIT_FAILURE);
}
if(listen(sock_serv, SOMAXCONN) < 0){
perror("listen error\n");
exit(EXIT_FAILURE);
}
if((new_sock = accept(sock_serv, NULL, 0)) < 0){
perror("accept error\n");
exit(EXIT_FAILURE);
}
read(new_sock , buff, N) ;
printf("Server got: %s\n" , buff);
close(sock_serv);
close(new_sock);
unlink(SERVER_PATH);
return 0;
}
and here is the client:
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/un.h>
#include <sys/socket.h>
#include<errno.h>
#include"thpool.h"
#include"functions.h"
#define SERVER_PATH "/tmp/server"
int main(void){
int sock_cl;
struct sockaddr* sa;
socklen_t sa_lenght;
sa = malloc(sizeof(struct sockaddr));
sa_lenght = strlen((char* )sa);
if((sock_cl = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
perror("socket creation error");
exit(EXIT_FAILURE);
}
sa->sa_family = AF_UNIX ;
strncpy (sa->sa_data, SERVER_PATH, sizeof(sa->sa_data));
while (connect(sock_cl , (struct sockaddr*)&sa , (socklen_t)sa_lenght) == -1) {
perror("connection to the server failed");
exit(EXIT_FAILURE);
}
write (sock_cl, "Hello!", 7);
printf("message sended\n");
close(sock_cl);
return 0;
}
I have a problem with the connect() function, the error is "invalid argument". Note that I first executed the server and then the client, so is not that the problem.
This is how you define sa, as a pointer to struct sockaddr.
struct sockaddr* sa;
Here you take the address of the variable sa and cast it to the type of sa.
(struct sockaddr*)&sa
The result is a pointer to pointer to struct sockaddr, which gets brute force cast to pointer to struct sockaddr.
Type-casting is a trap and you got caught in it.
To solve, I recommend using a tutorial on sockets.
I think that when comparing your client and the example client in this tutorial especially the pointer level issue you have created becomes nicely visible:
https://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
Your server and client are both misusing the sockaddr... structures. The error on the server side doesn't affect anything because it is not actually using the faulty sockaddr it allocates, it just leaks. But your client is completely misusing the sockaddr that is passed to connect(), which is why connect() fails.
Try this instead:
server
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/un.h>
#include <sys/socket.h>
#include "thpool.h"
#include "functions.h"
#define N 7
#define SERVER_PATH "/tmp/server"
int main(void){
unlink(SERVER_PATH);
struct sockaddr_un stru;
int sock_serv, new_sock;
ssize_t bufflen;
char buff[N];
if((sock_serv = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
printf("socket creation error");
exit(-1);
}
bzero(&stru, sizeof(stru));
stru.sun_family = AF_UNIX;
strncpy (stru.sun_path, SERVER_PATH, sizeof(stru.sun_path));
if((bind(sock_serv, (struct sockaddr*) &stru, sizeof(stru))) < 0){
perror("bind error");
exit(EXIT_FAILURE);
}
if(listen(sock_serv, SOMAXCONN) < 0){
perror("listen error");
exit(EXIT_FAILURE);
}
if((new_sock = accept(sock_serv, NULL, 0)) < 0){
perror("accept error");
exit(EXIT_FAILURE);
}
bufflen = read(new_sock, buff, N);
if (bufflen < 0) {
perror("read error");
}
else if (bufflen == 0) {
printf("Client disconnected\n");
}
else {
printf("Server got: %.*s\n", (int) bufflen, buff);
}
close(new_sock);
close(sock_serv);
unlink(SERVER_PATH);
return 0;
}
client
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <errno.h>
#include "thpool.h"
#include "functions.h"
#define SERVER_PATH "/tmp/server"
const char *msg = "Hello!";
int main(void){
int sock_cl;
struct sockaddr_un sa;
ssize_t sent;
if((sock_cl = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
perror("socket creation error");
exit(EXIT_FAILURE);
}
bzero(&s, sizeof(sa));
sa.sa_family = AF_UNIX;
strncpy (sa.sa_data, SERVER_PATH, sizeof(sa.sa_data));
if (connect(sock_cl, (struct sockaddr*) &sa, (socklen_t) sizeof(sa)) < 0) {
perror("connect error");
exit(EXIT_FAILURE);
}
sent = write(sock_cl, msg, strlen(msg)+1);
if (sent < 0) {
perror("write error");
}
else {
printf("Message sent: %.*s\n", (int) sent, msg);
}
close(sock_cl);
return 0;
}

C Socket, server and client. connect error: "No route to Host"

I've written the client code and the server, however, there is a problem with connect: "No route to host". It is strange because clients and servers operate in a different network. Also, if I ping [my ip] tells me timeout, if I telnet [my ip] tells me error. Can you advise me how to solve this problem? I opened port 2222 from the router but it still does not seem to work.
Sorry for my English
Client code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#define ADDRESS "[IP]"
#define PORT 2222
int main()
{
int sockid;
struct sockaddr_in c_address;
printf("[CLIENT] Eseguito.\n");
c_address.sin_family = AF_INET;
c_address.sin_addr.s_addr = inet_addr(ADDRESS);
c_address.sin_port = htons(PORT);
sockid = socket(AF_INET, SOCK_STREAM, 0);
int sock_conn;
sock_conn = connect(sockid, (struct sockaddr *)&c_address, sizeof(c_address));
if(sock_conn == -1)
{
perror("Connect client");
exit(EXIT_FAILURE);
}
while(1)
{
char text[128];
printf("[CLIENT] Scrivi qualcosa: ");
fgets(text, 128, stdin);
write(sockid, text, 128);
read(sockid, text, 128);
printf("[CLIENT] Testo ricevuto: %s.\n", text);
}
}
Server code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#define PORT 2222
void toggleCharacter(char *str);
int main()
{
int sockid;
struct sockaddr_in s_address;
printf("[SERVER] Eseguito.\n");
s_address.sin_family = AF_INET;
s_address.sin_addr.s_addr = htonl(INADDR_ANY);
s_address.sin_port = htons(PORT);
sockid = socket(AF_INET, SOCK_STREAM, 0);
if(bind(sockid, (struct sockaddr *)&s_address, sizeof(s_address)) == -1)
{
perror("Bind server");
exit(EXIT_FAILURE);
}
if(listen(sockid, 5) == -1)
{
perror("Listen server");
exit(EXIT_FAILURE);
}
int connection_socket;
connection_socket = accept(sockid, NULL, 0);
if(connection_socket == -1)
{
perror("Accept server");
exit(EXIT_FAILURE);
}
char text[128];
while(1)
{
read(connection_socket, text, 128);
printf("[SERVER] Messaggio ricevuto: %s.\n", text);
printf("[SERVER] Scrivi qualcosa: ");
fgets(text, 128, stdin);
write(connection_socket, text, 128);
}
close(connection_socket);
}

Why does this server not outputting anything?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
int main()
{
int sock, newsock;
struct sockaddr server_name = {AF_UNIX, "Fred"};
socklen_t len=sizeof(struct sockaddr)+5;
if( (sock=socket(AF_UNIX,SOCK_STREAM,0)) ==-1)
{
printf("error creating socket");
return -1;
}
if( bind(sock,&server_name,len) != 0 ) //binding
{
printf("socket bind error ");
return -1;
}
if(listen(sock,10)!=0) //set sock to listen
{
printf("error listening");
return -1;
}
printf("Waiting for connections....");
while(1)
{
newsock=accept(sock, (struct sockaddr*)NULL, NULL);
char temp[1000]="gggggg\n";
write(newsock,temp,strlen(temp));
write(newsock,temp,strlen(temp));
close(newsock);
sleep(1);
}
return 0;
}
"Waiting for connections..." doesn't appear on my screen. What's the problem? I tried print function everywhere. Nothing shows up..What is the problem? I don't see that I closed stdout..Can anyone help? Thank you.
The standard output is line buffered by default. Your program outputs something without the new line and then enters the loop. You need to add a new line like this:
printf("Waiting for connections....\n");
For similar reasons, the error messages should be output to standard error, because it's not buffered.
fprintf(stderr, "error creating socket\n");
Firstly, you should add '\n' add the end of log:"Waiting for connections....\n", then the log cann't be buffered, and be outputted.
Secondly, your program is error, the correct program is like this:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
int main()
{
int sock, newsock;
struct sockaddr_un server_name;
socklen_t len= sizeof(server_name);
unlink("Fred");
if( (sock=socket(AF_UNIX,SOCK_STREAM,0)) ==-1)
{
printf("error creating socket\n");
return -1;
}
server_name.sun_family = AF_UNIX;
strcpy(server_name.sun_path, "Fred");
if( bind(sock,(struct sockaddr*)&server_name,len) != 0 ) //binding
{
printf("socket bind error \n");
return -1;
}
if(listen(sock,10)!=0) //set sock to listen
{
printf("error listening\n");
return -1;
}
printf("Waiting for connections....\n");
while(1)
{
newsock=accept(sock, (struct sockaddr*)NULL, NULL);
char temp[1000]="gggggg\n";
write(newsock,temp,strlen(temp));
write(newsock,temp,strlen(temp));
close(newsock);
sleep(1);
}
return 0;
}

Client: recv transport endpoint not connected

I am trying to implement a client-server program.
However, while the server program runs fine, the client program exits with the error::
recv: transport endpoint not connected.
Its been puzzling me for quite a while now. Some help will be greatly appreciated!
Here is the server program ::
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
int main()
{
int sockid,newsockid,pid;
struct sockaddr_in myaddr,clientaddr;
socklen_t x;
x=sizeof(clientaddr);
char msg[20];
sockid=socket(AF_INET,SOCK_STREAM,0);
if(sockid == -1)
perror("SOCKET");
memset(&myaddr,0,sizeof(myaddr));
myaddr.sin_family=AF_INET;
myaddr.sin_port=htons(8888);
myaddr.sin_addr.s_addr=inet_addr(INADDR_ANY);
if(bind(sockid,(const struct sockaddr *)&myaddr,sizeof(myaddr)) == -1)
perror("bind");
listen(sockid,5);
newsockid=accept(sockid,(struct sockaddr *)&clientaddr,&x);
if(newsockid == -1)
perror("accept");
printf("NEW CLIENT ADDR:: %s",ntohs(clientaddr.sin_addr.s_addr));
pid=fork();
while(1)
{
if(pid == 0)
{
memset(msg,'\0',20);
if(recv(newsockid,msg,sizeof(msg),0) == -1)
perror("recv");
puts(msg);
if(strcmp(msg,"exit") == 0)
{
close(newsockid);
exit(getpid());
}
}
if(pid!=0)
{
memset(msg,'\0',20);
gets(msg);
if(send(newsockid,msg,sizeof(msg),0) == -1)
perror("send");
if(strcmp(msg,"exit") == 0)
{
close(newsockid);
exit(getpid());
}
}
}
return 0;
}
Also here is the client side of things::
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
int main()
{
int pid,sockfd;
char msg[20];
struct sockaddr_in myaddr;
sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
perror("socket");
myaddr.sin_family=AF_INET;
myaddr.sin_port=htons(8888);
myaddr.sin_addr.s_addr=inet_addr("127.0.0.1");
if(connect(sockfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) == -1)
perror("connect");
pid=fork();
while(1)
{
if(pid == 0)
{
memset(msg,'\0',20);
if(recv(sockfd,msg,sizeof(msg),0) == -1)
{
perror("recv");
exit(getpid());
}
puts(msg);
if(strcmp(msg,"exit") == 0)
{
close(sockfd);
exit(getpid());
}
}
if(pid!=0)
{
memset(msg,'\0',20);
gets(msg);
if(send(sockfd,msg,sizeof(msg),0) == -1)
perror("send");
if(strcmp(msg,"exit") == 0)
{
close(sockfd);
exit(getpid());
}
}
}
return 0;
}
There are 2 bugs in the server code.
One is in this line:
myaddr.sin_addr.s_addr=inet_addr(INADDR_ANY);
The inet_addr function expects a character string, while INADDR_ANY constant is an IP number with all zeros. The server code crashed with segmentation fault for me until this line was corrected (did it really work for you?). The correct usage:
myaddr.sin_addr.s_addr=htonl(INADDR_ANY);
Also, printf line is not correct - address is not short, but long, also you can't use %s (it would most likely crash). Note, that the compiler (well, gcc at least) warns about it - you should always enable and read compiler warnings. As a quick fix I've changed it to:
printf("NEW CLIENT ADDR:: %08x",ntohl(clientaddr.sin_addr.s_addr));
This is fine as long as you can read IP in hex :)
With those fixes it worked fine for me (I mean both server and client) - note, that there can be other bugs, I have to admit I didn't read it too carefuly.

Resources