fix for f12, gcc4.4
[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 static void
32 parse_mac(const char *mac, struct ipt_mac_info *info)
33 {
34         unsigned int i = 0;
35
36         if (strlen(mac) != ETH_ALEN*3-1)
37                 exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
38
39         for (i = 0; i < ETH_ALEN; i++) {
40                 long number;
41                 char *end;
42
43                 number = strtol(mac + i*3, &end, 16);
44
45                 if (end == mac + i*3 + 2
46                     && number >= 0
47                     && number <= 255)
48                         info->srcaddr[i] = number;
49                 else
50                         exit_error(PARAMETER_PROBLEM,
51                                    "Bad mac address `%s'", mac);
52         }
53 }
54
55 /* Function which parses command options; returns true if it
56    ate an option */
57 static int
58 parse(int c, char **argv, int invert, unsigned int *flags,
59       const struct ipt_entry *entry,
60       unsigned int *nfcache,
61       struct ipt_entry_match **match)
62 {
63         struct ipt_mac_info *macinfo = (struct ipt_mac_info *)(*match)->data;
64
65         switch (c) {
66         case '1':
67                 check_inverse(optarg, &invert, &optind, 0);
68                 parse_mac(argv[optind-1], macinfo);
69                 if (invert)
70                         macinfo->invert = 1;
71                 *flags = 1;
72                 break;
73
74         default:
75                 return 0;
76         }
77
78         return 1;
79 }
80
81 static void print_mac(unsigned char macaddress[ETH_ALEN])
82 {
83         unsigned int i;
84
85         printf("%02X", macaddress[0]);
86         for (i = 1; i < ETH_ALEN; i++)
87                 printf(":%02X", macaddress[i]);
88         printf(" ");
89 }
90
91 /* Final check; must have specified --mac. */
92 static void final_check(unsigned int flags)
93 {
94         if (!flags)
95                 exit_error(PARAMETER_PROBLEM,
96                            "You must specify `--mac-source'");
97 }
98
99 /* Prints out the matchinfo. */
100 static void
101 print(const struct ipt_ip *ip,
102       const struct ipt_entry_match *match,
103       int numeric)
104 {
105         printf("MAC ");
106
107         if (((struct ipt_mac_info *)match->data)->invert)
108                 printf("! ");
109         
110         print_mac(((struct ipt_mac_info *)match->data)->srcaddr);
111 }
112
113 /* Saves the union ipt_matchinfo in parsable form to stdout. */
114 static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
115 {
116         if (((struct ipt_mac_info *)match->data)->invert)
117                 printf("! ");
118
119         printf("--mac-source ");
120         print_mac(((struct ipt_mac_info *)match->data)->srcaddr);
121 }
122
123 static struct iptables_match mac = { 
124         .next           = NULL,
125         .name           = "mac",
126         .version        = IPTABLES_VERSION,
127         .size           = IPT_ALIGN(sizeof(struct ipt_mac_info)),
128         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_mac_info)),
129         .help           = &help,
130         .parse          = &parse,
131         .final_check    = &final_check,
132         .print          = &print,
133         .save           = &save,
134         .extra_opts     = opts
135 };
136
137 void _init(void)
138 {
139         register_match(&mac);
140 }