C / binding multiple sockets [on differnet ports] - c

I want to bind 4 sockets on different ports. Somehow I get always the : Address already in use error. For the first loop, the case PORT1 it is working, but when coming to the second run I get the above mentioned error. It would be nice, if someone could take a closer look at my code.
The output looks like that:
thread 0 started, pc_packet_receiver
sock_fd[8]
sock_fd[8], fdmax[8]
sock_fd[9]
error: could not bind UDP socket, port2
: Address already in use
As you can see, the first printf in the loop is processed twice and when bind is called for PORT2 the program crashes.
sock_fd is an array of file descriptors
sock_addr_port[1..4] are four different struct sock_addr
the values PORT1/PORT2/PORT3/PORT4 are defined in an enum [1..4]
in the end I want to add all sock_fd[i] into a FD_SET to processing them with select
thank you very much in advance for your help.
for(i = 0; i < 4; i++) {
if((sock_fd[i] = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("error: could not open UDP socket\n");
exit(EXIT_FAILURE);
}
printf("\tsock_fd[%d]\n", sock_fd[i]);
switch (i+1) {
case PORT1:
bzero(&sock_addr_port1, sock_len_port1);
sock_addr_port1.sin_family = AF_INET;
sock_addr_port1.sin_port = htons(ETH_PORT1);
sock_addr_port1.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock_fd[i], (struct sockaddr *) &sock_addr_port1, sock_len_port1) < 0) {
perror("error: could not bind UDP socket, port1\n");
exit(EXIT_FAILURE);
}
break;
case PORT2:
bzero(&sock_addr_port2, sock_len_port2);
sock_addr_port2.sin_family = AF_INET;
sock_addr_port2.sin_port = htons(ETH_PORT2);
sock_addr_port2.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock_fd[i], (struct sockaddr *) &sock_addr_port2, sock_len_port2) < 0) {
perror("error: could not bind UDP socket, port2\n");
exit(EXIT_FAILURE);
}
break;
case PORT3:
bzero(&sock_addr_port3, sock_len_port3);
sock_addr_port3.sin_family = AF_INET;
sock_addr_port3.sin_port = htons(ETH_PORT3);
sock_addr_port3.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock_fd[i], (struct sockaddr *) &sock_addr_port3, sock_len_port3) < 0) {
perror("error: could not bind UDP socket, port3\n");
exit(EXIT_FAILURE);
}
break;
case PORT4:
bzero(&sock_addr_port4, sock_len_port4);
sock_addr_port4.sin_family = AF_INET;
sock_addr_port4.sin_port = htons(ETH_PORT4);
sock_addr_port4.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock_fd[i], (struct sockaddr *) &sock_addr_port4, sock_len_port4) < 0) {
perror("error: could not bind UDP socket, port4\n");
exit(EXIT_FAILURE);
}
break;
default:
break;
}
FD_SET(sock_fd[i], &read_fds);
fdmax = sock_fd[i];
printf("sock_fd[%d], fdmax[%d]\n", sock_fd[i], fdmax);
}

There is another process running which uses ETH_PORT2 right now. You should be able to see this when you run netstat -tan (-tn on Windows) on the command line.
Google for "which process uses which port" to see how you can find out the process.

Related

User buffer size to receive multicast packets?

The below code is from Git. It joins a multicast group and receives packets.
Here we loop and receive the data in a buffer called msgbuf:
while (1)
{
char msgbuf[MSGBUFSIZE];
const int addrlen = sizeof(addr);
const int nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &addr, &addrlen);
How do I choose the size for the buffer msgBuf? Does it just have to be the max packet size? Or do I need to store multiple packets whilst I process the first?
Full code:
int main(int argc, char *argv[])
{
if (argc != 3) {
printf("Command line args should be multicast group and port\n");
printf("(e.g. for SSDP, `listener 239.255.255.250 1900`)\n");
return 1;
}
char* group = argv[1]; // e.g. 239.255.255.250 for SSDP
int port = atoi(argv[2]); // 0 if error, which is an invalid port
if(port <= 0)
{
perror("Invalid port");
return 1;
}
// create what looks like an ordinary UDP socket
//
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
{
perror("socket");
return 1;
}
// allow multiple sockets to use the same PORT number
//
u_int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &yes, sizeof(yes)) < 0)
{
perror("Reusing ADDR failed");
return 1;
}
// set up destination address
//
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY); // differs from sender
addr.sin_port = htons(port);
// bind to receive address
//
if (bind(fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
{
perror("bind");
return 1;
}
// use setsockopt() to request that the kernel join a multicast group
//
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(group);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*) &mreq, sizeof(mreq)) < 0)
{
perror("setsockopt");
return 1;
}
// now just enter a read-print loop
//
while (1)
{
char msgbuf[MSGBUFSIZE];
const int addrlen = sizeof(addr);
const int nbytes = recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &addr, &addrlen);
if (nbytes < 0)
{
perror("recvfrom");
return 1;
}
msgbuf[nbytes] = '\0';
puts(msgbuf);
}
return 0;
}
Unlike TCP which combines packets into a stream, UDP respects packet boundaries so recvfrom only gets one packet at a time.
So MSGBUFSIZE only needs to be as big as a single packet. If you're not using jumbo packets that would be 1500, otherwise it would be 9000.
as noted by #Ingo, in this code you should be using:
char msgbuf[MSGBUFSIZE + 1];
the + 1 is because recvfrom can write upto MSGBUFSIZE bytes into the array, and you then write another NUL byte at the end.
as far as choosing a value for MSGBUFSIZE, that would depend on the protocol specification. given that most physical networks would struggle to send more than 1500 bytes without fragmentation something like 2048 might be a reasonable value. you could also check for nbytes == MSGBUFSIZE (maybe also using MSG_TRUNC) and report a "packet truncated" warning, but this basically wouldn't happen for packets routed over the public internet
in response to:
do I need to store multiple packets whilst I process the first?
you'd normally let the network stack take care of that. recv maintains packet/datagram boundaries and hence will always start writing the next packet at the supplied buffer address. again it depends on the protocol how you detect and handle errors, e.g. missing or out-of-order packets, and timeouts

Resend all incoming packets

I am writing an educational Man in the Middle application (Linux sockets). What I am struggling with is how to resend TCP/UDP and ICMP packets coming from victim1 to victim2? My approach below seems not to be working:
unsigned char buffer[BUF_SZ];
struct ethhdr *eth_head = (struct ethhdr *)(buffer);
struct sockaddr_ll sock_adr_resnd = {0};
sock_adr_resnd.sll_family = AF_PACKET;
sock_adr_resnd.sll_ifindex = interface_i;
sock_adr_resnd.sll_protocol = htons(ETH_P_ALL);
sock_adr_resnd.sll_halen = MAC_LEN;
memcpy(sock_adr_resnd.sll_addr, source_mac, MAC_LEN); // my MAC
if ((sct = socket(AF_PACKET, SOCK_DGRAM, 0)) < 0) { //recieve all
perror("Socket open error ");
exit (EXIT_FAILURE);
}
if (bind(sct, (struct sockaddr *) &sock_adr_resnd, sizeof(sock_adr_resnd)) < 0) {
printf("Failed to bind socket \n");
}
int res_len = sizeof(sock_adr_resnd);
if (recvfrom(sct, buffer, BUF_SZ, 0, (struct sockaddr*)&sock_adr_resnd, (socklen_t *)&res_len) < 0)
{
process = 0; // nothing accepted
}
// change mac address to actual destination
memcpy(sock_adr.sll_addr, vic_mac1, MAC_LEN);
memcpy(eth_head->h_source, vic_mac1, MAC_LEN);
if (process) {
if (sendto(sct, buffer, BUF_SZ, 0, (struct sockaddr *)&sock_adr_resnd, sizeof(sock_adr_resnd)) < 0)
{
close(sct);
perror("sendto: ");
exit (EXIT_FAILURE);
}
}
What I am confused about is how the socket should be set. Shouldn't it be SOCK_RAW? Does the packet have to be proccessed differently based on type - UDP, TCP, ICMP?
The issue was that it is better to use RAW packets - so u can get the dest/source IP and also when recieving, there is no need to post anything about the source recieveng from, so in the end the changes are like so:
Change SOCK_DGRAM to SOCK_RAW
Pass just buffer to recvfrom() function
State the type of socket when creating it
You don't have to bind
if ((sct = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
perror("Socket open error ");
exit (EXIT_FAILURE);
}
if (recvfrom(sct, buffer, BUF_SZ, 0, NULL, NULL) < 0)
{
process = 0; // nothing accepted
}

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.

Too many open files when I run a infinite socket open and close

I have searched all about this question at this website.
my program scenario is:
there is one server that always listens for a request from a client.
there is one client that always requests a char from the server in 2 second periods
get the error message:
Too many open files" happened on socket() function after the program run about 1024 times.
My current solution is to increase the number of open files:
"ulimit -n 5000", but I don't think this is a perfect solution, because it will make the program run 5000 times.
So, does anybody have a better solution?
Environment:
ubuntu 10
c language
My code as following:
Client:
int sockfd;
struct sockaddr_in address;
int socket_port = 9734;
while (1) {
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
DieWithSystemMessage("socket() failed");//<<===========Too many open files
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = socket_port;
//Establish the connection to the server
if ((connect(sockfd, (struct sockaddr *) &address, sizeof(address)))
< 0)
DieWithSystemMessage("connect() failed");
if (rename_count % 2 == 0)
ch = 'A';
else if (rename_count % 2 == 1)
ch = 'B';
else
ch = 'E';
ssize_t numBytes = send(sockfd, &ch, strlen(&ch), 0);
if (numBytes < 0)
DieWithSystemMessage("send() failed");
else if (numBytes != strlen(&ch))
DieWithUserMessage("send()", "sent unexpected number of bytes");
//fflush(sockfd);
shutdown(sockfd, SHUT_RDWR);
rename_count++;
}
Server:
int server_sockfd, client_sockfd;
int server_len, client_len;
socklen_t clntAddrLen;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
uint64_t start_time_micro, end_time_micro;
int socket_num = 9734;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (server_sockfd < 0)
DieWithSystemMessage("socket() failed");
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = socket_num;
if ((bind(server_sockfd, (struct sockaddr *) &server_address,
sizeof(server_address))) < 0)
DieWithSystemMessage("bind() failed");
if ((listen(server_sockfd, 5)) < 0)
DieWithSystemMessage("listen() failed");
while (1) {
char ch;
printf("\nserver waiting\n");
//accept a connect
clntAddrLen = sizeof(client_address);
client_sockfd = accept(server_sockfd,
(struct sockaddr *) &client_address, &clntAddrLen);
if (client_sockfd < 0)
DieWithSystemMessage("accept() failed");
//reading and writing through client side
ssize_t numBytesRcvd = recv(client_sockfd, &ch, 1, 0);
if (numBytesRcvd < 0)
DieWithSystemMessage("recv() failed");
if (ch == 'A') {
rename_num = 0;//printf("A\n");
} else if (ch == 'B') {
rename_num = 1;//printf("B\n");
} else
;
printf("%d. Got it!!!\n", i);
close(client_sockfd);
}
close(server_sockfd);
You're shutting down the socket in the client but never closing it. It's not the same thing.
There is a big difference between shutdown() and close(). When you "shutdown" a socket, you're putting it into a "half-closed" condition where it is still possible to send or receive (depending on which half you shut down) over the connection.
The socket is still valid, TCP still maintains state information about the connection, and the port is still "open", and the socket/file-descriptor is still allocated to your process.
When you call close() the socket/file-descriptor is free'd but the rest remains. TCP must hold resources for some amount of time, typically 2 minutes (it depends on who did the close and some other things) during which the state information and the local port itself are still "in use".
So even though you may no longer exceed the file-descriptor limit for your process, it is theoretically possible to saturate the resources of the networking stack and still not be able to open a new connection.

Socket programming in C, using the select() function

Based from the answers I got from this thread, I've created this:
//Server
sock_init(); //from SFL, see http://legacy.imatix.com/html/sfl/
timeout = 50000;
serv_sock_input[0] = TCP(1234);
serv_sock_input[1] = UDP(9876);
input_protocols[0] = "tcp";
input_protocols[1] = "udp";
while (1)
{
FD_ZERO(&sock_set);
for (x = 0; x<number_of_inputs; x++)
{
FD_SET(serv_sock_input[x], &sock_set);
}
select_timeout.tv_sec = timeout;
select_timeout.tv_usec = 0;
if (select(0, &sock_set, NULL, NULL, &select_timeout) == 0)
printf("No requests");
else
{
for (x = 0; x<number_of_inputs; x++)
{
if (FD_ISSET(serv_sock_input[x],&sock_set))
{
printf("\nRequest on port %d: \n", x);
if ((strcmp(input_protocols[x],"tcp")) == 0) //in this case, 0 returned == TRUE
{
accept_socket(serv_sock_input[x]);
printf("Input TCP Port %d\n",x);
close_socket(serv_sock_input[x]);
}
else
{
printf("Input UDP Port %d\n",x);
}
}
}
}
}
sock_term();
}
int TCP (unsigned short port)
{
int sock;
struct sockaddr_in servAddr;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
exit(1);
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
exit(1);
if (listen(sock, 5) < 0)
exit(1);
return sock;
}
int UDP (unsigned short port)
{
int sock; /* socket to create */
struct sockaddr_in servAddr; /* Local address */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
exit(1);
/* Construct local address structure */
memset(&servAddr, 0, sizeof(servAddr)); /* Zero out structure */
servAddr.sin_family = AF_INET; /* Internet address family */
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
servAddr.sin_port = htons(port); /* Local port */
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
exit(1);
return sock;
}
//Client
sock_init();
if ((client_sock_output = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
exit(1);
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
client_addr.sin_port = htons(1234);
if (connect(client_sock_output, (struct sockaddr *) &client_addr, sizeof(client_addr)) < 0)
exit(1);
closesocket(client_sock_output);
sock_term();
When the server starts, the server gets blocked at the if(select(...)) statement.
So when I run the Server, and then the client, the client connects to the server (sometimes it takes a couple times to run the client before they connect). Then the if(select...)) statement is no longer true and it proceeds to the else.
After that, the client closes the connection, and the program. However, and this is where my problem happens, the if(select(...)) statement is always false. I get this output:
Request on port 0:
Input TCP Port 0
Request on port 1:
Input UDP Port 1
This output repeats forever. How come it doesn't get stuck at the if(select(...))?
You have two problems: you don't understand how accept() works in TCP, and you need to read the incoming data in UDP.
select() tells you that a listening socket has connection to accept, or reading socket has data to read.
For select to stop telling you this, you need to actually read the data or accept the connection.
In your UDP branch, you need to call receiv to actually get the data. If you don't, select will keep telling you that you have data.
In your TCP branch, you call accept_socket. I don't know what is your implementation of it, but it's most probably wrong to close the socket you just called accept() on. accept() returns a new socket for you - the one you should be using for IO. If anything needs to be closed, it's that new socket.
Please check why you have this in server.
if (select(0, &sock_set, NULL, NULL, &select_timeout) == 0)
replace it with
if (select(maxDescPlus1, &sock_set, NULL, NULL, &select_timeout) == 0)
where maxDescPlus1 --> is number of descriptors to select plus 1 value.

Resources