blob: 36d896927b78a09712f4d2f95021a96ebba19c34 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* 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 <iptables.h>
13#include <linux/netfilter_ipv4/ipt_mac.h>
14
15/* Function which prints out usage message. */
16static void
17help(void)
18{
19 printf(
20"MAC v%s options:\n"
21" --mac-source [!] XX:XX:XX:XX:XX:XX\n"
22" Match source MAC address\n"
23"\n", NETFILTER_VERSION);
24}
25
26static struct option opts[] = {
27 { "mac-source", 1, 0, '1' },
28 {0}
29};
30
31/* Initialize the match. */
32static void
33init(struct ipt_entry_match *m, unsigned int *nfcache)
34{
35 /* Can't cache this */
36 *nfcache |= NFC_UNKNOWN;
37}
38
39static void
40parse_mac(const char *mac, struct ipt_mac_info *info)
41{
42 unsigned int i = 0;
43
44 if (strlen(mac) != ETH_ALEN*3-1)
45 exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
46
47 for (i = 0; i < ETH_ALEN; i++) {
48 long number;
49 char *end;
50
51 number = strtol(mac + i*3, &end, 16);
52
53 if (end == mac + i*3 + 2
54 && number >= 0
55 && number <= 255)
56 info->srcaddr[i] = number;
57 else
58 exit_error(PARAMETER_PROBLEM,
59 "Bad mac address `%s'", mac);
60 }
61}
62
63/* Function which parses command options; returns true if it
64 ate an option */
65static int
66parse(int c, char **argv, int invert, unsigned int *flags,
67 const struct ipt_entry *entry,
68 unsigned int *nfcache,
69 struct ipt_entry_match **match)
70{
71 struct ipt_mac_info *macinfo = (struct ipt_mac_info *)(*match)->data;
72
73 switch (c) {
74 case '1':
75 if (check_inverse(optarg, &invert))
76 optind++;
77 parse_mac(argv[optind-1], macinfo);
78 if (invert)
79 macinfo->invert = 1;
80 *flags = 1;
81 break;
82
83 default:
84 return 0;
85 }
86
87 return 1;
88}
89
90static void print_mac(unsigned char macaddress[ETH_ALEN], int invert)
91{
92 unsigned int i;
93
94 printf("%s%02X", invert ? "!" : "", macaddress[0]);
95 for (i = 1; i < ETH_ALEN; i++)
96 printf(":%02X", macaddress[i]);
97 printf(" ");
98}
99
100/* Final check; must have specified --mac. */
101static void final_check(unsigned int flags)
102{
103 if (!flags)
104 exit_error(PARAMETER_PROBLEM,
105 "You must specify `--mac-source'");
106}
107
108/* Prints out the matchinfo. */
109static void
110print(const struct ipt_ip *ip,
111 const struct ipt_entry_match *match,
112 int numeric)
113{
114 printf("MAC ");
115 print_mac(((struct ipt_mac_info *)match->data)->srcaddr,
116 ((struct ipt_mac_info *)match->data)->invert);
117}
118
119/* Saves the union ipt_matchinfo in parsable form to stdout. */
120static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
121{
122 printf("--mac ");
123 print_mac(((struct ipt_mac_info *)match->data)->srcaddr,
124 ((struct ipt_mac_info *)match->data)->invert);
125}
126
127struct iptables_match mac
128= { NULL,
129 "mac",
130 NETFILTER_VERSION,
131 sizeof(struct ipt_mac_info),
132 &help,
133 &init,
134 &parse,
135 &final_check,
136 &print,
137 &save,
138 opts
139};
140
141void _init(void)
142{
143 register_match(&mac);
144}