segmentation fault(core dump created) in recvfrom - c

I was writing a simple C code to create a lisening socket. The code is teh following:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
void main() {
struct sockaddr_in server;
struct sockaddr_in client;
int clientlen;
char buf[1500];
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset((char *)&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(9090);
if(bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
error("ERROR on binding");
while(1) {
bzero(buf, 1500);
recvfrom(sock, buf, 1500-1, 0, (struct sockaddr *) &client, &clientlen);
printf("%s\n", buf);
printf("%d - %s\n", client.sin_port, client.sin_addr.s_addr);
}
close(sock);
}
The code compile with no problem but when I connect to the server with a client using netcat:
nc -u 10.0.2.4 9090
and I send some message, the message are replied and then I get the error. DO someone knows why I get this behaviour?
Thank you.

There are two main issues here. First, clientlen is expected to contain the size of the address structure before recvfrom is called, but it is uninitialized. So set it as follows:
int clientlen = sizeof(client);
Second, you're using %s to print client.sin_addr.s_addr but that field is not a string. You should use inet_ntoa to convert a struct inaddr_t to a string:
printf("%d - %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));

Related

Sending and receiving UDP packets through NAT

I've been fiddling with this for a bit now. I have a server with a static IP address and a client sitting behind a consumer grade NAT (read a router provided by my ISP).
I'm trying to send a message, using UDP to the server and then receiving a response on the same socket. I have tried in a variety of languages, but just for the sake of it, here is my C version. I'm not sure if this a code problem or a machine configuration.
The message to the server goes through just fine, but the client never receives the response.
Client:
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
// servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_addr.s_addr = inet_addr("87.118.127.66");
int n, len;
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
printf("Hello message sent.\n");
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &servaddr,
&len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
close(sockfd);
return 0;
}
Server:
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr); //len is value/resuslt
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &cliaddr,
len);
printf("Hello message sent.\n");
return 0;
}
UDP is a transport protocol and transport protocols carry a port. As you are working on this layer, the port has to be known/specified. But that is just not the case for recvfrom in your client code. It does not know from which port it should return the messages. Therefore you have to call bind and or connect in your client code.

error when connecting server and using system function in c

I'm new in c and especially in sockets and if this question is silly i'm sorry. Here is my code:
/****************** SERVER CODE ****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int welcomeSocket, newSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = 0;
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));
bind(welcomeSocket, (struct sockaddr *) &serverAddr,
sizeof(serverAddr));
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket,
(struct sockaddr *) &serverStorage, &addr_size);
strcpy(buffer,"Hello World\n");
send(newSocket,buffer,13,0);
memset(buffer, '\0', 1024);
while(recv(newSocket, &buffer, 1024, 0) > 0)
{
printf("%s", system(buffer));
memset(buffer, '\0', 1024);
}
return 0;
}
This is my server and i'm connecting with telnet(I know its not secure and let any user execute any command in server is neither but its for educational purposes). when i type "ls"(server program is run on linux) it gives me back this error not found
Segmentation fault (core dumped) and disconnects me. I hope you can help. thanks
Your program is crashing because of this line:
printf("%s", system(buffer));
as stated here: http://linux.die.net/man/3/system
the system() call is returning an integer, not a char*.
for what you want, you could use popen().
see the answer on this question for an example:
How to execute a command and get output of command within C++ using POSIX?
or
How to get the output of grep in C

C network server programming on linux

I would like to make program so that, when client disconnected, the server will back ready to accept a new request from client. Here is the code
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define MAXLINE 100
#define LISTENQ 10
int main()
{
int tmp, listenfd, connfd;
int sin_size;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
while(true)
{
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(13);
memset(&(servaddr.sin_zero),'\0',8);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd == -1){
perror("error socket");
exit(1);
}
tmp=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr));
if(tmp == -1){
perror("error bind..");
exit(1);
}
tmp=listen(listenfd, LISTENQ);
if(tmp == -1){
perror("error listen");
exit(1);
}
sin_size = sizeof(struct sockaddr_in);
connfd=accept(listenfd,(struct sockaddr *)&cliaddr, &sin_size);
if(connfd == -1){
perror("error accept");
exit(1);
}
ticks = time(NULL);
snprintf(buff,sizeof(buff),"Now Time: %.24s\r\n", ctime(&ticks));
write(connfd, buff, strlen(buff));
close(connfd);
close(listenfd);
}
}
I found a problem on this part
tmp=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr));
error: invalid conversion from 'int*' to 'socklen_t* {aka unsigned int*}' [-fpermissive]
connfd=accept(listenfd,(struct sockaddr *)&cliaddr, &sin_size);
error: initializing argument 3 of 'int accept(int, sockaddr*, socklen_t*)' [-fpermissive]
What should I do with those problem? Didn't the pointer right?
You need to use
socklen_t sin_size;
Chnage your declaration
socklen_t sin_size;
This solves your issue.
you can also Try this as last resort but above change would works fine for you.
Modify this statement
connfd=accept(listenfd,(struct sockaddr *)&cliaddr,(socklen_t * ) &sin_size);
See man accept
After seeing #alk comment i am adding this part from comment.
Especially when casting pointers, it might just cast away an compile-time error but very well might crash when running as the sizes of what the program expects when Dereferencing the pointer differs from reality.
Use while(1) instead of while(true) and use a C-compiler instead of a C++-compiler.
The errors come from compiling the source code with a C++compiler. If you use a C-Compiler your code does not produce the mentioned errors, except that now true is not defined.
Correct answer, need to run on root-access user
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#define MAXLINE 100
#define LISTENQ 10
int main()
{
int tmp, listenfd, connfd;
socklen_t sin_size;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
while(true)
{
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(13);
memset(&(servaddr.sin_zero),'\0',8);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd == -1){
perror("error socket");
exit(1);
}
tmp=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr));
if(tmp == -1){
perror("error bind..");
exit(1);
}
tmp=listen(listenfd, LISTENQ);
if(tmp == -1){
perror("error listen");
exit(1);
}
sin_size = sizeof(struct sockaddr_in);
connfd=accept(listenfd,(struct sockaddr *)&cliaddr, &sin_size);
if(connfd == -1){
perror("error accept");
exit(1);
}
ticks = time(NULL);
snprintf(buff,sizeof(buff),"Sekarang pukul: %.24s\r\n", ctime(&ticks));
write(connfd, buff, strlen(buff));
close(connfd);
close(listenfd);
}
}

Socket, accept() function, Invalid argument

I am getting an error "Invalid argument" when i call the accept() function on the server side of a client-server application. I don't get what is wrong and if you see what is wrong let me know please. Thanks.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char* argv[])
{
int sockfd, newsockfd, portno, len;
struct sockaddr_in server, client;
if(argc < 2){
perror("Add more arguments");
}
sockfd = socket(AF_UNIX,SOCK_STREAM,0);
if(sockfd < 0){
perror("Error at socket()");
}
printf("Socketfd: %d\n",sockfd);
bzero((char *)&server, sizeof(server));
portno = atoi(argv[1]);
server.sin_family = AF_UNIX;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portno);
if(bind (sockfd, (struct sockaddr *)&server, sizeof(server)) <0){
perror("Error at bind ()-server");
}
listen(sockfd,5);
int readval;
char buffer[256];
for(;;){
len = sizeof(client);
newsockfd = accept (sockfd, (struct sockaddr *)&server,&len);
if (newsockfd == -1){
perror("Erroare at accept()");
}
else do{
readval = (sockfd,buffer,sizeof(buffer));
if (readval < 0 ){
perror("Error at reading()");
}
else if (readval == 0){
printf("End conection");
}
else{
printf("Mesage is: %s\n", buffer);
}
}while (readval > 0);
close(newsockfd);
}
return 0;
}
You have to use sockaddr_un instead of sockaddr_in for Unix domain sockets OR substitute AF_UNIX with AF_INET.
Plus, check the return of listen.
Plus change this line
readval = (sockfd,buffer,sizeof(buffer));
with
readval = read(newsockfd,buffer,sizeof(buffer));
because data is going to be sent through the newly created socket and not on the listening one
Plus, as mentioned by #trojanfoe, subst the server with the client structure into the accept() call
This line:
newsockfd = accept (sockfd, (struct sockaddr *)&server, &len);
Should be:
newsockfd = accept (sockfd, (struct sockaddr *)&client, &len);
From the manpage:
The argument addr is a pointer to a sockaddr structure. This structure
is filled in with the address of the peer socket, as known to the
communications layer. The exact format of the address returned addr is
determined by the socket's address family (see socket(2) and the
respective protocol man pages). When addr is NULL, nothing is filled
in; in this case, addrlen is not used, and should also be NULL.
Also check the return value from listen().
I ran into a similar issue before and it was due to not having the read function in a loop. Here is an example I did before.
while (1) {
new_sockfd = accept(sockfd, (struct sockaddr *) &client_addr,
&sin_size);
if (new_sockfd == -1)
perror("accepting connection");
printf("server: got connection from %s port %d\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
recv_length = recv(new_sockfd, &buffer, DATA, 0);
while (recv_length > 0) {
printf("RECV: %d bytes\n", recv_length);
dump(buffer, recv_length);
recv_length = recv(new_sockfd, &buffer, DATA, 0);
}
close(new_sockfd);
}

Compile simple UDP server using clang got error: use of undeclared identifier 'SA'

I was trying to make the simple server code work:
/*
NAME: udpServer0
SYNOPSIS: udpServer0
DESCRIPTION: The program creates a datagram socket in the inet
domain, binds it to port 12345 and receives any message
arrived to the socket and prints it out
*/
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
int main(void)
{
int sd;
struct sockaddr_in server;
char buf[512];
int rc;
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(12345);
sd = socket (AF_INET,SOCK_DGRAM,0);
bind( sd, (SA *) &server, sizeof(server));
for(;;){
rc=recv (sd, buf, sizeof(buf), 0);
buf[rc]= (char) NULL;
printf("Received: %s\n", buf);
}
}
I got these error:
clang udp_server.c
udp_server.c:27:16: error: use of undeclared identifier 'SA'
bind( sd, (SA *) &server, sizeof(server));
^
udp_server.c:27:20: error: expected expression
bind( sd, (SA *) &server, sizeof(server));
^
2 errors generated.
Do I need to require some header to avoid this problem?
As the comments say you want: (struct sockaddr *) instead of (SA *).
SA must have been a typedef. If you want the best guide to socket programming see this: http://beej.us/guide/bgnet/output/html/multipage/index.html

Resources