1/*
2
3	macsave match (experimental)
4	Copyright (C) 2006 Jonathan Zarate
5
6	Licensed under GNU GPL v2 or later.
7
8*/
9#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <getopt.h>
13
14#include <iptables.h>
15#include <linux/netfilter_ipv4/ipt_macsave.h>
16
17
18static void help(void)
19{
20	printf(
21		"macsave match (experimental) v0.01\n"
22		"Copyright (C) 2006 Jonathan Zarate\n"
23		"Options:\n"
24		"[!] --mac <mac address>\n");
25}
26
27static void init(struct ipt_entry_match *m, unsigned int *nfcache)
28{
29	*nfcache |= NFC_UNKNOWN;
30}
31
32static struct option opts[] = {
33	{ .name = "mac",  .has_arg = 1, .flag = 0, .val = '1' },
34	{ .name = 0 }
35};
36
37static int parse(int c, char **argv, int invert, unsigned int *flags,
38				 const struct ipt_entry *entry, unsigned int *nfcache,
39				 struct ipt_entry_match **match)
40{
41	struct ipt_macsave_match_info *info;
42	char *mac;
43	long n;
44	int i;
45
46	if (c != '1') return 0;
47
48	if (*flags) exit_error(PARAMETER_PROBLEM, "Multiple MACs are not supported");
49	*flags = 1;
50
51	info = (struct ipt_macsave_match_info *)(*match)->data;
52
53	check_inverse(optarg, &invert, &optind, 0);
54	if (invert) info->invert = 1;
55
56	mac = argv[optind - 1];
57	i = 0;
58	while (*mac) {
59		n = strtol(mac, &mac, 16);
60		if ((n < 0) || (n > 255)) break;
61		info->mac[i++] = n;
62		if (i == 6) break;
63		if ((*mac != ':') && (*mac != '-')) exit_error(PARAMETER_PROBLEM, "Invalid MAC address");
64		++mac;
65	}
66	if ((i != 6) || (*mac != 0)) exit_error(PARAMETER_PROBLEM, "Invalid MAC address");
67	return 1;
68}
69
70static void final_check(unsigned int flags)
71{
72	if (flags != 1) exit_error(PARAMETER_PROBLEM, "--mac expected");
73}
74
75static void print_match(const struct ipt_macsave_match_info *info)
76{
77	printf("--mac %02X:%02X:%02X:%02X:%02X:%02X ",
78		info->mac[0], info->mac[1], info->mac[2],
79		info->mac[3], info->mac[4], info->mac[5]);
80}
81
82static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
83{
84	printf("macsave ");
85	print_match((const struct ipt_macsave_match_info *)match->data);
86}
87
88static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
89{
90	print_match((const struct ipt_macsave_match_info *)match->data);
91}
92
93
94static struct iptables_match macsave_match = {
95	.name          = "macsave",
96	.version       = IPTABLES_VERSION,
97	.size          = IPT_ALIGN(sizeof(struct ipt_macsave_match_info)),
98	.userspacesize = IPT_ALIGN(sizeof(struct ipt_macsave_match_info)),
99	.help          = &help,
100	.init          = &init,
101	.parse         = &parse,
102	.final_check   = &final_check,
103	.print         = &print,
104	.save          = &save,
105	.extra_opts    = opts
106};
107
108void _init(void)
109{
110	register_match(&macsave_match);
111}
112