On a second thought, after my previous message about getpeername(2), I
realized that you might actually need to get the peer name for the protocol
implementation.
More precisely, the verbose part of the server's reply to an HELO command
includes, according to the specifications, the brokername only. However the
examples show this part of the reply in the form brokername@host.domain.
So, while a strict interpretation of the specs does not require you to fish
for the client's machine name, it'd be nice to give it in the customary way
actually used by many servers in wide usage. Moreover, it's easy. Here's how
to do it in N easy steps:
(1) parse the addr of the connected socket returned by accept(2)
OR
call getpeername(2),
to get in the address of the machine at the
other end of the connected socket.
(2) gethostbyaddr(2), to get the peer's name
Here's an example program that binds to port, listens, accepts a connection,
then writes out the peer's address and exits.
/*
// peername.c - Accept a connection, print out the peer name and exit.
//
// Run as: peername [-p portnum]
// where portnum is the listening port (default 9908)
//
// Test it by
// shell on host groucho: % peername -p 8002
// shell on host harpo : % telnet groucho 8002
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#define PORT (9908)
int
main(int argc, char *argv[]) {
extern char *optarg;
extern int optind;
int c;
long port=0;
struct sockaddr_in skname, peername;
int peerlen;
struct hostent *peerent;
int lsk, csk;
/* Use getopt(3) to parse command line. */
if (argc>1) {
while (EOF!=(c=getopt(argc, argv, "p:"))) {
if (c=='p' && !port && (port=atol(optarg))>1023)
continue;
fprintf(stderr,
"Usage: peername [-p port]\n"
" port -- port number [9908]\n");
exit(1);
}
} else {
port=PORT;
}
/* Bind */
if (-1==(lsk=socket(AF_INET, SOCK_STREAM, 0))) {
perror("socket");
exit(2);
}
skname.sin_family=AF_INET;
skname.sin_port=htons(port);
skname.sin_addr.s_addr=INADDR_ANY;
if (-1==bind(lsk, (struct sockaddr*)&skname, sizeof(skname))) {
perror("bind");
exit(2);
}
/* Listen and accept */
listen(lsk, 1);
printf("peername: waiting for connections (port=%d).\n", port);
peerlen=sizeof(struct sockaddr_in);
if (-1==(csk=accept(lsk, (struct sockaddr*)&peername, &peerlen))) {
perror("accept");
exit(2);
}
/* Get peer addr:
// In this case it can be read directly on the sockaddr peername,
// which has been filled-in by accept(2).
// If we didn't have that sockaddr, either because we inherited
// the socket in a child, or because we called accept as
// csk=accept(lsk, NULL, 0);
// then we could get the name via getpeername(2) on the *connected*
// socket, i.e.
//
// if (-1==getpeername(csk, (struct sockaddr*)&peername, &peerlen))) {
// perror("getpeername");
// exit(2);
// }
//
// From this point on the program would be exactly the same as follows.
*/
if (NULL==(peerent=gethostbyaddr((void*)&peername.sin_addr.s_addr,
sizeof(struct in_addr),
AF_INET) )) {
perror("gethostbyaddr");
exit(3);
}
printf("peer: %s\n", peerent->h_name);
close(csk);
close(lsk);
return 0;
}