Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recovering IP/Port from Socket Descriptor

Tags:

c

tcp

sockets

inetd

I'm writing a clone of inetd in which I must run a server that prints the IP and port of the client connecting to it.

As I overwrite STDIN and STDOUT with the socket descriptor, my initial solution to do this was to recover the sockaddr_in structure, which contains the needed information. Doing this with getsockname(), however, is returning an empty structure, with all bits set to 0.

Any idea of what is wrong with my approach? Are there any other approaches I can use to recover the IP/Port?

Thanks

like image 452
konr Avatar asked Nov 15 '10 15:11

konr


People also ask

What will a socket descriptor hold?

Each socket within the network has a unique name associated with it called a socket descriptor—a fullword integer that designates a socket and allows application programs to refer to it when needed.

What is socket descriptor in Unix?

Sockets allow communication between two different processes on the same or different machines. To be more precise, it's a way to talk to other computers using standard Unix file descriptors. In Unix, every I/O action is done by writing or reading a file descriptor.

What is Sockfd?

sockfd is the listening socket descriptor. information about incoming connection is stored in. addr which is a pointer to a local struct sockaddr_in. addrlen is set to sizeof(struct sockaddr_in)

What network function in C sets up a socket and returns the socket descriptor used later?

The socket Function h> int socket (int family, int type, int protocol); This call returns a socket descriptor that you can use in later system calls or -1 on error.


3 Answers

As R.. pointed out, you should use getpeername. Both that function and getsockname take a file descriptor as its first argument, not a stream pointer (FILE *). Use fileno(stdin) to get the file descriptor for standard input (or hard-code it to STDIN_FILENO, as it's constant).

Also, the last argument to getsockname and getpeername should be a pointer to socklen_t, not a constant, and you should use a sockaddr_in for TCP/IP:

struct sockaddr_in peeraddr;
socklen_t peeraddrlen = sizeof(peeraddr);
getpeername(STDIN_FILENO, &peeraddr, &peeraddrlen);

See a complete example here.

like image 192
Fred Foo Avatar answered Oct 22 '22 04:10

Fred Foo


Use getpeername. I suspect your problem is that getsockname is returning the information for your own (local) side of the socket, which is probably bound to 0.0.0.0 (meaning it can accept connections from any interface).

Edit: I think I found your actual bug reading the code. This line is wrong:

getsockname(stdin, &addr, sizeof(addr));

The getsockname and getpeername functions take a socklen_t * (a pointer) as their third argument, not a size_t. The compiler should be telling you about this mistake unless you forgot to include a header with the prototype for getsockname. Also, as has already been said, stdin is incorrect. Try:

socklen_t len = sizeof addr;
getpeername(0, &addr, &len);

or (C99 only):

getpeername(0, &addr, (socklen_t[1]){sizeof addr});

You should also be checking the return value; if you did, you'd see that it's returning errors.

like image 32
R.. GitHub STOP HELPING ICE Avatar answered Oct 22 '22 06:10

R.. GitHub STOP HELPING ICE


If you need those info for the remote client, you have to call getpeername().

like image 28
Simone Avatar answered Oct 22 '22 04:10

Simone