UDP Server giving Segmentation Fault - linux

Ive written the following echo server using UDP but i have no idea that why it is giving me Segmentation Fault in sendto function, it receives fine but has problem sending data back to client. Ive been trying to find the problem for a few hours now but got no where. Can somebody please point out the fault or what i may be doing wrong.
Thanks
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define true 1
#define false 0
int main(int argc,char **args)
{
int BUF_LENGTH=101;
int port_no=1800;
struct sockaddr_in serv_addr,rmt_addr;
//rmt_addr=malloc(sizeof(struct sockaddr_in));
char *buffer=malloc(BUF_LENGTH);
int byte_recv=0;
int rmt_length=0;
int sock_id;
sock_id=socket(AF_INET,SOCK_DGRAM,0);
if(sock_id<0)
{
printf("Error creating socket : %d",sock_id);
return -1;
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(port_no);
serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
bind(sock_id,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
printf("Created\n");
while(true)
{
printf("Waiting\n");
byte_recv=recvfrom(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,&rmt_length);
printf("%s\n",buffer);
if(byte_recv<0)
{
printf("Error receiving: %d",byte_recv);
error("recvfrom");
return -2;
}
printf("%d:%d %s\n",rmt_length,rmt_addr.sin_port,inet_ntoa(rmt_addr.sin_addr));
byte_recv=sendto(sock_id,buffer,BUF_LENGTH,0,(struct sockaddr*)&rmt_addr,rmt_length); //The segmentation fault comes here
printf("Bytes sent: %d \n",byte_recv);
if(byte_recv<0)
error("sendto");
}
free(buffer);
return 0;
}

These lines:
error("recvfrom");
error("sendto");
don't do what you think they do. You probably meant to say perror.
Additionally, you aren't initializing rmt_length correctly. Try this:
int rmt_length=sizeof(rmt_addr);
Finally, you are echoing more bytes back than the server receives. Try this:
byte_recv=sendto(sock_id,buffer,byte_recv,0,(struct sockaddr*)&rmt_addr,rmt_length);

Related

Inter process communication using FIFO

Client server must pass to the Server process a filename and the Server process must return the number of lines in the file. My problem is that the received variable only contains 6 characters of the filename and it ends up by throwing segmentation fault dump core error. Do you know why this happens? This is my code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(){
int fd1,fd2;
const char *fifo1="./fifo1Channel";
const char *fifo2="./fifo2Channel";
mkfifo(fifo1,0666);
mkfifo(fifo2,0666);
char filename[30];
printf("Give me a filename:\n");
fgets(filename,30,stdin);
strtok(filename,"\n");
int pid=fork();
if(pid>0){
char received[30], ch;
FILE *fp;
fd1=open(fifo1, O_RDONLY);
read(fd1,received,strlen(received));
close(fd1);
printf("From server process:%s\n",received);
fp=fopen(received,"r");
int nrOfLines=0;
for(ch=getc(fp);ch!=EOF;ch=getc(fp))
if(ch=='\n')
nrOfLines++;
fd2=open(fifo2, O_WRONLY);
write(fd2,&nrOfLines,sizeof(nrOfLines));
close(fd2);
return 0;
}
if(pid==0){
int receivedNumber;
fd1=open(fifo1,O_WRONLY);
write(fd1,filename,strlen(filename));
close(fd1);
fd2=open(fifo2,O_RDONLY);
read(fd2,&receivedNumber,sizeof(receivedNumber));
close(fd2);
printf("From client process: %d\n",receivedNumber);
return 0;
}
return 0;
}
I think the problem was in server process. I replaced strlen(received) with 30, the maximum number of characters of filename, in function read and it works now!

setsockopt IPT_SO_SET_REPLACE flag return error (linux)

I try to use setsockopt with the flag IPT_SO_SET_REPLACE but i keep getting the wired error from errno Protocol not available this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <linux/sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <fcntl.h>
int main(void) {
int sock;
int ret;
void *data;
size_t size;
struct ipt_replace *repl;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("socket");
return -1;
}
size = sizeof(struct ipt_replace);
data = malloc(size); Protocol not available
if (data == NULL) {
perror("malloc");
return -1;
}
memset(data, 0, size);
repl = (struct ipt_replace *) data;
repl->num_counters = 0x1;
repl->size = 0xffffffff;
repl->valid_hooks = 0x1;
repl->num_entries = 0x1;
ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, size);
printf("\ndone %d\n", ret);
perror("error: ");
return 0;
}
this is the output :
sock:3
data:
size:92
done -1
error: : Protocol not available
Looking briefly at the kernel code, this would seem to indicate that the IP tables module isn't available (i.e. the kernel wasn't built with it configured, or it can't be found or loaded).
It appears to me that for a socket of the kind you created, the code flow is:
enter raw_setsockopt: level != SOL_RAW so...
call ip_setsockopt: level == SOL_IP but option isn't any of the IP_xxx options so...
call nf_setsockopt: Search loaded netfilter modules for one that has registered IPT_SO_SET_REPLACE.
I think the last must have failed, so you get ENOPROTOOPT back (== Protocol not available)

How does ptrace work with 2 different processes?

I was reading about ptrace on the net and found that a process can request to trace another process by using PTRACE_ATTACH but apparently all the examples available involve the use of fork().
What I want is to have 2 programs - prg1.c and prg2.c where prg2.c should trace prg1.c. I tried using PTRACE_ATTACH in prg2.c but it seems that the call failed - prg2.c couldn't trace prg1.c . How does ptrace work ? Can anybody explain ?
Code for prg1.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Hello world\n");
sleep(20);
execl("/bin/ls", "ls", NULL);
return 0;
}
Code for prg2.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc , char **argv)
{
int pid = atoi(argv[1]);
int status;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
printf("ptrace attach failed!");
return 0;
}
wait(&status);
sleep(5);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return 0;
}
I have included a sleep() to get the pid of prg1's executable(during that time) using ps -af and give it as an input to the executable of prg2.

linux socket accept can't been blocked

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
int main()
{
int server_sockfd,client_sockfd;
int server_len,client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
create a new socket
unlink("server_socket");
server_sockfd=socket(AF_INET,SOCK_STREAM,0);
name it
server_address.sin_family=AF_INET;
server_address.sin_addr.s_addr=htonl(INADDR_ANY);
server_address.sin_port=htons(9734);
server_len=sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_len);
set block
int flags=fcntl(server_sockfd,F_GETFL,0);
if(flags&O_NONBLOCK==1){
printf("NONBLOCK");
}else{
printf("BLOCK");
}
flags=flags&~O_NONBLOCK;
fcntl(server_sockfd,F_SETFL,flags);
if(flags&O_NONBLOCK==1){
printf("NONBLOCK");
}else{
printf("BLOCK");
}
listen
listen(server_sockfd,5);
while(1){
char ch;
printf("server waiting\n");
client_len=sizeof(client_address);
client_sockfd=
accept(server_sockfd,(struct sockaddr*)&client_sockfd,&client_len);
it is blocked at first time
read(client_sockfd,&ch,1);
ch++;
write(client_sockfd,&ch,1);
close(client_sockfd);
}
}
when the client connected first,I work,but the next won't work
A mismatch may occurs between client_address and client_sockfd.
The man page of accept() says:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
The addrlen argument is a value-result argument: the caller must initialize it to
contain the size (in bytes) of the structure pointed to by addr; on return it
will contain the actual size of the peer address.
Try:
client_sockfd=
accept( server_sockfd, (struct sockaddr*)&client_address, &client_len );

debugging server's cgi program

i am trying to make a webserver in C which can handle request to dynamic contents.
the webserver part is finish already. i'm trying to execute the following command:
http://localhost:1601/cgi-bin/test?3&7
with the code of program test is as follow:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <wordexp.h>
#define MAXLINE 300
int main(int narg, char * arg[]) {
char *buf, *p;
char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
int n1=0, n2=0;
/* Extract the two arguments */
if ((buf = getenv("QUERY_STRING")) != NULL) {
p = strchr(buf, '&');
*p = '\0';
strcpy(arg1, buf);
strcpy(arg2, p+1);
n1 = atoi(arg1);
n2 = atoi(arg2);
}
/* Make the response body */
sprintf(content, "Welcome to add.com: ");
sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
content, n1, n2, n1 + n2);
sprintf(content, "%sThanks for visiting!\r\n", content);
/* Generate the HTTP response */
printf("Content-length: %d\r\n", (int)strlen(content));
printf("Content-type: text/html\r\n\r\n");
printf("%s", content);
if (fork()==0) {
printf("asdfagloiauergauhfgaiudfhg");
execvp("ls",arg);
printf("child of adder error");
}
printf("%s", content);
fflush(stdout);
exit(0);
}
/* $end adder */
It run well. However, i wonder why the child code (the line printf("asdfagloiauergauhfgaiudfhg"); and execvp) didn't print out to the webserver's output. although everything else in test output correctly.
For starters you set the Content-length header to the length of the content, then sent the content, then sent more data in both threads. The browser is within its rights to ignore everything after content-length bytes in the output stream.

Resources