[comp.protocols.tcp-ip] Use of SOCK_RAW to implement new transport protocol on top of IP?

TAYBENGH@NUSDISCS.BITNET (03/05/91)

Hi netlander,
        I would like to use SOCK_RAW provided in BSD socket to implement a new
transport protocol on top of IP. Regretably, the documentation of SOCK_RAW
usage is very scare, it is not clearly discussed in BSD documantation, nor the
two precious books - The design and implementation of 4.3BSD OS (published by
Addsion-Wesley), and Unix Network Programming (published by Prentice-Hall).
As such, I would like to sort for the net experience. The questions are:

        1) How one can associate a new protocol (that is not defined in in.h -
socket) to the socket? Specifically, how one can initialize the rcp_proto
field so as to filter packets on input, and also the rcb_pcb field so as to
attach the new protocol-specific information? (note: the rcb_* and raw socket
are discussed in 11.7 of the BSD4.3 book - pg 332)

        2) If one cannot filter out the packets on input using the above
method, then if I open a socket using protocol 0 (the default protocol - IP?),
does this socket receive all the packets including TCP, UDP, ICMP, and pure IP
packets? (in fact, I did an experiment on SunOS4.1, I found out the socket
receives only the ICMP packets, not even the pure IP packets, the program
segment are attached as follow, did I did sth wrong?, I also crashed the system
several times when I tried to send out IP packets, is this a bug or I did sth
wrong again?) Moreover, how to initialize the socket so that it can receive all
IP packets in order to extract the newly defined packets?

        3) In SunOS4.1, I opened a raw socket with protocol 0 to receive IP
packets using the attached program segment shown below, then when I used ping
(within same host) to ping itself, this program only receive the echo ICMP
messages, but NOT the request ICMP messages. On the other hand, if I ping from
other host to this particular host, the request ICMP messages are also NOT
received by this program. As such it seems that all ICMP request messages are
filtered out by IP layer and thus cannot be received by user process? Is that
true? Morevoer, if I used an connected UDP socket to send message to an
unreachable port within the same host, this program is also able receives the
port unreachable ICMP messages (type=3, code=3). Why is it so? I thought it
should EITHER receive ALL ICMP messages (including echo, request and etc), OR
it should not receive any ICMP messages at all.

        4) After looking thru the in.h, I found out there is a IPPROTO_RAW (255)
, should I use this instead of the default 0 in order to receive pure IP
packets? If not, what is the purpose of this protocol?

        Could somebody please solve/explain all these puzzles? I am desparated,
please help. Thanks a lot.

        ==> Here are the receiving part (in C), this part can receive ICMP
        message, BUT NOT the pure IP packets sent by the below program.

        int     sock, socklen;
        struct  sockaddr_in     local_in, remote_in;
        char    buf[1024], hostname[15], s1[10];
        u_short local_port, remote_port;

        sock = socket(AF_INET, SOCK_RAW, 0);
        if (sock <0)
        {
            perror("opening datagram socket");
            exit(1);
        }
        for (;;)
        {
           int  i;
           long *lp;

           socklen = sizeof(remote_in);
           /* read from the socket */
           if (recvfrom(sock, buf, 1024, 0, &remote_in, &socklen)
               < 0)
              perror("receiving datagram packets");
           lp = (long *)buf;
           printf("-->%s\n", buf);
           for (i=0; i<12; i++)
              printf("x%2.2x: x%8.8x\n", i*sizeof(long), *lp++);
        }
        close(sock);

        ===> Here are the sending part (in C), the receving part above never
         receive the message sent here, anything worng here? This segment
        also crashed the SunOS4.1 many times, error message saying the panic
        in m_copy, any clues?

        char    buf[BUFLEN], remote_host[40], str[40];
        int     local_port, remote_port, size;
        struct  sockaddr_in     local_sock, remote_sock;
        struct  hostent         *host;

        if ((id = socket(AF_INET, SOCK_RAW, 0)) < 0)
           syserr("main(): socket()")

        /* Get the messages and sendto */
        for (;;)
        {
           printf("\nPls input the messages:\n");
           gets(buf);
           if (buf[0] == '\n' || buf[0] == '\0')
              break;
           host = gethostbyname(remote_host);
           bcopy(host->h_addr, &remote_sock.sin_addr, host->h_length);
           remote_sock.sin_family = AF_INET;
           size = sendto(id, buf, sizeof(buf), 0,
                        (struct sockaddr *)&remote_sock, sizeof(remote_sock));
           if (size < 0)
              syserr("main(): sendto()")
        }

        Sorry for the lenghty posting, Thanks in advance for any help.

- Beng Hang (EMAIL: taybengh@nusdiscs.bitnet)
  Dept of Information Systems and Computer Science
  National University of Singapore