blob: 2284d2ac151f6ef647a9a05aaab9ff663241c50e [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
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +000012#include <xtables.h>
13#include <linux/netfilter/xt_mac.h>
Marc Bouchere6869a82000-03-20 06:03:29 +000014
15/* Function which prints out usage message. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000016static void mac_help(void)
Marc Bouchere6869a82000-03-20 06:03:29 +000017{
18 printf(
19"MAC v%s options:\n"
20" --mac-source [!] XX:XX:XX:XX:XX:XX\n"
21" Match source MAC address\n"
Harald Welte80fe35d2002-05-29 13:08:15 +000022"\n", IPTABLES_VERSION);
Marc Bouchere6869a82000-03-20 06:03:29 +000023}
24
Jan Engelhardt181dead2007-10-04 16:27:07 +000025static const struct option mac_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000026 { "mac-source", 1, NULL, '1' },
Max Kellermann9ee386a2008-01-29 13:48:05 +000027 { .name = NULL }
Marc Bouchere6869a82000-03-20 06:03:29 +000028};
29
Marc Bouchere6869a82000-03-20 06:03:29 +000030static void
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +000031parse_mac(const char *mac, struct xt_mac_info *info)
Marc Bouchere6869a82000-03-20 06:03:29 +000032{
33 unsigned int i = 0;
34
35 if (strlen(mac) != ETH_ALEN*3-1)
36 exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
37
38 for (i = 0; i < ETH_ALEN; i++) {
39 long number;
40 char *end;
41
42 number = strtol(mac + i*3, &end, 16);
43
44 if (end == mac + i*3 + 2
45 && number >= 0
46 && number <= 255)
47 info->srcaddr[i] = number;
48 else
49 exit_error(PARAMETER_PROBLEM,
50 "Bad mac address `%s'", mac);
51 }
52}
53
54/* Function which parses command options; returns true if it
55 ate an option */
56static int
Jan Engelhardt181dead2007-10-04 16:27:07 +000057mac_parse(int c, char **argv, int invert, unsigned int *flags,
58 const void *entry, struct xt_entry_match **match)
Marc Bouchere6869a82000-03-20 06:03:29 +000059{
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +000060 struct xt_mac_info *macinfo = (struct xt_mac_info *)(*match)->data;
Marc Bouchere6869a82000-03-20 06:03:29 +000061
62 switch (c) {
63 case '1':
Harald Welteb77f1da2002-03-14 11:35:58 +000064 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000065 parse_mac(argv[optind-1], macinfo);
66 if (invert)
67 macinfo->invert = 1;
68 *flags = 1;
69 break;
70
71 default:
72 return 0;
73 }
74
75 return 1;
76}
77
Dave Zambonini78c57fa2003-06-14 14:27:51 +000078static void print_mac(unsigned char macaddress[ETH_ALEN])
Marc Bouchere6869a82000-03-20 06:03:29 +000079{
80 unsigned int i;
81
Dave Zambonini78c57fa2003-06-14 14:27:51 +000082 printf("%02X", macaddress[0]);
Marc Bouchere6869a82000-03-20 06:03:29 +000083 for (i = 1; i < ETH_ALEN; i++)
84 printf(":%02X", macaddress[i]);
85 printf(" ");
86}
87
88/* Final check; must have specified --mac. */
Jan Engelhardt181dead2007-10-04 16:27:07 +000089static void mac_check(unsigned int flags)
Marc Bouchere6869a82000-03-20 06:03:29 +000090{
91 if (!flags)
92 exit_error(PARAMETER_PROBLEM,
93 "You must specify `--mac-source'");
94}
95
96/* Prints out the matchinfo. */
97static void
Jan Engelhardt181dead2007-10-04 16:27:07 +000098mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
Marc Bouchere6869a82000-03-20 06:03:29 +000099{
100 printf("MAC ");
Dave Zambonini78c57fa2003-06-14 14:27:51 +0000101
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000102 if (((struct xt_mac_info *)match->data)->invert)
Dave Zambonini78c57fa2003-06-14 14:27:51 +0000103 printf("! ");
104
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000105 print_mac(((struct xt_mac_info *)match->data)->srcaddr);
Marc Bouchere6869a82000-03-20 06:03:29 +0000106}
107
108/* Saves the union ipt_matchinfo in parsable form to stdout. */
Jan Engelhardt181dead2007-10-04 16:27:07 +0000109static void mac_save(const void *ip, const struct xt_entry_match *match)
Marc Bouchere6869a82000-03-20 06:03:29 +0000110{
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000111 if (((struct xt_mac_info *)match->data)->invert)
Dave Zambonini78c57fa2003-06-14 14:27:51 +0000112 printf("! ");
113
Michael Schwendt010491f2002-09-12 07:14:55 +0000114 printf("--mac-source ");
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000115 print_mac(((struct xt_mac_info *)match->data)->srcaddr);
Marc Bouchere6869a82000-03-20 06:03:29 +0000116}
117
Jan Engelhardt181dead2007-10-04 16:27:07 +0000118static struct xtables_match mac_match = {
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000119 .family = AF_INET,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000120 .name = "mac",
121 .version = IPTABLES_VERSION,
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000122 .size = XT_ALIGN(sizeof(struct xt_mac_info)),
123 .userspacesize = XT_ALIGN(sizeof(struct xt_mac_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000124 .help = mac_help,
125 .parse = mac_parse,
126 .final_check = mac_check,
127 .print = mac_print,
128 .save = mac_save,
129 .extra_opts = mac_opts,
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000130};
131
Jan Engelhardt181dead2007-10-04 16:27:07 +0000132static struct xtables_match mac_match6 = {
Yasuyuki KOZAKAIba2d8912007-07-24 07:09:51 +0000133 .family = AF_INET6,
134 .name = "mac",
135 .version = IPTABLES_VERSION,
136 .size = XT_ALIGN(sizeof(struct xt_mac_info)),
137 .userspacesize = XT_ALIGN(sizeof(struct xt_mac_info)),
Jan Engelhardt181dead2007-10-04 16:27:07 +0000138 .help = mac_help,
139 .parse = mac_parse,
140 .final_check = mac_check,
141 .print = mac_print,
142 .save = mac_save,
143 .extra_opts = mac_opts,
Marc Bouchere6869a82000-03-20 06:03:29 +0000144};
145
146void _init(void)
147{
Jan Engelhardt181dead2007-10-04 16:27:07 +0000148 xtables_register_match(&mac_match);
149 xtables_register_match(&mac_match6);
Marc Bouchere6869a82000-03-20 06:03:29 +0000150}