(... where the 'B' suffix is intended to mean "BSD")

I would mail 9trouble, but I'm sure I have the wrong end of the stick
here, as seems to be too frequently the case, so let me ask for some
sanity checking.

The attached program (reveal) is a toy I use under NetBSD to disclose
the originating IP address for a TCP connection.  I use it daily and
it seems to behave the way I expect it to.

Having hacked the APE libraries to distraction for the benefit of GCC
(which is a separate discussion), I was hoping to use this as a
confidence booster, but was thoroughly disappointed.

Now, (a) I'm hoping someone can compile reveal.c (pcc -o reveal
-D_POSIX_SOURCES -D_BSD_EXTENSION reveal.c -lbsd) in a pristine APE
environment and prove to me that it works unmodified or, (b) somebody
can give me some pointers on figuring out how to make sure it works.

There are two scenarios: either I've messed the rather fragile-looking
"under a rock" code in the APE (BSD) library and caused a new problem,
or there is something in the existing code that needs fixing.

After some digging, the effect I have trouble believing ist that an
_OPEN("/net/tcp/27/listen", O_RDWR) fails silently and, crucially,
seems to somehow exit the actual listenproc, equally silently.
Verbatim, given a bit of debugging code:

        cpu% /tmp/reveal
        OPEN: /net/tcp/clone 2
        OPEN: 3 - r
        OPEN: /net/tcp/27/data 2
        OPEN: 4 - r
        OPEN: /adm/users 0
        OPEN: 3 - r
        findrock(4)
        Bind(/net/tcp/27/ctl)
        OPEN: /net/tcp/27/ctl 2
        OPEN: 5 - r
        Bind(bind 4523)
        Bound(bind 4523)
        
        Tired of waiting...
        Listen: open(/net/tcp/27/ctl)
        OPEN: /net/tcp/27/ctl 2
        OPEN: 5 - r
        Listen: write(bind 0)
        Listen: write(announce 4523)
        Listen: close
        OPEN: /proc/80443/noteid 0
        OPEN: 5 - r
        OPEN: /net/tcp/27/listen 2
        OPEN: /proc/80444/noteid 0
        OPEN: /proc/80442/noteid 0
        OPEN: 5 - r
        OPEN: 5 - r
        OPEN: /proc/80444/noteid 1
        OPEN: /proc/80442/noteid 1
        OPEN: 5 - r
        OPEN: 5 - r
        OPEN: /proc/80442/notepg 1
        _sock_findrock: 4
        OPEN: 5 - r
        PF_INET: 2
        SOCK_STREAM: 1
        OPEN: /proc/80442/noteid 1
        GET NAME: 4
        OPEN: 5 - r
        NAME? 4/0
        cpu% ERRNO: 12
        socket accept: Invalid argument
        OPEN: /proc/80444/noteid 0
        OPEN: 5 - r
        OPEN: /proc/80444/noteid 1
        OPEN: 5 - r
        
Of course, I'm prone to bark up the wrong tree and I don't see why
this should be an exceptional situation, but anything that puts me
back on the right path will be welcome.

Aplogies in advance for whatever stupidity might turn out to be the
root of this problem.

In passing, I don't have a convenient pristine APE environment to
check the code out and it is hard for me to construct one reliably
and, secondly, "reveal" is meant to drop into background, accepting
connections on TCP/4523 where it replies with the concatenation of the
originating IPv4 address and port number.  A version is running on
treacle.proxima.alt.za:

        term% telnet tcp!192.96.32.135!4523
        connected to tcp!192.96.32.135!4523 on /net/tcp/7
        155.239.76.121:21561

Thanks, as usual.

++L
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define REVEAL  (4523)

#define Q1(x)   (((x)>>24)&0xFF)
#define Q2(x)   (((x)>>16)&0xFF)
#define Q3(x)   (((x)>>8)&0xFF)
#define Q4(x)   (((x)>>0)&0xFF)

int main (int argc, char **argv) {
        int s0, s1;                     /* sockets */
        unsigned long h;
        int c, len;
        char s[32];
        struct sockaddr_in name;

        if ((s0 = socket (PF_INET, SOCK_STREAM, 0)) < 0) {
                perror ("Socket create");
                exit (1);
        }
        name.sin_family = AF_INET;
        name.sin_port = htons (REVEAL);
        name.sin_addr.s_addr = htonl (INADDR_ANY);
        if (bind (s0, (struct sockaddr *) &name, (int) (sizeof (name))) < 0) {
                perror ("socket bind");
                exit (2);
        }
        if (listen (s0, 1) < 0) {
                perror ("socket listen");
                exit (3);
        }
        switch (c = fork()) {
                case -1:
                        perror ("fork");
                        exit (4);
                case 0:
                        setpgid (0, 0);
                        while (1) {
                                len = (int) sizeof (name);
                                if ((s1 = accept (s0, (struct sockaddr *) 
&name, (socklen_t *) &len)) < 0) {
                                        fprintf (stderr, "ERRNO: %d\n", errno);
                                        perror ("socket accept");
                                        break;
                                }
                                h = ntohl (name.sin_addr.s_addr);
                                len = sprintf (s, "%d.%d.%d.%d:%u\n", Q1(h), 
Q2(h), Q3(h), Q4(h), ntohs (name.sin_port));
                                write (s1, s, len);
                                close (s1);
                        }
                default:
                        exit (0);
        }
}

Reply via email to