Commit af9b4549 authored by David S. Miller's avatar David S. Miller

Merge nuts.davemloft.net:/disk1/BK/nf-2.6.9

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 0b8cf496 b677b829
...@@ -51,10 +51,12 @@ enum ip_conntrack_status { ...@@ -51,10 +51,12 @@ enum ip_conntrack_status {
#include <linux/netfilter_ipv4/ip_conntrack_tcp.h> #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
#include <linux/netfilter_ipv4/ip_conntrack_icmp.h> #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
/* per conntrack: protocol private data */ /* per conntrack: protocol private data */
union ip_conntrack_proto { union ip_conntrack_proto {
/* insert conntrack proto private data here */ /* insert conntrack proto private data here */
struct ip_ct_sctp sctp;
struct ip_ct_tcp tcp; struct ip_ct_tcp tcp;
struct ip_ct_icmp icmp; struct ip_ct_icmp icmp;
}; };
...@@ -156,6 +158,12 @@ struct ip_conntrack_expect ...@@ -156,6 +158,12 @@ struct ip_conntrack_expect
union ip_conntrack_expect_help help; union ip_conntrack_expect_help help;
}; };
struct ip_conntrack_counter
{
u_int64_t packets;
u_int64_t bytes;
};
struct ip_conntrack_helper; struct ip_conntrack_helper;
struct ip_conntrack struct ip_conntrack
...@@ -173,6 +181,11 @@ struct ip_conntrack ...@@ -173,6 +181,11 @@ struct ip_conntrack
/* Timer function; drops refcnt when it goes off. */ /* Timer function; drops refcnt when it goes off. */
struct timer_list timeout; struct timer_list timeout;
#ifdef CONFIG_IP_NF_CT_ACCT
/* Accounting Information (same cache line as other written members) */
struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
#endif
/* If we're expecting another related connection, this will be /* If we're expecting another related connection, this will be
in expected linked list */ in expected linked list */
struct list_head sibling_list; struct list_head sibling_list;
...@@ -245,10 +258,17 @@ extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, ...@@ -245,10 +258,17 @@ extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
const struct ip_conntrack_tuple *orig); const struct ip_conntrack_tuple *orig);
/* Refresh conntrack for this many jiffies */ /* Refresh conntrack for this many jiffies */
extern void ip_ct_refresh(struct ip_conntrack *ct, extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
const struct sk_buff *skb,
unsigned long extra_jiffies); unsigned long extra_jiffies);
/* These are for NAT. Icky. */ /* These are for NAT. Icky. */
/* Update TCP window tracking data when NAT mangles the packet */
extern int ip_conntrack_tcp_update(struct sk_buff *skb,
struct ip_conntrack *conntrack,
int dir);
/* Call me when a conntrack is destroyed. */ /* Call me when a conntrack is destroyed. */
extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
...@@ -272,6 +292,26 @@ static inline int is_confirmed(struct ip_conntrack *ct) ...@@ -272,6 +292,26 @@ static inline int is_confirmed(struct ip_conntrack *ct)
extern unsigned int ip_conntrack_htable_size; extern unsigned int ip_conntrack_htable_size;
struct ip_conntrack_stat
{
unsigned int searched;
unsigned int found;
unsigned int new;
unsigned int invalid;
unsigned int ignore;
unsigned int delete;
unsigned int delete_list;
unsigned int insert;
unsigned int insert_failed;
unsigned int drop;
unsigned int early_drop;
unsigned int icmp_error;
unsigned int expect_new;
unsigned int expect_create;
unsigned int expect_delete;
};
/* eg. PROVIDES_CONNTRACK(ftp); */ /* eg. PROVIDES_CONNTRACK(ftp); */
#define PROVIDES_CONNTRACK(name) \ #define PROVIDES_CONNTRACK(name) \
int needs_ip_conntrack_##name; \ int needs_ip_conntrack_##name; \
......
...@@ -21,16 +21,18 @@ extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol); ...@@ -21,16 +21,18 @@ extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol);
extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol); extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
extern struct list_head protocol_list; extern struct list_head protocol_list;
/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */ extern int
extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb, ip_ct_get_tuple(const struct iphdr *iph,
enum ip_conntrack_info *ctinfo,
unsigned int hooknum);
extern int get_tuple(const struct iphdr *iph,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
struct ip_conntrack_tuple *tuple, struct ip_conntrack_tuple *tuple,
const struct ip_conntrack_protocol *protocol); const struct ip_conntrack_protocol *protocol);
extern int
ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
const struct ip_conntrack_tuple *orig,
const struct ip_conntrack_protocol *protocol);
/* Find a connection corresponding to a tuple. */ /* Find a connection corresponding to a tuple. */
struct ip_conntrack_tuple_hash * struct ip_conntrack_tuple_hash *
ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple, ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
#define _IP_CONNTRACK_PROTOCOL_H #define _IP_CONNTRACK_PROTOCOL_H
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack.h>
/* length of buffer to which print_tuple/print_conntrack members are
* writing */
#define IP_CT_PRINT_BUFLEN 100
struct ip_conntrack_protocol struct ip_conntrack_protocol
{ {
/* Next pointer. */ /* Next pointer. */
...@@ -50,6 +55,9 @@ struct ip_conntrack_protocol ...@@ -50,6 +55,9 @@ struct ip_conntrack_protocol
int (*exp_matches_pkt)(struct ip_conntrack_expect *exp, int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
const struct sk_buff *skb); const struct sk_buff *skb);
int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
unsigned int hooknum);
/* Module (if any) which this is connected to. */ /* Module (if any) which this is connected to. */
struct module *me; struct module *me;
}; };
...@@ -63,4 +71,17 @@ extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp; ...@@ -63,4 +71,17 @@ extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
extern struct ip_conntrack_protocol ip_conntrack_protocol_udp; extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp; extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
extern int ip_conntrack_protocol_tcp_init(void); extern int ip_conntrack_protocol_tcp_init(void);
/* Log invalid packets */
extern unsigned int ip_ct_log_invalid;
#ifdef DEBUG_INVALID_PACKETS
#define LOG_INVALID(proto) \
(ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
#else
#define LOG_INVALID(proto) \
((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
&& net_ratelimit())
#endif
#endif /*_IP_CONNTRACK_PROTOCOL_H*/ #endif /*_IP_CONNTRACK_PROTOCOL_H*/
#ifndef _IP_CONNTRACK_SCTP_H
#define _IP_CONNTRACK_SCTP_H
/* SCTP tracking. */
enum sctp_conntrack {
SCTP_CONNTRACK_NONE,
SCTP_CONNTRACK_CLOSED,
SCTP_CONNTRACK_COOKIE_WAIT,
SCTP_CONNTRACK_COOKIE_ECHOED,
SCTP_CONNTRACK_ESTABLISHED,
SCTP_CONNTRACK_SHUTDOWN_SENT,
SCTP_CONNTRACK_SHUTDOWN_RECD,
SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
SCTP_CONNTRACK_MAX
};
struct ip_ct_sctp
{
enum sctp_conntrack state;
u_int32_t vtag[IP_CT_DIR_MAX];
u_int32_t ttag[IP_CT_DIR_MAX];
};
#endif /* _IP_CONNTRACK_SCTP_H */
...@@ -4,25 +4,44 @@ ...@@ -4,25 +4,44 @@
enum tcp_conntrack { enum tcp_conntrack {
TCP_CONNTRACK_NONE, TCP_CONNTRACK_NONE,
TCP_CONNTRACK_ESTABLISHED,
TCP_CONNTRACK_SYN_SENT, TCP_CONNTRACK_SYN_SENT,
TCP_CONNTRACK_SYN_RECV, TCP_CONNTRACK_SYN_RECV,
TCP_CONNTRACK_ESTABLISHED,
TCP_CONNTRACK_FIN_WAIT, TCP_CONNTRACK_FIN_WAIT,
TCP_CONNTRACK_TIME_WAIT,
TCP_CONNTRACK_CLOSE,
TCP_CONNTRACK_CLOSE_WAIT, TCP_CONNTRACK_CLOSE_WAIT,
TCP_CONNTRACK_LAST_ACK, TCP_CONNTRACK_LAST_ACK,
TCP_CONNTRACK_TIME_WAIT,
TCP_CONNTRACK_CLOSE,
TCP_CONNTRACK_LISTEN, TCP_CONNTRACK_LISTEN,
TCP_CONNTRACK_MAX TCP_CONNTRACK_MAX,
TCP_CONNTRACK_IGNORE
};
/* Window scaling is advertised by the sender */
#define IP_CT_TCP_STATE_FLAG_WINDOW_SCALE 0x01
/* SACK is permitted by the sender */
#define IP_CT_TCP_FLAG_SACK_PERM 0x02
struct ip_ct_tcp_state {
u_int32_t td_end; /* max of seq + len */
u_int32_t td_maxend; /* max of ack + max(win, 1) */
u_int32_t td_maxwin; /* max(win) */
u_int8_t td_scale; /* window scale factor */
u_int8_t loose; /* used when connection picked up from the middle */
u_int8_t flags; /* per direction state flags */
}; };
struct ip_ct_tcp struct ip_ct_tcp
{ {
enum tcp_conntrack state; struct ip_ct_tcp_state seen[2]; /* connection parameters per direction */
u_int8_t state; /* state of the connection (enum tcp_conntrack) */
/* Poor man's window tracking: sequence number of valid ACK /* For detecting stale connections */
handshake completion packet */ u_int8_t last_dir; /* Direction of the last packet (enum ip_conntrack_dir) */
u_int32_t handshake_ack; u_int8_t retrans; /* Number of retransmitted packets */
u_int8_t last_index; /* Index of the last packet */
u_int32_t last_seq; /* Last sequence number seen in dir */
u_int32_t last_end; /* Last seq + len */
}; };
#endif /* _IP_CONNTRACK_TCP_H */ #endif /* _IP_CONNTRACK_TCP_H */
...@@ -25,6 +25,9 @@ union ip_conntrack_manip_proto ...@@ -25,6 +25,9 @@ union ip_conntrack_manip_proto
struct { struct {
u_int16_t id; u_int16_t id;
} icmp; } icmp;
struct {
u_int16_t port;
} sctp;
}; };
/* The manipulable part of the tuple. */ /* The manipulable part of the tuple. */
...@@ -55,6 +58,9 @@ struct ip_conntrack_tuple ...@@ -55,6 +58,9 @@ struct ip_conntrack_tuple
struct { struct {
u_int8_t type, code; u_int8_t type, code;
} icmp; } icmp;
struct {
u_int16_t port;
} sctp;
} u; } u;
/* The protocol. */ /* The protocol. */
......
...@@ -38,11 +38,12 @@ struct ip_nat_helper ...@@ -38,11 +38,12 @@ struct ip_nat_helper
struct ip_nat_info *info); struct ip_nat_info *info);
}; };
extern struct list_head helpers;
extern int ip_nat_helper_register(struct ip_nat_helper *me); extern int ip_nat_helper_register(struct ip_nat_helper *me);
extern void ip_nat_helper_unregister(struct ip_nat_helper *me); extern void ip_nat_helper_unregister(struct ip_nat_helper *me);
extern struct ip_nat_helper *
ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
/* These return true or false. */ /* These return true or false. */
extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb, extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
struct ip_conntrack *ct, struct ip_conntrack *ct,
......
...@@ -336,7 +336,6 @@ ipt_get_target(struct ipt_entry *e) ...@@ -336,7 +336,6 @@ ipt_get_target(struct ipt_entry *e)
* Main firewall chains definitions and global var's definitions. * Main firewall chains definitions and global var's definitions.
*/ */
#ifdef __KERNEL__ #ifdef __KERNEL__
static DECLARE_MUTEX(ipt_mutex);
#include <linux/init.h> #include <linux/init.h>
extern void ipt_init(void) __init; extern void ipt_init(void) __init;
......
#ifndef _IPT_SCTP_H_
#define _IPT_SCTP_H_
#define IPT_SCTP_SRC_PORTS 0x01
#define IPT_SCTP_DEST_PORTS 0x02
#define IPT_SCTP_CHUNK_TYPES 0x04
#define IPT_SCTP_VALID_FLAGS 0x07
#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
struct ipt_sctp_flag_info {
u_int8_t chunktype;
u_int8_t flag;
u_int8_t flag_mask;
};
#define IPT_NUM_SCTP_FLAGS 4
struct ipt_sctp_info {
u_int16_t dpts[2]; /* Min, Max */
u_int16_t spts[2]; /* Min, Max */
u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
u_int32_t chunk_match_type;
struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
int flag_count;
u_int32_t flags;
u_int32_t invflags;
};
#define bytes(type) (sizeof(type) * 8)
#define SCTP_CHUNKMAP_SET(chunkmap, type) \
do { \
chunkmap[type / bytes(u_int32_t)] |= \
1 << (type % bytes(u_int32_t)); \
} while (0)
#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
do { \
chunkmap[type / bytes(u_int32_t)] &= \
~(1 << (type % bytes(u_int32_t))); \
} while (0)
#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
({ \
(chunkmap[type / bytes (u_int32_t)] & \
(1 << (type % bytes (u_int32_t)))) ? 1: 0; \
})
#define SCTP_CHUNKMAP_RESET(chunkmap) \
do { \
int i; \
for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
chunkmap[i] = 0; \
} while (0)
#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
do { \
int i; \
for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
chunkmap[i] = ~0; \
} while (0)
#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
do { \
int i; \
for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
destmap[i] = srcmap[i]; \
} while (0)
#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
({ \
int i; \
int flag = 1; \
for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
if (chunkmap[i]) { \
flag = 0; \
break; \
} \
} \
flag; \
})
#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
({ \
int i; \
int flag = 1; \
for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
if (chunkmap[i] != ~0) { \
flag = 0; \
break; \
} \
} \
flag; \
})
#endif /* _IPT_SCTP_H_ */
...@@ -107,10 +107,6 @@ struct ip6t_counters ...@@ -107,10 +107,6 @@ struct ip6t_counters
u_int64_t pcnt, bcnt; /* Packet and byte counters */ u_int64_t pcnt, bcnt; /* Packet and byte counters */
}; };
#ifdef __KERNEL__
static DECLARE_MUTEX(ip6t_mutex);
#endif
/* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
#define IP6T_F_PROTO 0x01 /* Set if rule cares about upper #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper
protocols */ protocols */
......
...@@ -410,6 +410,18 @@ enum ...@@ -410,6 +410,18 @@ enum
NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12, NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13, NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
NET_IPV4_NF_CONNTRACK_BUCKETS=14, NET_IPV4_NF_CONNTRACK_BUCKETS=14,
NET_IPV4_NF_CONNTRACK_LOG_INVALID=15,
NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS=16,
NET_IPV4_NF_CONNTRACK_TCP_LOOSE=17,
NET_IPV4_NF_CONNTRACK_TCP_BE_LIBERAL=18,
NET_IPV4_NF_CONNTRACK_TCP_MAX_RETRANS=19,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED=20,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT=21,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED=22,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED=23,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT=24,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
}; };
/* /proc/sys/net/ipv6 */ /* /proc/sys/net/ipv6 */
......
...@@ -628,5 +628,17 @@ config IP_NF_MATCH_REALM ...@@ -628,5 +628,17 @@ config IP_NF_MATCH_REALM
If you want to compile it as a module, say M here and read If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'. Documentation/modules.txt. If unsure, say `N'.
config IP_NF_CT_ACCT
bool "Connection tracking flow accounting"
depends on IP_NF_CONNTRACK
config IP_NF_MATCH_SCTP
tristate 'SCTP protocol match support'
depends on IP_NF_IPTABLES
config IP_NF_CT_PROTO_SCTP
tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)'
depends on IP_NF_CONNTRACK && EXPERIMENTAL
endmenu endmenu
...@@ -19,6 +19,9 @@ ipchains-objs := $(ip_nf_compat-objs) ipchains_core.o ...@@ -19,6 +19,9 @@ ipchains-objs := $(ip_nf_compat-objs) ipchains_core.o
# connection tracking # connection tracking
obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
# SCTP protocol connection tracking
obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
# connection tracking helpers # connection tracking helpers
obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
...@@ -43,6 +46,7 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o ...@@ -43,6 +46,7 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
# matches # matches
obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/moduleparam.h>
#include <net/checksum.h> #include <net/checksum.h>
#include <net/udp.h> #include <net/udp.h>
...@@ -34,7 +35,7 @@ static unsigned int master_timeout = 300; ...@@ -34,7 +35,7 @@ static unsigned int master_timeout = 300;
MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
MODULE_DESCRIPTION("Amanda connection tracking module"); MODULE_DESCRIPTION("Amanda connection tracking module");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(master_timeout, "i"); module_param(master_timeout, int, 0600);
MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
static char *conns[] = { "DATA ", "MESG ", "INDEX " }; static char *conns[] = { "DATA ", "MESG ", "INDEX " };
...@@ -58,7 +59,7 @@ static int help(struct sk_buff *skb, ...@@ -58,7 +59,7 @@ static int help(struct sk_buff *skb,
/* increase the UDP timeout of the master connection as replies from /* increase the UDP timeout of the master connection as replies from
* Amanda clients to the server can be quite delayed */ * Amanda clients to the server can be quite delayed */
ip_ct_refresh(ct, master_timeout * HZ); ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ);
/* No data? */ /* No data? */
dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr); dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr);
......
This diff is collapsed.
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/netfilter_ipv4/lockhelp.h> #include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h> #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
#include <linux/moduleparam.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
...@@ -33,10 +34,10 @@ struct module *ip_conntrack_ftp = THIS_MODULE; ...@@ -33,10 +34,10 @@ struct module *ip_conntrack_ftp = THIS_MODULE;
#define MAX_PORTS 8 #define MAX_PORTS 8
static int ports[MAX_PORTS]; static int ports[MAX_PORTS];
static int ports_c; static int ports_c;
MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); module_param_array(ports, int, ports_c, 0400);
static int loose; static int loose;
MODULE_PARM(loose, "i"); module_param(loose, int, 0600);
#if 0 #if 0
#define DEBUGP printk #define DEBUGP printk
...@@ -420,10 +421,10 @@ static int __init init(void) ...@@ -420,10 +421,10 @@ static int __init init(void)
int i, ret; int i, ret;
char *tmpname; char *tmpname;
if (ports[0] == 0) if (ports_c == 0)
ports[0] = FTP_PORT; ports[ports_c++] = FTP_PORT;
for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { for (i = 0; i < ports_c; i++) {
ftp[i].tuple.src.u.tcp.port = htons(ports[i]); ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
ftp[i].tuple.dst.protonum = IPPROTO_TCP; ftp[i].tuple.dst.protonum = IPPROTO_TCP;
ftp[i].mask.src.u.tcp.port = 0xFFFF; ftp[i].mask.src.u.tcp.port = 0xFFFF;
...@@ -449,7 +450,6 @@ static int __init init(void) ...@@ -449,7 +450,6 @@ static int __init init(void)
fini(); fini();
return ret; return ret;
} }
ports_c++;
} }
return 0; return 0;
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/netfilter_ipv4/lockhelp.h> #include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_irc.h> #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
#include <linux/moduleparam.h>
#define MAX_PORTS 8 #define MAX_PORTS 8
static int ports[MAX_PORTS]; static int ports[MAX_PORTS];
...@@ -44,11 +45,11 @@ static char irc_buffer[65536]; ...@@ -44,11 +45,11 @@ static char irc_buffer[65536];
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); module_param_array(ports, int, ports_c, 0400);
MODULE_PARM_DESC(ports, "port numbers of IRC servers"); MODULE_PARM_DESC(ports, "port numbers of IRC servers");
MODULE_PARM(max_dcc_channels, "i"); module_param(max_dcc_channels, int, 0400);
MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session"); MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
MODULE_PARM(dcc_timeout, "i"); module_param(dcc_timeout, int, 0400);
MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " }; static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
...@@ -252,10 +253,10 @@ static int __init init(void) ...@@ -252,10 +253,10 @@ static int __init init(void)
} }
/* If no port given, default to standard irc port */ /* If no port given, default to standard irc port */
if (ports[0] == 0) if (ports_c == 0)
ports[0] = IRC_PORT; ports[ports_c++] = IRC_PORT;
for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { for (i = 0; i < ports_c; i++) {
hlpr = &irc_helpers[i]; hlpr = &irc_helpers[i];
hlpr->tuple.src.u.tcp.port = htons(ports[i]); hlpr->tuple.src.u.tcp.port = htons(ports[i]);
hlpr->tuple.dst.protonum = IPPROTO_TCP; hlpr->tuple.dst.protonum = IPPROTO_TCP;
...@@ -284,7 +285,6 @@ static int __init init(void) ...@@ -284,7 +285,6 @@ static int __init init(void)
fini(); fini();
return -EBUSY; return -EBUSY;
} }
ports_c++;
} }
return 0; return 0;
} }
......
...@@ -50,9 +50,9 @@ static unsigned int generic_print_conntrack(char *buffer, ...@@ -50,9 +50,9 @@ static unsigned int generic_print_conntrack(char *buffer,
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int packet(struct ip_conntrack *conntrack, static int packet(struct ip_conntrack *conntrack,
const struct sk_buff *skb, const struct sk_buff *skb,
enum ip_conntrack_info conntrackinfo) enum ip_conntrack_info ctinfo)
{ {
ip_ct_refresh(conntrack, ip_ct_generic_timeout); ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_generic_timeout);
return NF_ACCEPT; return NF_ACCEPT;
} }
...@@ -62,8 +62,14 @@ static int new(struct ip_conntrack *conntrack, const struct sk_buff *skb) ...@@ -62,8 +62,14 @@ static int new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
return 1; return 1;
} }
struct ip_conntrack_protocol ip_conntrack_generic_protocol struct ip_conntrack_protocol ip_conntrack_generic_protocol =
= { { NULL, NULL }, 0, "unknown", {
generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple, .proto = 0,
generic_print_conntrack, packet, new, NULL, NULL, NULL }; .name = "unknown",
.pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple,
.print_tuple = generic_print_tuple,
.print_conntrack = generic_print_conntrack,
.packet = packet,
.new = new,
};
...@@ -12,6 +12,11 @@ ...@@ -12,6 +12,11 @@
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/icmp.h> #include <linux/icmp.h>
#include <net/ip.h>
#include <net/checksum.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
unsigned long ip_ct_icmp_timeout = 30*HZ; unsigned long ip_ct_icmp_timeout = 30*HZ;
...@@ -94,7 +99,7 @@ static int icmp_packet(struct ip_conntrack *ct, ...@@ -94,7 +99,7 @@ static int icmp_packet(struct ip_conntrack *ct,
ct->timeout.function((unsigned long)ct); ct->timeout.function((unsigned long)ct);
} else { } else {
atomic_inc(&ct->proto.icmp.count); atomic_inc(&ct->proto.icmp.count);
ip_ct_refresh(ct, ip_ct_icmp_timeout); ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
} }
return NF_ACCEPT; return NF_ACCEPT;
...@@ -122,7 +127,147 @@ static int icmp_new(struct ip_conntrack *conntrack, ...@@ -122,7 +127,147 @@ static int icmp_new(struct ip_conntrack *conntrack,
return 1; return 1;
} }
struct ip_conntrack_protocol ip_conntrack_protocol_icmp static int
= { { NULL, NULL }, IPPROTO_ICMP, "icmp", icmp_error_message(struct sk_buff *skb,
icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple, enum ip_conntrack_info *ctinfo,
icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL }; unsigned int hooknum)
{
struct ip_conntrack_tuple innertuple, origtuple;
struct {
struct icmphdr icmp;
struct iphdr ip;
} inside;
struct ip_conntrack_protocol *innerproto;
struct ip_conntrack_tuple_hash *h;
int dataoff;
IP_NF_ASSERT(skb->nfct == NULL);
/* Not enough header? */
if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
return NF_ACCEPT;
/* Ignore ICMP's containing fragments (shouldn't happen) */
if (inside.ip.frag_off & htons(IP_OFFSET)) {
DEBUGP("icmp_error_track: fragment of proto %u\n",
inside.ip.protocol);
return NF_ACCEPT;
}
innerproto = ip_ct_find_proto(inside.ip.protocol);
dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
/* Are they talking about one of our connections? */
if (!ip_ct_get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
return NF_ACCEPT;
}
/* Ordinarily, we'd expect the inverted tupleproto, but it's
been preserved inside the ICMP. */
if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
DEBUGP("icmp_error_track: Can't invert tuple\n");
return NF_ACCEPT;
}
*ctinfo = IP_CT_RELATED;
h = ip_conntrack_find_get(&innertuple, NULL);
if (!h) {
/* Locally generated ICMPs will match inverted if they
haven't been SNAT'ed yet */
/* FIXME: NAT code has to handle half-done double NAT --RR */
if (hooknum == NF_IP_LOCAL_OUT)
h = ip_conntrack_find_get(&origtuple, NULL);
if (!h) {
DEBUGP("icmp_error_track: no match\n");
return NF_ACCEPT;
}
/* Reverse direction from that found */
if (DIRECTION(h) != IP_CT_DIR_REPLY)
*ctinfo += IP_CT_IS_REPLY;
} else {
if (DIRECTION(h) == IP_CT_DIR_REPLY)
*ctinfo += IP_CT_IS_REPLY;
}
/* Update skb to refer to this connection */
skb->nfct = &h->ctrack->infos[*ctinfo];
return -NF_ACCEPT;
}
/* Small and modified version of icmp_rcv */
static int
icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
unsigned int hooknum)
{
struct icmphdr icmph;
/* Not enough header? */
if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph))!=0) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_icmp: short packet ");
return -NF_ACCEPT;
}
/* See ip_conntrack_proto_tcp.c */
if (hooknum != NF_IP_PRE_ROUTING)
goto checksum_skipped;
switch (skb->ip_summed) {
case CHECKSUM_HW:
if (!(u16)csum_fold(skb->csum))
break;
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_icmp: bad HW ICMP checksum ");
return -NF_ACCEPT;
case CHECKSUM_NONE:
if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_icmp: bad ICMP checksum ");
return -NF_ACCEPT;
}
default:
break;
}
checksum_skipped:
/*
* 18 is the highest 'known' ICMP type. Anything else is a mystery
*
* RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently
* discarded.
*/
if (icmph.type > NR_ICMP_TYPES) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_icmp: invalid ICMP type ");
return -NF_ACCEPT;
}
/* Need to track icmp error message? */
if (icmph.type != ICMP_DEST_UNREACH
&& icmph.type != ICMP_SOURCE_QUENCH
&& icmph.type != ICMP_TIME_EXCEEDED
&& icmph.type != ICMP_PARAMETERPROB
&& icmph.type != ICMP_REDIRECT)
return NF_ACCEPT;
return icmp_error_message(skb, ctinfo, hooknum);
}
struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
{
.proto = IPPROTO_ICMP,
.name = "icmp",
.pkt_to_tuple = icmp_pkt_to_tuple,
.invert_tuple = icmp_invert_tuple,
.print_tuple = icmp_print_tuple,
.print_conntrack = icmp_print_conntrack,
.packet = icmp_packet,
.new = icmp_new,
.error = icmp_error,
};
This diff is collapsed.
This diff is collapsed.
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/udp.h> #include <linux/udp.h>
#include <net/checksum.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
unsigned long ip_ct_udp_timeout = 30*HZ; unsigned long ip_ct_udp_timeout = 30*HZ;
...@@ -60,16 +62,17 @@ static unsigned int udp_print_conntrack(char *buffer, ...@@ -60,16 +62,17 @@ static unsigned int udp_print_conntrack(char *buffer,
/* Returns verdict for packet, and may modify conntracktype */ /* Returns verdict for packet, and may modify conntracktype */
static int udp_packet(struct ip_conntrack *conntrack, static int udp_packet(struct ip_conntrack *conntrack,
const struct sk_buff *skb, const struct sk_buff *skb,
enum ip_conntrack_info conntrackinfo) enum ip_conntrack_info ctinfo)
{ {
/* If we've seen traffic both ways, this is some kind of UDP /* If we've seen traffic both ways, this is some kind of UDP
stream. Extend timeout. */ stream. Extend timeout. */
if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream); ip_ct_refresh_acct(conntrack, ctinfo, skb,
ip_ct_udp_timeout_stream);
/* Also, more likely to be important, and not a probe */ /* Also, more likely to be important, and not a probe */
set_bit(IPS_ASSURED_BIT, &conntrack->status); set_bit(IPS_ASSURED_BIT, &conntrack->status);
} else } else
ip_ct_refresh(conntrack, ip_ct_udp_timeout); ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
return NF_ACCEPT; return NF_ACCEPT;
} }
...@@ -80,7 +83,60 @@ static int udp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb) ...@@ -80,7 +83,60 @@ static int udp_new(struct ip_conntrack *conntrack, const struct sk_buff *skb)
return 1; return 1;
} }
struct ip_conntrack_protocol ip_conntrack_protocol_udp static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
= { { NULL, NULL }, IPPROTO_UDP, "udp", unsigned int hooknum)
udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack, {
udp_packet, udp_new, NULL, NULL, NULL }; struct iphdr *iph = skb->nh.iph;
unsigned int udplen = skb->len - iph->ihl * 4;
struct udphdr hdr;
/* Header is too small? */
if (skb_copy_bits(skb, iph->ihl*4, &hdr, sizeof(hdr)) != 0) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_udp: short packet ");
return -NF_ACCEPT;
}
/* Truncated/malformed packets */
if (ntohs(hdr.len) > udplen || ntohs(hdr.len) < sizeof(hdr)) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_udp: truncated/malformed packet ");
return -NF_ACCEPT;
}
/* Packet with no checksum */
if (!hdr.check)
return NF_ACCEPT;
/* Checksum invalid? Ignore.
* We skip checking packets on the outgoing path
* because the semantic of CHECKSUM_HW is different there
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
if (hooknum == NF_IP_PRE_ROUTING
&& csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, udplen, 0))) {
if (LOG_INVALID(IPPROTO_UDP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_udp: bad UDP checksum ");
return -NF_ACCEPT;
}
return NF_ACCEPT;
}
struct ip_conntrack_protocol ip_conntrack_protocol_udp =
{
.proto = IPPROTO_UDP,
.name = "udp",
.pkt_to_tuple = udp_pkt_to_tuple,
.invert_tuple = udp_invert_tuple,
.print_tuple = udp_print_tuple,
.print_conntrack = udp_print_conntrack,
.packet = udp_packet,
.new = udp_new,
.error = udp_error,
};
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_tftp.h> #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
#include <linux/moduleparam.h>
MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>"); MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
MODULE_DESCRIPTION("tftp connection tracking helper"); MODULE_DESCRIPTION("tftp connection tracking helper");
...@@ -27,7 +28,7 @@ MODULE_LICENSE("GPL"); ...@@ -27,7 +28,7 @@ MODULE_LICENSE("GPL");
#define MAX_PORTS 8 #define MAX_PORTS 8
static int ports[MAX_PORTS]; static int ports[MAX_PORTS];
static int ports_c; static int ports_c;
MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); module_param_array(ports, int, ports_c, 0400);
MODULE_PARM_DESC(ports, "port numbers of tftp servers"); MODULE_PARM_DESC(ports, "port numbers of tftp servers");
#if 0 #if 0
...@@ -104,10 +105,10 @@ static int __init init(void) ...@@ -104,10 +105,10 @@ static int __init init(void)
int i, ret; int i, ret;
char *tmpname; char *tmpname;
if (!ports[0]) if (ports_c == 0)
ports[0]=TFTP_PORT; ports[ports_c++] = TFTP_PORT;
for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) { for (i = 0; i < ports_c; i++) {
/* Create helper structure */ /* Create helper structure */
memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper)); memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
...@@ -137,7 +138,6 @@ static int __init init(void) ...@@ -137,7 +138,6 @@ static int __init init(void)
fini(); fini();
return(ret); return(ret);
} }
ports_c++;
} }
return(0); return(0);
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#include <linux/netfilter_ipv4/ip_nat.h> #include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_core.h> #include <linux/netfilter_ipv4/ip_nat_core.h>
#include <linux/netfilter_ipv4/listhelp.h> #include <linux/netfilter_ipv4/listhelp.h>
...@@ -144,7 +145,8 @@ check_for_demasq(struct sk_buff **pskb) ...@@ -144,7 +145,8 @@ check_for_demasq(struct sk_buff **pskb)
switch ((*pskb)->nh.iph->protocol) { switch ((*pskb)->nh.iph->protocol) {
case IPPROTO_ICMP: case IPPROTO_ICMP:
/* ICMP errors. */ /* ICMP errors. */
ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING); protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
ct = (struct ip_conntrack *)(*pskb)->nfct->master;
if (ct) { if (ct) {
/* We only do SNAT in the compatibility layer. /* We only do SNAT in the compatibility layer.
So we can manipulate ICMP errors from So we can manipulate ICMP errors from
...@@ -165,7 +167,8 @@ check_for_demasq(struct sk_buff **pskb) ...@@ -165,7 +167,8 @@ check_for_demasq(struct sk_buff **pskb)
case IPPROTO_UDP: case IPPROTO_UDP:
IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0); IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) { if (!ip_ct_get_tuple((*pskb)->nh.iph, *pskb,
(*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
if (net_ratelimit()) if (net_ratelimit())
printk("ip_fw_compat_masq: Can't get tuple\n"); printk("ip_fw_compat_masq: Can't get tuple\n");
return NF_ACCEPT; return NF_ACCEPT;
......
...@@ -49,7 +49,6 @@ static unsigned int ip_nat_htable_size; ...@@ -49,7 +49,6 @@ static unsigned int ip_nat_htable_size;
static struct list_head *bysource; static struct list_head *bysource;
static struct list_head *byipsproto; static struct list_head *byipsproto;
LIST_HEAD(protos); LIST_HEAD(protos);
LIST_HEAD(helpers);
extern struct ip_nat_protocol unknown_nat_protocol; extern struct ip_nat_protocol unknown_nat_protocol;
...@@ -498,13 +497,6 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, ...@@ -498,13 +497,6 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
return ret; return ret;
} }
static inline int
helper_cmp(const struct ip_nat_helper *helper,
const struct ip_conntrack_tuple *tuple)
{
return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
}
/* Where to manip the reply packets (will be reverse manip). */ /* Where to manip the reply packets (will be reverse manip). */
static unsigned int opposite_hook[NF_IP_NUMHOOKS] static unsigned int opposite_hook[NF_IP_NUMHOOKS]
= { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING, = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
...@@ -643,8 +635,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, ...@@ -643,8 +635,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
/* If there's a helper, assign it; based on new tuple. */ /* If there's a helper, assign it; based on new tuple. */
if (!conntrack->master) if (!conntrack->master)
info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, info->helper = ip_nat_find_helper(&reply);
&reply);
/* It's done. */ /* It's done. */
info->initialized |= (1 << HOOK2MANIP(hooknum)); info->initialized |= (1 << HOOK2MANIP(hooknum));
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/tcp.h> #include <linux/tcp.h>
#include <linux/moduleparam.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <linux/netfilter_ipv4/ip_nat.h> #include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_helper.h> #include <linux/netfilter_ipv4/ip_nat_helper.h>
...@@ -33,7 +34,7 @@ MODULE_DESCRIPTION("ftp NAT helper"); ...@@ -33,7 +34,7 @@ MODULE_DESCRIPTION("ftp NAT helper");
static int ports[MAX_PORTS]; static int ports[MAX_PORTS];
static int ports_c; static int ports_c;
MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); module_param_array(ports, int, ports_c, 0400);
DECLARE_LOCK_EXTERN(ip_ftp_lock); DECLARE_LOCK_EXTERN(ip_ftp_lock);
...@@ -313,10 +314,10 @@ static int __init init(void) ...@@ -313,10 +314,10 @@ static int __init init(void)
int i, ret = 0; int i, ret = 0;
char *tmpname; char *tmpname;
if (ports[0] == 0) if (ports_c == 0)
ports[0] = FTP_PORT; ports[ports_c] = FTP_PORT;
for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { for (i = 0; i < ports_c; i++) {
ftp[i].tuple.dst.protonum = IPPROTO_TCP; ftp[i].tuple.dst.protonum = IPPROTO_TCP;
ftp[i].tuple.src.u.tcp.port = htons(ports[i]); ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
ftp[i].mask.dst.protonum = 0xFFFF; ftp[i].mask.dst.protonum = 0xFFFF;
...@@ -343,7 +344,6 @@ static int __init init(void) ...@@ -343,7 +344,6 @@ static int __init init(void)
fini(); fini();
return ret; return ret;
} }
ports_c++;
} }
return ret; return ret;
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#define DUMP_OFFSET(x) #define DUMP_OFFSET(x)
#endif #endif
static LIST_HEAD(helpers);
DECLARE_LOCK(ip_nat_seqofs_lock); DECLARE_LOCK(ip_nat_seqofs_lock);
/* Setup TCP sequence correction given this change at this sequence */ /* Setup TCP sequence correction given this change at this sequence */
...@@ -419,6 +420,18 @@ int ip_nat_helper_register(struct ip_nat_helper *me) ...@@ -419,6 +420,18 @@ int ip_nat_helper_register(struct ip_nat_helper *me)
return ret; return ret;
} }
struct ip_nat_helper *
ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
{
struct ip_nat_helper *h;
READ_LOCK(&ip_nat_lock);
h = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple);
READ_UNLOCK(&ip_nat_lock);
return h;
}
static int static int
kill_helper(const struct ip_conntrack *i, void *helper) kill_helper(const struct ip_conntrack *i, void *helper)
{ {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/netfilter_ipv4/ip_nat_rule.h> #include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/netfilter_ipv4/ip_conntrack_irc.h> #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/moduleparam.h>
#if 0 #if 0
#define DEBUGP printk #define DEBUGP printk
...@@ -41,7 +42,7 @@ static int ports_c; ...@@ -41,7 +42,7 @@ static int ports_c;
MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
MODULE_DESCRIPTION("IRC (DCC) NAT helper"); MODULE_DESCRIPTION("IRC (DCC) NAT helper");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i"); module_param_array(ports, int, ports_c, 0400);
MODULE_PARM_DESC(ports, "port numbers of IRC servers"); MODULE_PARM_DESC(ports, "port numbers of IRC servers");
/* protects irc part of conntracks */ /* protects irc part of conntracks */
...@@ -235,11 +236,10 @@ static int __init init(void) ...@@ -235,11 +236,10 @@ static int __init init(void)
struct ip_nat_helper *hlpr; struct ip_nat_helper *hlpr;
char *tmpname; char *tmpname;
if (ports[0] == 0) { if (ports_c == 0)
ports[0] = IRC_PORT; ports[ports_c++] = IRC_PORT;
}
for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) { for (i = 0; i < ports_c; i++) {
hlpr = &ip_nat_irc_helpers[i]; hlpr = &ip_nat_irc_helpers[i];
hlpr->tuple.dst.protonum = IPPROTO_TCP; hlpr->tuple.dst.protonum = IPPROTO_TCP;
hlpr->tuple.src.u.tcp.port = htons(ports[i]); hlpr->tuple.src.u.tcp.port = htons(ports[i]);
...@@ -269,7 +269,6 @@ static int __init init(void) ...@@ -269,7 +269,6 @@ static int __init init(void)
fini(); fini();
return 1; return 1;
} }
ports_c++;
} }
return ret; return ret;
} }
......
...@@ -132,7 +132,8 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb, ...@@ -132,7 +132,8 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
ct = ip_conntrack_get(*pskb, &ctinfo); ct = ip_conntrack_get(*pskb, &ctinfo);
/* Connection must be valid and new. */ /* Connection must be valid and new. */
IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
IP_NF_ASSERT(out); IP_NF_ASSERT(out);
return ip_nat_setup_info(ct, targinfo, hooknum); return ip_nat_setup_info(ct, targinfo, hooknum);
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_nat.h> #include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_helper.h> #include <linux/netfilter_ipv4/ip_nat_helper.h>
...@@ -1253,6 +1254,9 @@ static unsigned int nat_help(struct ip_conntrack *ct, ...@@ -1253,6 +1254,9 @@ static unsigned int nat_help(struct ip_conntrack *ct,
struct iphdr *iph = (*pskb)->nh.iph; struct iphdr *iph = (*pskb)->nh.iph;
struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
if (!skb_ip_make_writable(pskb, (*pskb)->len))
return NF_DROP;
spin_lock_bh(&snmp_lock); spin_lock_bh(&snmp_lock);
/* /*
...@@ -1357,4 +1361,4 @@ static void __exit fini(void) ...@@ -1357,4 +1361,4 @@ static void __exit fini(void)
module_init(init); module_init(init);
module_exit(fini); module_exit(fini);
MODULE_PARM(debug, "i"); module_param(debug, bool, 0600);
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/netfilter_ipv4/ip_conntrack_tftp.h> #include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
#include <linux/netfilter_ipv4/ip_nat_helper.h> #include <linux/netfilter_ipv4/ip_nat_helper.h>
#include <linux/netfilter_ipv4/ip_nat_rule.h> #include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/moduleparam.h>
MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>"); MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
MODULE_DESCRIPTION("tftp NAT helper"); MODULE_DESCRIPTION("tftp NAT helper");
...@@ -41,7 +42,7 @@ MODULE_LICENSE("GPL"); ...@@ -41,7 +42,7 @@ MODULE_LICENSE("GPL");
static int ports[MAX_PORTS]; static int ports[MAX_PORTS];
static int ports_c = 0; static int ports_c = 0;
MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i"); module_param_array(ports, int, ports_c, 0400);
MODULE_PARM_DESC(ports, "port numbers of tftp servers"); MODULE_PARM_DESC(ports, "port numbers of tftp servers");
#if 0 #if 0
...@@ -162,10 +163,10 @@ static int __init init(void) ...@@ -162,10 +163,10 @@ static int __init init(void)
int i, ret = 0; int i, ret = 0;
char *tmpname; char *tmpname;
if (!ports[0]) if (ports_c == 0)
ports[0] = TFTP_PORT; ports[ports_c++] = TFTP_PORT;
for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) { for (i = 0; i < ports_c; i++) {
memset(&tftp[i], 0, sizeof(struct ip_nat_helper)); memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
tftp[i].tuple.dst.protonum = IPPROTO_UDP; tftp[i].tuple.dst.protonum = IPPROTO_UDP;
...@@ -194,7 +195,6 @@ static int __init init(void) ...@@ -194,7 +195,6 @@ static int __init init(void)
fini(); fini();
return ret; return ret;
} }
ports_c++;
} }
return ret; return ret;
} }
......
...@@ -61,6 +61,8 @@ do { \ ...@@ -61,6 +61,8 @@ do { \
#endif #endif
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
static DECLARE_MUTEX(ipt_mutex);
/* Must have mutex */ /* Must have mutex */
#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
......
...@@ -28,7 +28,7 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); ...@@ -28,7 +28,7 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables syslog logging module"); MODULE_DESCRIPTION("iptables syslog logging module");
static unsigned int nflog = 1; static unsigned int nflog = 1;
MODULE_PARM(nflog, "i"); module_param(nflog, int, 0400);
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module"); MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
#if 0 #if 0
......
...@@ -92,8 +92,8 @@ masquerade_target(struct sk_buff **pskb, ...@@ -92,8 +92,8 @@ masquerade_target(struct sk_buff **pskb,
return NF_ACCEPT; return NF_ACCEPT;
ct = ip_conntrack_get(*pskb, &ctinfo); ct = ip_conntrack_get(*pskb, &ctinfo);
IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
|| ctinfo == IP_CT_RELATED)); || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
mr = targinfo; mr = targinfo;
......
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
* by that factor. * by that factor.
* *
* flushtimeout: * flushtimeout:
* Specify, after how many clock ticks (intel: 100 per second) the queue * Specify, after how many hundredths of a second the queue should be
* should be flushed even if it is not full yet. * flushed even if it is not full yet.
* *
* ipt_ULOG.c,v 1.22 2002/10/30 09:07:31 laforge Exp * ipt_ULOG.c,v 1.22 2002/10/30 09:07:31 laforge Exp
*/ */
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/moduleparam.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_ULOG.h> #include <linux/netfilter_ipv4/ipt_ULOG.h>
...@@ -74,15 +75,15 @@ MODULE_DESCRIPTION("iptables userspace logging module"); ...@@ -74,15 +75,15 @@ MODULE_DESCRIPTION("iptables userspace logging module");
#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) #define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
static unsigned int nlbufsiz = 4096; static unsigned int nlbufsiz = 4096;
MODULE_PARM(nlbufsiz, "i"); module_param(nlbufsiz, uint, 0600); /* FIXME: Check size < 128k --RR */
MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
static unsigned int flushtimeout = 10 * HZ; static unsigned int flushtimeout = 10;
MODULE_PARM(flushtimeout, "i"); module_param(flushtimeout, int, 0600);
MODULE_PARM_DESC(flushtimeout, "buffer flush timeout"); MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)");
static unsigned int nflog = 1; static unsigned int nflog = 1;
MODULE_PARM(nflog, "i"); module_param(nflog, int, 0400);
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module"); MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
/* global data structures */ /* global data structures */
...@@ -97,7 +98,6 @@ typedef struct { ...@@ -97,7 +98,6 @@ typedef struct {
static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; /* array of buffers */ static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; /* array of buffers */
static struct sock *nflognl; /* our socket */ static struct sock *nflognl; /* our socket */
static size_t qlen; /* current length of multipart-nlmsg */
DECLARE_LOCK(ulog_lock); /* spinlock */ DECLARE_LOCK(ulog_lock); /* spinlock */
/* send one ulog_buff_t to userspace */ /* send one ulog_buff_t to userspace */
...@@ -116,7 +116,7 @@ static void ulog_send(unsigned int nlgroupnum) ...@@ -116,7 +116,7 @@ static void ulog_send(unsigned int nlgroupnum)
NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum); NETLINK_CB(ub->skb).dst_groups = (1 << nlgroupnum);
DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %u\n", DEBUGP("ipt_ULOG: throwing %d packets to netlink mask %u\n",
ub->qlen, nlgroup); ub->qlen, nlgroupnum);
netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC); netlink_broadcast(nflognl, ub->skb, 0, (1 << nlgroupnum), GFP_ATOMIC);
ub->qlen = 0; ub->qlen = 0;
...@@ -126,7 +126,7 @@ static void ulog_send(unsigned int nlgroupnum) ...@@ -126,7 +126,7 @@ static void ulog_send(unsigned int nlgroupnum)
} }
/* timer function to flush queue in ULOG_FLUSH_INTERVAL time */ /* timer function to flush queue in flushtimeout time */
static void ulog_timer(unsigned long data) static void ulog_timer(unsigned long data)
{ {
DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n"); DEBUGP("ipt_ULOG: timer function called, calling ulog_send\n");
...@@ -261,20 +261,21 @@ static void ipt_ulog_packet(unsigned int hooknum, ...@@ -261,20 +261,21 @@ static void ipt_ulog_packet(unsigned int hooknum,
ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
} }
/* if threshold is reached, send message to userspace */
if (qlen >= loginfo->qthreshold) {
if (loginfo->qthreshold > 1)
nlh->nlmsg_type = NLMSG_DONE;
}
ub->lastnlh = nlh; ub->lastnlh = nlh;
/* if timer isn't already running, start it */ /* if timer isn't already running, start it */
if (!timer_pending(&ub->timer)) { if (!timer_pending(&ub->timer)) {
ub->timer.expires = jiffies + flushtimeout; ub->timer.expires = jiffies + flushtimeout * HZ / 100;
add_timer(&ub->timer); add_timer(&ub->timer);
} }
/* if threshold is reached, send message to userspace */
if (ub->qlen >= loginfo->qthreshold) {
if (loginfo->qthreshold > 1)
nlh->nlmsg_type = NLMSG_DONE;
ulog_send(groupnum);
}
UNLOCK_BH(&ulog_lock); UNLOCK_BH(&ulog_lock);
return; return;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/moduleparam.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_recent.h> #include <linux/netfilter_ipv4/ipt_recent.h>
...@@ -37,12 +38,12 @@ KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. htt ...@@ -37,12 +38,12 @@ KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. htt
MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>"); MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER); MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(ip_list_tot,"i"); module_param(ip_list_tot, int, 0400);
MODULE_PARM(ip_pkt_list_tot,"i"); module_param(ip_pkt_list_tot, int, 0400);
MODULE_PARM(ip_list_hash_size,"i"); module_param(ip_list_hash_size, int, 0400);
MODULE_PARM(ip_list_perms,"i"); module_param(ip_list_perms, int, 0400);
#ifdef DEBUG #ifdef DEBUG
MODULE_PARM(debug,"i"); module_param(debug, int, 0600);
MODULE_PARM_DESC(debug,"debugging level, defaults to 1"); MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
#endif #endif
MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list"); MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
......
#include <linux/module.h>
#include <linux/skbuff.h>
#include <net/ip.h>
#include <linux/sctp.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_sctp.h>
#ifdef DEBUG_SCTP
#define duprintf(format, args...) printk(format , ## args)
#else
#define duprintf(format, args...)
#endif
#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
|| (!!((invflag) & (option)) ^ (cond)))
static int
match_flags(const struct ipt_sctp_flag_info *flag_info,
const int flag_count,
u_int8_t chunktype,
u_int8_t chunkflags)
{
int i;
for (i = 0; i < flag_count; i++) {
if (flag_info[i].chunktype == chunktype) {
return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
}
}
return 1;
}
static int
match_packet(const struct sk_buff *skb,
const u_int32_t *chunkmap,
int chunk_match_type,
const struct ipt_sctp_flag_info *flag_info,
const int flag_count,
int *hotdrop)
{
int offset;
u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
sctp_chunkhdr_t sch;
#ifdef DEBUG_SCTP
int i = 0;
#endif
if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
}
offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
do {
if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
duprintf("Dropping invalid SCTP packet.\n");
*hotdrop = 1;
return 0;
}
duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
++i, offset, sch.type, htons(sch.length), sch.flags);
offset += (htons(sch.length) + 3) & ~3;
duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
switch (chunk_match_type) {
case SCTP_CHUNK_MATCH_ANY:
if (match_flags(flag_info, flag_count,
sch.type, sch.flags)) {
return 1;
}
break;
case SCTP_CHUNK_MATCH_ALL:
if (match_flags(flag_info, flag_count,
sch.type, sch.flags)) {
SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
}
break;
case SCTP_CHUNK_MATCH_ONLY:
if (!match_flags(flag_info, flag_count,
sch.type, sch.flags)) {
return 0;
}
break;
}
} else {
switch (chunk_match_type) {
case SCTP_CHUNK_MATCH_ONLY:
return 0;
}
}
} while (offset < skb->len);
switch (chunk_match_type) {
case SCTP_CHUNK_MATCH_ALL:
return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
case SCTP_CHUNK_MATCH_ANY:
return 0;
case SCTP_CHUNK_MATCH_ONLY:
return 1;
}
/* This will never be reached, but required to stop compiler whine */
return 0;
}
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)
{
const struct ipt_sctp_info *info;
sctp_sctphdr_t sh;
info = (const struct ipt_sctp_info *)matchinfo;
if (offset) {
duprintf("Dropping non-first fragment.. FIXME\n");
return 0;
}
if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
duprintf("Dropping evil TCP offset=0 tinygram.\n");
*hotdrop = 1;
return 0;
}
duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
return SCCHECK(((ntohs(sh.source) >= info->spts[0])
&& (ntohs(sh.source) <= info->spts[1])),
IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
&& SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
&& (ntohs(sh.dest) <= info->dpts[1])),
IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
&& SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
info->flag_info, info->flag_count,
hotdrop),
IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
}
static int
checkentry(const char *tablename,
const struct ipt_ip *ip,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
const struct ipt_sctp_info *info;
info = (const struct ipt_sctp_info *)matchinfo;
return ip->proto == IPPROTO_SCTP
&& !(ip->invflags & IPT_INV_PROTO)
&& matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
&& !(info->flags & ~IPT_SCTP_VALID_FLAGS)
&& !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
&& !(info->invflags & ~info->flags)
&& ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
(info->chunk_match_type &
(SCTP_CHUNK_MATCH_ALL
| SCTP_CHUNK_MATCH_ANY
| SCTP_CHUNK_MATCH_ONLY)));
}
static struct ipt_match sctp_match =
{
.list = { NULL, NULL},
.name = "sctp",
.match = &match,
.checkentry = &checkentry,
.destroy = NULL,
.me = THIS_MODULE
};
static int __init init(void)
{
return ipt_register_match(&sctp_match);
}
static void __exit fini(void)
{
ipt_unregister_match(&sctp_match);
}
module_init(init);
module_exit(fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kiran Kumar Immidi");
MODULE_DESCRIPTION("Match for SCTP protocol packets");
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -155,7 +156,7 @@ static struct nf_hook_ops ipt_ops[] = { ...@@ -155,7 +156,7 @@ static struct nf_hook_ops ipt_ops[] = {
/* Default to forward because I got too much mail already. */ /* Default to forward because I got too much mail already. */
static int forward = NF_ACCEPT; static int forward = NF_ACCEPT;
MODULE_PARM(forward, "i"); module_param(forward, bool, 0000);
static int __init init(void) static int __init init(void)
{ {
......
...@@ -66,6 +66,7 @@ do { \ ...@@ -66,6 +66,7 @@ do { \
#endif #endif
#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
static DECLARE_MUTEX(ip6t_mutex);
/* Must have mutex */ /* Must have mutex */
#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -26,7 +27,7 @@ MODULE_DESCRIPTION("IP6 tables LOG target module"); ...@@ -26,7 +27,7 @@ MODULE_DESCRIPTION("IP6 tables LOG target module");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static unsigned int nflog = 1; static unsigned int nflog = 1;
MODULE_PARM(nflog, "i"); module_param(nflog, int, 0400);
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module"); MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
struct in_device; struct in_device;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netfilter_ipv6/ip6_tables.h> #include <linux/netfilter_ipv6/ip6_tables.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -156,7 +157,7 @@ static struct nf_hook_ops ip6t_ops[] = { ...@@ -156,7 +157,7 @@ static struct nf_hook_ops ip6t_ops[] = {
/* Default to forward because I got too much mail already. */ /* Default to forward because I got too much mail already. */
static int forward = NF_ACCEPT; static int forward = NF_ACCEPT;
MODULE_PARM(forward, "i"); module_param(forward, bool, 0000);
static int __init init(void) static int __init init(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment