how to find clients ip address using tcp socket programming in c - c

I am trying to develop a TCP server, in that server clients are connecting with the server after the set up the connection. But how do i find the ip address from that connection. Sample codes are given here.
int connfd;
int listenfd;
struct sockaddr_in cliaddr;
socklen_t clilen;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
this is not the exact code. But now i need to find the client address as a string.

accept() gives you the client's remote IP address and port number in the sockaddr_in struct that it fills in, in the sin_addr and sin_port struct members, respectively. Both values are numeric values in network byte order. You can use a function like inet_ntoa() to convert the IP into a human-readible string, and ntohs() to convert the port number into an integer whose byte order matches the calling machine so you can work with it more naturally.
Also look at the getpeername() and getsockname() functions.

cliaddr is the structure variable for of structure sockaddr_in for the client.
cliaddr.sin_addr.s_addr contains the client's IP address.
inet_ntop(AF_INET, &(cliaddr.sin_addr), clientAddr, CLADDR_LEN); Retrieves the IP address of the client into a string clientAddr.

Related

Send Raw arp reply packet in windows

I am currently learning how to use the windows raw sockets.
I created a raw arp reply frame(includes all headers (ethernet+arp headers)), and when I send it using sendto function,
It fails and return SOCKET_ERROR with error code 10047.
The parameters I used to create the socket are as follows:
socket s = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
and also I changed the socket options as follows:
int on=1;
setsockopt(s,IPPROTO_IP, 2,(char*)&on,sizeof(on));
(By the way, '2' is equal to IP_HDRINCL, for some reason, visual studio didn't recognize it..)
I try to send the packet as follows:
socketaddr sa = { 0 };
int SentBytesCount = sendto(s, (char*)&arp_raw_msg,sizeof(Arp_Frame),0,&sa,sizeof(sa));
Where Arp_Frame is a struct that includes ethernet header+arp header+18 Bytes for padding.
After this call I get that SentBytesCount is equal to SOCKET_ERROR(-1), and no packet is sent.
Thank you for your help!
Winsock error 10047 is WSAEAFNOSUPPORT:
Address family not supported by protocol family.
An address incompatible with the requested protocol was used. All sockets are created with an associated address family (that is, AF_INET for Internet Protocols) and a generic protocol type (that is, SOCK_STREAM). This error is returned if an incorrect protocol is explicitly requested in the socket call, or if an address of the wrong family is used for a socket, for example, in sendto.
You created an AF_INET (IPv4) socket, but you are not passing sendto() a valid sockaddr_in containing an IPv4 address and port, hence the error. You are passing it an empty socketaddr (what is that?) instead.
Any sockaddr_... struct you use with a socket must match what the socket's address family expects, as set by the socket() call (in your case, AF_INET, which uses sockaddr_in addresses).
sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("destination IP address");
sa.sin_port = htons(Destination port number);
int SentBytesCount = sendto(s, (char*)&arp_raw_msg, sizeof(Arp_Frame), 0, (struct sockaddr*)&sa, sizeof(sa));
As for IP_HDRINCL, it is defined in ws2tcpip.h.

socket connect() vs bind()

Both connect() and bind() system calls 'associate' the socket file descriptor to an address (typically an ip/port combination). Their prototypes are like:-
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
and
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
What is the exact difference between 2 calls? When should one use connect() and when bind()?
Specifically, in some sample server client codes, found that client is using connect() and server is using the bind() call. Reason was not fully clear to me.
To make understanding better , lets find out where exactly bind and connect comes into picture,
Further to positioning of two calls , as clarified by Sourav,
bind() associates the socket with its local address [that's why server side binds, so that clients can use that address to connect to server.]
connect() is used to connect to a remote [server] address, that's why is client side, connect [read as: connect to server] is used.
We cannot use them interchangeably (even when we have client/server on same machine) because of specific roles and corresponding implementation.
I will further recommend to correlate these calls TCP/IP handshake .
So, who will send SYN here, it will be connect(). While bind() is used for defining the communication end point.
The one liner : bind() to own address, connect() to remote address.
Quoting from the man page of bind()
bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. addrlen specifies the size, in bytes, of the address structure pointed to by addr. Traditionally, this operation is called "assigning a name to a socket".
and, from the same for connect()
The connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.
To clarify,
bind() associates the socket with its local address [that's why
server side binds, so that clients can use that address to connect
to server.]
connect() is used to connect to a remote [server] address, that's
why is client side, connect [read as: connect to server] is used.
I think it would help your comprehension if you think of connect() and listen() as counterparts, rather than connect() and bind(). The reason for this is that you can call or omit bind() before either, although it's rarely a good idea to call it before connect(), or not to call it before listen().
If it helps to think in terms of servers and clients, it is listen() which is the hallmark of the former, and connect() the latter. bind() can be found - or not found - on either.
If we assume our server and client are on different machines, it becomes easier to understand the various functions.
bind() acts locally, which is to say it binds the end of the connection on the machine on which it is called, to the requested address and assigns the requested port to you. It does that irrespective of whether that machine will be a client or a server. connect() initiates a connection to a server, which is to say it connects to the requested address and port on the server, from a client. That server will almost certainly have called bind() prior to listen(), in order for you to be able to know on which address and port to connect to it with using connect().
If you don't call bind(), a port and address will be implicitly assigned and bound on the local machine for you when you call either connect() (client) or listen() (server). However, that's a side effect of both, not their purpose. A port assigned in this manner is ephemeral.
An important point here is that the client does not need to be bound, because clients connect to servers, and so the server will know the address and port of the client even though you are using an ephemeral port, rather than binding to something specific. On the other hand, although the server could call listen() without calling bind(), in that scenario they would need to discover their assigned ephemeral port, and communicate that to any client that it wants to connect to it.
I assume as you mention connect() you're interested in TCP, but this also carries over to UDP, where not calling bind() before the first sendto() (UDP is connection-less) also causes a port and address to be implicitly assigned and bound. One function you cannot call without binding is recvfrom(), which will return an error, because without an assigned port and bound address, there is nothing to receive from (or too much, depending on how you interpret the absence of a binding).
bind tells the running process to claim a port. i.e, it should bind itself to port 80 and listen for incomming requests. with bind, your process becomes a server. when you use connect, you tell your process to connect to a port that is ALREADY in use. your process becomes a client. the difference is important: bind wants a port that is not in use (so that it can claim it and become a server), and connect wants a port that is already in use (so it can connect to it and talk to the server)
From Wikipedia http://en.wikipedia.org/wiki/Berkeley_sockets#bind.28.29
connect():
The connect() system call connects a socket, identified by its file descriptor, to a remote host specified by that host's address in the argument list.
Certain types of sockets are connectionless, most commonly user datagram protocol sockets. For these sockets, connect takes on a special meaning: the default target for sending and receiving data gets set to the given address, allowing the use of functions such as send() and recv() on connectionless sockets.
connect() returns an integer representing the error code: 0 represents success, while -1 represents an error.
bind():
bind() assigns a socket to an address. When a socket is created using socket(), it is only given a protocol family, but not assigned an address. This association with an address must be performed with the bind() system call before the socket can accept connections to other hosts. bind() takes three arguments:
sockfd, a descriptor representing the socket to perform the bind on.
my_addr, a pointer to a sockaddr structure representing the address to bind to.
addrlen, a socklen_t field specifying the size of the sockaddr structure.
Bind() returns 0 on success and -1 if an error occurs.
Examples:
1.)Using Connect
#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 the IP address to desired host to connect to */
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.17");
/* 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;
}
2.)Bind Example:
int main()
{
struct sockaddr_in source, destination = {}; //two sockets declared as previously
int sock = 0;
int datalen = 0;
int pkt = 0;
uint8_t *send_buffer, *recv_buffer;
struct sockaddr_storage fromAddr; // same as the previous entity struct sockaddr_storage serverStorage;
unsigned int addrlen; //in the previous example socklen_t addr_size;
struct timeval tv;
tv.tv_sec = 3; /* 3 Seconds Time-out */
tv.tv_usec = 0;
/* creating the socket */
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
printf("Failed to create socket\n");
/*set the socket options*/
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
/*Inititalize source to zero*/
memset(&source, 0, sizeof(source)); //source is an instance of sockaddr_in. Initialization to zero
/*Inititalize destinaton to zero*/
memset(&destination, 0, sizeof(destination));
/*---- Configure settings of the source address struct, WHERE THE PACKET IS COMING FROM ----*/
/* Address family = Internet */
source.sin_family = AF_INET;
/* Set IP address to localhost */
source.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY = 0.0.0.0
/* Set port number, using htons function to use proper byte order */
source.sin_port = htons(7005);
/* Set all bits of the padding field to 0 */
memset(source.sin_zero, '\0', sizeof source.sin_zero); //optional
/*bind socket to the source WHERE THE PACKET IS COMING FROM*/
if (bind(sock, (struct sockaddr *) &source, sizeof(source)) < 0)
printf("Failed to bind socket");
/* setting the destination, i.e our OWN IP ADDRESS AND PORT */
destination.sin_family = AF_INET;
destination.sin_addr.s_addr = inet_addr("127.0.0.1");
destination.sin_port = htons(7005);
//Creating a Buffer;
send_buffer=(uint8_t *) malloc(350);
recv_buffer=(uint8_t *) malloc(250);
addrlen=sizeof(fromAddr);
memset((void *) recv_buffer, 0, 250);
memset((void *) send_buffer, 0, 350);
sendto(sock, send_buffer, 20, 0,(struct sockaddr *) &destination, sizeof(destination));
pkt=recvfrom(sock, recv_buffer, 98,0,(struct sockaddr *)&destination, &addrlen);
if(pkt > 0)
printf("%u bytes received\n", pkt);
}
I hope that clarifies the difference
Please note that the socket type that you declare will depend on what you require, this is extremely important
Too Long; Don't Read: The difference is whether the source (local) or the destination address/port is being set. In short, bind() set the source and connect() set the destination. Regardless of TCP or UDP.
bind()
bind() set the socket's local (source) address. This is the address where packets are received. Packets sent by the socket carry this as the source address, so the other host will know where to send back its packets.
If receive is not needed the socket source address is useless. Protocols like TCP require receiving enabled in order to send properly, as the destination host send back a confirmation when one or more packets have arrived (i.e. acknowledgement).
connect()
TCP has a "connected" state. connect() triggers the TCP code to try to establish a connection to the other side.
UDP has no "connected" state. connect() only set a default address to where packets are sent when no address is specified. When connect() is not used, sendto() or sendmsg() must be used containing the destination address.
When connect() or a send function is called, and no address is bound, Linux automatically bind the socket to a random port. For technical details, take a look at inet_autobind() in Linux kernel source code.
Side notes
listen() is TCP only.
In AF_INET family, the socket's source or destination address (struct sockaddr_in) is composed by an IP address (see IP header), and TCP or UDP port (see TCP and UDP header).

GetPeerName() returning constant IP address

Anytime I call GetPeerName() on a socket in use, I get a constant IP address.
SOCKADDR_IN clientAddr;
IN_ADDR clientIn;
int nClientAddrLen;
getpeername(fd, (LPSOCKADDR)&clientAddr, &nClientAddrLen);
memcpy(&clientIn, &clientAddr.sin_addr.s_addr, 4);
printf("client IP address is %s, port is %d", inet_ntoa(clientIn),ntohs(clientAddr.sin_port));
Where fd is my already connected socket. I get the same host and port number every time. I am assuming I might be overlooking some small error, but I simply cannot find it. Can anyone offer any assistance?

Sockets - How to find out what port and address I'm assigned

I'm having trouble figuring this out - I'm working with sockets in C using this guide - http://binarii.com/files/papers/c_sockets.txt
I'm trying to automatically get my ip and port using:
server.sin_port = 0; /* bind() will choose a random port*/
server.sin_addr.s_addr = INADDR_ANY; /* puts server's IP automatically */
...
...
bind(int fd, struct sockaddr *my_addr,int addrlen); // Bind function
After a successful bind, how do I find out what IP and Port I'm actually assigned?
If it's a server socket, you should call listen() on your socket, and then getsockname() to find the port number on which it is listening:
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
if (getsockname(sock, (struct sockaddr *)&sin, &len) == -1)
perror("getsockname");
else
printf("port number %d\n", ntohs(sin.sin_port));
As for the IP address, if you use INADDR_ANY then the server socket can accept connections to any of the machine's IP addresses and the server socket itself does not have a specific IP address. For example if your machine has two IP addresses then you might get two incoming connections on this server socket, each with a different local IP address. You can use getsockname() on the socket for a specific connection (which you get from accept()) in order to find out which local IP address is being used on that connection.
The comment in your code is wrong. INADDR_ANY doesn't put server's IP automatically'. It essentially puts 0.0.0.0, for the reasons explained in mark4o's answer.

How to get ip address from sock structure in c?

I'm writing simple server/client and trying to get client IP address and save it on server side to decide which client should get into critical section. I googled it several times but couldn't find proper way to get IP address from sock structure.
I believe this is a way to get IP from sock struct after server accept request from client. More specifically in c after server execute
csock = accept(ssock, (struct sockaddr *)&client_addr, &clen)
Thanks
OK assuming you are using IPV4 then do the following:
struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&client_addr;
struct in_addr ipAddr = pV4Addr->sin_addr;
If you then want the ip address as a string then do the following:
char str[INET_ADDRSTRLEN];
inet_ntop( AF_INET, &ipAddr, str, INET_ADDRSTRLEN );
IPV6 is pretty easy as well ...
struct sockaddr_in6* pV6Addr = (struct sockaddr_in6*)&client_addr;
struct in6_addr ipAddr = pV6Addr->sin6_addr;
and getting a string is almost identical to IPV4
char str[INET6_ADDRSTRLEN];
inet_ntop( AF_INET6, &ipAddr, str, INET6_ADDRSTRLEN );
The easier and correct way for extracting IP address and port number would be:
printf("IP address is: %s\n", inet_ntoa(client_addr.sin_addr));
printf("port is: %d\n", (int) ntohs(client_addr.sin_port));
The SoapBox's accepted answer won't be correct for all architectures. See Big and Little Endian.
Assuming client_addr is a struct sockaddr_in (which it usually is). You can get the IP address (as a 32-bit unsigned integer) from client_addr.sin_addr.s_addr.
You can convert it to a string this way:
printf("%d.%d.%d.%d\n",
int(client.sin_addr.s_addr&0xFF),
int((client.sin_addr.s_addr&0xFF00)>>8),
int((client.sin_addr.s_addr&0xFF0000)>>16),
int((client.sin_addr.s_addr&0xFF000000)>>24));

Resources