Commit a49d1a90 authored by David S. Miller's avatar David S. Miller
Browse files
parents 2e7d21c5 0197dee7
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
#ifndef XT_HMARK_H_
#define XT_HMARK_H_

#include <linux/types.h>

enum {
	XT_HMARK_SADDR_MASK,
	XT_HMARK_DADDR_MASK,
	XT_HMARK_SPI,
	XT_HMARK_SPI_MASK,
	XT_HMARK_SPORT,
	XT_HMARK_DPORT,
	XT_HMARK_SPORT_MASK,
	XT_HMARK_DPORT_MASK,
	XT_HMARK_PROTO_MASK,
	XT_HMARK_RND,
	XT_HMARK_MODULUS,
	XT_HMARK_OFFSET,
	XT_HMARK_CT,
	XT_HMARK_METHOD_L3,
	XT_HMARK_METHOD_L3_4,
};
#define XT_HMARK_FLAG(flag)	(1 << flag)

union hmark_ports {
	struct {
		__u16	src;
		__u16	dst;
	} p16;
	__u32	v32;
};

struct xt_hmark_info {
	union nf_inet_addr	src_mask;
	union nf_inet_addr	dst_mask;
	union hmark_ports	port_mask;
	union hmark_ports	port_set;
	__u32			flags;
	__u16			proto_mask;
	__u32			hashrnd;
	__u32			hmodulus;
	__u32			hoffset;	/* Mark offset to start from */
};

#endif /* XT_HMARK_H_ */
+9 −1
Original line number Diff line number Diff line
@@ -6,7 +6,11 @@
/* timings are in milliseconds. */
#define XT_HASHLIMIT_SCALE 10000
/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
   seconds, or one every 59 hours. */
 * seconds, or one packet every 59 hours.
 */

/* packet length accounting is done in 16-byte steps */
#define XT_HASHLIMIT_BYTE_SHIFT 4

/* details of this structure hidden by the implementation */
struct xt_hashlimit_htable;
@@ -17,6 +21,10 @@ enum {
	XT_HASHLIMIT_HASH_SIP = 1 << 2,
	XT_HASHLIMIT_HASH_SPT = 1 << 3,
	XT_HASHLIMIT_INVERT   = 1 << 4,
	XT_HASHLIMIT_BYTES    = 1 << 5,
#ifdef __KERNEL__
	XT_HASHLIMIT_MAX      = 1 << 6,
#endif
};

struct hashlimit_cfg {
+6 −1
Original line number Diff line number Diff line
@@ -298,9 +298,14 @@ ip6t_ext_hdr(u8 nexthdr)
	       (nexthdr == IPPROTO_DSTOPTS);
}

enum {
	IP6T_FH_F_FRAG	= (1 << 0),
	IP6T_FH_F_AUTH	= (1 << 1),
};

/* find specified header and get offset to it */
extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
			 int target, unsigned short *fragoff);
			 int target, unsigned short *fragoff, int *fragflg);

#ifdef CONFIG_COMPAT
#include <net/compat.h>
+31 −5
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ ip6_packet_match(const struct sk_buff *skb,
		int protohdr;
		unsigned short _frag_off;

		protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
		protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off, NULL);
		if (protohdr < 0) {
			if (_frag_off == 0)
				*hotdrop = true;
@@ -362,6 +362,7 @@ ip6t_do_table(struct sk_buff *skb,
		const struct xt_entry_match *ematch;

		IP_NF_ASSERT(e);
		acpar.thoff = 0;
		if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,
		    &acpar.thoff, &acpar.fragoff, &acpar.hotdrop)) {
 no_match:
@@ -2278,6 +2279,10 @@ static void __exit ip6_tables_fini(void)
 * if target < 0. "last header" is transport protocol header, ESP, or
 * "No next header".
 *
 * Note that *offset is used as input/output parameter. an if it is not zero,
 * then it must be a valid offset to an inner IPv6 header. This can be used
 * to explore inner IPv6 header, eg. ICMPv6 error messages.
 *
 * If target header is found, its offset is set in *offset and return protocol
 * number. Otherwise, return -1.
 *
@@ -2289,17 +2294,33 @@ static void __exit ip6_tables_fini(void)
 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
 * isn't NULL.
 *
 * if flags is not NULL and it's a fragment, then the frag flag IP6T_FH_F_FRAG
 * will be set. If it's an AH header, the IP6T_FH_F_AUTH flag is set and
 * target < 0, then this function will stop at the AH header.
 */
int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
		  int target, unsigned short *fragoff)
		  int target, unsigned short *fragoff, int *flags)
{
	unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
	u8 nexthdr = ipv6_hdr(skb)->nexthdr;
	unsigned int len = skb->len - start;
	unsigned int len;

	if (fragoff)
		*fragoff = 0;

	if (*offset) {
		struct ipv6hdr _ip6, *ip6;

		ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
		if (!ip6 || (ip6->version != 6)) {
			printk(KERN_ERR "IPv6 header not found\n");
			return -EBADMSG;
		}
		start = *offset + sizeof(struct ipv6hdr);
		nexthdr = ip6->nexthdr;
	}
	len = skb->len - start;

	while (nexthdr != target) {
		struct ipv6_opt_hdr _hdr, *hp;
		unsigned int hdrlen;
@@ -2316,6 +2337,9 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
		if (nexthdr == NEXTHDR_FRAGMENT) {
			unsigned short _frag_off;
			__be16 *fp;

			if (flags)	/* Indicate that this is a fragment */
				*flags |= IP6T_FH_F_FRAG;
			fp = skb_header_pointer(skb,
						start+offsetof(struct frag_hdr,
							       frag_off),
@@ -2336,9 +2360,11 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
				return -ENOENT;
			}
			hdrlen = 8;
		} else if (nexthdr == NEXTHDR_AUTH)
		} else if (nexthdr == NEXTHDR_AUTH) {
			if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
				break;
			hdrlen = (hp->hdrlen + 2) << 2;
		else
		} else
			hdrlen = ipv6_optlen(hp);

		nexthdr = hp->nexthdr;
+2 −2
Original line number Diff line number Diff line
@@ -41,11 +41,11 @@ static bool ah_mt6(const struct sk_buff *skb, struct xt_action_param *par)
	struct ip_auth_hdr _ah;
	const struct ip_auth_hdr *ah;
	const struct ip6t_ah *ahinfo = par->matchinfo;
	unsigned int ptr;
	unsigned int ptr = 0;
	unsigned int hdrlen = 0;
	int err;

	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
	err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL, NULL);
	if (err < 0) {
		if (err != -ENOENT)
			par->hotdrop = true;
Loading