SOURCES (LINUX_2_6): linux-2.6-nf-osf.patch (NEW) - [base] osf match.
pluto
pluto at pld-linux.org
Thu Sep 15 10:19:36 CEST 2005
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 <johnpol at 2ka.mipt.ru>
++ *
++ *
++ * 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 <johnpol at 2ka.mipt.ru>
++ *
++ *
++ * 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 <lcamtuf at coredump.cx>
++ * 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>>
More information about the pld-cvs-commit
mailing list