Return to BSD News archive
Newsgroups: comp.unix.bsd.freebsd.misc
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!news.unimelb.edu.au!munnari.OZ.AU!news.ecn.uoknor.edu!feed1.news.erols.com!disgorge.news.demon.net!demon!dispatch.news.demon.net!demon!rill.news.pipex.net!pipex!oleane!in2p3.fr!univ-lyon1.fr!fdn.fr!r2d2.fdn.org!sphynx.fdn.fr!causse
From: causse@sphynx.fdn.fr (Philippe Causse)
Subject: Re: Accept()-ing a connection from a specific IP address...
X-Newsreader: TIN [version 1.2 PL2]
Organization: individual - paris - france
Message-ID: <EAnnEo.12E@sphynx.fdn.fr>
References: <864144757.18711@dejanews.com> <EAHuuM.129@sphynx.fdn.fr> <5lvqjg$7rq$1@goof.Germany.EU.net>
Date: Fri, 23 May 1997 22:20:47 GMT
Lines: 162
Xref: euryale.cc.adfa.oz.au comp.unix.bsd.freebsd.misc:41533
Bernard Steiner (knob@wizards.staff.Germany.EU.net) wrote:
: In article <EAHuuM.129@sphynx.fdn.fr>,
: causse@sphynx.fdn.fr (Philippe Causse) writes:
: > moballa@WESTECHMobile.com wrote:
: >: Is there any way to use the Accept() routine to only accept a connection
: >: from a specific IP address? Currently my program accepts a connection
: >: from anyone issuing a connect() call to it. I would like to specify that
: >: it should only accept a connection from a particular IP address.
: > Afetr you created your `listening' socket:
: > 1) bind it to the interface you whish to accept calls from
: > (getnetent could help)
: That helps in cases where you wish to service requests only on a particular
: interface (or similar).
That's exactly what I meant...
: > 2) When accept() returns, check the peer address and if
: > the address is not an "allowed one", you should immediately
: > close the returned socket.
: That does not help really, since AFAIK accept() does a three-way handshake and
: closing the connection immediately is quite different from not accepting it.
It may be more polite to accept, then write a short message like
500 - Service not available
and close nicely. Yes,it'll require a few more packets, but saying "goodbye"
never hurted anyone...
: What I would like to know is whether or not it is now possible to
: (a) use the rcvmsg() (or was that recvfrom() ?) calls for bound TCP sockets
: *and
According to the man page, it says recvfrom can be used on a socket, whether
it is connection-oriented or not. Although does not state that recvfrom
can be used on a passive socket! The demo program attached illustrates
that you cannot guess the peer's address before accept() has been done
(for TCP stuff, of course).
: (b) somehow discard TCP SYNs from illegitimate addresses and optionally tell
: the other side we are refusing connections ?
Then you should probably setup a firwall ! AFAIK this is the only way to
reject connection attemps. (kinda fascit stuff IMHO).
: > Other option (simpler, faster): use the tcp_wrappers library !
: You mean reverse-engineer the thing ;-)
Not at all. Just making use of the tcpwrappers API in your program like
a few others did (ypserv for example). And if your server is started from
inetd, it's trivial to start put it under tcpwrapper's control... RTFM!
: Bernard
----[cut here]---
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERVER_PORT 4321
/*
* Method 1 : does not work.
* Peek some data in the TCP queue to look for IP address...
*/
void filter_connect_1(int so)
{
struct sockaddr_in peer_addr;
int peer_addr_len = sizeof(peer_addr);
int sts;
char buf[1];
bzero(&peer_addr, peer_addr_len);
sts = recvfrom(so, buf, sizeof(buf), MSG_PEEK,
(struct sockaddr *)&peer_addr, &peer_addr_len);
if(sts < 0) perror("recvfrom");
printf("Rejecting incoming connect() from %s\n",
inet_ntoa(peer_addr.sin_addr));
close( accept(so, NULL, 0));
}
/*
* Method 2 : does work :-)
* Check the result of accept.
*/
void filter_connect_2(int so)
{
FILE * cli;
int cli_sock;
struct sockaddr_in peer_addr;
int peer_addr_len = sizeof(peer_addr);
bzero(&peer_addr, peer_addr_len);
cli_sock = accept(so, (struct sockaddr *)&peer_addr, &peer_addr_len);
if( cli_sock < 0) perror("accept");
printf("Incoming connect() from %s\n", inet_ntoa(peer_addr.sin_addr));
cli = fdopen(cli_sock, "w");
fprintf(cli, "500 - Not authorized to connect\r\n");
fflush(cli);
fclose(cli);
close(cli_sock);
}
int main()
{
int sts;
int so; /* server socket */
struct sockaddr_in serv_addr;
int serv_addr_len;
fd_set readfds;
int nfds;
serv_addr.sin_port = htons(SERVER_PORT);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_len = sizeof(serv_addr); /* total length */
bzero(&serv_addr.sin_zero, sizeof(serv_addr.sin_zero));
serv_addr_len = sizeof(serv_addr);
so = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);
assert(so >= 0);
sts = bind(so, (struct sockaddr *)&serv_addr, serv_addr_len);
assert( sts == 0);
sts = listen(so, 5);
assert(sts == 0);
while(1)
{
puts("--> select()");
nfds = so + 1;
FD_ZERO(&readfds);
FD_SET(so, &readfds);
sts = select(nfds, &readfds, 0, 0, NULL);
puts("<-- select()");
/* filter_connect_1(so); */ /* doesn't work */
filter_connect_2(so); /* works */
}
close(so);
return EXIT_FAILURE;
}
------[cut here, compile and telnet to port 4321]-----
--
-------------------------------------------------------------------
P. Causse http://www.fdn.fr/~pcausse
4.4BSD/X11R6/Motif-2.0/C++ mailto:causse@sphynx.fdn.fr (UUCP)