blob: 5779e8b649384cb188ce3818a96f5e638f8aef4c [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':
Harald Welteb77f1da2002-03-14 11:35:58 +000075 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000076 parse_mac(argv[optind-1], macinfo);
77 if (invert)
78 macinfo->invert = 1;
79 *flags = 1;
80 break;
81
82 default:
83 return 0;
84 }
85
86 return 1;
87}
88
89static void print_mac(unsigned char macaddress[ETH_ALEN], int invert)
90{
91 unsigned int i;
92
93 printf("%s%02X", invert ? "!" : "", macaddress[0]);
94 for (i = 1; i < ETH_ALEN; i++)
95 printf(":%02X", macaddress[i]);
96 printf(" ");
97}
98
99/* Final check; must have specified --mac. */
100static void final_check(unsigned int flags)
101{
102 if (!flags)
103 exit_error(PARAMETER_PROBLEM,
104 "You must specify `--mac-source'");
105}
106
107/* Prints out the matchinfo. */
108static void
109print(const struct ipt_ip *ip,
110 const struct ipt_entry_match *match,
111 int numeric)
112{
113 printf("MAC ");
114 print_mac(((struct ipt_mac_info *)match->data)->srcaddr,
115 ((struct ipt_mac_info *)match->data)->invert);
116}
117
118/* Saves the union ipt_matchinfo in parsable form to stdout. */
119static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
120{
121 printf("--mac ");
122 print_mac(((struct ipt_mac_info *)match->data)->srcaddr,
123 ((struct ipt_mac_info *)match->data)->invert);
124}
125
Harald Welte3efb6ea2001-08-06 18:50:21 +0000126static
Marc Bouchere6869a82000-03-20 06:03:29 +0000127struct iptables_match mac
128= { NULL,
129 "mac",
130 NETFILTER_VERSION,
Rusty Russell73f72f52000-07-03 10:17:57 +0000131 IPT_ALIGN(sizeof(struct ipt_mac_info)),
132 IPT_ALIGN(sizeof(struct ipt_mac_info)),
Marc Bouchere6869a82000-03-20 06:03:29 +0000133 &help,
134 &init,
135 &parse,
136 &final_check,
137 &print,
138 &save,
139 opts
140};
141
142void _init(void)
143{
144 register_match(&mac);
145}