1#include <stdio.h>
2#if defined(__GLIBC__) && __GLIBC__ == 2
3#include <net/ethernet.h>
4#else
5#include <linux/if_ether.h>
6#endif
7#include <xtables.h>
8#include <linux/netfilter/xt_mac.h>
9
10enum {
11	O_MAC = 0,
12};
13
14static void mac_help(void)
15{
16	printf(
17"mac match options:\n"
18"[!] --mac-source XX:XX:XX:XX:XX:XX\n"
19"				Match source MAC address\n");
20}
21
22#define s struct xt_mac_info
23static const struct xt_option_entry mac_opts[] = {
24	{.name = "mac-source", .id = O_MAC, .type = XTTYPE_ETHERMAC,
25	 .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT,
26	 XTOPT_POINTER(s, srcaddr)},
27	XTOPT_TABLEEND,
28};
29#undef s
30
31static void mac_parse(struct xt_option_call *cb)
32{
33	struct xt_mac_info *macinfo = cb->data;
34
35	xtables_option_parse(cb);
36	if (cb->invert)
37		macinfo->invert = 1;
38}
39
40static void print_mac(const unsigned char *macaddress)
41{
42	unsigned int i;
43
44	printf(" %02X", macaddress[0]);
45	for (i = 1; i < ETH_ALEN; ++i)
46		printf(":%02X", macaddress[i]);
47}
48
49static void
50mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
51{
52	const struct xt_mac_info *info = (void *)match->data;
53	printf(" MAC");
54
55	if (info->invert)
56		printf(" !");
57
58	print_mac(info->srcaddr);
59}
60
61static void mac_save(const void *ip, const struct xt_entry_match *match)
62{
63	const struct xt_mac_info *info = (void *)match->data;
64
65	if (info->invert)
66		printf(" !");
67
68	printf(" --mac-source");
69	print_mac(info->srcaddr);
70}
71
72static struct xtables_match mac_match = {
73	.family		= NFPROTO_UNSPEC,
74 	.name		= "mac",
75	.version	= XTABLES_VERSION,
76	.size		= XT_ALIGN(sizeof(struct xt_mac_info)),
77	.userspacesize	= XT_ALIGN(sizeof(struct xt_mac_info)),
78	.help		= mac_help,
79	.x6_parse	= mac_parse,
80	.print		= mac_print,
81	.save		= mac_save,
82	.x6_options	= mac_opts,
83};
84
85void _init(void)
86{
87	xtables_register_match(&mac_match);
88}
89