iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libipt_mac.c
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 <iptables.h>
13 #include <linux/netfilter_ipv4/ipt_mac.h>
14
15 /* Function which prints out usage message. */
16 static void
17 help(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", IPTABLES_VERSION);
24 }
25
26 static struct option opts[] = {
27         { "mac-source", 1, 0, '1' },
28         {0}
29 };
30
31 /* Initialize the match. */
32 static void
33 init(struct ipt_entry_match *m, unsigned int *nfcache)
34 {
35         /* Can't cache this */
36         *nfcache |= NFC_UNKNOWN;
37 }
38
39 static void
40 parse_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 */
65 static int
66 parse(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                 check_inverse(optarg, &invert, &optind, 0);
76                 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
89 static void print_mac(unsigned char macaddress[ETH_ALEN])
90 {
91         unsigned int i;
92
93         printf("%02X", 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. */
100 static 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. */
108 static void
109 print(const struct ipt_ip *ip,
110       const struct ipt_entry_match *match,
111       int numeric)
112 {
113         printf("MAC ");
114
115         if (((struct ipt_mac_info *)match->data)->invert)
116                 printf("! ");
117         
118         print_mac(((struct ipt_mac_info *)match->data)->srcaddr);
119 }
120
121 /* Saves the union ipt_matchinfo in parsable form to stdout. */
122 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
123 {
124         if (((struct ipt_mac_info *)match->data)->invert)
125                 printf("! ");
126
127         printf("--mac-source ");
128         print_mac(((struct ipt_mac_info *)match->data)->srcaddr);
129 }
130
131 static
132 struct iptables_match mac
133 = { NULL,
134     "mac",
135     IPTABLES_VERSION,
136     IPT_ALIGN(sizeof(struct ipt_mac_info)),
137     IPT_ALIGN(sizeof(struct ipt_mac_info)),
138     &help,
139     &init,
140     &parse,
141     &final_check,
142     &print,
143     &save,
144     opts
145 };
146
147 void _init(void)
148 {
149         register_match(&mac);
150 }