linux/net/ipv4/netfilter/arpt_mangle.c
<<
>>
Prefs
   1/* module that allows mangling of the arp payload */
   2#include <linux/module.h>
   3#include <linux/netfilter.h>
   4#include <linux/netfilter_arp/arpt_mangle.h>
   5#include <net/sock.h>
   6
   7MODULE_LICENSE("GPL");
   8MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
   9MODULE_DESCRIPTION("arptables arp payload mangle target");
  10
  11static unsigned int
  12target(struct sk_buff *skb,
  13       const struct net_device *in, const struct net_device *out,
  14       unsigned int hooknum, const struct xt_target *target,
  15       const void *targinfo)
  16{
  17        const struct arpt_mangle *mangle = targinfo;
  18        struct arphdr *arp;
  19        unsigned char *arpptr;
  20        int pln, hln;
  21
  22        if (skb_make_writable(skb, skb->len))
  23                return NF_DROP;
  24
  25        arp = arp_hdr(skb);
  26        arpptr = skb_network_header(skb) + sizeof(*arp);
  27        pln = arp->ar_pln;
  28        hln = arp->ar_hln;
  29        /* We assume that pln and hln were checked in the match */
  30        if (mangle->flags & ARPT_MANGLE_SDEV) {
  31                if (ARPT_DEV_ADDR_LEN_MAX < hln ||
  32                   (arpptr + hln > skb_tail_pointer(skb)))
  33                        return NF_DROP;
  34                memcpy(arpptr, mangle->src_devaddr, hln);
  35        }
  36        arpptr += hln;
  37        if (mangle->flags & ARPT_MANGLE_SIP) {
  38                if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
  39                   (arpptr + pln > skb_tail_pointer(skb)))
  40                        return NF_DROP;
  41                memcpy(arpptr, &mangle->u_s.src_ip, pln);
  42        }
  43        arpptr += pln;
  44        if (mangle->flags & ARPT_MANGLE_TDEV) {
  45                if (ARPT_DEV_ADDR_LEN_MAX < hln ||
  46                   (arpptr + hln > skb_tail_pointer(skb)))
  47                        return NF_DROP;
  48                memcpy(arpptr, mangle->tgt_devaddr, hln);
  49        }
  50        arpptr += hln;
  51        if (mangle->flags & ARPT_MANGLE_TIP) {
  52                if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
  53                   (arpptr + pln > skb_tail_pointer(skb)))
  54                        return NF_DROP;
  55                memcpy(arpptr, &mangle->u_t.tgt_ip, pln);
  56        }
  57        return mangle->target;
  58}
  59
  60static bool
  61checkentry(const char *tablename, const void *e, const struct xt_target *target,
  62           void *targinfo, unsigned int hook_mask)
  63{
  64        const struct arpt_mangle *mangle = targinfo;
  65
  66        if (mangle->flags & ~ARPT_MANGLE_MASK ||
  67            !(mangle->flags & ARPT_MANGLE_MASK))
  68                return false;
  69
  70        if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
  71           mangle->target != ARPT_CONTINUE)
  72                return false;
  73        return true;
  74}
  75
  76static struct arpt_target arpt_mangle_reg __read_mostly = {
  77        .name           = "mangle",
  78        .target         = target,
  79        .targetsize     = sizeof(struct arpt_mangle),
  80        .checkentry     = checkentry,
  81        .me             = THIS_MODULE,
  82};
  83
  84static int __init arpt_mangle_init(void)
  85{
  86        if (arpt_register_target(&arpt_mangle_reg))
  87                return -EINVAL;
  88
  89        return 0;
  90}
  91
  92static void __exit arpt_mangle_fini(void)
  93{
  94        arpt_unregister_target(&arpt_mangle_reg);
  95}
  96
  97module_init(arpt_mangle_init);
  98module_exit(arpt_mangle_fini);
  99