Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Feb 2004 21:59:38 -0500
From:      Matthew Goward <mgoward@mail.msen.com>
To:        freebsd-questions@freebsd.org
Subject:   Divert and ipfw rule numbers
Message-ID:  <20040226215938.O8241@conch.msen.com>

next in thread | raw e-mail | index | archive | help
I am currently playing with a toy app using divert and ipfw
on 5.2.1.  One of the bits of info I am trying to get ahold of
is the rule number in ipfw that sent the diverted packet over to
me.  The DIVERT(4) man page states:

	Diverted packets may be read unaltered via read(2), recv(2),
	or recvfrom(2).  In the latter case, the address returned
	will have its port set to some tag supplied by the packet
	diverter, (usually the ipfw rule number)

But I cant seem to get it to do so, nor am i really sure I want
it to do so.  I still need the source and dest ip and ports, 
along with the IPFW rule number.  Here is a bit of what I have 
(all the error checking and setup stuff pulled out for brievity)

get a socket
fd=socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT))

bind to it:
  bindPort.sin_family=AF_INET;
  bindPort.sin_port=htons(atol(port));
  bindPort.sin_addr.s_addr=0;
  if ((ret=bind(fd,(struct sockaddr *) &bindPort,
                sizeof(struct sockaddr_in))) != 0) {
		blah blah error checking}

stolen from the divert socket mini faq to try and use the data
start grabbing data:
  sinlen=sizeof(struct sockaddr_in);

  while(1) {
    n=recvfrom(fd, packet, BUFSIZE, 0, (struct sockaddr *) &sin, &sinlen);

    iphdr=(struct ip*)packet;

    if (iphdr->ip_p == IPPROTO_TCP) {
      tcphdr = (struct tcphdr *) (packet + sizeof(struct ip));
      }
    else if (iphdr->ip_p == IPPROTO_UDP) {
      udphdr = (struct udphdr *) (packet + sizeof(struct ip));
      }

      printf("\n");
      printf("%s: Source address: %s\n",progname, inet_ntoa(iphdr->ip_src));
      if (iphdr->ip_p == IPPROTO_TCP)
        printf("%s: Source port: %d\n",progname, ntohs(tcphdr->th_sport));

      printf("%s: Destination address: %s\n", progname,
                                        inet_ntoa(iphdr->ip_dst));
      if (iphdr->ip_p == IPPROTO_TCP)
        printf("%s: Destination port: %d\n\n",progname,
                                        ntohs(tcphdr->th_dport));

      printf("%s: Receiving IF address: %s\n", progname,
                                        inet_ntoa(sin.sin_addr));
      printf("%s: Protocol number: %i\n", progname, iphdr->ip_p);
      printf("%s: Header length: %i\n", progname, iphdr->ip_hl);
      printf("%s: Header ttl: %i\n", progname, iphdr->ip_ttl);
      printf("%s: Header sum: %i\n\n", progname, iphdr->ip_sum);

      if (iphdr->ip_p == IPPROTO_TCP) {
        printf("%s: Sequence Number %d\n",progname, ntohs(tcphdr->th_seq));
        printf("%s: Acknowledgement Number %d\n\n",progname,
                                                ntohs(tcphdr->th_ack));
        }
      }

And it all works as you would expect.  This really was from source port 1360
and to port 25.  

The packet in hex:
69 16 00 52 247 230 64 00 64 06 61 91 192 168 66 11 
192 168 66 22 05 80 00 25 49 238 186 32 30 184 225 162 
128 16 226 64 195 168 00 00 01 01 08 10 27 81 180 235 
00 38 09 44 
Source address: 192.168.66.11
Source port: 1360
Destination address: 192.168.66.22
Destination port: 25
Receiving IF address: 192.168.66.22
Protocol number: 6
Header length: 5
Header ttl: 64
Header sum: 23357

Sequence Number 12782
Acknowledgement Number 7864

DIVERT 52 bytes
52 bytes reinjected.

Now, I need the data this way as i am also stuffing it off to a file in pcap
format.  But from reading the divert man page I would expect to see the rule
number somewhere.


Sorry to have rambled on so much.    I just want to know how I can continue to
get all the data I have now, but also find out what rule number ipfw is hitting
on before diverting to me.  

Thank you so much for you help,

Matthew Goward
m g o w a r d @ e v i l o v e r l o r d . o r g 


mgoward@IneedAname 906> uname -a
FreeBSD IneedAname 5.2.1-RELEASE FreeBSD 5.2.1-RELEASE #2: Thu Feb 26 12:57:33 GMT 2004     root@IneedAname:/usr/obj/usr/src/sys/MATT  i38

mgoward@IneedAname 909> diff MATT GENERIC
49c49
< options       SCSI_DELAY=2000         #Delay (in ms) before probing SCSI
---
> options       SCSI_DELAY=15000        #Delay (in ms) before probing SCSI
60,69d59
< options         IPFIREWALL              #firewall
< options         IPFIREWALL_VERBOSE      #enable logging to syslogd(8)
< options         IPDIVERT                #divert sockets
< options         IPFIREWALL_VERBOSE_LIMIT=100 
< #options        IPFIREWALL_DEFAULT_TO_ACCEPT
< options         RANDOM_IP_ID
< options         DUMMYNET
< options         TCP_DROP_SYNFIN
< options         IPSTEALTH
< #options         "ICMP_BANDLIM"


00001    48    2549 divert 5555 tcp from 192.168.66.11 to 192.168.66.22 dst-port 25
00001     0       0 divert 5555 udp from 192.168.55.22 to 192.168.66.22 dst-port 25
00002     0       0 divert 5555 tcp from 192.168.66.22 25 to 192.168.55.22
00002     0       0 divert 5555 udp from 192.168.66.22 25 to 192.168.55.22
00100    54    2914 allow ip from any to any via lo0
00200     0       0 deny ip from any to 127.0.0.0/8
00300     0       0 deny ip from 127.0.0.0/8 to any
65000 34423 9607284 allow ip from any to any
65535     0       0 deny ip from any to any

ipfw2 initialized, divert enabled, rule-based forwarding enabled, default to deny, logging limited to 100 packets/entry by default

if anything else would be helpfull let me know.



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