From 5bd47dc8bd8b44933c0888c304cd66851551a56f Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 18 Feb 2008 08:03:28 +0000 Subject: [PATCH] generic-2.4: add ip6t_REJECT support SVN-Revision: 10482 --- target/linux/generic-2.4/config-default | 1 + .../patches/623-netfilter_ip6t_reject.patch | 360 ++++++++++++++++++ 2 files changed, 361 insertions(+) create mode 100644 target/linux/generic-2.4/patches/623-netfilter_ip6t_reject.patch diff --git a/target/linux/generic-2.4/config-default b/target/linux/generic-2.4/config-default index 411e2c3aca..acf57937a1 100644 --- a/target/linux/generic-2.4/config-default +++ b/target/linux/generic-2.4/config-default @@ -198,6 +198,7 @@ CONFIG_IP6_NF_MATCH_RANDOM=m CONFIG_IP6_NF_TARGET_IMQ=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_TARGET_MARK=m +CONFIG_IP6_NF_TARGET_REJECT=m # CONFIG_IPMI_DEVICE_INTERFACE is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_IPMI_KCS is not set diff --git a/target/linux/generic-2.4/patches/623-netfilter_ip6t_reject.patch b/target/linux/generic-2.4/patches/623-netfilter_ip6t_reject.patch new file mode 100644 index 0000000000..2caae3ab01 --- /dev/null +++ b/target/linux/generic-2.4/patches/623-netfilter_ip6t_reject.patch @@ -0,0 +1,360 @@ +Index: linux-2.4.35.4/net/ipv6/netfilter/ip6t_REJECT.c +=================================================================== +--- /dev/null ++++ linux-2.4.35.4/net/ipv6/netfilter/ip6t_REJECT.c +@@ -0,0 +1,301 @@ ++/* ++ * This is a module which is used for rejecting packets. ++ * Added support for customized reject packets (Jozsef Kadlecsik). ++ * Sun 12 Nov 2000 ++ * Port to IPv6 / ip6tables (Harald Welte ) ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if 1 ++#define DEBUGP printk ++#else ++#define DEBUGP(format, args...) ++#endif ++ ++#if 0 ++/* Send RST reply */ ++static void send_reset(struct sk_buff *oldskb) ++{ ++ struct sk_buff *nskb; ++ struct tcphdr *otcph, *tcph; ++ struct rtable *rt; ++ unsigned int otcplen; ++ int needs_ack; ++ ++ /* IP header checks: fragment, too short. */ ++ if (oldskb->nh.iph->frag_off & htons(IP_OFFSET) ++ || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr)) ++ return; ++ ++ otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl); ++ otcplen = oldskb->len - oldskb->nh.iph->ihl*4; ++ ++ /* No RST for RST. */ ++ if (otcph->rst) ++ return; ++ ++ /* Check checksum. */ ++ if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr, ++ oldskb->nh.iph->daddr, ++ csum_partial((char *)otcph, otcplen, 0)) != 0) ++ return; ++ ++ /* Copy skb (even if skb is about to be dropped, we can't just ++ clone it because there may be other things, such as tcpdump, ++ interested in it) */ ++ nskb = skb_copy(oldskb, GFP_ATOMIC); ++ if (!nskb) ++ return; ++ ++ /* This packet will not be the same as the other: clear nf fields */ ++ nf_conntrack_put(nskb->nfct); ++ nskb->nfct = NULL; ++ nskb->nfcache = 0; ++#ifdef CONFIG_NETFILTER_DEBUG ++ nskb->nf_debug = 0; ++#endif ++ ++ tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); ++ ++ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr); ++ tcph->source = xchg(&tcph->dest, tcph->source); ++ ++ /* Truncate to length (no data) */ ++ tcph->doff = sizeof(struct tcphdr)/4; ++ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr)); ++ nskb->nh.iph->tot_len = htons(nskb->len); ++ ++ if (tcph->ack) { ++ needs_ack = 0; ++ tcph->seq = otcph->ack_seq; ++ tcph->ack_seq = 0; ++ } else { ++ needs_ack = 1; ++ tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin ++ + otcplen - (otcph->doff<<2)); ++ tcph->seq = 0; ++ } ++ ++ /* Reset flags */ ++ ((u_int8_t *)tcph)[13] = 0; ++ tcph->rst = 1; ++ tcph->ack = needs_ack; ++ ++ tcph->window = 0; ++ tcph->urg_ptr = 0; ++ ++ /* Adjust TCP checksum */ ++ tcph->check = 0; ++ tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), ++ nskb->nh.iph->saddr, ++ nskb->nh.iph->daddr, ++ csum_partial((char *)tcph, ++ sizeof(struct tcphdr), 0)); ++ ++ /* Adjust IP TTL, DF */ ++ nskb->nh.iph->ttl = MAXTTL; ++ /* Set DF, id = 0 */ ++ nskb->nh.iph->frag_off = htons(IP_DF); ++ nskb->nh.iph->id = 0; ++ ++ /* Adjust IP checksum */ ++ nskb->nh.iph->check = 0; ++ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, ++ nskb->nh.iph->ihl); ++ ++ /* Routing */ ++ if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr, ++ RT_TOS(nskb->nh.iph->tos) | RTO_CONN, ++ 0) != 0) ++ goto free_nskb; ++ ++ dst_release(nskb->dst); ++ nskb->dst = &rt->u.dst; ++ ++ /* "Never happens" */ ++ if (nskb->len > nskb->dst->pmtu) ++ goto free_nskb; ++ ++ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev, ++ ip_finish_output); ++ return; ++ ++ free_nskb: ++ kfree_skb(nskb); ++} ++#endif ++ ++static unsigned int reject6_target(struct sk_buff **pskb, ++ unsigned int hooknum, ++ const struct net_device *in, ++ const struct net_device *out, ++ const void *targinfo, ++ void *userinfo) ++{ ++ const struct ip6t_reject_info *reject = targinfo; ++ struct sk_buff *skb2 = NULL; ++ struct rt6_info *rt6i; ++ struct net_device odev; ++ ++ if (!out) { ++ skb2 = skb_clone(*pskb, GFP_ATOMIC); ++ if (skb2 == NULL) { ++ return NF_DROP; ++ } ++ dst_release(skb2->dst); ++ skb2->dst = NULL; ++ ++ rt6i = rt6_lookup(&skb2->nh.ipv6h->saddr, NULL, 0, 0); ++ if (rt6i && rt6i->rt6i_dev) { ++ skb2->dev = rt6i->rt6i_dev; ++ rt6i = rt6_lookup(&skb2->nh.ipv6h->daddr, &skb2->nh.ipv6h->saddr, 0, 0); ++ } ++ memcpy(&odev, skb2->dev, sizeof(odev)); /* XXX 'out' has 'const' qualifier... */ ++ } else { ++ memcpy(&odev, out, sizeof(odev)); ++ } ++ ++ printk(KERN_DEBUG "%s: medium point\n", __FUNCTION__); ++ /* WARNING: This code causes reentry within ip6tables. ++ This means that the ip6tables jump stack is now crap. We ++ must return an absolute verdict. --RR */ ++ DEBUGP("REJECTv6: calling icmpv6_send\n"); ++ switch (reject->with) { ++ case IP6T_ICMP6_NO_ROUTE: ++ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, &odev); ++ break; ++ case IP6T_ICMP6_ADM_PROHIBITED: ++ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, &odev); ++ break; ++ case IP6T_ICMP6_NOT_NEIGHBOUR: ++ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, &odev); ++ break; ++ case IP6T_ICMP6_ADDR_UNREACH: ++ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, &odev); ++ break; ++ case IP6T_ICMP6_PORT_UNREACH: ++ icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, &odev); ++ break; ++#if 0 ++ case IPT_ICMP_ECHOREPLY: { ++ struct icmp6hdr *icmph = (struct icmphdr *) ++ ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl); ++ unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4; ++ ++ /* Not non-head frags, or truncated */ ++ if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0) ++ && datalen >= 4) { ++ /* Usually I don't like cut & pasting code, ++ but dammit, my party is starting in 45 ++ mins! --RR */ ++ struct icmp_bxm icmp_param; ++ ++ icmp_param.icmph=*icmph; ++ icmp_param.icmph.type=ICMP_ECHOREPLY; ++ icmp_param.data_ptr=(icmph+1); ++ icmp_param.data_len=datalen; ++ icmp_reply(&icmp_param, *pskb); ++ } ++ } ++ break; ++ case IPT_TCP_RESET: ++ send_reset(*pskb); ++ break; ++#endif ++ default: ++ printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with); ++ break; ++ } ++ ++ if (skb2) kfree_skb(skb2); ++ ++ return NF_DROP; ++} ++ ++static inline int find_ping_match(const struct ip6t_entry_match *m) ++{ ++ const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data; ++ ++ if (strcmp(m->u.kernel.match->name, "icmp6") == 0 ++ && icmpinfo->type == ICMPV6_ECHO_REQUEST ++ && !(icmpinfo->invflags & IP6T_ICMP_INV)) ++ return 1; ++ ++ return 0; ++} ++ ++static int check(const char *tablename, ++ const struct ip6t_entry *e, ++ void *targinfo, ++ unsigned int targinfosize, ++ unsigned int hook_mask) ++{ ++ const struct ip6t_reject_info *rejinfo = targinfo; ++ ++ if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { ++ DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize); ++ return 0; ++ } ++ ++ /* Only allow these for packet filtering. */ ++ if (strcmp(tablename, "filter") != 0) { ++ DEBUGP("REJECTv6: bad table `%s'.\n", tablename); ++ return 0; ++ } ++ if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN) ++ | (1 << NF_IP6_FORWARD) ++ | (1 << NF_IP6_LOCAL_OUT))) != 0) { ++ DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask); ++ return 0; ++ } ++ ++ if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) { ++ /* Must specify that it's an ICMP ping packet. */ ++ if (e->ipv6.proto != IPPROTO_ICMPV6 ++ || (e->ipv6.invflags & IP6T_INV_PROTO)) { ++ DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n"); ++ return 0; ++ } ++ /* Must contain ICMP match. */ ++ if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) { ++ DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n"); ++ return 0; ++ } ++ } else if (rejinfo->with == IP6T_TCP_RESET) { ++ /* Must specify that it's a TCP packet */ ++ if (e->ipv6.proto != IPPROTO_TCP ++ || (e->ipv6.invflags & IP6T_INV_PROTO)) { ++ DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n"); ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++static struct ip6t_target ip6t_reject_reg ++= { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE }; ++ ++static int __init init(void) ++{ ++ if (ip6t_register_target(&ip6t_reject_reg)) ++ return -EINVAL; ++ return 0; ++} ++ ++static void __exit fini(void) ++{ ++ ip6t_unregister_target(&ip6t_reject_reg); ++} ++ ++module_init(init); ++module_exit(fini); +Index: linux-2.4.35.4/include/linux/netfilter_ipv6/ip6t_REJECT.h +=================================================================== +--- linux-2.4.35.4.orig/include/linux/netfilter_ipv6/ip6t_REJECT.h ++++ linux-2.4.35.4/include/linux/netfilter_ipv6/ip6t_REJECT.h +@@ -2,15 +2,17 @@ + #define _IP6T_REJECT_H + + enum ip6t_reject_with { +- IP6T_ICMP_NET_UNREACHABLE, +- IP6T_ICMP_HOST_UNREACHABLE, +- IP6T_ICMP_PROT_UNREACHABLE, +- IP6T_ICMP_PORT_UNREACHABLE, +- IP6T_ICMP_ECHOREPLY ++ IP6T_ICMP6_NO_ROUTE, ++ IP6T_ICMP6_ADM_PROHIBITED, ++ IP6T_ICMP6_NOT_NEIGHBOUR, ++ IP6T_ICMP6_ADDR_UNREACH, ++ IP6T_ICMP6_PORT_UNREACH, ++ IP6T_ICMP6_ECHOREPLY, ++ IP6T_TCP_RESET + }; + + struct ip6t_reject_info { + enum ip6t_reject_with with; /* reject type */ + }; + +-#endif /*_IPT_REJECT_H*/ ++#endif /*_IP6T_REJECT_H*/ +Index: linux-2.4.35.4/net/ipv6/netfilter/Makefile +=================================================================== +--- linux-2.4.35.4.orig/net/ipv6/netfilter/Makefile ++++ linux-2.4.35.4/net/ipv6/netfilter/Makefile +@@ -34,5 +34,7 @@ obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue. + obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o + obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o + obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o ++obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o ++ + + include $(TOPDIR)/Rules.make +Index: linux-2.4.35.4/net/ipv6/netfilter/Config.in +=================================================================== +--- linux-2.4.35.4.orig/net/ipv6/netfilter/Config.in ++++ linux-2.4.35.4/net/ipv6/netfilter/Config.in +@@ -61,6 +61,9 @@ if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; + if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then + dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_FILTER + fi ++ if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then ++ dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER ++ fi + + # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then + # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER