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