[LWN Logo]

Date:         Tue, 15 Feb 2000 10:03:48 +0100
From: Jens Hektor <hektor@RZ.RWTH-AACHEN.DE>
Subject:      Packet filter logging: MAC & TCP flags
To: BUGTRAQ@SECURITYFOCUS.COM

Hi,

as a response to Dragos Ruiu's posting the following might
be of interest to some of you.

In the need for more detailed information recorded by the
linux kernel v2.2 packet filtering facility I developed
a patch that shows MAC adress and TCP flags for every packet
that is marked for logging in the chain-rules.

Maybe this is a more convenient solution for those who use
linux boxes as packet filters.

This patch is essentially a backport from the linux kernel v2.3
ipfilter package. It has been sent to R.Russel for approval and
maybe it finds the way into stock 2.2.

Bye, Jens Hektor

-------------- cut here -----------------
*** linux-2.2.14/net/ipv4/ip_fw.c.orig  Wed Feb  2 08:05:48 2000
--- linux-2.2.14/net/ipv4/ip_fw.c       Wed Feb  2 08:29:09 2000
***************
*** 411,417 ****
                        __u16 src_port,
                        __u16 dst_port,
                        unsigned int count,
!                       int syn)
  {
        __u32 *opt = (__u32 *) (ip + 1);
        int opti;
--- 411,418 ----
                        __u16 src_port,
                        __u16 dst_port,
                        unsigned int count,
!                         int syn,
!                         unsigned char *machdr)
  {
        __u32 *opt = (__u32 *) (ip + 1);
        int opti;
***************
*** 443,449 ****

        for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
                printk(" O=0x%8.8X", *opt++);
!       printk(" %s(#%d)\n", syn ? "SYN " : /* "PENANCE" */ "", count);
  }

  /* function for checking chain labels for user space. */
--- 444,476 ----

        for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
                printk(" O=0x%8.8X", *opt++);
!       printk(" %s(#%d)", syn ? "SYN " : /* "PENANCE" */ "", count);
!
!         /* This code added to get a more detailed information about
!          * portscanners */
!         if (ip->protocol == IPPROTO_TCP
!             && !(ip->frag_off & __constant_htons(IP_OFFSET))) {
!                 struct tcphdr *tcp = (struct tcphdr *)((__u32 *)ip + ip->ihl);
!                 printk(" FLAGS:%c%c%c%c%c%c",
!                        tcp->urg ? 'U' : '-',
!                        tcp->ack ? 'A' : '-',
!                        tcp->psh ? 'P' : '-',
!                        tcp->rst ? 'R' : '-',
!                        tcp->syn ? 'S' : '-',
!                        tcp->fin ? 'F' : '-');
!         }
!
!         if (machdr) {
!                 /* We don't need to be efficient. */
!                 struct device *dev = dev_get(ifname);
!
!                 if (dev) {
!                         unsigned int i;
!                         for (i = 0; i < dev->hard_header_len; i++)
!                                 printk("%c%02x", i ? ':' : ' ', machdr[i]);
!                 }
!         }
!         printk("\n");
  }

  /* function for checking chain labels for user space. */
***************
*** 541,552 ****
              unsigned int slot,
              __u16 src_port, __u16 dst_port,
              unsigned int count,
!             int tcpsyn)
  {
        f->counters[slot].bcnt+=ntohs(ip->tot_len);
        f->counters[slot].pcnt++;
        if (f->ipfw.fw_flg & IP_FW_F_PRN) {
!               dump_packet(ip,rif,f,label,src_port,dst_port,count,tcpsyn);
        }
        ip->tos = (ip->tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor;

--- 568,581 ----
              unsigned int slot,
              __u16 src_port, __u16 dst_port,
              unsigned int count,
!               int tcpsyn,
!               int validmac)
  {
        f->counters[slot].bcnt+=ntohs(ip->tot_len);
        f->counters[slot].pcnt++;
        if (f->ipfw.fw_flg & IP_FW_F_PRN) {
!                 dump_packet(ip,rif,f,label,src_port,dst_port,count,tcpsyn,
!                             validmac ? skb->mac.raw : NULL);
        }
        ip->tos = (ip->tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor;

***************
*** 599,605 ****
            struct ip_chain *chain,
            struct sk_buff *skb,
            unsigned int slot,
!           int testing)
  {
        struct tcphdr           *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
        struct udphdr           *udp=(struct udphdr *)((__u32 *)ip+ip->ihl);
--- 628,635 ----
            struct ip_chain *chain,
            struct sk_buff *skb,
            unsigned int slot,
!             int testing,
!             int validmac)
  {
        struct tcphdr           *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
        struct udphdr           *udp=(struct udphdr *)((__u32 *)ip+ip->ihl);
***************
*** 632,638 ****
        if (offset == 1 && ip->protocol == IPPROTO_TCP) {
                if (!testing && net_ratelimit()) {
                        printk("Suspect TCP fragment.\n");
!                       dump_packet(ip,rif,NULL,NULL,0,0,0,0);
                }
                return FW_BLOCK;
        }
--- 662,669 ----
        if (offset == 1 && ip->protocol == IPPROTO_TCP) {
                if (!testing && net_ratelimit()) {
                        printk("Suspect TCP fragment.\n");
!                         dump_packet(ip,rif,NULL,NULL,0,0,0,0,
!                                     validmac ? skb->mac.raw : NULL);
                }
                return FW_BLOCK;
        }
***************
*** 667,673 ****
                if (offset && (ntohs(ip->frag_off) & IP_MF)) {
                        if (!testing && net_ratelimit()) {
                                printk("Suspect short first fragment.\n");
!                               dump_packet(ip,rif,NULL,NULL,0,0,0,0);
                        }
                        return FW_BLOCK;
                }
--- 698,705 ----
                if (offset && (ntohs(ip->frag_off) & IP_MF)) {
                        if (!testing && net_ratelimit()) {
                                printk("Suspect short first fragment.\n");
!                                 dump_packet(ip,rif,NULL,NULL,0,0,0,0,
!                                             validmac ? skb->mac.raw : NULL);
                        }
                        return FW_BLOCK;
                }
***************
*** 745,751 ****
                                    && !ip_fw_domatch(f, ip, rif, chain->label,
                                                      skb, slot,
                                                      src_port, dst_port,
!                                                     count, tcpsyn)) {
                                        ret = FW_BLOCK;
                                        goto out;
                                }
--- 777,784 ----
                                    && !ip_fw_domatch(f, ip, rif, chain->label,
                                                      skb, slot,
                                                      src_port, dst_port,
!                                                       count, tcpsyn,
!                                                       validmac)) {
                                        ret = FW_BLOCK;
                                        goto out;
                                }
***************
*** 1357,1363 ****
                        else {
                                ret = ip_fw_check(ip,
new->fwt_packet.fwp_vianame,
                                                  NULL, chain,
!                                                 NULL, SLOT_NUMBER(), 1);
                                switch (ret) {
                                case FW_ACCEPT:
                                        ret = 0; break;
--- 1390,1396 ----
                        else {
                                ret = ip_fw_check(ip,
new->fwt_packet.fwp_vianame,
                                                  NULL, chain,
!                                                   NULL, SLOT_NUMBER(), 1, 0);
                                switch (ret) {
                                case FW_ACCEPT:
                                        ret = 0; break;
***************
*** 1698,1704 ****
                     void *phdr, void *arg, struct sk_buff **pskb)
  {
        return ip_fw_check(phdr, dev->name,
!                          arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
  }

  int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev,
--- 1731,1738 ----
                     void *phdr, void *arg, struct sk_buff **pskb)
  {
        return ip_fw_check(phdr, dev->name,
!                            arg, IP_FW_INPUT_CHAIN, *pskb, SLOT_NUMBER(), 0,
!                            1);
  }

  int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev,
***************
*** 1709,1722 ****
            || (*pskb)->len < sizeof(struct iphdr))
                return FW_ACCEPT;
        return ip_fw_check(phdr, dev->name,
!                          arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0);
  }

  int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev,
                       void *phdr, void *arg, struct sk_buff **pskb)
  {
        return ip_fw_check(phdr, dev->name,
!                          arg, IP_FW_FORWARD_CHAIN, *pskb, SLOT_NUMBER(), 0);
  }

  struct firewall_ops ipfw_ops=
--- 1743,1758 ----
            || (*pskb)->len < sizeof(struct iphdr))
                return FW_ACCEPT;
        return ip_fw_check(phdr, dev->name,
!                            arg, IP_FW_OUTPUT_CHAIN, *pskb, SLOT_NUMBER(), 0,
!                            0);
  }

  int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev,
                       void *phdr, void *arg, struct sk_buff **pskb)
  {
        return ip_fw_check(phdr, dev->name,
!                            arg, IP_FW_FORWARD_CHAIN, *pskb, SLOT_NUMBER(), 0,
!                            0);
  }

  struct firewall_ops ipfw_ops=
-------------- cut here -----------------

--
Jens Hektor, RWTH Aachen, Rechenzentrum, Seffenter Weg 23, 52074 Aachen
Computing Center Technical University Aachen, firewalls/network security
mailto:hektor@RZ.RWTH-Aachen.DE, Tel.: nur TH 31376, Raum: 2.35
Private: Rochusstr. 26, D52062 Aachen, Fon: +49 241 29888, Fax: % 29889