Commit b01a55a8 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

parents 940e3318 482a8524
#ifndef __LINUX_GENERIC_NETLINK_H
#define __LINUX_GENERIC_NETLINK_H
#include <linux/netlink.h>
#define GENL_NAMSIZ 16 /* length of family name */
#define GENL_MIN_ID NLMSG_MIN_TYPE
#define GENL_MAX_ID 1023
struct genlmsghdr {
__u8 cmd;
__u8 version;
__u16 reserved;
};
#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
/*
* List of reserved static generic netlink identifiers:
*/
#define GENL_ID_GENERATE 0
#define GENL_ID_CTRL NLMSG_MIN_TYPE
/**************************************************************************
* Controller
**************************************************************************/
enum {
CTRL_CMD_UNSPEC,
CTRL_CMD_NEWFAMILY,
CTRL_CMD_DELFAMILY,
CTRL_CMD_GETFAMILY,
CTRL_CMD_NEWOPS,
CTRL_CMD_DELOPS,
CTRL_CMD_GETOPS,
__CTRL_CMD_MAX,
};
#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
enum {
CTRL_ATTR_UNSPEC,
CTRL_ATTR_FAMILY_ID,
CTRL_ATTR_FAMILY_NAME,
__CTRL_ATTR_MAX,
};
#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
#endif /* __LINUX_GENERIC_NETLINK_H */
#ifndef _NF_CONNTRACK_COMMON_H
#define _NF_CONNTRACK_COMMON_H
/* Connection state tracking for netfilter. This is separated from,
but required by, the NAT layer; it can also be used by an iptables
extension. */
enum ip_conntrack_info
{
/* Part of an established connection (either direction). */
IP_CT_ESTABLISHED,
/* Like NEW, but related to an existing connection, or ICMP error
(in either direction). */
IP_CT_RELATED,
/* Started a new connection to track (only
IP_CT_DIR_ORIGINAL); may be a retransmission. */
IP_CT_NEW,
/* >= this indicates reply direction */
IP_CT_IS_REPLY,
/* Number of distinct IP_CT types (no NEW in reply dirn). */
IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
};
/* Bitset representing status of connection. */
enum ip_conntrack_status {
/* It's an expected connection: bit 0 set. This bit never changed */
IPS_EXPECTED_BIT = 0,
IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
/* We've seen packets both ways: bit 1 set. Can be set, not unset. */
IPS_SEEN_REPLY_BIT = 1,
IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
/* Conntrack should never be early-expired. */
IPS_ASSURED_BIT = 2,
IPS_ASSURED = (1 << IPS_ASSURED_BIT),
/* Connection is confirmed: originating packet has left box */
IPS_CONFIRMED_BIT = 3,
IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
/* Connection needs src nat in orig dir. This bit never changed. */
IPS_SRC_NAT_BIT = 4,
IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
/* Connection needs dst nat in orig dir. This bit never changed. */
IPS_DST_NAT_BIT = 5,
IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
/* Both together. */
IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
/* Connection needs TCP sequence adjusted. */
IPS_SEQ_ADJUST_BIT = 6,
IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
/* NAT initialization bits. */
IPS_SRC_NAT_DONE_BIT = 7,
IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
IPS_DST_NAT_DONE_BIT = 8,
IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
/* Both together */
IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
/* Connection is dying (removed from lists), can not be unset. */
IPS_DYING_BIT = 9,
IPS_DYING = (1 << IPS_DYING_BIT),
};
/* Connection tracking event bits */
enum ip_conntrack_events
{
/* New conntrack */
IPCT_NEW_BIT = 0,
IPCT_NEW = (1 << IPCT_NEW_BIT),
/* Expected connection */
IPCT_RELATED_BIT = 1,
IPCT_RELATED = (1 << IPCT_RELATED_BIT),
/* Destroyed conntrack */
IPCT_DESTROY_BIT = 2,
IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
/* Timer has been refreshed */
IPCT_REFRESH_BIT = 3,
IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
/* Status has changed */
IPCT_STATUS_BIT = 4,
IPCT_STATUS = (1 << IPCT_STATUS_BIT),
/* Update of protocol info */
IPCT_PROTOINFO_BIT = 5,
IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
/* Volatile protocol info */
IPCT_PROTOINFO_VOLATILE_BIT = 6,
IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
/* New helper for conntrack */
IPCT_HELPER_BIT = 7,
IPCT_HELPER = (1 << IPCT_HELPER_BIT),
/* Update of helper info */
IPCT_HELPINFO_BIT = 8,
IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
/* Volatile helper info */
IPCT_HELPINFO_VOLATILE_BIT = 9,
IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
/* NAT info */
IPCT_NATINFO_BIT = 10,
IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
/* Counter highest bit has been set */
IPCT_COUNTER_FILLING_BIT = 11,
IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
};
enum ip_conntrack_expect_events {
IPEXP_NEW_BIT = 0,
IPEXP_NEW = (1 << IPEXP_NEW_BIT),
};
#ifdef __KERNEL__
struct ip_conntrack_counter
{
u_int32_t packets;
u_int32_t bytes;
};
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 error;
unsigned int expect_new;
unsigned int expect_create;
unsigned int expect_delete;
};
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_COMMON_H */
#ifndef _NF_CONNTRACK_FTP_H
#define _NF_CONNTRACK_FTP_H
/* FTP tracking. */
/* This enum is exposed to userspace */
enum ip_ct_ftp_type
{
/* PORT command from client */
IP_CT_FTP_PORT,
/* PASV response from server */
IP_CT_FTP_PASV,
/* EPRT command from client */
IP_CT_FTP_EPRT,
/* EPSV response from server */
IP_CT_FTP_EPSV,
};
#ifdef __KERNEL__
#define FTP_PORT 21
#define NUM_SEQ_TO_REMEMBER 2
/* This structure exists only once per master */
struct ip_ct_ftp_master {
/* Valid seq positions for cmd matching after newline */
u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
/* 0 means seq_match_aft_nl not set */
int seq_aft_nl_num[IP_CT_DIR_MAX];
};
struct ip_conntrack_expect;
/* For NAT to hook in when we find a packet which describes what other
* connection we should expect. */
extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
enum ip_ct_ftp_type type,
unsigned int matchoff,
unsigned int matchlen,
struct ip_conntrack_expect *exp,
u32 *seq);
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_FTP_H */
#ifndef _NF_CONNTRACK_SCTP_H
#define _NF_CONNTRACK_SCTP_H
/* SCTP tracking. */
#include <linux/netfilter/nf_conntrack_tuple_common.h>
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 /* _NF_CONNTRACK_SCTP_H */
#ifndef _NF_CONNTRACK_TCP_H
#define _NF_CONNTRACK_TCP_H
/* TCP tracking. */
/* This is exposed to userspace (ctnetlink) */
enum tcp_conntrack {
TCP_CONNTRACK_NONE,
TCP_CONNTRACK_SYN_SENT,
TCP_CONNTRACK_SYN_RECV,
TCP_CONNTRACK_ESTABLISHED,
TCP_CONNTRACK_FIN_WAIT,
TCP_CONNTRACK_CLOSE_WAIT,
TCP_CONNTRACK_LAST_ACK,
TCP_CONNTRACK_TIME_WAIT,
TCP_CONNTRACK_CLOSE,
TCP_CONNTRACK_LISTEN,
TCP_CONNTRACK_MAX,
TCP_CONNTRACK_IGNORE
};
/* Window scaling is advertised by the sender */
#define IP_CT_TCP_FLAG_WINDOW_SCALE 0x01
/* SACK is permitted by the sender */
#define IP_CT_TCP_FLAG_SACK_PERM 0x02
/* This sender sent FIN first */
#define IP_CT_TCP_FLAG_CLOSE_INIT 0x03
#ifdef __KERNEL__
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 options */
};
struct ip_ct_tcp
{
struct ip_ct_tcp_state seen[2]; /* connection parameters per direction */
u_int8_t state; /* state of the connection (enum tcp_conntrack) */
/* For detecting stale connections */
u_int8_t last_dir; /* Direction of the last packet (enum ip_conntrack_dir) */
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_ack; /* Last sequence number seen in opposite dir */
u_int32_t last_end; /* Last seq + len */
};
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_TCP_H */
#ifndef _NF_CONNTRACK_TUPLE_COMMON_H
#define _NF_CONNTRACK_TUPLE_COMMON_H
enum ip_conntrack_dir
{
IP_CT_DIR_ORIGINAL,
IP_CT_DIR_REPLY,
IP_CT_DIR_MAX
};
#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
#ifndef _IP_CONNTRACK_H #ifndef _IP_CONNTRACK_H
#define _IP_CONNTRACK_H #define _IP_CONNTRACK_H
/* Connection state tracking for netfilter. This is separated from,
but required by, the NAT layer; it can also be used by an iptables
extension. */
enum ip_conntrack_info
{
/* Part of an established connection (either direction). */
IP_CT_ESTABLISHED,
/* Like NEW, but related to an existing connection, or ICMP error
(in either direction). */
IP_CT_RELATED,
/* Started a new connection to track (only
IP_CT_DIR_ORIGINAL); may be a retransmission. */
IP_CT_NEW,
/* >= this indicates reply direction */
IP_CT_IS_REPLY,
/* Number of distinct IP_CT types (no NEW in reply dirn). */
IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
};
/* Bitset representing status of connection. */
enum ip_conntrack_status {
/* It's an expected connection: bit 0 set. This bit never changed */
IPS_EXPECTED_BIT = 0,
IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
/* We've seen packets both ways: bit 1 set. Can be set, not unset. */
IPS_SEEN_REPLY_BIT = 1,
IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
/* Conntrack should never be early-expired. */
IPS_ASSURED_BIT = 2,
IPS_ASSURED = (1 << IPS_ASSURED_BIT),
/* Connection is confirmed: originating packet has left box */
IPS_CONFIRMED_BIT = 3,
IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
/* Connection needs src nat in orig dir. This bit never changed. */
IPS_SRC_NAT_BIT = 4,
IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
/* Connection needs dst nat in orig dir. This bit never changed. */
IPS_DST_NAT_BIT = 5,
IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
/* Both together. */
IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
/* Connection needs TCP sequence adjusted. */
IPS_SEQ_ADJUST_BIT = 6,
IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
/* NAT initialization bits. */
IPS_SRC_NAT_DONE_BIT = 7,
IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
IPS_DST_NAT_DONE_BIT = 8,
IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
/* Both together */
IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
/* Connection is dying (removed from lists), can not be unset. */
IPS_DYING_BIT = 9,
IPS_DYING = (1 << IPS_DYING_BIT),
};
/* Connection tracking event bits */
enum ip_conntrack_events
{
/* New conntrack */
IPCT_NEW_BIT = 0,
IPCT_NEW = (1 << IPCT_NEW_BIT),
/* Expected connection */
IPCT_RELATED_BIT = 1,
IPCT_RELATED = (1 << IPCT_RELATED_BIT),
/* Destroyed conntrack */
IPCT_DESTROY_BIT = 2,
IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
/* Timer has been refreshed */
IPCT_REFRESH_BIT = 3,
IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
/* Status has changed */
IPCT_STATUS_BIT = 4,
IPCT_STATUS = (1 << IPCT_STATUS_BIT),
/* Update of protocol info */
IPCT_PROTOINFO_BIT = 5,
IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
/* Volatile protocol info */
IPCT_PROTOINFO_VOLATILE_BIT = 6,
IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
/* New helper for conntrack */
IPCT_HELPER_BIT = 7,
IPCT_HELPER = (1 << IPCT_HELPER_BIT),
/* Update of helper info */
IPCT_HELPINFO_BIT = 8,
IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
/* Volatile helper info */
IPCT_HELPINFO_VOLATILE_BIT = 9,
IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
/* NAT info */ #include <linux/netfilter/nf_conntrack_common.h>
IPCT_NATINFO_BIT = 10,
IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
/* Counter highest bit has been set */
IPCT_COUNTER_FILLING_BIT = 11,
IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
};
enum ip_conntrack_expect_events {
IPEXP_NEW_BIT = 0,
IPEXP_NEW = (1 << IPEXP_NEW_BIT),
};
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/config.h> #include <linux/config.h>
...@@ -194,12 +69,6 @@ do { \ ...@@ -194,12 +69,6 @@ do { \
#define IP_NF_ASSERT(x) #define IP_NF_ASSERT(x)
#endif #endif
struct ip_conntrack_counter
{
u_int32_t packets;
u_int32_t bytes;
};
struct ip_conntrack_helper; struct ip_conntrack_helper;
struct ip_conntrack struct ip_conntrack
...@@ -426,25 +295,6 @@ static inline int is_dying(struct ip_conntrack *ct) ...@@ -426,25 +295,6 @@ static inline int is_dying(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 error;
unsigned int expect_new;
unsigned int expect_create;
unsigned int expect_delete;
};
#define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++) #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
#ifdef CONFIG_IP_NF_CONNTRACK_EVENTS #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
......
#ifndef _IP_CONNTRACK_FTP_H #ifndef _IP_CONNTRACK_FTP_H
#define _IP_CONNTRACK_FTP_H #define _IP_CONNTRACK_FTP_H
/* FTP tracking. */
#ifdef __KERNEL__ #include <linux/netfilter/nf_conntrack_ftp.h>
#define FTP_PORT 21
#endif /* __KERNEL__ */
enum ip_ct_ftp_type
{
/* PORT command from client */
IP_CT_FTP_PORT,
/* PASV response from server */
IP_CT_FTP_PASV,
/* EPRT command from client */
IP_CT_FTP_EPRT,
/* EPSV response from server */
IP_CT_FTP_EPSV,
};
#define NUM_SEQ_TO_REMEMBER 2
/* This structure exists only once per master */
struct ip_ct_ftp_master {
/* Valid seq positions for cmd matching after newline */
u_int32_t seq_aft_nl[IP_CT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
/* 0 means seq_match_aft_nl not set */
int seq_aft_nl_num[IP_CT_DIR_MAX];
};
struct ip_conntrack_expect;
/* For NAT to hook in when we find a packet which describes what other
* connection we should expect. */
extern unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
enum ip_ct_ftp_type type,
unsigned int matchoff,
unsigned int matchlen,
struct ip_conntrack_expect *exp,
u32 *seq);
#endif /* _IP_CONNTRACK_FTP_H */ #endif /* _IP_CONNTRACK_FTP_H */
#ifndef _IP_CONNTRACK_ICMP_H #ifndef _IP_CONNTRACK_ICMP_H
#define _IP_CONNTRACK_ICMP_H #define _IP_CONNTRACK_ICMP_H
/* ICMP tracking. */
#include <asm/atomic.h>
struct ip_ct_icmp #include <net/netfilter/ipv4/nf_conntrack_icmp.h>
{
/* Optimization: when number in == number out, forget immediately. */
atomic_t count;
};
#endif /* _IP_CONNTRACK_ICMP_H */ #endif /* _IP_CONNTRACK_ICMP_H */
#ifndef _IP_CONNTRACK_SCTP_H #ifndef _IP_CONNTRACK_SCTP_H
#define _IP_CONNTRACK_SCTP_H #define _IP_CONNTRACK_SCTP_H
/* SCTP tracking. */
enum sctp_conntrack { #include <linux/netfilter/nf_conntrack_sctp.h>
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 */ #endif /* _IP_CONNTRACK_SCTP_H */
#ifndef _IP_CONNTRACK_TCP_H #ifndef _IP_CONNTRACK_TCP_H
#define _IP_CONNTRACK_TCP_H #define _IP_CONNTRACK_TCP_H
/* TCP tracking. */
enum tcp_conntrack { #include <linux/netfilter/nf_conntrack_tcp.h>
TCP_CONNTRACK_NONE,
TCP_CONNTRACK_SYN_SENT,
TCP_CONNTRACK_SYN_RECV,
TCP_CONNTRACK_ESTABLISHED,
TCP_CONNTRACK_FIN_WAIT,
TCP_CONNTRACK_CLOSE_WAIT,
TCP_CONNTRACK_LAST_ACK,
TCP_CONNTRACK_TIME_WAIT,
TCP_CONNTRACK_CLOSE,
TCP_CONNTRACK_LISTEN,
TCP_CONNTRACK_MAX,
TCP_CONNTRACK_IGNORE
};
/* Window scaling is advertised by the sender */
#define IP_CT_TCP_FLAG_WINDOW_SCALE 0x01
/* SACK is permitted by the sender */
#define IP_CT_TCP_FLAG_SACK_PERM 0x02
/* This sender sent FIN first */
#define IP_CT_TCP_FLAG_CLOSE_INIT 0x03
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 options */
};
struct ip_ct_tcp
{
struct ip_ct_tcp_state seen[2]; /* connection parameters per direction */
u_int8_t state; /* state of the connection (enum tcp_conntrack) */
/* For detecting stale connections */
u_int8_t last_dir; /* Direction of the last packet (enum ip_conntrack_dir) */
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_ack; /* Last sequence number seen in opposite dir */
u_int32_t last_end; /* Last seq + len */
};
#endif /* _IP_CONNTRACK_TCP_H */ #endif /* _IP_CONNTRACK_TCP_H */
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _IP_CONNTRACK_TUPLE_H #define _IP_CONNTRACK_TUPLE_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
/* A `tuple' is a structure containing the information to uniquely /* A `tuple' is a structure containing the information to uniquely
identify a connection. ie. if two packets have the same tuple, they identify a connection. ie. if two packets have the same tuple, they
...@@ -88,13 +89,6 @@ struct ip_conntrack_tuple ...@@ -88,13 +89,6 @@ struct ip_conntrack_tuple
(tuple)->dst.u.all = 0; \ (tuple)->dst.u.all = 0; \
} while (0) } while (0)
enum ip_conntrack_dir
{
IP_CT_DIR_ORIGINAL,
IP_CT_DIR_REPLY,
IP_CT_DIR_MAX
};
#ifdef __KERNEL__ #ifdef __KERNEL__
#define DUMP_TUPLE(tp) \ #define DUMP_TUPLE(tp) \
...@@ -103,8 +97,6 @@ DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \ ...@@ -103,8 +97,6 @@ DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n", \
NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \ NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all), \
NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all)) NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
/* If we're the first tuple, it's the original dir. */ /* If we're the first tuple, it's the original dir. */
#define DIRECTION(h) ((enum ip_conntrack_dir)(h)->tuple.dst.dir) #define DIRECTION(h) ((enum ip_conntrack_dir)(h)->tuple.dst.dir)
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
enum nf_ip6_hook_priorities { enum nf_ip6_hook_priorities {
NF_IP6_PRI_FIRST = INT_MIN, NF_IP6_PRI_FIRST = INT_MIN,
NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
NF_IP6_PRI_SELINUX_FIRST = -225, NF_IP6_PRI_SELINUX_FIRST = -225,
NF_IP6_PRI_CONNTRACK = -200, NF_IP6_PRI_CONNTRACK = -200,
NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175, NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
......
...@@ -71,7 +71,8 @@ struct nlmsghdr ...@@ -71,7 +71,8 @@ struct nlmsghdr
#define NLMSG_ALIGNTO 4 #define NLMSG_ALIGNTO 4
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) ) #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr))) #define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0))) #define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ #define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
...@@ -86,6 +87,8 @@ struct nlmsghdr ...@@ -86,6 +87,8 @@ struct nlmsghdr
#define NLMSG_DONE 0x3 /* End of a dump */ #define NLMSG_DONE 0x3 /* End of a dump */
#define NLMSG_OVERRUN 0x4 /* Data lost */ #define NLMSG_OVERRUN 0x4 /* Data lost */
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
struct nlmsgerr struct nlmsgerr
{ {
int error; int error;
...@@ -108,6 +111,25 @@ enum { ...@@ -108,6 +111,25 @@ enum {
NETLINK_CONNECTED, NETLINK_CONNECTED,
}; };
/*
* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
* +---------------------+- - -+- - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |
* | (struct nlattr) | ing | | ing |
* +---------------------+- - -+- - - - - - - - - -+- - -+
* <-------------- nlattr->nla_len -------------->
*/
struct nlattr
{
__u16 nla_len;
__u16 nla_type;
};
#define NLA_ALIGNTO 4
#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/capability.h> #include <linux/capability.h>
......
...@@ -274,6 +274,9 @@ struct sk_buff { ...@@ -274,6 +274,9 @@ struct sk_buff {
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
__u8 ipvs_property:1; __u8 ipvs_property:1;
#endif #endif
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct sk_buff *nfct_reasm;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge; struct nf_bridge_info *nf_bridge;
#endif #endif
...@@ -1313,10 +1316,26 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct) ...@@ -1313,10 +1316,26 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
if (nfct) if (nfct)
atomic_inc(&nfct->use); atomic_inc(&nfct->use);
} }
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
{
if (skb)
atomic_inc(&skb->users);
}
static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
{
if (skb)
kfree_skb(skb);
}
#endif
static inline void nf_reset(struct sk_buff *skb) static inline void nf_reset(struct sk_buff *skb)
{ {
nf_conntrack_put(skb->nfct); nf_conntrack_put(skb->nfct);
skb->nfct = NULL; skb->nfct = NULL;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put_reasm(skb->nfct_reasm);
skb->nfct_reasm = NULL;
#endif
} }
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
......
...@@ -205,6 +205,7 @@ enum ...@@ -205,6 +205,7 @@ enum
NET_ECONET=16, NET_ECONET=16,
NET_SCTP=17, NET_SCTP=17,
NET_LLC=18, NET_LLC=18,
NET_NETFILTER=19,
}; };
/* /proc/sys/kernel/random */ /* /proc/sys/kernel/random */
...@@ -270,6 +271,42 @@ enum ...@@ -270,6 +271,42 @@ enum
NET_UNIX_MAX_DGRAM_QLEN=3, NET_UNIX_MAX_DGRAM_QLEN=3,
}; };
/* /proc/sys/net/netfilter */
enum
{
NET_NF_CONNTRACK_MAX=1,
NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT=2,
NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV=3,
NET_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED=4,
NET_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT=5,
NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT=6,
NET_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK=7,
NET_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT=8,
NET_NF_CONNTRACK_TCP_TIMEOUT_CLOSE=9,
NET_NF_CONNTRACK_UDP_TIMEOUT=10,
NET_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11,
NET_NF_CONNTRACK_ICMP_TIMEOUT=12,
NET_NF_CONNTRACK_GENERIC_TIMEOUT=13,
NET_NF_CONNTRACK_BUCKETS=14,
NET_NF_CONNTRACK_LOG_INVALID=15,
NET_NF_CONNTRACK_TCP_TIMEOUT_MAX_RETRANS=16,
NET_NF_CONNTRACK_TCP_LOOSE=17,
NET_NF_CONNTRACK_TCP_BE_LIBERAL=18,
NET_NF_CONNTRACK_TCP_MAX_RETRANS=19,
NET_NF_CONNTRACK_SCTP_TIMEOUT_CLOSED=20,
NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_WAIT=21,
NET_NF_CONNTRACK_SCTP_TIMEOUT_COOKIE_ECHOED=22,
NET_NF_CONNTRACK_SCTP_TIMEOUT_ESTABLISHED=23,
NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT=24,
NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
NET_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
NET_NF_CONNTRACK_COUNT=27,
NET_NF_CONNTRACK_ICMPV6_TIMEOUT=28,
NET_NF_CONNTRACK_FRAG6_TIMEOUT=29,
NET_NF_CONNTRACK_FRAG6_LOW_THRESH=30,
NET_NF_CONNTRACK_FRAG6_HIGH_THRESH=31,
};
/* /proc/sys/net/ipv4 */ /* /proc/sys/net/ipv4 */
enum enum
{ {
......
#ifndef __NET_GENERIC_NETLINK_H
#define __NET_GENERIC_NETLINK_H
#include <linux/genetlink.h>
#include <net/netlink.h>
/**
* struct genl_family - generic netlink family
* @id: protocol family idenfitier
* @hdrsize: length of user specific header in bytes
* @name: name of family
* @version: protocol version
* @maxattr: maximum number of attributes supported
* @attrbuf: buffer to store parsed attributes
* @ops_list: list of all assigned operations
* @family_list: family list
*/
struct genl_family
{
unsigned int id;
unsigned int hdrsize;
char name[GENL_NAMSIZ];
unsigned int version;
unsigned int maxattr;
struct module * owner;
struct nlattr ** attrbuf; /* private */
struct list_head ops_list; /* private */
struct list_head family_list; /* private */
};
#define GENL_ADMIN_PERM 0x01
/**
* struct genl_info - receiving information
* @snd_seq: sending sequence number
* @snd_pid: netlink pid of sender
* @nlhdr: netlink message header
* @genlhdr: generic netlink message header
* @userhdr: user specific header
* @attrs: netlink attributes
*/
struct genl_info
{
u32 snd_seq;
u32 snd_pid;
struct nlmsghdr * nlhdr;
struct genlmsghdr * genlhdr;
void * userhdr;
struct nlattr ** attrs;
};
/**
* struct genl_ops - generic netlink operations
* @cmd: command identifier
* @flags: flags
* @policy: attribute validation policy
* @doit: standard command callback
* @dumpit: callback for dumpers
* @ops_list: operations list
*/
struct genl_ops
{
unsigned int cmd;
unsigned int flags;
struct nla_policy *policy;
int (*doit)(struct sk_buff *skb,
struct genl_info *info);
int (*dumpit)(struct sk_buff *skb,
struct netlink_callback *cb);
struct list_head ops_list;
};
extern int genl_register_family(struct genl_family *family);
extern int genl_unregister_family(struct genl_family *family);
extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
extern struct sock *genl_sock;
/**
* genlmsg_put - Add generic netlink header to netlink message
* @skb: socket buffer holding the message
* @pid: netlink pid the message is addressed to
* @seq: sequence number (usually the one of the sender)
* @type: netlink message type
* @hdrlen: length of the user specific header
* @flags netlink message flags
* @cmd: generic netlink command
* @version: version
*
* Returns pointer to user specific header
*/
static inline void *genlmsg_put(struct sk_buff *skb, u32 pid, u32 seq,
int type, int hdrlen, int flags,
u8 cmd, u8 version)
{
struct nlmsghdr *nlh;
struct genlmsghdr *hdr;
nlh = nlmsg_put(skb, pid, seq, type, GENL_HDRLEN + hdrlen, flags);
if (nlh == NULL)
return NULL;
hdr = nlmsg_data(nlh);
hdr->cmd = cmd;
hdr->version = version;
hdr->reserved = 0;
return (char *) hdr + GENL_HDRLEN;
}
/**
* genlmsg_end - Finalize a generic netlink message
* @skb: socket buffer the message is stored in
* @hdr: user specific header
*/
static inline int genlmsg_end(struct sk_buff *skb, void *hdr)
{
return nlmsg_end(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_cancel - Cancel construction of a generic netlink message
* @skb: socket buffer the message is stored in
* @hdr: generic netlink message header
*/
static inline int genlmsg_cancel(struct sk_buff *skb, void *hdr)
{
return nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
}
/**
* genlmsg_multicast - multicast a netlink message
* @skb: netlink message as socket buffer
* @pid: own netlink pid to avoid sending to yourself
* @group: multicast group id
*/
static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid,
unsigned int group)
{
return nlmsg_multicast(genl_sock, skb, pid, group);
}
/**
* genlmsg_unicast - unicast a netlink message
* @skb: netlink message as socket buffer
* @pid: netlink pid of the destination socket
*/
static inline int genlmsg_unicast(struct sk_buff *skb, u32 pid)
{
return nlmsg_unicast(genl_sock, skb, pid);
}
#endif /* __NET_GENERIC_NETLINK_H */
#ifndef _NF_CONNTRACK_ICMP_H
#define _NF_CONNTRACK_ICMP_H
/* ICMP tracking. */
#include <asm/atomic.h>
struct ip_ct_icmp
{
/* Optimization: when number in == number out, forget immediately. */
atomic_t count;
};
#endif /* _NF_CONNTRACK_ICMP_H */
/*
* IPv4 support for nf_conntrack.
*
* 23 Mar 2004: Yasuyuki Kozakai @ USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - move L3 protocol dependent part from include/linux/netfilter_ipv4/
* ip_conntarck.h
*/
#ifndef _NF_CONNTRACK_IPV4_H
#define _NF_CONNTRACK_IPV4_H
#ifdef CONFIG_IP_NF_NAT_NEEDED
#include <linux/netfilter_ipv4/ip_nat.h>
/* per conntrack: nat application helper private data */
union ip_conntrack_nat_help {
/* insert nat helper private data here */
};
struct nf_conntrack_ipv4_nat {
struct ip_nat_info info;
union ip_conntrack_nat_help help;
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
int masq_index;
#endif
};
#endif /* CONFIG_IP_NF_NAT_NEEDED */
struct nf_conntrack_ipv4 {
#ifdef CONFIG_IP_NF_NAT_NEEDED
struct nf_conntrack_ipv4_nat *nat;
#endif
};
/* Returns new sk_buff, or NULL */
struct sk_buff *
nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
/* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */
extern void need_ip_conntrack(void);
#endif /*_NF_CONNTRACK_IPV4_H*/
/*
* ICMPv6 tracking.
*
* 21 Apl 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - separated from nf_conntrack_icmp.h
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_icmp.h
*/
#ifndef _NF_CONNTRACK_ICMPV6_H
#define _NF_CONNTRACK_ICMPV6_H
#include <asm/atomic.h>
#ifndef ICMPV6_NI_QUERY
#define ICMPV6_NI_QUERY 139
#endif
#ifndef ICMPV6_NI_REPLY
#define ICMPV6_NI_REPLY 140
#endif
struct nf_ct_icmpv6
{
/* Optimization: when number in == number out, forget immediately. */
atomic_t count;
};
#endif /* _NF_CONNTRACK_ICMPV6_H */
This diff is collapsed.
#ifndef _NF_CONNTRACK_COMPAT_H
#define _NF_CONNTRACK_COMPAT_H
#ifdef __KERNEL__
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
#include <linux/netfilter_ipv4/ip_conntrack.h>
#ifdef CONFIG_IP_NF_CONNTRACK_MARK
static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
u_int32_t *ctinfo)
{
struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
if (ct)
return &ct->mark;
else
return NULL;
}
#endif /* CONFIG_IP_NF_CONNTRACK_MARK */
#ifdef CONFIG_IP_NF_CT_ACCT
static inline struct ip_conntrack_counter *
nf_ct_get_counters(const struct sk_buff *skb)
{
enum ip_conntrack_info ctinfo;
struct ip_conntrack *ct = ip_conntrack_get(skb, &ctinfo);
if (ct)
return ct->counters;
else
return NULL;
}
#endif /* CONFIG_IP_NF_CT_ACCT */
static inline int nf_ct_is_untracked(const struct sk_buff *skb)
{
return (skb->nfct == &ip_conntrack_untracked.ct_general);
}
static inline void nf_ct_untrack(struct sk_buff *skb)
{
skb->nfct = &ip_conntrack_untracked.ct_general;
}
static inline int nf_ct_get_ctinfo(const struct sk_buff *skb,
enum ip_conntrack_info *ctinfo)
{
struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
return (ct != NULL);
}
#else /* CONFIG_IP_NF_CONNTRACK */
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/nf_conntrack.h>
#ifdef CONFIG_NF_CONNTRACK_MARK
static inline u_int32_t *nf_ct_get_mark(const struct sk_buff *skb,
u_int32_t *ctinfo)
{
struct nf_conn *ct = nf_ct_get(skb, ctinfo);
if (ct)
return &ct->mark;
else
return NULL;
}
#endif /* CONFIG_NF_CONNTRACK_MARK */
#ifdef CONFIG_NF_CT_ACCT
static inline struct ip_conntrack_counter *
nf_ct_get_counters(const struct sk_buff *skb)
{
enum ip_conntrack_info ctinfo;
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct)
return ct->counters;
else
return NULL;
}
#endif /* CONFIG_NF_CT_ACCT */
static inline int nf_ct_is_untracked(const struct sk_buff *skb)
{
return (skb->nfct == &nf_conntrack_untracked.ct_general);
}
static inline void nf_ct_untrack(struct sk_buff *skb)
{
skb->nfct = &nf_conntrack_untracked.ct_general;
}
static inline int nf_ct_get_ctinfo(const struct sk_buff *skb,
enum ip_conntrack_info *ctinfo)
{
struct nf_conn *ct = nf_ct_get(skb, ctinfo);
return (ct != NULL);
}
#endif /* CONFIG_IP_NF_CONNTRACK */
#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_COMPAT_H */
/*
* This header is used to share core functionality between the
* standalone connection tracking module, and the compatibility layer's use
* of connection tracking.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_core.h
*/
#ifndef _NF_CONNTRACK_CORE_H
#define _NF_CONNTRACK_CORE_H
#include <linux/netfilter.h>
/* This header is used to share core functionality between the
standalone connection tracking module, and the compatibility layer's use
of connection tracking. */
extern unsigned int nf_conntrack_in(int pf,
unsigned int hooknum,
struct sk_buff **pskb);
extern int nf_conntrack_init(void);
extern void nf_conntrack_cleanup(void);
struct nf_conntrack_l3proto;
extern struct nf_conntrack_l3proto *nf_ct_find_l3proto(u_int16_t pf);
/* Like above, but you already have conntrack read lock. */
extern struct nf_conntrack_l3proto *__nf_ct_find_l3proto(u_int16_t l3proto);
struct nf_conntrack_protocol;
extern int
nf_ct_get_tuple(const struct sk_buff *skb,
unsigned int nhoff,
unsigned int dataoff,
u_int16_t l3num,
u_int8_t protonum,
struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_protocol *protocol);
extern int
nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_protocol *protocol);
/* Find a connection corresponding to a tuple. */
extern struct nf_conntrack_tuple_hash *
nf_conntrack_find_get(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack);
extern int __nf_conntrack_confirm(struct sk_buff **pskb);
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
static inline int nf_conntrack_confirm(struct sk_buff **pskb)
{
struct nf_conn *ct = (struct nf_conn *)(*pskb)->nfct;
int ret = NF_ACCEPT;
if (ct) {
if (!nf_ct_is_confirmed(ct))
ret = __nf_conntrack_confirm(pskb);
nf_ct_deliver_cached_events(ct);
}
return ret;
}
extern void __nf_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb);
extern struct list_head *nf_conntrack_hash;
extern struct list_head nf_conntrack_expect_list;
extern rwlock_t nf_conntrack_lock ;
#endif /* _NF_CONNTRACK_CORE_H */
/*
* connection tracking helpers.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_helper.h
*/
#ifndef _NF_CONNTRACK_HELPER_H
#define _NF_CONNTRACK_HELPER_H
#include <net/netfilter/nf_conntrack.h>
struct module;
struct nf_conntrack_helper
{
struct list_head list; /* Internal use. */
const char *name; /* name of the module */
struct module *me; /* pointer to self */
unsigned int max_expected; /* Maximum number of concurrent
* expected connections */
unsigned int timeout; /* timeout for expecteds */
/* Mask of things we will help (compared against server response) */
struct nf_conntrack_tuple tuple;
struct nf_conntrack_tuple mask;
/* Function to call when data passes; return verdict, or -1 to
invalidate. */
int (*help)(struct sk_buff **pskb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info conntrackinfo);
};
extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
/* Allocate space for an expectation: this is mandatory before calling
nf_conntrack_expect_related. You will have to call put afterwards. */
extern struct nf_conntrack_expect *
nf_conntrack_expect_alloc(struct nf_conn *master);
extern void nf_conntrack_expect_put(struct nf_conntrack_expect *exp);
/* Add an expected connection: can have more than one per connection */
extern int nf_conntrack_expect_related(struct nf_conntrack_expect *exp);
extern void nf_conntrack_unexpect_related(struct nf_conntrack_expect *exp);
#endif /*_NF_CONNTRACK_HELPER_H*/
/*
* Copyright (C)2003,2004 USAGI/WIDE Project
*
* Header for use in defining a given L3 protocol for connection tracking.
*
* Author:
* Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
*
* Derived from include/netfilter_ipv4/ip_conntrack_protocol.h
*/
#ifndef _NF_CONNTRACK_L3PROTO_H
#define _NF_CONNTRACK_L3PROTO_H
#include <linux/seq_file.h>
#include <net/netfilter/nf_conntrack.h>
struct nf_conntrack_l3proto
{
/* Next pointer. */
struct list_head list;
/* L3 Protocol Family number. ex) PF_INET */
u_int16_t l3proto;
/* Protocol name */
const char *name;
/*
* Try to fill in the third arg: nhoff is offset of l3 proto
* hdr. Return true if possible.
*/
int (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple);
/*
* Invert the per-proto part of the tuple: ie. turn xmit into reply.
* Some packets can't be inverted: return 0 in that case.
*/
int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
/* Print out the per-protocol part of the tuple. */
int (*print_tuple)(struct seq_file *s,
const struct nf_conntrack_tuple *);
/* Print out the private part of the conntrack. */
int (*print_conntrack)(struct seq_file *s, const struct nf_conn *);
/* Returns verdict for packet, or -1 for invalid. */
int (*packet)(struct nf_conn *conntrack,
const struct sk_buff *skb,
enum ip_conntrack_info ctinfo);
/*
* Called when a new connection for this protocol found;
* returns TRUE if it's OK. If so, packet() called next.
*/
int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb);
/* Called when a conntrack entry is destroyed */
void (*destroy)(struct nf_conn *conntrack);
/*
* Called before tracking.
* *dataoff: offset of protocol header (TCP, UDP,...) in *pskb
* *protonum: protocol number
*/
int (*prepare)(struct sk_buff **pskb, unsigned int hooknum,
unsigned int *dataoff, u_int8_t *protonum);
u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
/* Module (if any) which this is connected to. */
struct module *me;
};
extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX];
/* Protocol registration. */
extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
static inline struct nf_conntrack_l3proto *
nf_ct_find_l3proto(u_int16_t l3proto)
{
return nf_ct_l3protos[l3proto];
}
/* Existing built-in protocols */
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
extern struct nf_conntrack_l3proto nf_conntrack_generic_l3proto;
#endif /*_NF_CONNTRACK_L3PROTO_H*/
/*
* Header for use in defining a given protocol for connection tracking.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalized L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h
*/
#ifndef _NF_CONNTRACK_PROTOCOL_H
#define _NF_CONNTRACK_PROTOCOL_H
#include <net/netfilter/nf_conntrack.h>
struct seq_file;
struct nf_conntrack_protocol
{
/* Next pointer. */
struct list_head list;
/* L3 Protocol number. */
u_int16_t l3proto;
/* Protocol number. */
u_int8_t proto;
/* Protocol name */
const char *name;
/* Try to fill in the third arg: dataoff is offset past network protocol
hdr. Return true if possible. */
int (*pkt_to_tuple)(const struct sk_buff *skb,
unsigned int dataoff,
struct nf_conntrack_tuple *tuple);
/* Invert the per-proto part of the tuple: ie. turn xmit into reply.
* Some packets can't be inverted: return 0 in that case.
*/
int (*invert_tuple)(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
/* Print out the per-protocol part of the tuple. Return like seq_* */
int (*print_tuple)(struct seq_file *s,
const struct nf_conntrack_tuple *);
/* Print out the private part of the conntrack. */
int (*print_conntrack)(struct seq_file *s, const struct nf_conn *);
/* Returns verdict for packet, or -1 for invalid. */
int (*packet)(struct nf_conn *conntrack,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
int pf,
unsigned int hooknum);
/* Called when a new connection for this protocol found;
* returns TRUE if it's OK. If so, packet() called next. */
int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb,
unsigned int dataoff);
/* Called when a conntrack entry is destroyed */
void (*destroy)(struct nf_conn *conntrack);
int (*error)(struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo,
int pf, unsigned int hooknum);
/* Module (if any) which this is connected to. */
struct module *me;
};
/* Existing built-in protocols */
extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6;
extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6;
extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
#define MAX_NF_CT_PROTO 256
extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
extern struct nf_conntrack_protocol *
nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol);
/* Protocol registration. */
extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
/* Log invalid packets */
extern unsigned int nf_ct_log_invalid;
#ifdef CONFIG_SYSCTL
#ifdef DEBUG_INVALID_PACKETS
#define LOG_INVALID(proto) \
(nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW)
#else
#define LOG_INVALID(proto) \
((nf_ct_log_invalid == (proto) || nf_ct_log_invalid == IPPROTO_RAW) \
&& net_ratelimit())
#endif
#else
#define LOG_INVALID(proto) 0
#endif /* CONFIG_SYSCTL */
#endif /*_NF_CONNTRACK_PROTOCOL_H*/
/*
* Definitions and Declarations for tuple.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
*/
#ifndef _NF_CONNTRACK_TUPLE_H
#define _NF_CONNTRACK_TUPLE_H
#include <linux/netfilter/nf_conntrack_tuple_common.h>
/* A `tuple' is a structure containing the information to uniquely
identify a connection. ie. if two packets have the same tuple, they
are in the same connection; if not, they are not.
We divide the structure along "manipulatable" and
"non-manipulatable" lines, for the benefit of the NAT code.
*/
#define NF_CT_TUPLE_L3SIZE 4
/* The l3 protocol-specific manipulable parts of the tuple: always in
network order! */
union nf_conntrack_man_l3proto {
u_int32_t all[NF_CT_TUPLE_L3SIZE];
u_int32_t ip;
u_int32_t ip6[4];
};
/* The protocol-specific manipulable parts of the tuple: always in
network order! */
union nf_conntrack_man_proto
{
/* Add other protocols here. */
u_int16_t all;
struct {
u_int16_t port;
} tcp;
struct {
u_int16_t port;
} udp;
struct {
u_int16_t id;
} icmp;
struct {
u_int16_t port;
} sctp;
};
/* The manipulable part of the tuple. */
struct nf_conntrack_man
{
union nf_conntrack_man_l3proto u3;
union nf_conntrack_man_proto u;
/* Layer 3 protocol */
u_int16_t l3num;
};
/* This contains the information to distinguish a connection. */
struct nf_conntrack_tuple
{
struct nf_conntrack_man src;
/* These are the parts of the tuple which are fixed. */
struct {
union {
u_int32_t all[NF_CT_TUPLE_L3SIZE];
u_int32_t ip;
u_int32_t ip6[4];
} u3;
union {
/* Add other protocols here. */
u_int16_t all;
struct {
u_int16_t port;
} tcp;
struct {
u_int16_t port;
} udp;
struct {
u_int8_t type, code;
} icmp;
struct {
u_int16_t port;
} sctp;
} u;
/* The protocol. */
u_int8_t protonum;
/* The direction (for tuplehash) */
u_int8_t dir;
} dst;
};
/* This is optimized opposed to a memset of the whole structure. Everything we
* really care about is the source/destination unions */
#define NF_CT_TUPLE_U_BLANK(tuple) \
do { \
(tuple)->src.u.all = 0; \
(tuple)->dst.u.all = 0; \
memset(&(tuple)->src.u3, 0, sizeof((tuple)->src.u3)); \
memset(&(tuple)->dst.u3, 0, sizeof((tuple)->dst.u3)); \
} while (0)
#ifdef __KERNEL__
#define NF_CT_DUMP_TUPLE(tp) \
DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \
(tp), (tp)->src.l3num, (tp)->dst.protonum, \
NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \
NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all))
/* If we're the first tuple, it's the original dir. */
#define NF_CT_DIRECTION(h) \
((enum ip_conntrack_dir)(h)->tuple.dst.dir)
/* Connections have two entries in the hash table: one for each way */
struct nf_conntrack_tuple_hash
{
struct list_head list;
struct nf_conntrack_tuple tuple;
};
#endif /* __KERNEL__ */
static inline int nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return (t1->src.u3.all[0] == t2->src.u3.all[0] &&
t1->src.u3.all[1] == t2->src.u3.all[1] &&
t1->src.u3.all[2] == t2->src.u3.all[2] &&
t1->src.u3.all[3] == t2->src.u3.all[3] &&
t1->src.u.all == t2->src.u.all &&
t1->src.l3num == t2->src.l3num &&
t1->dst.protonum == t2->dst.protonum);
}
static inline int nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return (t1->dst.u3.all[0] == t2->dst.u3.all[0] &&
t1->dst.u3.all[1] == t2->dst.u3.all[1] &&
t1->dst.u3.all[2] == t2->dst.u3.all[2] &&
t1->dst.u3.all[3] == t2->dst.u3.all[3] &&
t1->dst.u.all == t2->dst.u.all &&
t1->src.l3num == t2->src.l3num &&
t1->dst.protonum == t2->dst.protonum);
}
static inline int nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return nf_ct_tuple_src_equal(t1, t2) && nf_ct_tuple_dst_equal(t1, t2);
}
static inline int nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *mask)
{
int count = 0;
for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
if ((t->src.u3.all[count] ^ tuple->src.u3.all[count]) &
mask->src.u3.all[count])
return 0;
}
for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++){
if ((t->dst.u3.all[count] ^ tuple->dst.u3.all[count]) &
mask->dst.u3.all[count])
return 0;
}
if ((t->src.u.all ^ tuple->src.u.all) & mask->src.u.all ||
(t->dst.u.all ^ tuple->dst.u.all) & mask->dst.u.all ||
(t->src.l3num ^ tuple->src.l3num) & mask->src.l3num ||
(t->dst.protonum ^ tuple->dst.protonum) & mask->dst.protonum)
return 0;
return 1;
}
#endif /* _NF_CONNTRACK_TUPLE_H */
This diff is collapsed.
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <net/udp.h> #include <net/udp.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/netlink.h>
DECLARE_MUTEX(rtnl_sem); DECLARE_MUTEX(rtnl_sem);
...@@ -462,11 +463,6 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) ...@@ -462,11 +463,6 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL); netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL);
} }
static int rtnetlink_done(struct netlink_callback *cb)
{
return 0;
}
/* Protected by RTNL sempahore. */ /* Protected by RTNL sempahore. */
static struct rtattr **rta_buf; static struct rtattr **rta_buf;
static int rtattr_max; static int rtattr_max;
...@@ -524,8 +520,6 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) ...@@ -524,8 +520,6 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
} }
if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
u32 rlen;
if (link->dumpit == NULL) if (link->dumpit == NULL)
link = &(rtnetlink_links[PF_UNSPEC][type]); link = &(rtnetlink_links[PF_UNSPEC][type]);
...@@ -533,14 +527,11 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) ...@@ -533,14 +527,11 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
goto err_inval; goto err_inval;
if ((*errp = netlink_dump_start(rtnl, skb, nlh, if ((*errp = netlink_dump_start(rtnl, skb, nlh,
link->dumpit, link->dumpit, NULL)) != 0) {
rtnetlink_done)) != 0) {
return -1; return -1;
} }
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len) netlink_queue_skip(nlh, skb);
rlen = skb->len;
skb_pull(skb, rlen);
return -1; return -1;
} }
...@@ -579,75 +570,13 @@ err_inval: ...@@ -579,75 +570,13 @@ err_inval:
return -1; return -1;
} }
/*
* Process one packet of messages.
* Malformed skbs with wrong lengths of messages are discarded silently.
*/
static inline int rtnetlink_rcv_skb(struct sk_buff *skb)
{
int err;
struct nlmsghdr * nlh;
while (skb->len >= NLMSG_SPACE(0)) {
u32 rlen;
nlh = (struct nlmsghdr *)skb->data;
if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
return 0;
rlen = NLMSG_ALIGN(nlh->nlmsg_len);
if (rlen > skb->len)
rlen = skb->len;
if (rtnetlink_rcv_msg(skb, nlh, &err)) {
/* Not error, but we must interrupt processing here:
* Note, that in this case we do not pull message
* from skb, it will be processed later.
*/
if (err == 0)
return -1;
netlink_ack(skb, nlh, err);
} else if (nlh->nlmsg_flags&NLM_F_ACK)
netlink_ack(skb, nlh, 0);
skb_pull(skb, rlen);
}
return 0;
}
/*
* rtnetlink input queue processing routine:
* - process as much as there was in the queue upon entry.
* - feed skbs to rtnetlink_rcv_skb, until it refuse a message,
* that will occur, when a dump started.
*/
static void rtnetlink_rcv(struct sock *sk, int len) static void rtnetlink_rcv(struct sock *sk, int len)
{ {
unsigned int qlen = skb_queue_len(&sk->sk_receive_queue); unsigned int qlen = 0;
do { do {
struct sk_buff *skb;
rtnl_lock(); rtnl_lock();
netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg);
if (qlen > skb_queue_len(&sk->sk_receive_queue))
qlen = skb_queue_len(&sk->sk_receive_queue);
for (; qlen; qlen--) {
skb = skb_dequeue(&sk->sk_receive_queue);
if (rtnetlink_rcv_skb(skb)) {
if (skb->len)
skb_queue_head(&sk->sk_receive_queue,
skb);
else {
kfree_skb(skb);
qlen--;
}
break;
}
kfree_skb(skb);
}
up(&rtnl_sem); up(&rtnl_sem);
netdev_run_todo(); netdev_run_todo();
......
...@@ -336,6 +336,9 @@ void __kfree_skb(struct sk_buff *skb) ...@@ -336,6 +336,9 @@ void __kfree_skb(struct sk_buff *skb)
} }
#ifdef CONFIG_NETFILTER #ifdef CONFIG_NETFILTER
nf_conntrack_put(skb->nfct); nf_conntrack_put(skb->nfct);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put_reasm(skb->nfct_reasm);
#endif
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(skb->nf_bridge); nf_bridge_put(skb->nf_bridge);
#endif #endif
...@@ -414,9 +417,17 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) ...@@ -414,9 +417,17 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
C(nfct); C(nfct);
nf_conntrack_get(skb->nfct); nf_conntrack_get(skb->nfct);
C(nfctinfo); C(nfctinfo);
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
C(nfct_reasm);
nf_conntrack_get_reasm(skb->nfct_reasm);
#endif
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
C(ipvs_property); C(ipvs_property);
#endif #endif
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
C(nfct_reasm);
nf_conntrack_get_reasm(skb->nfct_reasm);
#endif
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
C(nf_bridge); C(nf_bridge);
nf_bridge_get(skb->nf_bridge); nf_bridge_get(skb->nf_bridge);
...@@ -474,6 +485,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) ...@@ -474,6 +485,10 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->nfct = old->nfct; new->nfct = old->nfct;
nf_conntrack_get(old->nfct); nf_conntrack_get(old->nfct);
new->nfctinfo = old->nfctinfo; new->nfctinfo = old->nfctinfo;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
new->nfct_reasm = old->nfct_reasm;
nf_conntrack_get_reasm(old->nfct_reasm);
#endif
#if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE) #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
new->ipvs_property = old->ipvs_property; new->ipvs_property = old->ipvs_property;
#endif #endif
......
...@@ -724,12 +724,6 @@ done: ...@@ -724,12 +724,6 @@ done:
return skb->len; return skb->len;
} }
static int inet_diag_dump_done(struct netlink_callback *cb)
{
return 0;
}
static __inline__ int static __inline__ int
inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{ {
...@@ -760,8 +754,7 @@ inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -760,8 +754,7 @@ inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
goto err_inval; goto err_inval;
} }
return netlink_dump_start(idiagnl, skb, nlh, return netlink_dump_start(idiagnl, skb, nlh,
inet_diag_dump, inet_diag_dump, NULL);
inet_diag_dump_done);
} else { } else {
return inet_diag_get_exact(skb, nlh); return inet_diag_get_exact(skb, nlh);
} }
......
...@@ -5,6 +5,20 @@ ...@@ -5,6 +5,20 @@
menu "IP: Netfilter Configuration" menu "IP: Netfilter Configuration"
depends on INET && NETFILTER depends on INET && NETFILTER
config NF_CONNTRACK_IPV4
tristate "IPv4 support for new connection tracking (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
into connections.
This is IPv4 support on Layer 3 independent connection tracking.
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
To compile it as a module, choose M here. If unsure, say N.
# connection tracking, helpers and protocols # connection tracking, helpers and protocols
config IP_NF_CONNTRACK config IP_NF_CONNTRACK
tristate "Connection tracking (required for masq/NAT)" tristate "Connection tracking (required for masq/NAT)"
...@@ -209,8 +223,8 @@ config IP_NF_MATCH_PKTTYPE ...@@ -209,8 +223,8 @@ config IP_NF_MATCH_PKTTYPE
tristate "Packet type match support" tristate "Packet type match support"
depends on IP_NF_IPTABLES depends on IP_NF_IPTABLES
help help
Packet type matching allows you to match a packet by Packet type matching allows you to match a packet by
its "class", eg. BROADCAST, MULTICAST, ... its "class", eg. BROADCAST, MULTICAST, ...
Typical usage: Typical usage:
iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
...@@ -317,7 +331,8 @@ config IP_NF_MATCH_TCPMSS ...@@ -317,7 +331,8 @@ config IP_NF_MATCH_TCPMSS
config IP_NF_MATCH_HELPER config IP_NF_MATCH_HELPER
tristate "Helper match support" tristate "Helper match support"
depends on IP_NF_CONNTRACK && IP_NF_IPTABLES depends on IP_NF_IPTABLES
depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
help help
Helper matching allows you to match packets in dynamic connections Helper matching allows you to match packets in dynamic connections
tracked by a conntrack-helper, ie. ip_conntrack_ftp tracked by a conntrack-helper, ie. ip_conntrack_ftp
...@@ -326,7 +341,8 @@ config IP_NF_MATCH_HELPER ...@@ -326,7 +341,8 @@ config IP_NF_MATCH_HELPER
config IP_NF_MATCH_STATE config IP_NF_MATCH_STATE
tristate "Connection state match support" tristate "Connection state match support"
depends on IP_NF_CONNTRACK && IP_NF_IPTABLES depends on IP_NF_IPTABLES
depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
help help
Connection state matching allows you to match packets based on their Connection state matching allows you to match packets based on their
relationship to a tracked connection (ie. previous packets). This relationship to a tracked connection (ie. previous packets). This
...@@ -336,7 +352,8 @@ config IP_NF_MATCH_STATE ...@@ -336,7 +352,8 @@ config IP_NF_MATCH_STATE
config IP_NF_MATCH_CONNTRACK config IP_NF_MATCH_CONNTRACK
tristate "Connection tracking match support" tristate "Connection tracking match support"
depends on IP_NF_CONNTRACK && IP_NF_IPTABLES depends on IP_NF_IPTABLES
depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
help help
This is a general conntrack match module, a superset of the state match. This is a general conntrack match module, a superset of the state match.
...@@ -422,7 +439,8 @@ config IP_NF_MATCH_COMMENT ...@@ -422,7 +439,8 @@ config IP_NF_MATCH_COMMENT
config IP_NF_MATCH_CONNMARK config IP_NF_MATCH_CONNMARK
tristate 'Connection mark match support' tristate 'Connection mark match support'
depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES depends on IP_NF_IPTABLES
depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
help help
This option adds a `connmark' match, which allows you to match the This option adds a `connmark' match, which allows you to match the
connection mark value previously set for the session by `CONNMARK'. connection mark value previously set for the session by `CONNMARK'.
...@@ -433,7 +451,8 @@ config IP_NF_MATCH_CONNMARK ...@@ -433,7 +451,8 @@ config IP_NF_MATCH_CONNMARK
config IP_NF_MATCH_CONNBYTES config IP_NF_MATCH_CONNBYTES
tristate 'Connection byte/packet counter match support' tristate 'Connection byte/packet counter match support'
depends on IP_NF_CT_ACCT && IP_NF_IPTABLES depends on IP_NF_IPTABLES
depends on IP_NF_CT_ACCT || (NF_CT_ACCT && NF_CONNTRACK_IPV4)
help help
This option adds a `connbytes' match, which allows you to match the This option adds a `connbytes' match, which allows you to match the
number of bytes and/or packets for each direction within a connection. number of bytes and/or packets for each direction within a connection.
...@@ -747,7 +766,8 @@ config IP_NF_TARGET_TTL ...@@ -747,7 +766,8 @@ config IP_NF_TARGET_TTL
config IP_NF_TARGET_CONNMARK config IP_NF_TARGET_CONNMARK
tristate 'CONNMARK target support' tristate 'CONNMARK target support'
depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE depends on IP_NF_MANGLE
depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
help help
This option adds a `CONNMARK' target, which allows one to manipulate This option adds a `CONNMARK' target, which allows one to manipulate
the connection mark value. Similar to the MARK target, but the connection mark value. Similar to the MARK target, but
...@@ -759,7 +779,8 @@ config IP_NF_TARGET_CONNMARK ...@@ -759,7 +779,8 @@ config IP_NF_TARGET_CONNMARK
config IP_NF_TARGET_CLUSTERIP config IP_NF_TARGET_CLUSTERIP
tristate "CLUSTERIP target support (EXPERIMENTAL)" tristate "CLUSTERIP target support (EXPERIMENTAL)"
depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES && EXPERIMENTAL depends on IP_NF_IPTABLES && EXPERIMENTAL
depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
help help
The CLUSTERIP target allows you to build load-balancing clusters of The CLUSTERIP target allows you to build load-balancing clusters of
network servers without having a dedicated load-balancing network servers without having a dedicated load-balancing
...@@ -782,7 +803,7 @@ config IP_NF_RAW ...@@ -782,7 +803,7 @@ config IP_NF_RAW
config IP_NF_TARGET_NOTRACK config IP_NF_TARGET_NOTRACK
tristate 'NOTRACK target support' tristate 'NOTRACK target support'
depends on IP_NF_RAW depends on IP_NF_RAW
depends on IP_NF_CONNTRACK depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4
help help
The NOTRACK target allows a select rule to specify The NOTRACK target allows a select rule to specify
which packets *not* to enter the conntrack/NAT which packets *not* to enter the conntrack/NAT
......
...@@ -103,3 +103,9 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o ...@@ -103,3 +103,9 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o
obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
# objects for l3 independent conntrack
nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
# l3 independent conntrack
obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
...@@ -1376,7 +1376,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, ...@@ -1376,7 +1376,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
ip_conntrack_expect_put(exp); ip_conntrack_expect_put(exp);
} }
} }
write_unlock(&ip_conntrack_lock); write_unlock_bh(&ip_conntrack_lock);
} else { } else {
/* This basically means we have to flush everything*/ /* This basically means we have to flush everything*/
write_lock_bh(&ip_conntrack_lock); write_lock_bh(&ip_conntrack_lock);
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <net/netfilter/nf_conntrack_compat.h>
#define CLUSTERIP_VERSION "0.8" #define CLUSTERIP_VERSION "0.8"
...@@ -316,14 +316,14 @@ target(struct sk_buff **pskb, ...@@ -316,14 +316,14 @@ target(struct sk_buff **pskb,
{ {
const struct ipt_clusterip_tgt_info *cipinfo = targinfo; const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); u_int32_t *mark, hash;
u_int32_t hash;
/* don't need to clusterip_config_get() here, since refcount /* don't need to clusterip_config_get() here, since refcount
* is only decremented by destroy() - and ip_tables guarantees * is only decremented by destroy() - and ip_tables guarantees
* that the ->target() function isn't called after ->destroy() */ * that the ->target() function isn't called after ->destroy() */
if (!ct) { mark = nf_ct_get_mark((*pskb), &ctinfo);
if (mark == NULL) {
printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); printk(KERN_ERR "CLUSTERIP: no conntrack!\n");
/* FIXME: need to drop invalid ones, since replies /* FIXME: need to drop invalid ones, since replies
* to outgoing connections of other nodes will be * to outgoing connections of other nodes will be
...@@ -346,7 +346,7 @@ target(struct sk_buff **pskb, ...@@ -346,7 +346,7 @@ target(struct sk_buff **pskb,
switch (ctinfo) { switch (ctinfo) {
case IP_CT_NEW: case IP_CT_NEW:
ct->mark = hash; *mark = hash;
break; break;
case IP_CT_RELATED: case IP_CT_RELATED:
case IP_CT_RELATED+IP_CT_IS_REPLY: case IP_CT_RELATED+IP_CT_IS_REPLY:
...@@ -363,7 +363,7 @@ target(struct sk_buff **pskb, ...@@ -363,7 +363,7 @@ target(struct sk_buff **pskb,
#ifdef DEBUG_CLUSTERP #ifdef DEBUG_CLUSTERP
DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
#endif #endif
DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark); DEBUGP("hash=%u ct_hash=%u ", hash, *mark);
if (!clusterip_responsible(cipinfo->config, hash)) { if (!clusterip_responsible(cipinfo->config, hash)) {
DEBUGP("not responsible\n"); DEBUGP("not responsible\n");
return NF_DROP; return NF_DROP;
......
...@@ -29,7 +29,7 @@ MODULE_LICENSE("GPL"); ...@@ -29,7 +29,7 @@ MODULE_LICENSE("GPL");
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_CONNMARK.h> #include <linux/netfilter_ipv4/ipt_CONNMARK.h>
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <net/netfilter/nf_conntrack_compat.h>
static unsigned int static unsigned int
target(struct sk_buff **pskb, target(struct sk_buff **pskb,
...@@ -43,24 +43,24 @@ target(struct sk_buff **pskb, ...@@ -43,24 +43,24 @@ target(struct sk_buff **pskb,
u_int32_t diff; u_int32_t diff;
u_int32_t nfmark; u_int32_t nfmark;
u_int32_t newmark; u_int32_t newmark;
u_int32_t ctinfo;
u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
enum ip_conntrack_info ctinfo; if (ctmark) {
struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
if (ct) {
switch(markinfo->mode) { switch(markinfo->mode) {
case IPT_CONNMARK_SET: case IPT_CONNMARK_SET:
newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
if (newmark != ct->mark) if (newmark != *ctmark)
ct->mark = newmark; *ctmark = newmark;
break; break;
case IPT_CONNMARK_SAVE: case IPT_CONNMARK_SAVE:
newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
if (ct->mark != newmark) if (*ctmark != newmark)
ct->mark = newmark; *ctmark = newmark;
break; break;
case IPT_CONNMARK_RESTORE: case IPT_CONNMARK_RESTORE:
nfmark = (*pskb)->nfmark; nfmark = (*pskb)->nfmark;
diff = (ct->mark ^ nfmark) & markinfo->mask; diff = (*ctmark ^ nfmark) & markinfo->mask;
if (diff != 0) if (diff != 0)
(*pskb)->nfmark = nfmark ^ diff; (*pskb)->nfmark = nfmark ^ diff;
break; break;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <net/netfilter/nf_conntrack_compat.h>
static unsigned int static unsigned int
target(struct sk_buff **pskb, target(struct sk_buff **pskb,
...@@ -23,7 +23,7 @@ target(struct sk_buff **pskb, ...@@ -23,7 +23,7 @@ target(struct sk_buff **pskb,
If there is a real ct entry correspondig to this packet, If there is a real ct entry correspondig to this packet,
it'll hang aroun till timing out. We don't deal with it it'll hang aroun till timing out. We don't deal with it
for performance reasons. JK */ for performance reasons. JK */
(*pskb)->nfct = &ip_conntrack_untracked.ct_general; nf_ct_untrack(*pskb);
(*pskb)->nfctinfo = IP_CT_NEW; (*pskb)->nfctinfo = IP_CT_NEW;
nf_conntrack_get((*pskb)->nfct); nf_conntrack_get((*pskb)->nfct);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <net/netfilter/nf_conntrack_compat.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_connbytes.h> #include <linux/netfilter_ipv4/ipt_connbytes.h>
...@@ -46,60 +46,59 @@ match(const struct sk_buff *skb, ...@@ -46,60 +46,59 @@ match(const struct sk_buff *skb,
int *hotdrop) int *hotdrop)
{ {
const struct ipt_connbytes_info *sinfo = matchinfo; const struct ipt_connbytes_info *sinfo = matchinfo;
enum ip_conntrack_info ctinfo;
struct ip_conntrack *ct;
u_int64_t what = 0; /* initialize to make gcc happy */ u_int64_t what = 0; /* initialize to make gcc happy */
const struct ip_conntrack_counter *counters;
if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo))) if (!(counters = nf_ct_get_counters(skb)))
return 0; /* no match */ return 0; /* no match */
switch (sinfo->what) { switch (sinfo->what) {
case IPT_CONNBYTES_PKTS: case IPT_CONNBYTES_PKTS:
switch (sinfo->direction) { switch (sinfo->direction) {
case IPT_CONNBYTES_DIR_ORIGINAL: case IPT_CONNBYTES_DIR_ORIGINAL:
what = ct->counters[IP_CT_DIR_ORIGINAL].packets; what = counters[IP_CT_DIR_ORIGINAL].packets;
break; break;
case IPT_CONNBYTES_DIR_REPLY: case IPT_CONNBYTES_DIR_REPLY:
what = ct->counters[IP_CT_DIR_REPLY].packets; what = counters[IP_CT_DIR_REPLY].packets;
break; break;
case IPT_CONNBYTES_DIR_BOTH: case IPT_CONNBYTES_DIR_BOTH:
what = ct->counters[IP_CT_DIR_ORIGINAL].packets; what = counters[IP_CT_DIR_ORIGINAL].packets;
what += ct->counters[IP_CT_DIR_REPLY].packets; what += counters[IP_CT_DIR_REPLY].packets;
break; break;
} }
break; break;
case IPT_CONNBYTES_BYTES: case IPT_CONNBYTES_BYTES:
switch (sinfo->direction) { switch (sinfo->direction) {
case IPT_CONNBYTES_DIR_ORIGINAL: case IPT_CONNBYTES_DIR_ORIGINAL:
what = ct->counters[IP_CT_DIR_ORIGINAL].bytes; what = counters[IP_CT_DIR_ORIGINAL].bytes;
break; break;
case IPT_CONNBYTES_DIR_REPLY: case IPT_CONNBYTES_DIR_REPLY:
what = ct->counters[IP_CT_DIR_REPLY].bytes; what = counters[IP_CT_DIR_REPLY].bytes;
break; break;
case IPT_CONNBYTES_DIR_BOTH: case IPT_CONNBYTES_DIR_BOTH:
what = ct->counters[IP_CT_DIR_ORIGINAL].bytes; what = counters[IP_CT_DIR_ORIGINAL].bytes;
what += ct->counters[IP_CT_DIR_REPLY].bytes; what += counters[IP_CT_DIR_REPLY].bytes;
break; break;
} }
break; break;
case IPT_CONNBYTES_AVGPKT: case IPT_CONNBYTES_AVGPKT:
switch (sinfo->direction) { switch (sinfo->direction) {
case IPT_CONNBYTES_DIR_ORIGINAL: case IPT_CONNBYTES_DIR_ORIGINAL:
what = div64_64(ct->counters[IP_CT_DIR_ORIGINAL].bytes, what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
ct->counters[IP_CT_DIR_ORIGINAL].packets); counters[IP_CT_DIR_ORIGINAL].packets);
break; break;
case IPT_CONNBYTES_DIR_REPLY: case IPT_CONNBYTES_DIR_REPLY:
what = div64_64(ct->counters[IP_CT_DIR_REPLY].bytes, what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
ct->counters[IP_CT_DIR_REPLY].packets); counters[IP_CT_DIR_REPLY].packets);
break; break;
case IPT_CONNBYTES_DIR_BOTH: case IPT_CONNBYTES_DIR_BOTH:
{ {
u_int64_t bytes; u_int64_t bytes;
u_int64_t pkts; u_int64_t pkts;
bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes + bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
ct->counters[IP_CT_DIR_REPLY].bytes; counters[IP_CT_DIR_REPLY].bytes;
pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets+ pkts = counters[IP_CT_DIR_ORIGINAL].packets+
ct->counters[IP_CT_DIR_REPLY].packets; counters[IP_CT_DIR_REPLY].packets;
/* FIXME_THEORETICAL: what to do if sum /* FIXME_THEORETICAL: what to do if sum
* overflows ? */ * overflows ? */
......
...@@ -28,7 +28,7 @@ MODULE_LICENSE("GPL"); ...@@ -28,7 +28,7 @@ MODULE_LICENSE("GPL");
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_connmark.h> #include <linux/netfilter_ipv4/ipt_connmark.h>
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <net/netfilter/nf_conntrack_compat.h>
static int static int
match(const struct sk_buff *skb, match(const struct sk_buff *skb,
...@@ -39,12 +39,12 @@ match(const struct sk_buff *skb, ...@@ -39,12 +39,12 @@ match(const struct sk_buff *skb,
int *hotdrop) int *hotdrop)
{ {
const struct ipt_connmark_info *info = matchinfo; const struct ipt_connmark_info *info = matchinfo;
enum ip_conntrack_info ctinfo; u_int32_t ctinfo;
struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo);
if (!ct) if (!ctmark)
return 0; return 0;
return ((ct->mark & info->mask) == info->mark) ^ info->invert; return (((*ctmark) & info->mask) == info->mark) ^ info->invert;
} }
static int static int
......
...@@ -10,7 +10,14 @@ ...@@ -10,7 +10,14 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
#else
#include <net/netfilter/nf_conntrack.h>
#endif
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_conntrack.h> #include <linux/netfilter_ipv4/ipt_conntrack.h>
...@@ -18,6 +25,8 @@ MODULE_LICENSE("GPL"); ...@@ -18,6 +25,8 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
MODULE_DESCRIPTION("iptables connection tracking match module"); MODULE_DESCRIPTION("iptables connection tracking match module");
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
static int static int
match(const struct sk_buff *skb, match(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
...@@ -102,6 +111,93 @@ match(const struct sk_buff *skb, ...@@ -102,6 +111,93 @@ match(const struct sk_buff *skb,
return 1; return 1;
} }
#else /* CONFIG_IP_NF_CONNTRACK */
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_conntrack_info *sinfo = matchinfo;
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
unsigned int statebit;
ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
if (ct == &nf_conntrack_untracked)
statebit = IPT_CONNTRACK_STATE_UNTRACKED;
else if (ct)
statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
else
statebit = IPT_CONNTRACK_STATE_INVALID;
if(sinfo->flags & IPT_CONNTRACK_STATE) {
if (ct) {
if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip !=
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip)
statebit |= IPT_CONNTRACK_STATE_SNAT;
if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip !=
ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip)
statebit |= IPT_CONNTRACK_STATE_DNAT;
}
if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE))
return 0;
}
if(sinfo->flags & IPT_CONNTRACK_PROTO) {
if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO))
return 0;
}
if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) {
if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC))
return 0;
}
if(sinfo->flags & IPT_CONNTRACK_ORIGDST) {
if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST))
return 0;
}
if(sinfo->flags & IPT_CONNTRACK_REPLSRC) {
if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC))
return 0;
}
if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST))
return 0;
}
if(sinfo->flags & IPT_CONNTRACK_STATUS) {
if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS))
return 0;
}
if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
unsigned long expires;
if(!ct)
return 0;
expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES))
return 0;
}
return 1;
}
#endif /* CONFIG_NF_IP_CONNTRACK */
static int check(const char *tablename, static int check(const char *tablename,
const struct ipt_ip *ip, const struct ipt_ip *ip,
void *matchinfo, void *matchinfo,
......
...@@ -13,9 +13,15 @@ ...@@ -13,9 +13,15 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
#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_helper.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#else
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_helper.h>
#endif
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_helper.h> #include <linux/netfilter_ipv4/ipt_helper.h>
...@@ -29,6 +35,7 @@ MODULE_DESCRIPTION("iptables helper match module"); ...@@ -29,6 +35,7 @@ MODULE_DESCRIPTION("iptables helper match module");
#define DEBUGP(format, args...) #define DEBUGP(format, args...)
#endif #endif
#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
static int static int
match(const struct sk_buff *skb, match(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
...@@ -73,6 +80,53 @@ out_unlock: ...@@ -73,6 +80,53 @@ out_unlock:
return ret; return ret;
} }
#else /* CONFIG_IP_NF_CONNTRACK */
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_helper_info *info = matchinfo;
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
int ret = info->invert;
ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
if (!ct) {
DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
return ret;
}
if (!ct->master) {
DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
return ret;
}
read_lock_bh(&nf_conntrack_lock);
if (!ct->master->helper) {
DEBUGP("ipt_helper: master ct %p has no helper\n",
exp->expectant);
goto out_unlock;
}
DEBUGP("master's name = %s , info->name = %s\n",
ct->master->helper->name, info->name);
if (info->name[0] == '\0')
ret ^= 1;
else
ret ^= !strncmp(ct->master->helper->name, info->name,
strlen(ct->master->helper->name));
out_unlock:
read_unlock_bh(&nf_conntrack_lock);
return ret;
}
#endif
static int check(const char *tablename, static int check(const char *tablename,
const struct ipt_ip *ip, const struct ipt_ip *ip,
void *matchinfo, void *matchinfo,
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/netfilter_ipv4/ip_conntrack.h> #include <net/netfilter/nf_conntrack_compat.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_state.h> #include <linux/netfilter_ipv4/ipt_state.h>
...@@ -30,9 +30,9 @@ match(const struct sk_buff *skb, ...@@ -30,9 +30,9 @@ match(const struct sk_buff *skb,
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
unsigned int statebit; unsigned int statebit;
if (skb->nfct == &ip_conntrack_untracked.ct_general) if (nf_ct_is_untracked(skb))
statebit = IPT_STATE_UNTRACKED; statebit = IPT_STATE_UNTRACKED;
else if (!ip_conntrack_get(skb, &ctinfo)) else if (!nf_ct_get_ctinfo(skb, &ctinfo))
statebit = IPT_STATE_INVALID; statebit = IPT_STATE_INVALID;
else else
statebit = IPT_STATE_BIT(ctinfo); statebit = IPT_STATE_BIT(ctinfo);
......
This diff is collapsed.
/* (C) 1999-2001 Paul `Rusty' Russell
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - enable working with Layer 3 protocol independent connection tracking.
*
* Derived from net/ipv4/netfilter/ip_conntrack_proto_icmp.c
*/
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/netfilter.h>
#include <linux/in.h>
#include <linux/icmp.h>
#include <linux/seq_file.h>
#include <net/ip.h>
#include <net/checksum.h>
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_protocol.h>
#include <net/netfilter/nf_conntrack_core.h>
unsigned long nf_ct_icmp_timeout = 30*HZ;
#if 0
#define DEBUGP printk
#else
#define DEBUGP(format, args...)
#endif
static int icmp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
{
struct icmphdr _hdr, *hp;
hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
if (hp == NULL)
return 0;
tuple->dst.u.icmp.type = hp->type;
tuple->src.u.icmp.id = hp->un.echo.id;
tuple->dst.u.icmp.code = hp->code;
return 1;
}
static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
/* Add 1; spaces filled with 0. */
static u_int8_t invmap[]
= { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
[ICMP_ECHOREPLY] = ICMP_ECHO + 1,
[ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
[ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
[ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
[ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
[ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
if (orig->dst.u.icmp.type >= sizeof(invmap)
|| !invmap[orig->dst.u.icmp.type])
return 0;
tuple->src.u.icmp.id = orig->src.u.icmp.id;
tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1;
tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
return 1;
}
/* Print out the per-protocol part of the tuple. */
static int icmp_print_tuple(struct seq_file *s,
const struct nf_conntrack_tuple *tuple)
{
return seq_printf(s, "type=%u code=%u id=%u ",
tuple->dst.u.icmp.type,
tuple->dst.u.icmp.code,
ntohs(tuple->src.u.icmp.id));
}
/* Print out the private part of the conntrack. */
static int icmp_print_conntrack(struct seq_file *s,
const struct nf_conn *conntrack)
{
return 0;
}
/* Returns verdict for packet, or -1 for invalid. */
static int icmp_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
int pf,
unsigned int hooknum)
{
/* Try to delete connection immediately after all replies:
won't actually vanish as we still have skb, and del_timer
means this will only run once even if count hits zero twice
(theoretically possible with SMP) */
if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
if (atomic_dec_and_test(&ct->proto.icmp.count)
&& del_timer(&ct->timeout))
ct->timeout.function((unsigned long)ct);
} else {
atomic_inc(&ct->proto.icmp.count);
nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout);
}
return NF_ACCEPT;
}
/* Called when a new connection for this protocol found. */
static int icmp_new(struct nf_conn *conntrack,
const struct sk_buff *skb, unsigned int dataoff)
{
static u_int8_t valid_new[]
= { [ICMP_ECHO] = 1,
[ICMP_TIMESTAMP] = 1,
[ICMP_INFO_REQUEST] = 1,
[ICMP_ADDRESS] = 1 };
if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
|| !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
/* Can't create a new ICMP `conn' with this. */
DEBUGP("icmp: can't create new conn with type %u\n",
conntrack->tuplehash[0].tuple.dst.u.icmp.type);
NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
return 0;
}
atomic_set(&conntrack->proto.icmp.count, 0);
return 1;
}
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
static int
icmp_error_message(struct sk_buff *skb,
enum ip_conntrack_info *ctinfo,
unsigned int hooknum)
{
struct nf_conntrack_tuple innertuple, origtuple;
struct {
struct icmphdr icmp;
struct iphdr ip;
} _in, *inside;
struct nf_conntrack_protocol *innerproto;
struct nf_conntrack_tuple_hash *h;
int dataoff;
NF_CT_ASSERT(skb->nfct == NULL);
/* Not enough header? */
inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in);
if (inside == NULL)
return -NF_ACCEPT;
/* Ignore ICMP's containing fragments (shouldn't happen) */
if (inside->ip.frag_off & htons(IP_OFFSET)) {
DEBUGP("icmp_error_message: fragment of proto %u\n",
inside->ip.protocol);
return -NF_ACCEPT;
}
innerproto = nf_ct_find_proto(PF_INET, inside->ip.protocol);
dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
inside->ip.protocol, &origtuple,
&nf_conntrack_l3proto_ipv4, innerproto)) {
DEBUGP("icmp_error_message: ! 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 (!nf_ct_invert_tuple(&innertuple, &origtuple,
&nf_conntrack_l3proto_ipv4, innerproto)) {
DEBUGP("icmp_error_message: no match\n");
return -NF_ACCEPT;
}
*ctinfo = IP_CT_RELATED;
h = nf_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 = nf_conntrack_find_get(&origtuple, NULL);
if (!h) {
DEBUGP("icmp_error_message: no match\n");
return -NF_ACCEPT;
}
/* Reverse direction from that found */
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
*ctinfo += IP_CT_IS_REPLY;
} else {
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
*ctinfo += IP_CT_IS_REPLY;
}
/* Update skb to refer to this connection */
skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
skb->nfctinfo = *ctinfo;
return -NF_ACCEPT;
}
/* Small and modified version of icmp_rcv */
static int
icmp_error(struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum)
{
struct icmphdr _ih, *icmph;
/* Not enough header? */
icmph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_ih), &_ih);
if (icmph == NULL) {
if (LOG_INVALID(IPPROTO_ICMP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
"nf_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, NULL,
"nf_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,
NULL,
"nf_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, NULL,
"nf_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 nf_conntrack_protocol nf_conntrack_protocol_icmp =
{
.list = { NULL, NULL },
.l3proto = PF_INET,
.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,
.destroy = NULL,
.me = NULL
};
EXPORT_SYMBOL(nf_conntrack_protocol_icmp);
...@@ -176,6 +176,11 @@ resubmit: ...@@ -176,6 +176,11 @@ resubmit:
if (ipprot->flags & INET6_PROTO_FINAL) { if (ipprot->flags & INET6_PROTO_FINAL) {
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
/* Free reference early: we don't need it any more,
and it may hold ip_conntrack module loaded
indefinitely. */
nf_reset(skb);
skb_postpull_rcsum(skb, skb->nh.raw, skb_postpull_rcsum(skb, skb->nh.raw,
skb->h.raw - skb->nh.raw); skb->h.raw - skb->nh.raw);
hdr = skb->nh.ipv6h; hdr = skb->nh.ipv6h;
......
...@@ -441,9 +441,15 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) ...@@ -441,9 +441,15 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
#ifdef CONFIG_NETFILTER #ifdef CONFIG_NETFILTER
to->nfmark = from->nfmark; to->nfmark = from->nfmark;
/* Connection association is same as pre-frag packet */ /* Connection association is same as pre-frag packet */
nf_conntrack_put(to->nfct);
to->nfct = from->nfct; to->nfct = from->nfct;
nf_conntrack_get(to->nfct); nf_conntrack_get(to->nfct);
to->nfctinfo = from->nfctinfo; to->nfctinfo = from->nfctinfo;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_conntrack_put_reasm(to->nfct_reasm);
to->nfct_reasm = from->nfct_reasm;
nf_conntrack_get_reasm(to->nfct_reasm);
#endif
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
nf_bridge_put(to->nf_bridge); nf_bridge_put(to->nf_bridge);
to->nf_bridge = from->nf_bridge; to->nf_bridge = from->nf_bridge;
......
...@@ -278,5 +278,19 @@ config IP6_NF_RAW ...@@ -278,5 +278,19 @@ config IP6_NF_RAW
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
<file:Documentation/modules.txt>. If unsure, say `N'. <file:Documentation/modules.txt>. If unsure, say `N'.
config NF_CONNTRACK_IPV6
tristate "IPv6 support for new connection tracking (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
into connections.
This is IPv6 support on Layer 3 independent connection tracking.
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
To compile it as a module, choose M here. If unsure, say N.
endmenu endmenu
...@@ -27,3 +27,9 @@ obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o ...@@ -27,3 +27,9 @@ obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
# objects for l3 independent conntrack
nf_conntrack_ipv6-objs := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
# l3 independent conntrack
obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
...@@ -56,9 +56,9 @@ checkentry(const char *tablename, ...@@ -56,9 +56,9 @@ checkentry(const char *tablename,
return 1; return 1;
} }
static struct ip6t_target ip6t_mark_reg = { static struct ip6t_target ip6t_mark_reg = {
.name = "MARK", .name = "MARK",
.target = target, .target = target,
.checkentry = checkentry, .checkentry = checkentry,
.me = THIS_MODULE .me = THIS_MODULE
}; };
......
This diff is collapsed.
/*
* Copyright (C)2003,2004 USAGI/WIDE Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Author:
* Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - ICMPv6 tracking support. Derived from the original ip_conntrack code
* net/ipv4/netfilter/ip_conntrack_proto_icmp.c which had the following
* copyright information:
* (C) 1999-2001 Paul `Rusty' Russell
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
*/
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/in6.h>
#include <linux/icmpv6.h>
#include <linux/ipv6.h>
#include <net/ipv6.h>
#include <net/ip6_checksum.h>
#include <linux/seq_file.h>
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_protocol.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
unsigned long nf_ct_icmpv6_timeout = 30*HZ;
#if 0
#define DEBUGP printk
#else
#define DEBUGP(format, args...)
#endif
static int icmpv6_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
{
struct icmp6hdr _hdr, *hp;
hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
if (hp == NULL)
return 0;
tuple->dst.u.icmp.type = hp->icmp6_type;
tuple->src.u.icmp.id = hp->icmp6_identifier;
tuple->dst.u.icmp.code = hp->icmp6_code;
return 1;
}
static int icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
/* Add 1; spaces filled with 0. */
static u_int8_t invmap[] = {
[ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
[ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
[ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
[ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1
};
__u8 type = orig->dst.u.icmp.type - 128;
if (type >= sizeof(invmap) || !invmap[type])
return 0;
tuple->src.u.icmp.id = orig->src.u.icmp.id;
tuple->dst.u.icmp.type = invmap[type] - 1;
tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
return 1;
}
/* Print out the per-protocol part of the tuple. */
static int icmpv6_print_tuple(struct seq_file *s,
const struct nf_conntrack_tuple *tuple)
{
return seq_printf(s, "type=%u code=%u id=%u ",
tuple->dst.u.icmp.type,
tuple->dst.u.icmp.code,
ntohs(tuple->src.u.icmp.id));
}
/* Print out the private part of the conntrack. */
static int icmpv6_print_conntrack(struct seq_file *s,
const struct nf_conn *conntrack)
{
return 0;
}
/* Returns verdict for packet, or -1 for invalid. */
static int icmpv6_packet(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
int pf,
unsigned int hooknum)
{
/* Try to delete connection immediately after all replies:
won't actually vanish as we still have skb, and del_timer
means this will only run once even if count hits zero twice
(theoretically possible with SMP) */
if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
if (atomic_dec_and_test(&ct->proto.icmp.count)
&& del_timer(&ct->timeout))
ct->timeout.function((unsigned long)ct);
} else {
atomic_inc(&ct->proto.icmp.count);
nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb);
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout);
}
return NF_ACCEPT;
}
/* Called when a new connection for this protocol found. */
static int icmpv6_new(struct nf_conn *conntrack,
const struct sk_buff *skb,
unsigned int dataoff)
{
static u_int8_t valid_new[] = {
[ICMPV6_ECHO_REQUEST - 128] = 1,
[ICMPV6_NI_QUERY - 128] = 1
};
if (conntrack->tuplehash[0].tuple.dst.u.icmp.type - 128 >= sizeof(valid_new)
|| !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type - 128]) {
/* Can't create a new ICMPv6 `conn' with this. */
DEBUGP("icmp: can't create new conn with type %u\n",
conntrack->tuplehash[0].tuple.dst.u.icmp.type);
NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
return 0;
}
atomic_set(&conntrack->proto.icmp.count, 0);
return 1;
}
extern int
nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len);
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
static int
icmpv6_error_message(struct sk_buff *skb,
unsigned int icmp6off,
enum ip_conntrack_info *ctinfo,
unsigned int hooknum)
{
struct nf_conntrack_tuple intuple, origtuple;
struct nf_conntrack_tuple_hash *h;
struct icmp6hdr _hdr, *hp;
unsigned int inip6off;
struct nf_conntrack_protocol *inproto;
u_int8_t inprotonum;
unsigned int inprotoff;
NF_CT_ASSERT(skb->nfct == NULL);
hp = skb_header_pointer(skb, icmp6off, sizeof(_hdr), &_hdr);
if (hp == NULL) {
DEBUGP("icmpv6_error: Can't get ICMPv6 hdr.\n");
return -NF_ACCEPT;
}
inip6off = icmp6off + sizeof(_hdr);
if (skb_copy_bits(skb, inip6off+offsetof(struct ipv6hdr, nexthdr),
&inprotonum, sizeof(inprotonum)) != 0) {
DEBUGP("icmpv6_error: Can't get nexthdr in inner IPv6 header.\n");
return -NF_ACCEPT;
}
inprotoff = nf_ct_ipv6_skip_exthdr(skb,
inip6off + sizeof(struct ipv6hdr),
&inprotonum,
skb->len - inip6off
- sizeof(struct ipv6hdr));
if ((inprotoff < 0) || (inprotoff > skb->len) ||
(inprotonum == NEXTHDR_FRAGMENT)) {
DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n");
return -NF_ACCEPT;
}
inproto = nf_ct_find_proto(PF_INET6, inprotonum);
/* Are they talking about one of our connections? */
if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
&origtuple, &nf_conntrack_l3proto_ipv6, inproto)) {
DEBUGP("icmpv6_error: Can't get tuple\n");
return -NF_ACCEPT;
}
/* Ordinarily, we'd expect the inverted tupleproto, but it's
been preserved inside the ICMP. */
if (!nf_ct_invert_tuple(&intuple, &origtuple,
&nf_conntrack_l3proto_ipv6, inproto)) {
DEBUGP("icmpv6_error: Can't invert tuple\n");
return -NF_ACCEPT;
}
*ctinfo = IP_CT_RELATED;
h = nf_conntrack_find_get(&intuple, NULL);
if (!h) {
DEBUGP("icmpv6_error: no match\n");
return -NF_ACCEPT;
} else {
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
*ctinfo += IP_CT_IS_REPLY;
}
/* Update skb to refer to this connection */
skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
skb->nfctinfo = *ctinfo;
return -NF_ACCEPT;
}
static int
icmpv6_error(struct sk_buff *skb, unsigned int dataoff,
enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum)
{
struct icmp6hdr _ih, *icmp6h;
icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih);
if (icmp6h == NULL) {
if (LOG_INVALID(IPPROTO_ICMPV6))
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
"nf_ct_icmpv6: short packet ");
return -NF_ACCEPT;
}
if (hooknum != NF_IP6_PRE_ROUTING)
goto skipped;
/* Ignore it if the checksum's bogus. */
if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,
skb->len - dataoff, IPPROTO_ICMPV6,
skb_checksum(skb, dataoff,
skb->len - dataoff, 0))) {
nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
"nf_ct_icmpv6: ICMPv6 checksum failed\n");
return -NF_ACCEPT;
}
skipped:
/* is not error message ? */
if (icmp6h->icmp6_type >= 128)
return NF_ACCEPT;
return icmpv6_error_message(skb, dataoff, ctinfo, hooknum);
}
struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 =
{
.l3proto = PF_INET6,
.proto = IPPROTO_ICMPV6,
.name = "icmpv6",
.pkt_to_tuple = icmpv6_pkt_to_tuple,
.invert_tuple = icmpv6_invert_tuple,
.print_tuple = icmpv6_print_tuple,
.print_conntrack = icmpv6_print_conntrack,
.packet = icmpv6_packet,
.new = icmpv6_new,
.error = icmpv6_error,
};
EXPORT_SYMBOL(nf_conntrack_protocol_icmpv6);
This diff is collapsed.
...@@ -174,8 +174,10 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) ...@@ -174,8 +174,10 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
/* Not releasing hash table! */ /* Not releasing hash table! */
if (clone) if (clone) {
nf_reset(clone);
rawv6_rcv(sk, clone); rawv6_rcv(sk, clone);
}
} }
sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr, sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr,
IP6CB(skb)->iif); IP6CB(skb)->iif);
......
...@@ -1710,7 +1710,7 @@ static void fib6_dump_end(struct netlink_callback *cb) ...@@ -1710,7 +1710,7 @@ static void fib6_dump_end(struct netlink_callback *cb)
static int fib6_dump_done(struct netlink_callback *cb) static int fib6_dump_done(struct netlink_callback *cb)
{ {
fib6_dump_end(cb); fib6_dump_end(cb);
return cb->done(cb); return cb->done ? cb->done(cb) : 0;
} }
int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
......
menu "Core Netfilter Configuration"
depends on NET && NETFILTER
config NETFILTER_NETLINK config NETFILTER_NETLINK
tristate "Netfilter netlink interface" tristate "Netfilter netlink interface"
help help
...@@ -22,3 +25,74 @@ config NETFILTER_NETLINK_LOG ...@@ -22,3 +25,74 @@ config NETFILTER_NETLINK_LOG
and is also scheduled to replace the old syslog-based ipt_LOG and is also scheduled to replace the old syslog-based ipt_LOG
and ip6t_LOG modules. and ip6t_LOG modules.
config NF_CONNTRACK
tristate "Layer 3 Independent Connection tracking (EXPERIMENTAL)"
depends on EXPERIMENTAL && IP_NF_CONNTRACK=n
default n
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
into connections.
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
To compile it as a module, choose M here. If unsure, say N.
config NF_CT_ACCT
bool "Connection tracking flow accounting"
depends on NF_CONNTRACK
help
If this option is enabled, the connection tracking code will
keep per-flow packet and byte counters.
Those counters can be used for flow-based accounting or the
`connbytes' match.
If unsure, say `N'.
config NF_CONNTRACK_MARK
bool 'Connection mark tracking support'
depends on NF_CONNTRACK
help
This option enables support for connection marks, used by the
`CONNMARK' target and `connmark' match. Similar to the mark value
of packets, but this mark value is kept in the conntrack session
instead of the individual packets.
config NF_CONNTRACK_EVENTS
bool "Connection tracking events"
depends on NF_CONNTRACK
help
If this option is enabled, the connection tracking code will
provide a notifier chain that can be used by other kernel code
to get notified aboutchanges in the connection tracking state.
If unsure, say `N'.
config NF_CT_PROTO_SCTP
tristate 'SCTP protocol on new connection tracking support (EXPERIMENTAL)'
depends on EXPERIMENTAL && NF_CONNTRACK
default n
help
With this option enabled, the layer 3 independent connection
tracking code will be able to do state tracking on SCTP connections.
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
config NF_CONNTRACK_FTP
tristate "FTP support on new connection tracking (EXPERIMENTAL)"
depends on EXPERIMENTAL && NF_CONNTRACK
help
Tracking FTP connections is problematic: special helpers are
required for tracking them, and doing masquerading and other forms
of Network Address Translation on them.
This is FTP support on Layer 3 independent connection tracking.
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
To compile it as a module, choose M here. If unsure, say N.
endmenu
...@@ -5,3 +5,11 @@ obj-$(CONFIG_NETFILTER) = netfilter.o ...@@ -5,3 +5,11 @@ obj-$(CONFIG_NETFILTER) = netfilter.o
obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
# SCTP protocol connection tracking
obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
# Makefile for the netlink driver. # Makefile for the netlink driver.
# #
obj-y := af_netlink.o obj-y := af_netlink.o attr.o genetlink.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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