0

Question: xinetd (extended Internet services daemon) maps input to a service's standard input and output to a service's standard out.

In other words, assuming a custom TCP service written in C, data coming into port X is mapped to stdin of the service and stdout of the service is mapped to data coming out of port Y.

Again, assuming a custom TCP service written in C, is there a way for that service to determine the connecting client's IP Address?

Web Research: As of the posting of this question, there are NO other questions on Stack Exchange (or elsewhere) that specifically deal with xinetd TCP services written in C attempting to determine the connecting client's IP Address.

There are similar questions:

But none that answer the specific question detailed in this post.

FOLLOW UP NOTE: xinetd takes the socket descriptor associated with TCP port X and maps it to the service's standard input.

Being cognizant of this fact would have allowed for a better web search that resulted in the following answers:

HighExodus
  • 104
  • 2
  • 11

1 Answers1

4

Yes, with getpeername(2) on its stdin (0) or stdout (1) file descriptor.

Example: when run from xinetd or inetd, this will print the address of the client connected to its stdin:

#define _DEFAULT_SOURCE
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in.h>
#include <stdio.h>
#include <err.h>
#include <netdb.h>

int main(void){
        union {
                struct sockaddr a;
                struct sockaddr_in in;
                struct sockaddr_in6 in6;
        } na;
        char host[NI_MAXHOST], port[NI_MAXSERV]; int e;
        socklen_t nl = sizeof na;
        if(getpeername(0, &na.a, &nl)) err(1, "getpeername");
        if(e = getnameinfo(&na.a, nl, host, sizeof host, port, sizeof port,
                        NI_NUMERICHOST|NI_NUMERICSERV))
                errx(1, "getnameinfo: %s", gai_strerror(e));
        switch(na.a.sa_family){
        case AF_INET:
                errx(0, "connection from %s:%s", host, port);
        case AF_INET6:
                errx(0, "connection from [%s]:%s", host, port);
        default:
                errx(0, "connection from unknown address family %d",
                        na.a.sa_family);
        }
}
  • I believe `_POSIX_HOST_NAME_MAX` is defined as 255. 128 may be a tad bit small (or it may be larger than needed). Also see [Maximum hostname length on Linux](https://stackoverflow.com/q/18851234/608639). – jww Apr 20 '19 at 03:31
  • yes, but I'm using `NI_NUMERICHOST`, so even 40 bytes should be enough ;-) –  Apr 20 '19 at 03:39
  • I don't think get peername will work on an unconnected socket? – Leo Smith Jul 24 '23 at 08:54