Author: pluto                        Date: Thu Sep 15 08:19:36 2005 GMT
Module: SOURCES                       Tag: LINUX_2_6
---- Log message:
- [base] osf match.

---- Files affected:
SOURCES:
   linux-2.6-nf-osf.patch (NONE -> 1.1.2.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-2.6-nf-osf.patch
diff -u /dev/null SOURCES/linux-2.6-nf-osf.patch:1.1.2.1
--- /dev/null   Thu Sep 15 10:19:36 2005
+++ SOURCES/linux-2.6-nf-osf.patch      Thu Sep 15 10:19:31 2005
@@ -0,0 +1,1055 @@
+ include/linux/netfilter_ipv4/ipt_osf.h |  151 +++++
+ net/ipv4/netfilter/Kconfig             |   22 
+ net/ipv4/netfilter/Makefile            |    3 
+ net/ipv4/netfilter/ipt_osf.c           |  854 
+++++++++++++++++++++++++++++++++
+ 4 files changed, 1030 insertions(+)
+
+diff -uNr linux-2.6.13.1/include.orig/linux/netfilter_ipv4/ipt_osf.h 
linux-2.6.13.1/include/linux/netfilter_ipv4/ipt_osf.h
+--- linux-2.6.13.1/include.orig/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 
01:00:00.000000000 +0100
++++ linux-2.6.13.1/include/linux/netfilter_ipv4/ipt_osf.h      2005-09-15 
10:18:40.315124250 +0200
+@@ -0,0 +1,151 @@
++/*
++ * ipt_osf.h
++ *
++ * Copyright (c) 2003 Evgeniy Polyakov <[EMAIL PROTECTED]>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _IPT_OSF_H
++#define _IPT_OSF_H
++
++#define MAXGENRELEN            32
++#define MAXDETLEN              64
++
++#define IPT_OSF_GENRE          1
++#define        IPT_OSF_SMART           2
++#define IPT_OSF_LOG            4
++#define IPT_OSF_NETLINK                8
++#define IPT_OSF_CONNECTOR     16
++
++#define IPT_OSF_LOGLEVEL_ALL   0
++#define IPT_OSF_LOGLEVEL_FIRST 1
++
++#ifndef __KERNEL__
++#include <netinet/ip.h>
++#include <netinet/tcp.h>
++
++struct list_head
++{
++       struct list_head *prev, *next;
++};
++#endif
++
++struct ipt_osf_info
++{
++       char                    genre[MAXGENRELEN];
++       int                     len;
++       unsigned long           flags;
++       int                     loglevel;
++       int                     invert; /* UNSUPPORTED */
++};
++
++struct osf_wc
++{
++       char                    wc;
++       unsigned long           val;
++};
++
++/* This struct represents IANA options
++ * http://www.iana.org/assignments/tcp-parameters
++ */
++struct osf_opt
++{
++       unsigned char           kind;
++       unsigned char           length;
++       struct osf_wc           wc;
++};
++
++struct osf_finger
++{
++       struct list_head        flist;
++       struct osf_wc           wss;
++       unsigned char           ttl;
++       unsigned char           df;
++       unsigned long           ss;
++       unsigned char           genre[MAXGENRELEN];
++       unsigned char           version[MAXGENRELEN], subtype[MAXGENRELEN];
++
++       /* Not needed, but for consistency with original table from Michal 
Zalewski */
++       unsigned char           details[MAXDETLEN]; 
++
++       int                     opt_num;
++       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or 
EOL */
++
++};
++
++struct ipt_osf_nlmsg
++{
++       struct osf_finger       f;
++       struct iphdr            ip;
++       struct tcphdr           tcp;
++};
++
++#ifdef __KERNEL__
++
++#include <linux/list.h>
++#include <net/tcp.h>
++
++
++/* Defines for IANA option kinds */
++
++#define OSFOPT_EOL             0       /* End of options */
++#define OSFOPT_NOP             1       /* NOP */
++#define OSFOPT_MSS             2       /* Maximum segment size */
++#define OSFOPT_WSO             3       /* Window scale option */
++#define OSFOPT_SACKP           4       /* SACK permitted */
++#define OSFOPT_SACK            5       /* SACK */
++#define OSFOPT_ECHO            6
++#define OSFOPT_ECHOREPLY       7
++#define OSFOPT_TS              8       /* Timestamp option */
++#define OSFOPT_POCP            9       /* Partial Order Connection Permitted 
*/
++#define OSFOPT_POSP            10      /* Partial Order Service Profile */
++/* Others are not used in current OSF */
++
++static struct osf_opt IANA_opts[] = 
++{
++       {0, 1,},
++       {1, 1,},
++       {2, 4,},
++       {3, 3,},
++       {4, 2,},
++       {5, 1 ,}, /* SACK length is not defined */
++       {6, 6,},
++       {7, 6,},
++       {8, 10,},
++       {9, 2,},
++       {10, 3,},
++       {11, 1,}, /* CC: Suppose 1 */
++       {12, 1,}, /* the same */
++       {13, 1,}, /* and here too */
++       {14, 3,},
++       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
++       {16, 1,},
++       {17, 1,},
++       {18, 3,},
++       {19, 18,},
++       {20, 1,},
++       {21, 1,},
++       {22, 1,},
++       {23, 1,},
++       {24, 1,},
++       {25, 1,},
++       {26, 1,},
++};
++
++#endif /* __KERNEL__ */
++
++#endif /* _IPT_OSF_H */
+diff -uNr linux-2.6.13.1/net.orig/ipv4/netfilter/ipt_osf.c 
linux-2.6.13.1/net/ipv4/netfilter/ipt_osf.c
+--- linux-2.6.13.1/net.orig/ipv4/netfilter/ipt_osf.c   1970-01-01 
01:00:00.000000000 +0100
++++ linux-2.6.13.1/net/ipv4/netfilter/ipt_osf.c        2005-09-15 
10:18:40.319124500 +0200
+@@ -0,0 +1,854 @@
++/*
++ * ipt_osf.c
++ *
++ * Copyright (c) 2003-2005 Evgeniy Polyakov <[EMAIL PROTECTED]>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/*
++ * OS fingerprint matching module.
++ * It simply compares various parameters from SYN packet with
++ * some hardcoded ones.
++ *
++ * Original table was created by Michal Zalewski <[EMAIL PROTECTED]>
++ * for his p0f.
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/smp.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/file.h>
++#include <linux/ip.h>
++#include <linux/proc_fs.h>
++#include <linux/fs.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/ctype.h>
++#include <linux/list.h>
++#include <linux/if.h>
++#include <linux/inetdevice.h>
++#include <net/ip.h>
++#include <linux/tcp.h>
++
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++#include <linux/netfilter_ipv4/ipt_osf.h>
++
++#define OSF_DEBUG
++
++#ifdef OSF_DEBUG
++#define log(x...)             printk(KERN_INFO "ipt_osf: " x)
++#define loga(x...)            printk(x)
++#else
++#define log(x...)             do {} while(0)
++#define loga(x...)            do {} while(0)
++#endif
++
++#define FMATCH_WRONG          0
++#define FMATCH_OK             1
++#define FMATCH_OPT_WRONG      2
++
++#define OPTDEL                        ','
++#define OSFPDEL               ':'
++#define MAXOPTSTRLEN          128
++#define OSFFLUSH              "FLUSH"
++
++static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
++static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
++static struct list_head       finger_list;    
++static int match(const struct sk_buff *, const struct net_device *, const 
struct net_device *,
++                    const void *, int, 
++                    int *);
++static int checkentry(const char *, const struct ipt_ip *, void *,
++                         unsigned int, unsigned int);
++
++static unsigned long seq, ipt_osf_groups = 1;
++static struct sock *nts;
++
++static struct ipt_match osf_match = { 
++      .name = "osf", 
++      .match = &match, 
++      .checkentry = &checkentry, 
++      .me = THIS_MODULE 
++};
++
++
++#ifdef CONFIG_CONNECTOR
++#include <linux/connector.h>
++
++/*
++ * They should live in connector.h.
++ */
++#define CN_IDX_OSF            0x0001
++#define CN_VAL_OSF            0x0000
++
++static char osf_finger_buf[sizeof(struct ipt_osf_nlmsg) + sizeof(struct 
cn_msg)];
++static struct cb_id osf_id = {CN_IDX_OSF, CN_VAL_OSF};
++static u32 osf_seq;
++
++static void ipt_osf_send_connector(struct osf_finger *f, const struct sk_buff 
*sk)
++{
++      struct cn_msg *m;
++      struct ipt_osf_nlmsg *data;
++      
++      m = (struct cn_msg *)osf_finger_buf;
++      data = (struct ipt_osf_nlmsg *)(m+1);
++
++      memcpy(&m->id, &osf_id, sizeof(m->id));
++      m->seq = osf_seq++;
++      m->ack = 0;
++      m->len = sizeof(*data);
++      
++      memcpy(&data->f, f, sizeof(struct osf_finger));
++      memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
++      memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + 
sk->nh.iph->ihl), sizeof(struct tcphdr));
++
++      cn_netlink_send(m, m->id.idx, GFP_ATOMIC);
++}
++#else
++static void ipt_osf_send_connector(struct osf_finger *f, const struct sk_buff 
*sk)
++{
++}
++#endif
++
++static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
++{
++      unsigned int size;
++      struct sk_buff *skb;
++      struct ipt_osf_nlmsg *data;
++      struct nlmsghdr *nlh;
++
++      if (!nts)
++              return;
++
++      size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
++
++      skb = alloc_skb(size, GFP_ATOMIC);
++      if (!skb) {
++              log("skb_alloc() failed.\n");
++              return;
++      }
++      
++      nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
++      
++      data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
++
++      memcpy(&data->f, f, sizeof(struct osf_finger));
++      memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
++      memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + 
sk->nh.iph->ihl), sizeof(struct tcphdr));
++
++      NETLINK_CB(skb).dst_groups = ipt_osf_groups;
++      netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
++
++nlmsg_failure:
++      return;
++}
++
++static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, 
unsigned char f_ttl)
++{
++      struct iphdr *ip = skb->nh.iph;
++
++      if (flags & IPT_OSF_SMART) {
++              struct in_device *in_dev = in_dev_get(skb->dev);
++
++              for_ifa(in_dev) {
++                      if (inet_ifa_match(ip->saddr, ifa)) {
++                              in_dev_put(in_dev);
++                              return (ip->ttl == f_ttl);
++                      }
++              }
++              endfor_ifa(in_dev);
++              
++              in_dev_put(in_dev);
++              return (ip->ttl <= f_ttl);
++      }
++      else
++              return (ip->ttl == f_ttl);
++}
++
++static int
++match(const struct sk_buff *skb, const struct net_device *in, const struct 
net_device *out,
++      const void *matchinfo, int offset,
++      int *hotdrop)
++{
++      struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
++      struct iphdr _iph, *ip;
++      struct tcphdr _tcph, *tcp;
++      int fmatch = FMATCH_WRONG, fcount = 0;
++      unsigned long totlen, optsize = 0, window;
++      unsigned char df, *optp = NULL, *_optp = NULL;
++      unsigned char opts[MAX_IPOPTLEN];
++      char check_WSS = 0;
++      struct osf_finger *f;
++      int off;
++
++      if (!info)
++              return 0;
++      
++      off = 0;
++      
++      ip = skb_header_pointer(skb, off, sizeof(_iph), &_iph);
++      if (!ip)
++              return 0;
++                              
++      tcp = skb_header_pointer(skb, off + ip->ihl * 4, sizeof(_tcph), &_tcph);
++      if (!tcp)
++              return 0;
++      
++      if (!tcp->syn)
++              return 0;
++      
++      totlen = ntohs(ip->tot_len);
++      df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
++      window = ntohs(tcp->window);
++      
++      if (tcp->doff*4 > sizeof(struct tcphdr)) {
++              optsize = tcp->doff*4 - sizeof(struct tcphdr);
++
++              if (optsize > sizeof(opts)) {
++                      log("%s: BUG: too big options size: optsize=%lu, 
max=%zu.\n",
++                                      __func__, optsize, sizeof(opts));
++                      optsize = sizeof(opts);
++              }
++              
++              _optp = optp = skb_header_pointer(skb, off + ip->ihl*4 + 
sizeof(_tcph), optsize, opts);
++      }
++
++      /* Actually we can create hash/table of all genres and search
++       * only in appropriate part, but here is initial variant,
++       * so will use slow path.
++       */
++      read_lock(&osf_lock);
++      list_for_each_entry(f, &finger_list, flist) {
++      
++              if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, 
f->genre)) 
++                      continue;
++
++              optp = _optp;
++              fmatch = FMATCH_WRONG;
++
++              if (totlen == f->ss && df == f->df && 
++                      smart_dec(skb, info->flags, f->ttl)) {
++                      unsigned long foptsize;
++                      int optnum;
++                      unsigned short mss = 0;
++
++                      check_WSS = 0;
++
++                      switch (f->wss.wc) {
++                              case 0:   check_WSS = 0; break;
++                              case 'S': check_WSS = 1; break;
++                              case 'T': check_WSS = 2; break;
++                              case '%': check_WSS = 3; break;
++                              default: log("Wrong fingerprint wss.wc=%d, %s - 
%s\n", 
++                                                       f->wss.wc, f->genre, 
f->details);
++                                       check_WSS = 4;
++                                       break;
++                      }
++                      if (check_WSS == 4)
++                              continue;
++
++                      /* Check options */
++
++                      foptsize = 0;
++                      for (optnum=0; optnum<f->opt_num; ++optnum)
++                              foptsize += f->opt[optnum].length;
++
++                              
++                      if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN 
|| optsize != foptsize)
++                              continue;
++
++                      if (!optp) {
++                              fmatch = FMATCH_OK;
++                              loga("\tYEP : matching without options.\n");
++                              if ((info->flags & IPT_OSF_LOG) && 
++                                      info->loglevel == 
IPT_OSF_LOGLEVEL_FIRST)
++                                      break;
++                              else
++                                      continue;
++                      }
++
++                      for (optnum=0; optnum<f->opt_num; ++optnum) {
++                              if (f->opt[optnum].kind == (*optp)) {
++                                      unsigned char len = 
f->opt[optnum].length;
++                                      unsigned char *optend = optp + len;
++                                      int loop_cont = 0;
++
++                                      fmatch = FMATCH_OK;
++
++
++                                      switch (*optp) {
++                                              case OSFOPT_MSS:
++                                                      mss = ntohs(*(unsigned 
short *)(optp+2));
++                                                      break;
++                                              case OSFOPT_TS:
++                                                      loop_cont = 1;
++                                                      break;
++                                      }
++                                      
++                                      if (loop_cont) {
++                                              optp = optend;
++                                              continue;
++                                      }
++                                      
++                                      if (len != 1) {
++                                              /* Skip kind and length fields*/
++                                              optp += 2; 
++
++                                              if (f->opt[optnum].wc.val != 0) 
{
++                                                      unsigned long tmp = 0;
++                                                      
++                                                      /* Hmmm... It looks a 
bit ugly. :) */
++                                                      memcpy(&tmp, optp, 
++                                                              (len > 
sizeof(unsigned long)?
++                                                                      
sizeof(unsigned long):len));
++                                                      /* 2 + 2: optlen(2 
bytes) + 
++                                                       *      kind(1 byte) + 
length(1 byte) */
++                                                      if (len == 4) 
++                                                              tmp = 
ntohs(tmp);
++                                                      else
++                                                              tmp = 
ntohl(tmp);
++
++                                                      if 
(f->opt[optnum].wc.wc == '%') {
++                                                              if ((tmp % 
f->opt[optnum].wc.val) != 0)
++                                                                      fmatch 
= FMATCH_OPT_WRONG;
++                                                      }
++                                                      else if (tmp != 
f->opt[optnum].wc.val)
++                                                              fmatch = 
FMATCH_OPT_WRONG;
++                                              }
++                                      }
++
++                                      optp = optend;
++                              } else
++                                      fmatch = FMATCH_OPT_WRONG;
++
++                              if (fmatch != FMATCH_OK)
++                                      break;
++                      }
++
++                      if (fmatch != FMATCH_OPT_WRONG) {
++                              fmatch = FMATCH_WRONG;
++
++                              switch (check_WSS) {
++                                      case 0:
++                                              if (f->wss.val == 0 || window 
== f->wss.val)
++                                                      fmatch = FMATCH_OK;
++                                              break;
++                                      case 1: /* MSS */
++/* Lurked in OpenBSD */
++#define SMART_MSS     1460
++                                              if (window == f->wss.val*mss || 
++                                                      window == 
f->wss.val*SMART_MSS)
++                                                      fmatch = FMATCH_OK;
++                                              break;
++                                      case 2: /* MTU */
++                                              if (window == 
f->wss.val*(mss+40) ||
++                                                      window == 
f->wss.val*(SMART_MSS+40))
++                                                      fmatch = FMATCH_OK;
++                                              break;
++                                      case 3: /* MOD */
++                                              if ((window % f->wss.val) == 0)
++                                                      fmatch = FMATCH_OK;
++                                              break;
++                              }
++                      }
++                                      
++
++                      if (fmatch == FMATCH_OK) {
++                              fcount++;
++                              log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> 
%u.%u.%u.%u:%u hops=%d\n", 
++                                      f->genre, f->version,
++                                      f->subtype, f->details,
++                                      NIPQUAD(ip->saddr), ntohs(tcp->source),
++                                      NIPQUAD(ip->daddr), ntohs(tcp->dest),
++                                      f->ttl - ip->ttl);
++                              if (info->flags & IPT_OSF_NETLINK) {
++                                      spin_lock_bh(&ipt_osf_netlink_lock);
++                                      ipt_osf_nlsend(f, skb);
++                                      spin_unlock_bh(&ipt_osf_netlink_lock);
++                              }
++                              if (info->flags & IPT_OSF_CONNECTOR) {
++                                      spin_lock_bh(&ipt_osf_netlink_lock);
++                                      ipt_osf_send_connector(f, skb);
++                                      spin_unlock_bh(&ipt_osf_netlink_lock);
++                              }
++                              if ((info->flags & IPT_OSF_LOG) && 
++                                      info->loglevel == 
IPT_OSF_LOGLEVEL_FIRST)
++                                      break;
++                      }
++              }
++      }
++      if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK | 
IPT_OSF_CONNECTOR))) {
++              unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
++              unsigned int i, optsize;
++              struct osf_finger fg;
++
++              memset(&fg, 0, sizeof(fg));
++
++              if ((info->flags & IPT_OSF_LOG))
++                      log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, 
totlen);
++              if (optp) {
++                      optsize = tcp->doff * 4 - sizeof(struct tcphdr);
++                      if (skb_copy_bits(skb, off + ip->ihl*4 + sizeof(struct 
tcphdr),
++                                        opt, optsize) < 0) {
++                              if (info->flags & IPT_OSF_LOG)
++                                      loga("TRUNCATED");
++                              if (info->flags & IPT_OSF_NETLINK)
++                                      strcpy(fg.details, "TRUNCATED");
++                      } else {
++                              for (i = 0; i < optsize; i++) {
++                                      if (info->flags & IPT_OSF_LOG)
++                                              loga("%02X", opt[i]);
++                              }
++                              if (info->flags & IPT_OSF_NETLINK)
++                                      memcpy(fg.details, opt, MAXDETLEN);
++                      }
++              }
++              if ((info->flags & IPT_OSF_LOG))
++                      loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
<<Diff was trimmed, longer than 597 lines>>
_______________________________________________
pld-cvs-commit mailing list
pld-cvs-commit@lists.pld-linux.org
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to