linux/net/bridge/netfilter/ebt_arpreply.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  ebt_arpreply
   4 *
   5 *      Authors:
   6 *      Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
   7 *      Bart De Schuymer <bdschuym@pandora.be>
   8 *
   9 *  August, 2003
  10 *
  11 */
  12#include <linux/if_arp.h>
  13#include <net/arp.h>
  14#include <linux/module.h>
  15#include <linux/netfilter/x_tables.h>
  16#include <linux/netfilter_bridge/ebtables.h>
  17#include <linux/netfilter_bridge/ebt_arpreply.h>
  18
  19static unsigned int
  20ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par)
  21{
  22        const struct ebt_arpreply_info *info = par->targinfo;
  23        const __be32 *siptr, *diptr;
  24        __be32 _sip, _dip;
  25        const struct arphdr *ap;
  26        struct arphdr _ah;
  27        const unsigned char *shp;
  28        unsigned char _sha[ETH_ALEN];
  29
  30        ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
  31        if (ap == NULL)
  32                return EBT_DROP;
  33
  34        if (ap->ar_op != htons(ARPOP_REQUEST) ||
  35            ap->ar_hln != ETH_ALEN ||
  36            ap->ar_pro != htons(ETH_P_IP) ||
  37            ap->ar_pln != 4)
  38                return EBT_CONTINUE;
  39
  40        shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha);
  41        if (shp == NULL)
  42                return EBT_DROP;
  43
  44        siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN,
  45                                   sizeof(_sip), &_sip);
  46        if (siptr == NULL)
  47                return EBT_DROP;
  48
  49        diptr = skb_header_pointer(skb,
  50                                   sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip),
  51                                   sizeof(_dip), &_dip);
  52        if (diptr == NULL)
  53                return EBT_DROP;
  54
  55        arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr,
  56                 (struct net_device *)xt_in(par),
  57                 *diptr, shp, info->mac, shp);
  58
  59        return info->target;
  60}
  61
  62static int ebt_arpreply_tg_check(const struct xt_tgchk_param *par)
  63{
  64        const struct ebt_arpreply_info *info = par->targinfo;
  65        const struct ebt_entry *e = par->entryinfo;
  66
  67        if (BASE_CHAIN && info->target == EBT_RETURN)
  68                return -EINVAL;
  69        if (e->ethproto != htons(ETH_P_ARP) ||
  70            e->invflags & EBT_IPROTO)
  71                return -EINVAL;
  72        if (ebt_invalid_target(info->target))
  73                return -EINVAL;
  74
  75        return 0;
  76}
  77
  78static struct xt_target ebt_arpreply_tg_reg __read_mostly = {
  79        .name           = "arpreply",
  80        .revision       = 0,
  81        .family         = NFPROTO_BRIDGE,
  82        .table          = "nat",
  83        .hooks          = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING),
  84        .target         = ebt_arpreply_tg,
  85        .checkentry     = ebt_arpreply_tg_check,
  86        .targetsize     = sizeof(struct ebt_arpreply_info),
  87        .me             = THIS_MODULE,
  88};
  89
  90static int __init ebt_arpreply_init(void)
  91{
  92        return xt_register_target(&ebt_arpreply_tg_reg);
  93}
  94
  95static void __exit ebt_arpreply_fini(void)
  96{
  97        xt_unregister_target(&ebt_arpreply_tg_reg);
  98}
  99
 100module_init(ebt_arpreply_init);
 101module_exit(ebt_arpreply_fini);
 102MODULE_DESCRIPTION("Ebtables: ARP reply target");
 103MODULE_LICENSE("GPL");
 104