Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Jun 1999 19:56:49 +0200
From:      Sheldon Hearn <sheldonh@uunet.co.za>
To:        hackers@freebsd.org
Subject:   Obtaining client host IP before accept()
Message-ID:  <51363.929728609@axl.noc.iafrica.com>

next in thread | raw e-mail | index | archive | help

Hi folks,

I found a thread in the freebsd-hackers archive from 1997 that covered
my question, but the answers didn't nail it down to a "yes" or "no"
satisfactorily.

We could save ourselves a lot of angst in the work we're doing on inetd
if we could determine the client IP address of a TCP socket before
calling accept(). Alternatively, we'd love a way to accept() without
acknowledging a connection, so that the connection request could be left
for a child that expected to do its own socket() and bind() calls.

My take on the previous thread is that this is impossible in userland.
I'd appreciate it someone who knows the answer for a fact could look at
the code below and answer the following question:

	Will the IP address of the client host ever enter buf[] if the
	accept() is _not_ uncommented?

I don't need portability, since this is for use within the FreeBSD inetd
exclusively.

Thanks,
Sheldon.

--------
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>

/*
 * Use an arbitrary port that you know isn't in use on the system. I
 * don't run ircd, so this is safe for me.
 */
#define LISTEN_PORT	(6667)

#define BUFSIZE		(1500)

int
main(void)
{
	int ctl;
	int peek;
	int i = 1;
	int port = LISTEN_PORT;
	char buf[BUFSIZE];
	struct sockaddr_in	server_addr;
	struct sockaddr_in	client_addr;
	struct in_addr		bind_address;
	struct msghdr		msg;

	if ((ctl = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
		err(errno, "error creating socket");
	printf("socket number %d created\n", ctl);

	if (setsockopt(ctl, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i)))
		err(errno, "error setsockopt(SO_REUSEADDR): ");
	if (setsockopt(ctl, SOL_SOCKET, SO_REUSEPORT, (char *)&i, sizeof(i)))
		err(errno, "error setsockopt(SO_REUSEPORT): ");
	printf("setsockopt(SO_REUSEADDR|SO_REUSEPORT) successful\n");

	bind_address.s_addr = htonl(INADDR_ANY);
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr = bind_address;
	server_addr.sin_port = htons(port);

	if (bind(ctl, (struct sockaddr *)&server_addr, sizeof(server_addr)))
		err(errno, "error (%d) bind(%lu:%d)", errno,
		    server_addr.sin_addr.s_addr, port);
	printf("bound to port %d\n", port);

	if (listen(ctl, 0))
		err(errno, "error listening: ");
	printf("listening...\n");

/*
	i = sizeof(client_addr);
	if (peek = accept(ctl, (struct sockaddr *)&client_addr, &i) < 0)
		err(errno, "accept() failed: ");
	printf("connection accepted from %s\n",
	    inet_ntoa(client_addr.sin_addr));
*/

	msg.msg_name = (void *)&server_addr;
	msg.msg_namelen = sizeof(server_addr);
	msg.msg_iovlen = 0;
	msg.msg_control = (caddr_t)&buf;
	msg.msg_controllen = 1;
	while (recvmsg(ctl, &msg, MSG_PEEK) < 0) {
		warn("recvmsg failed: ");
		printf("msg_flags = %i\n", msg.msg_flags);
		sleep(2);
	}
	printf("recvmsg successful, wtf?\n");

	close(ctl);
/*
	close(peek);
*/
	return(0);
}


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?51363.929728609>