ip6t_eui64.c (1657B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* Kernel module to match EUI64 address parameters. */ 3 4/* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu> 5 */ 6 7#include <linux/module.h> 8#include <linux/skbuff.h> 9#include <linux/ipv6.h> 10#include <linux/if_ether.h> 11 12#include <linux/netfilter/x_tables.h> 13#include <linux/netfilter_ipv6/ip6_tables.h> 14 15MODULE_DESCRIPTION("Xtables: IPv6 EUI64 address match"); 16MODULE_LICENSE("GPL"); 17MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>"); 18 19static bool 20eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par) 21{ 22 unsigned char eui64[8]; 23 24 if (!(skb_mac_header(skb) >= skb->head && 25 skb_mac_header(skb) + ETH_HLEN <= skb->data) && 26 par->fragoff != 0) { 27 par->hotdrop = true; 28 return false; 29 } 30 31 memset(eui64, 0, sizeof(eui64)); 32 33 if (eth_hdr(skb)->h_proto == htons(ETH_P_IPV6)) { 34 if (ipv6_hdr(skb)->version == 0x6) { 35 memcpy(eui64, eth_hdr(skb)->h_source, 3); 36 memcpy(eui64 + 5, eth_hdr(skb)->h_source + 3, 3); 37 eui64[3] = 0xff; 38 eui64[4] = 0xfe; 39 eui64[0] ^= 0x02; 40 41 if (!memcmp(ipv6_hdr(skb)->saddr.s6_addr + 8, eui64, 42 sizeof(eui64))) 43 return true; 44 } 45 } 46 47 return false; 48} 49 50static struct xt_match eui64_mt6_reg __read_mostly = { 51 .name = "eui64", 52 .family = NFPROTO_IPV6, 53 .match = eui64_mt6, 54 .matchsize = sizeof(int), 55 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN) | 56 (1 << NF_INET_FORWARD), 57 .me = THIS_MODULE, 58}; 59 60static int __init eui64_mt6_init(void) 61{ 62 return xt_register_match(&eui64_mt6_reg); 63} 64 65static void __exit eui64_mt6_exit(void) 66{ 67 xt_unregister_match(&eui64_mt6_reg); 68} 69 70module_init(eui64_mt6_init); 71module_exit(eui64_mt6_exit);