libxt_mac.c revision 967279231a9ecfa99f26694a954afc535c63db1d
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
15/* Function which prints out usage message. */
16static void mac_help(void)
17{
18	printf(
19"mac match options:\n"
20"[!] --mac-source XX:XX:XX:XX:XX:XX\n"
21"				Match source MAC address\n");
22}
23
24static const struct option mac_opts[] = {
25	{ "mac-source", 1, NULL, '1' },
26	{ .name = NULL }
27};
28
29static void
30parse_mac(const char *mac, struct xt_mac_info *info)
31{
32	unsigned int i = 0;
33
34	if (strlen(mac) != ETH_ALEN*3-1)
35		exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
36
37	for (i = 0; i < ETH_ALEN; i++) {
38		long number;
39		char *end;
40
41		number = strtol(mac + i*3, &end, 16);
42
43		if (end == mac + i*3 + 2
44		    && number >= 0
45		    && number <= 255)
46			info->srcaddr[i] = number;
47		else
48			exit_error(PARAMETER_PROBLEM,
49				   "Bad mac address `%s'", mac);
50	}
51}
52
53/* Function which parses command options; returns true if it
54   ate an option */
55static int
56mac_parse(int c, char **argv, int invert, unsigned int *flags,
57          const void *entry, struct xt_entry_match **match)
58{
59	struct xt_mac_info *macinfo = (struct xt_mac_info *)(*match)->data;
60
61	switch (c) {
62	case '1':
63		check_inverse(optarg, &invert, &optind, 0);
64		parse_mac(argv[optind-1], macinfo);
65		if (invert)
66			macinfo->invert = 1;
67		*flags = 1;
68		break;
69
70	default:
71		return 0;
72	}
73
74	return 1;
75}
76
77static void print_mac(unsigned char macaddress[ETH_ALEN])
78{
79	unsigned int i;
80
81	printf("%02X", macaddress[0]);
82	for (i = 1; i < ETH_ALEN; i++)
83		printf(":%02X", macaddress[i]);
84	printf(" ");
85}
86
87/* Final check; must have specified --mac. */
88static void mac_check(unsigned int flags)
89{
90	if (!flags)
91		exit_error(PARAMETER_PROBLEM,
92			   "You must specify `--mac-source'");
93}
94
95/* Prints out the matchinfo. */
96static void
97mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
98{
99	printf("MAC ");
100
101	if (((struct xt_mac_info *)match->data)->invert)
102		printf("! ");
103
104	print_mac(((struct xt_mac_info *)match->data)->srcaddr);
105}
106
107/* Saves the union ipt_matchinfo in parsable form to stdout. */
108static void mac_save(const void *ip, const struct xt_entry_match *match)
109{
110	if (((struct xt_mac_info *)match->data)->invert)
111		printf("! ");
112
113	printf("--mac-source ");
114	print_mac(((struct xt_mac_info *)match->data)->srcaddr);
115}
116
117static struct xtables_match mac_match = {
118	.family		= AF_INET,
119 	.name		= "mac",
120	.version	= XTABLES_VERSION,
121	.size		= XT_ALIGN(sizeof(struct xt_mac_info)),
122	.userspacesize	= XT_ALIGN(sizeof(struct xt_mac_info)),
123	.help		= mac_help,
124	.parse		= mac_parse,
125	.final_check	= mac_check,
126	.print		= mac_print,
127	.save		= mac_save,
128	.extra_opts	= mac_opts,
129};
130
131static struct xtables_match mac_match6 = {
132	.family		= AF_INET6,
133 	.name		= "mac",
134	.version	= XTABLES_VERSION,
135	.size		= XT_ALIGN(sizeof(struct xt_mac_info)),
136	.userspacesize	= XT_ALIGN(sizeof(struct xt_mac_info)),
137	.help		= mac_help,
138	.parse		= mac_parse,
139	.final_check	= mac_check,
140	.print		= mac_print,
141	.save		= mac_save,
142	.extra_opts	= mac_opts,
143};
144
145void _init(void)
146{
147	xtables_register_match(&mac_match);
148	xtables_register_match(&mac_match6);
149}
150