Passive socket not accepting ftp - c

I'm making an ftp server, and when i'm trying to connect to it with filezilla, the server is not accepting the connection on the passive socket. It hangs at the accept call.
Here's a part of my code :
if ((server->pasv_sock = accept(server->sockt, (struct sockaddr*)&sin_clt,
(socklen_t*)&size_sin) == -1))
My socket is bind to a specific port and the client tries to connect with this one. Telnet is not connecting either.
If you can help me find what's wrong, thank you :)

Did you remember to call listen before accept?
Remember: socket -> bind -> listen -> accept.
Edit: Here's some commentary on your code.
struct protoent *pe;
struct sockaddr_in sin;
int sock;
struct sockaddr_in sin_clt;
int size_sin;
if ((pe = getprotobyname("TCP")) == NULL)
perro("getprotobyname");
sock = xsocket(AF_INET, SOCK_STREAM, pe->p_proto);
Using getprotobyname is unnecessary, since the name is hard-coded and there's only one IP stream protocol anyway. Use 0 instead of pe->p_proto, and don't bother calling getprotobyname.
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
You don't initialize sin.sin_port. That's an error.
while (bind(sock, (const struct sockaddr*)&sin,
(socklen_t)sizeof(sin)) == -1 && server->port2 <= 65535)
sin.sin_port = htons(server->port2++);
This loop is a bit of a mess. It might be mostly correct, but it's hard to tell. Let's rewrite it so it's obviously correct rather than not obviously incorrect.
if (listen(sock, 1) == -1)
perror("listen");
size_sin = sizeof(sin_clt);
if ((server->pasv_sock = accept(sock, (struct sockaddr*)&sin_clt,
(socklen_t*)&size_sin) == -1))
This definitely doesn't do what you want.
Discussion: I'll add parentheses to the last line to show you what it actually does.
if ((server->pasv_sock = accept(...) == -1))
is the same as
if ((server->pasv_sock = (accept(...) == -1)))
I'm guessing that you got a compiler warning that complained about the assignment, which suggested adding parentheses... but the parentheses you added were in the wrong place. The reason the compiler was warning you was because this is a common source of errors, and it's impossible for the compiler to know what you actually mean by that statement. You mean something more like this:
if ((server->pasv_sock = accept(...)) == -1)
But I don't recommend that. Easier to read and more fool-proof is to pull assignments out of if predicates,
server->pasv_sock = accept(...);
if (server->pasv_sock == -1)
And no, there's no difference in the resulting assembly code; so there's no performance difference.
There's another problem with this line, but it's somewhat pedantic. You shouldn't cast (socklen_t *) &size_sin. Instead, you should change the declaration of size_sin to have the socklen_t type to begin with. The only reason it works is because socklen_t is typedefed to int, but pretend you don't know that and use the right type to begin with.
Sample code:
int port, sock, r, csock;
struct sockaddr_in saddr, caddr;
socklen_t caddrlen;
// This is a simpler way to get a TCP socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) abort();
// Loop over available ports, and bind to one
// (I'm not sure if this is the best way to do this)
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = INADDR_ANY;
for (port = 10000; port < 65536; ++port) {
saddr.sin_port = htons(port);
r = bind(sock, (struct sockaddr *) &saddr, (socklen_t) sizeof(saddr));
if (!r)
break;
}
if (r) abort();
// Listen and accept a connection
r = listen(sock, 1);
if (r < 0) abort();
caddrlen = (socklen_t) sizeof(caddr);
csock = accept(sock, (struct sockaddr *) &caddr, &caddrlen);
if (csock < 0) abort();
// You don't want to listen for more connections
close(sock);
Reccomendations: For now, try to stay away from putting side effects (accept, bind, assignments, etc.) in conditionals. I'm not saying that it's never okay to do this, but it looks like that's where your problems are and it's very easy to just move the side effects to a separate line of code, then only do the final comparison in the if condition or while condition.
// Both of these are correct.
// The bottom one is obviously correct.
// Correctness is not always good enough.
// Being obviously correct is important!
if ((p->x = func()) == NULL)
...
p->x = func();
if (p->x == NULL)
...

Related

Not receiving multicast data using code which works on another machine

We receive multicast data to two machines- Prod and Dev. The below code worked on Prod, but has never worked on Dev (even though the boxes should be set up identically). However, when I run
tshark -i <interface> -c 50
on Dev packets are being received from the same multicast address and port as Prod.
I have posted the code below. The program reaches the log line "Listening for packets" but then appears to simply block on recvfrom().
I would like to clarify I am not doing anything daft. Is there anything else I can check to see what's happening with the packets? I cannot speak with our vendor yet because they will simply run tshark and say the problem must be with our code.
std::string address("1.2.3.4"); // Not real address
const char *group = address.c_str();
int port = 26477;
_sock = socket(AF_INET, SOCK_DGRAM, 0);
assert(_sock >= 0);
u_int yes = 1;
int result = setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes));
assert(result >= 0);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
result = bind(_sock, (struct sockaddr *)&addr, sizeof(addr));
assert(result >= 0);
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(group);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
result = setsockopt(_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq));
assert(result >= 0);
LOG("Listening for packets...."); // CODE REACHES HERE
while (1)
{
socklen_t addrlen = sizeof(addr);
const size_t maxNumBytesToRead = MSGBUFSIZE - 1;
// I think code is just blocking here, waiting for packets
const int nbytes = recvfrom(_sock, msgbuf, maxNumBytesToRead, 0, (struct sockaddr *)&addr, &addrlen);
}
You're specifying INADDR_ANY as the interface to join the multicast group on. This means the system will choose a default interface. If your system has more than one active interface, it might not be the one you intended.
What's probably happening here is that your PROD machine happens to be joining on the desired interface, while the DEV machine is joining on a different interface.
Change mreq.imr_interface to contain the IP address of the network interface you want to bind to.

TCP sockets in c

I'm attempting to write a TCP socket interface for my program and I'm pulling my hair out with an accept() error (I think). For this I've created some boiled down test code.
First I do a little set up
int server_socket = 0;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
int accepted_connection = 0;
struct sockaddr_in server_address;
server_address.sin_port = htons(9001);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
struct sockaddr_in client_address;
client_address.sin_port = 0;
client_address.sin_family = AF_INET;
char * server_socket_read_buffer[100] = {0};
int server_socket_read_length = 0;
All pretty simple stuff. Just allocate some variables. Next I bind and listen
if (bind(server_socket,(struct sockaddr *)&server_address, sizeof(server_address)) < 0)
{
perror("Bind() on server_socket has failed\n");
}
if (listen(server_socket, 10) < 0)
{
perror("Listen() on server_socket has failed\n");
}
Next is the part where I believe I have my problem
printf("Attempting accept!\n");
if (accepted_connection = accept(server_socket, (struct sockaddr *)NULL, NULL) < 0)
{
perror("Accept failed\n");
}
sleep(10);
if (server_socket_read_length = read(accepted_connection, &server_socket_read_buffer, server_socket_read_length) < 0)
{
perror("Read failed\n");
}
printf("Read %d bytes from socket\n", server_socket_read_length);
for (int i = 0; i<server_socket_read_length;i++)
{
printf("%x\n",server_socket_read_buffer[i]);
}
This compiles and runs. When I use nc with the command 'nc 127.0.0.1 9001' I get a connection, but no data is read. In particular I get 0 bytes of data. I thought this might be due to the NULLs in the accept line, but changing those to a proper struct and length prevent my code from compiling.
If anyone can shed some light on what I'm doing wrong I would be very grateful.
There are a couple of errors:
INADDR_ANY is in host byte order and needs to be converted to network one like htonl(INADDR_ANY). But it does not matter since constant INADDR_ANY is defined as 0.
This
char * server_socket_read_buffer[100]
should be
char server_socket_read_buffer[100]
This
read(accepted_connection, &server_socket_read_buffer, server_socket_read_length)
should be
read(accepted_connection, server_socket_read_buffer, sizeof server_socket_read_buffer)
You are passing in server_socket_read_length = 0 which causes a maximum read length of zero. Pass the buffer size. The declaration of server_socket_read_buffer is incorrect as well. Probably you should allocate a bigger buffer (like 4KB) on the heap.
Also remove the sleep.
The rest is probably working because nc obtains a connection and you are able to accept and read without error.
So after more struggle I found my final answer. The block
if (accepted_connection = accept(server_socket, (struct sockaddr *)NULL, NULL) < 0)
{
//code
}
Doesn't work. My read later on was blocking because accepted_connection wasn't a valid socket. Changing to
(accepted_connection = accept(server_socket, (struct sockaddr *)NULL, NULL);
if accepted_connection < 0)
{
//code
}
resolved my issue. As far as I can gather the file descriptor wasn't being created inline with the if() and reading data from an integer isn't very helpful.
Thanks for the input everyone.

getpeername() won't return a correct port but it returns a correct address of remote host socket language C

I would like to ask about the getpeername() function since it returns data as the title states. I tried to get value directly from accept() function, and the result also happens the same. Value of port seems to appear randomly even though value of address is correct(address is 127.0.0.1 since I run multi-processes on an only machine). The return code of getpeername() is 0 (status = 0). I'm using gcc version 4.8.1. I write a peer 2 peer chat application without server. The following is my code:
struct sockaddr_in addr;
socklen_t addr_len;
int tempPort, serverSockfd;
char test[100];
// Get serverSockfd successfully....
serverSockFd = initializeSock(PORT) // In this function I initialize socket(), bind() and listen(), serverSockFd is returned by the value of socket()
addr_len = sizeof addr;
newSock = accept(serverSockfd, (struct sockaddr *)&addr, &addr_len);
tempPort = ntohs(addr.sin_port);
inet_ntop(AF_INET, &(addr.sin_addr), test, sizeof test);
printf("tempPort\t%d\n", tempPort);
printf("test\t%s\n", test);
addr_len = sizeof addr;
if ((status = getpeername(newSock, (struct sockaddr *) &addr, &addr_len)) != 0){
printf("getpeername() error!\n");
}
tempPort = ntohs(addr.sin_port);
inet_ntop(AF_INET, &(addr.sin_addr), test, sizeof test);
printf("tempPort\t%d\n", tempPort);
printf("test\t%s\n", test);
Thanks very much for any your comment. Here is a partial code in initializeSock():
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd < 0)
{
perror("SocketInit(): socket() error!\n");
exit(1);
}
ret_val = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*) &flag, sizeof(flag));
if(ret_val == -1)
{
perror("SocketInit(): setsockopt(SO_REUSEADDR) error!\n");
exit(1);
}
gethostname(hostname,100);
host_entry = gethostbyname(hostname);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list));
ret_val = bind(sd, (struct sockaddr*) &addr, sizeof(addr));
if(ret_val == -1)
{
perror("SocketInit(): bind() error!\n");
printf("For port:%d\n",port);
exit(1);
}
....
return sd;
This is the code to connect to server part of a peer. ConnectSock(portOfPeerA):
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd < 0)
{
perror("ConnectToServer(): socket() error!\n");
exit(1);
}
if (port != 0) {
addr.sin_family = AF_INET;
addr.sin_port = htons(portOfPeerA);
addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list));
// Do I need to bind() the port of peer B when it would like to connect to peer A?
ret_val = connect(sd, (struct sockaddr*)&addr, sizeof(addr));
if(ret_val == -1)
{
printf("Error connect());
exit(1);
}
...
I don't know which port you accept from the peer, but if the peer is connecting to your server (e.g. then one calling accept) it will connect from a (more or less) random port, that's how TCP works. It connects from a fixed port only if the peer explicitly binds to that port before connecting.
This means, that the peers originating port is not defined on the server side (where your code fragments are from) but on the client side (the side which calls connect and where you only do connect but no bind).
But, please note that it might give problems with repeated connections, if both client and server use fixed IP and ports, because then you will get the same 4-tupel in TCP which defines the connections for repeated connections and thus go into all this trouble with the various TIME_WAIT states. So it is better to let the client just pick an available port and not force it to use a specific one.
getpeername() (and accept()) reports the IP and port that the remote party is locally bound to on its end. If the remote party is a client that did not call bind() before calling connect() then connect() performs an implicit bind to a random available port. That is what you are seeing, and that it typical usage. Most clients do not need to call bind() before connect(), but there are use cases where doing so is necessary, so don't rule it out.

Broadcasting in C

I have an application written in C that is a server and a client at the same time. What I do is the following:
sock = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&server, length);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(MYPORT);
char broadcast = '1';
int broadcastlen = sizeof(broadcast);
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast, &broadcastlen) < 0) {
close(sock);
error("Error in setting broadcast option");
}
if (bind(sock, (struct sockaddr*) &server, sizeof(server)) < 0) {
close(sock);
error("Error in BINDING");
}
bzero(&sender, length);
bcast.sin_family = AF_INET;
bcast.sin_addr.s_addr = NBCAST; // NBCAST is the broadcast address of the subnet
bcast.sin_port = htons(MYPORT);
if (sendto(sock, dateQuery, strlen(dateQuery) + 1, 0, (struct sockaddr*)&bcast, sizeof(bcast)) < 0) {
close(sock);
error("ERROR in sending");
}
Up to this point everything works well. But I start a thread with the sock parameter to listen to, and do the following:
int len = sizeof(struct sockaddr_in);
struct sockaddr_in sender_addr;
recfrom(sock, recvbuff, recvbufflen, 0, (struct sockaddr*) &sender_addr, &len);
And it blocks there forever. I tried to make it work from different PCs, but it doesn't seem to work, because the thread is blocked due to recvfrom(). Can anyone tell me what is wrong with my code?
Thanks
EDIT: if my code is broken, could you please suggest a way to solve this? So, my task is to implement an application in C that is a server and a client at the same time. I send a broadcast message every 3 seconds, and I have to answer to that broadcast message with the system time.
So far this is the idea I came up with, of course I did not answer to that broadcast message since I couldn't even read it.
I just solved the problem. The code works perfectly, I just had to disable the firewall. But I don't know exactly how did this help me. Any way, thanks for the answers and comments.
Perhaps, you have to make the socket non-blocking?
Try:
u_long iMode = 1;
ioctlsocket(sock, FIONBIO, &iMode);

accept fails with EFAULT

I have a socket server running on multiple machines. It works like a charm besides on one machine.
The server binds correctly but returns an error (EFAULT) when the client attempts to connect.
Perhaps someone has an idea what the source of the problem might be. Thanks a lot in advance!
Some information about the machine:
Linux version 2.6.18.3
gcc version 3.3.5 (Debian 1:3.3.5-13)
The socket server source is pretty straight forward.
...
...
struct sockaddr_in server_addr;
struct sockaddr* client;
socklen_t alen;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
...
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0){
...
}
if(listen(sockfd,BACKLOG) == -1){
...
}
alen = sizeof(client);
new_fd = accept(sockfd, client, &alen);
if (new_fd == -1) {
/*
* this part of the code is executed
* errno is set to 14
*/
}
Thank you for pointing me in the right direction.
Use this:
struct sockaddr_in client;
...
alen = sizeof(client);
new_fd = accept(sockfd, (struct sockaddr *) &client, &alen);
accept expects a pointer to an existing buffer which it'll fill in. You have two errors, you set alen to the size of a pointer, and you pass an uninitialized pointer to accept.
From the accept(2) man page:
EFAULT The addr argument is not in a writable part of the user address
space.
Check to make sure that you've allocated client appropriately.

Resources