Some TCP states not showing in the terminal - linux

I have written a basic client server code to understand the TCP states.
Client code :
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Connect the socket to the server using the address struct ----*/
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
/*---- Read the message from the server into the buffer ----*/
recv(clientSocket, buffer, 1024, 0);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
return 0;
}
Server 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 = inet_addr("127.0.0.1");
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);
return 0;
}
I am running the command netstat -an | grep 7891, so at various points of time, I am getting the states ESTABLISHED, LISTENING, FINWAIT2, CLOSE_WAIT and TIME_WAIT.
How to get the other states like SYN_RECV, SYN_SENT, FINWAIT1, CLOSING and LAST ACK.
I have tried with various netstat options and ss options but to no vain.

You do not see SYN_RECV, SYN_SENT and other, because these stages are too short. For example, when after succesfull accept() on server side you have got ESTABLISHED, all previous states would be performed rapidly by TCP stack.
So, you are watching only long states of tcp connections.
You can achieve SYN_* states by simulating SYN-flood: use backlog parameter for listen(...,1) at server side and sleep before return 0. And try to launch several separate clients. As result you will get: 1 in ETSABLISHED and several in SYN_* states.
About finalize states. You should call shutdown() and close() and set sleep between them too. I recommend you to use fork() to make child process and use synchronizations primitives to understand TCP states

Related

netstat does not show listening port of udp server?

I have the following udp server:
/************* UDP SERVER CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
int main(){
int udpSocket, nBytes;
char buffer[1024];
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
int i;
/*Create UDP socket*/
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(20001);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*Bind socket with address struct*/
bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
while(1){
/* Try to receive any incoming UDP datagram. Address and port of
requesting client will be stored on serverStorage variable */
nBytes = recvfrom(udpSocket,buffer,1024,0,(struct sockaddr *)&serverStorage, &addr_size);
/*Convert message received to uppercase*/
for(i=0;i<nBytes-1;i++)
buffer[i] = toupper(buffer[i]);
/*Send uppercase message back to client, using serverStorage as the address*/
sendto(udpSocket,buffer,nBytes,0,(struct sockaddr *)&serverStorage,addr_size);
}
return 0;
}
I compiled and launched the udp server on my linux. and then I tried to see the listening UDP port with hetstat command but I did not see my server port listening:
sudo netstat -nulp | grep LISTEN
What I m missing?
You may use the following command to specifically show the UDP bound ports:
netstat -n --udp --listen
-n is for numerical representation of the ports, you may omit this
--udp is to show only UDP protocol related information
--listen is to list only ports those have are bound to accept packets/connections
The short command is: netstat -nul

Connecting to yourself (and hogging a port number)

We ran across a situation where an application apparently "half-connects" to itself through an system assigned port number and "gets stuck" on Linux (Centos 6.4 in particular).
The situation is as follows:
A (python) app is trying to connect to some service, let's say at IP address 192.168.1.201:8081. For some reason, the assigned outgoing port is 8081. The connect succeeds but no further activity occurs on the socket because it is not really connected but sort of half-way connected (My guess is that only half the handshake is completed and Linux is doing the rest in the background to improve parallelism). A read statement on the socket hangs waiting for the rest of the connect to complete.
Here is a simple C++ program that replicates the problem. Run it with the IP address of the host you are running on. It is peculiar because we are binding the connecting socket to a port (which is legal), and then connecting to the same address and port without an error message being generated, without a "listen," and with the read hanging.
./foo 192.168.1.201
Connected...going to read...'
ss -na
ESTAB 0 0 192.168.1.201:8081 192.168.1.201:8081
If you kill the program, the socket goes into Time-Wait:
TIME-WAIT 0 0 192.168.1.201:8081 192.168.1.201:8081
The question is: Can this happen with system assigned ports? Can you get into a state where somehow the outbound address/port ends up matching the destination address/port and the system deadlocks? That appears to be what we are seeing.
Thanks,
-- Mike
Program:
#include <assert.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int ret;
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
struct sockaddr_in sa_loc;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&sa_loc, 0, sizeof(struct sockaddr_in));
sa_loc.sin_family = AF_INET;
sa_loc.sin_port = htons(8081);
sa_loc.sin_addr.s_addr = inet_addr(argv[1]);
ret = bind(sockfd, (struct sockaddr *)&sa_loc, sizeof(struct sockaddr));
if (ret != 0) {
perror("bind");
exit(1);
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8081);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
ret = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (ret != 0) {
perror("connect");
exit(1);
}
printf("Connected...going to read...\n"); fflush(stdout);
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0) {
recvBuff[n] = 0;
printf("%s", recvBuff); fflush(stdout);
}
if(n <= 0) {
perror("read");
exit(1);
}
return 0;
}
By binding the socket to a port and then connecting to the very same port, you established a kind of loopback connection of the socket to itself.
Can this happen with system assigned ports?
No, it can't, because connect(3) promises:
If the socket has not already been bound to a local address,
connect() shall bind it to an address which, unless the
socket's address family is AF_UNIX, is an unused local address.
This unused local address is never the same as the one a running server's socket is bound to. Plus, the bind() in your client wouldn't have succeeded if a server for that port ran already.
Can you get into a state where somehow the outbound address/port ends
up matching the destination address/port and the system deadlocks?
We can only get into the observed state if we explicitly program that way, by binding to the very same port we're then connecting to. Also, the system doesn't deadlock, only the application blocks, quite simply because it calls read(), waiting for data which is never written.

setsockopt on "accepted" fd on Linux

I have had a rather strange observation about behavior of setsockopt on Linux for SO_REUSEADDR. In one line: if I apply the sockopt to an fd returned by accept on a "listening socket" the socketoption is reflected on the port held by the listening socket.
Ok some code.
Server : Opens a socket, applies SO_REUSEADDR to be true. Accepts a connection and then applies SO_REUSEADDR to be false on the fd on the fd returned by accept.
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
int main(void)
{
int s, len;
int sin_size;
int reuse = 1;
int ret;
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
my_addr.sin_port = htons(33235);
if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Socket Error\n");
return -1;
}
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
if( bind(s, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) < 0)
{
printf("Bind Error\n");
return -1;
}
listen(s, 6);
reuse = 0;
memset(&my_addr, 0, sizeof(my_addr));
while(1) {
ret = accept(s, (struct sockaddr*)&my_addr, &len);
if (ret<0) {
printf("Accept failed\n");
} else {
printf("Accepted a client setting reuse add to 0\n");
setsockopt(ret, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
}
}
printf("Server exiting\n");
return 0;
}
Client : Client connects to the server, and doesn't do anything after that ensuring that the server socket stays in TIME_WAIT state.
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
int main(void)
{
int s, len;
int sin_size;
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
my_addr.sin_port = htons(33235);
if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Socket Error\n");
return -1;
}
if (!connect(s,(struct sockaddr*)&my_addr, sizeof(struct sockaddr)))
{
printf("Client Connected successfully\n");
}
else
{
printf("%s\n",strerror(errno));
}
while(1) sleep(1);
return 0;
}
Steps that I do reproduce the issue.
Run server.
Connect client.
Kill and restart server. The server fails with Bind Failure
I tested this on mac os. And the bind didn't fail. I have digged up all Posix specifications and none of them say that this code is undefined.
Question:
Can someone with more experience on this share their understanding of the issue?
One way to think about it is that SO_REUSEADDR determines if you can have another socket bound to that same address. It's a property of any socket (listen or connection), but very commonly inherited from listen via accept. In linux it's mapped to the struct sock "sk_reuse" flag.
If you clear this flag on a FD you "accepted" then from that point on the IP/Port pair is considered busy-and-non-reusable. The SO_REUSEADDR flag on the listen socket does not change, but the flag on the accepted socket affects bind logic. You could probably check this with getsockopt.
If you want to know more you can try to read the inet_csk_get_port function: http://lxr.free-electrons.com/source/net/ipv4/inet_connection_sock.c#L100. This is where the actual "binding" takes place.

How getservbyname can get the server port information if it is run on a client machine?

The following client program trys to connect to a server and finds the current time and date on that server.
/* Start with the usual includes and declarations. */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *host;
int sockfd;
int len, result;
struct sockaddr_in address;
struct hostent *hostinfo;
struct servent *servinfo;
char buffer[128];
if(argc == 1)
host = "localhost";
else
host = argv[1];
/* Find the host address and report an error if none is found. */
hostinfo = gethostbyname(host);
if(!hostinfo) {
fprintf(stderr, "no host: %s\n", host);
exit(1);
}
/* Check that the daytime service exists on the host. */
servinfo = getservbyname("daytime", "tcp");
if(!servinfo) {
fprintf(stderr,"no daytime service\n");
exit(1);
}
printf("daytime port is %d\n", ntohs(servinfo -> s_port));
/* Create a socket. */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* Construct the address for use with connect... */
address.sin_family = AF_INET;
address.sin_port = servinfo -> s_port;
address.sin_addr = *(struct in_addr *)*hostinfo -> h_addr_list;
len = sizeof(address);
/* ...then connect and get the information. */
result = connect(sockfd, (struct sockaddr *)&address, len);
if(result == -1) {
perror("oops: getdate");
exit(1);
}
result = read(sockfd, buffer, sizeof(buffer));
buffer[result] = '\0';
printf("read %d bytes: %s", result, buffer);
close(sockfd);
exit(0);
}
Question:
We run the above program on a client machine, how the function getservbyname can get the
server information without a reference to the server machine in the parameter list?
It examines /etc/services for an entry with the given service name and protocol.
$ grep "^daytime\s.*/tcp" /etc/services
daytime 13/tcp
getservbyname simply looks in /etc/services to find the "daytime" service using the "tcp" protocol.
It's just a convenience, to save you from parsing that file.
Edit (clarification)
Each of these protocols has a friendly name ("daytime", "http", etc) and a useful name (the port number - 13, 80 etc). /etc/services holds this mapping, nothing more.

Is raw socket on loopback interface possible?

We are trying to communicate with the server listening on Linux loopback interface via raw socket and it seems like the server does not get a single packet from us. The packets we send are visible in Wireshark.
Is raw socket on loopback possible at all? (Please, don't ask why we need it: it's too complicated to explain here)
EDIT: this is how we open it
_I_RawSocket = socket( PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)))
memset( &ifr, 0, sizeof( ifr ) );
strcpy( ifr.ifr_ifrn.ifrn_name, _InterfaceName);
ioctl( _I_RawSocket, SIOCGIFINDEX, &ifr )
memset( &sll, 0, sizeof( sll ) );
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons( ETH_P_ALL );
bind( _I_RawSocket, (struct sockaddr *) &sll, sizeof( sll ))
The server is lighttpd and it's reachable via normal socket on localhost.
netstat --raw prints empty table but I'm absolutely sure we have two functional raw sockets on normal eth devices.
Raw sockets behave particularly fizzy with bind() and connect(), but I can't confirm that your issue lies with them. I suggest you follow a more straightforward approach:
Sender
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define DEST "127.0.0.1"
int main(int argc, char **argv)
{
int s;
struct sockaddr_in dst_addr;
char packet[50];
struct iphdr *ip = (struct iphdr *)packet;
if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}
dst_addr.sin_family = AF_INET;
dst_addr.sin_port = 0; /* not needed in SOCK_RAW */
inet_pton(AF_INET, DEST, (struct in_addr *)&dst_addr.sin_addr.s_addr);
memset(dst_addr.sin_zero, 0, sizeof(dst_addr.sin_zero));
memset(packet, 'A', sizeof(packet)); /* payload will be all As */
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = htons(40);
ip->frag_off = 0; /* NF */
ip->ttl = 64;
ip->protocol = IPPROTO_RAW; /* this has to be IPPROTO_RAW */
ip->check = 0;
ip->saddr = dst_addr.sin_addr.s_addr;
ip->daddr = dst_addr.sin_addr.s_addr;
while(42) {
sleep(5);
if (sendto(s, packet, sizeof(packet), 0,
(struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)) < 0)
perror("uh oh:");
}
return(0);
}
Receiver
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int s;
struct sockaddr_in src_addr;
char packet[50];
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("error:");
exit(EXIT_FAILURE);
}
memset(packet, 0, sizeof(packet));
socklen_t *len = (socklen_t *)sizeof(src_addr);
int fromlen = sizeof(src_addr);
while(42) {
if (recvfrom(s, &packet, sizeof(packet), 0,
(struct sockaddr *)&src_addr, &fromlen) < 0)
perror("uh oh:");
int i = sizeof(struct iphdr); /* print the payload */
for(; i < sizeof(packet); i++) {
printf("%c", packet[i]);
}
printf("\n");
}
return(0);
}
I hope these behave exactly like you want them to. Read man 7 raw for the gory details of why this works and more importantly man 7 packet if you want to extend it. Also, take note that IPPROTO_RAW implies the IP_HDRINCL socket option, which is why we're constructing the ip header ourselves - although the IP checksum and total length are computed and filled in by the kernel, still.
edit: In addition, if you wanted a raw socket with which to send valid data to an application like lighttpd, you'd have to match the protocol argument to socket() as well as provide valid values for the IP header fields. A proper ethernet header is not mandatory - the only important field will be filled for you by the kernel stack.
Please make sure bind to if_index
if (ioctl(sock, SIOCGIFINDEX, &stEthReq ) < 0 )
{
printf( "failed to get IF index!" );
return -1;
}
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sll_family = AF_PACKET;
client_addr.sll_ifindex = stEthReq.ifr_ifru.ifru_ivalue;
client_addr.sll_protocol = VOS_HTONS(usEthType);
ret = bind(sock,(struct sockaddr *)(&client_addr), sizeof(client_addr));

Resources