libxt_mac.c revision bbe83862a5e1baf15f7c923352d4afdf59bc70e2
1/* Shared library add-on to iptables to add MAC address support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7#if defined(__GLIBC__) && __GLIBC__ == 2
8#include <net/ethernet.h>
9#else
10#include <linux/if_ether.h>
11#endif
12#include <xtables.h>
13#include <linux/netfilter/xt_mac.h>
14
15static void mac_help(void)
16{
17	printf(
18"mac match options:\n"
19"[!] --mac-source XX:XX:XX:XX:XX:XX\n"
20"				Match source MAC address\n");
21}
22
23static const struct option mac_opts[] = {
24	{ "mac-source", 1, NULL, '1' },
25	{ .name = NULL }
26};
27
28static void
29parse_mac(const char *mac, struct xt_mac_info *info)
30{
31	unsigned int i = 0;
32
33	if (strlen(mac) != ETH_ALEN*3-1)
34		xtables_error(PARAMETER_PROBLEM, "Bad mac address \"%s\"", mac);
35
36	for (i = 0; i < ETH_ALEN; i++) {
37		long number;
38		char *end;
39
40		number = strtol(mac + i*3, &end, 16);
41
42		if (end == mac + i*3 + 2
43		    && number >= 0
44		    && number <= 255)
45			info->srcaddr[i] = number;
46		else
47			xtables_error(PARAMETER_PROBLEM,
48				   "Bad mac address `%s'", mac);
49	}
50}
51
52static int
53mac_parse(int c, char **argv, int invert, unsigned int *flags,
54          const void *entry, struct xt_entry_match **match)
55{
56	struct xt_mac_info *macinfo = (struct xt_mac_info *)(*match)->data;
57
58	switch (c) {
59	case '1':
60		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
61		parse_mac(optarg, macinfo);
62		if (invert)
63			macinfo->invert = 1;
64		*flags = 1;
65		break;
66
67	default:
68		return 0;
69	}
70
71	return 1;
72}
73
74static void print_mac(const unsigned char macaddress[ETH_ALEN])
75{
76	unsigned int i;
77
78	printf("%02X", macaddress[0]);
79	for (i = 1; i < ETH_ALEN; i++)
80		printf(":%02X", macaddress[i]);
81	printf(" ");
82}
83
84static void mac_check(unsigned int flags)
85{
86	if (!flags)
87		xtables_error(PARAMETER_PROBLEM,
88			   "You must specify `--mac-source'");
89}
90
91static void
92mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
93{
94	const struct xt_mac_info *info = (void *)match->data;
95	printf("MAC ");
96
97	if (info->invert)
98		printf("! ");
99
100	print_mac(info->srcaddr);
101}
102
103static void mac_save(const void *ip, const struct xt_entry_match *match)
104{
105	const struct xt_mac_info *info = (void *)match->data;
106
107	if (info->invert)
108		printf("! ");
109
110	printf("--mac-source ");
111	print_mac(info->srcaddr);
112}
113
114static struct xtables_match mac_match = {
115	.family		= NFPROTO_UNSPEC,
116 	.name		= "mac",
117	.version	= XTABLES_VERSION,
118	.size		= XT_ALIGN(sizeof(struct xt_mac_info)),
119	.userspacesize	= XT_ALIGN(sizeof(struct xt_mac_info)),
120	.help		= mac_help,
121	.parse		= mac_parse,
122	.final_check	= mac_check,
123	.print		= mac_print,
124	.save		= mac_save,
125	.extra_opts	= mac_opts,
126};
127
128void _init(void)
129{
130	xtables_register_match(&mac_match);
131}
132