blob: 7e5f113e0b29d93201cc051aaa348f868b1cc715 [file] [log] [blame]
Bart De Schuymer5a824802003-08-14 19:24:25 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <netinet/ether.h>
5#include <getopt.h>
6#include "../include/ebtables_u.h"
7#include <linux/netfilter_bridge/ebt_arpreply.h>
8
9static int mac_supplied;
10
11#define REPLY_MAC '1'
12#define REPLY_TARGET '2'
13static struct option opts[] =
14{
15 { "arpreply-mac" , required_argument, 0, REPLY_MAC },
16 { "arpreply-target" , required_argument, 0, REPLY_TARGET },
17 { 0 }
18};
19
20static void print_help()
21{
22 printf(
23 "arpreply target options:\n"
24 " --arpreply-mac address : source MAC of generated reply\n"
25 " --arpreply-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
26 " (standard target is DROP)\n");
27}
28
29static void init(struct ebt_entry_target *target)
30{
31 struct ebt_arpreply_info *replyinfo =
32 (struct ebt_arpreply_info *)target->data;
33
34 replyinfo->target = EBT_DROP;
35 memset(replyinfo->mac, 0, ETH_ALEN);
36 mac_supplied = 0;
37}
38
39#define OPT_REPLY_MAC 0x01
40#define OPT_REPLY_TARGET 0x02
41static int parse(int c, char **argv, int argc,
42 const struct ebt_u_entry *entry, unsigned int *flags,
43 struct ebt_entry_target **target)
44{
45 struct ebt_arpreply_info *replyinfo =
46 (struct ebt_arpreply_info *)(*target)->data;
47 struct ether_addr *addr;
48
49 switch (c) {
50 case REPLY_MAC:
51 check_option(flags, OPT_REPLY_MAC);
52 if (!(addr = ether_aton(optarg)))
53 print_error("Problem with specified "
54 "--arpreply-mac mac");
55 memcpy(replyinfo->mac, addr, ETH_ALEN);
56 mac_supplied = 1;
57 break;
58 case REPLY_TARGET:
59 check_option(flags, OPT_REPLY_TARGET);
60 if (FILL_TARGET(optarg, replyinfo->target))
61 print_error("Illegal --arpreply-target target");
62 break;
63
64 default:
65 return 0;
66 }
67 return 1;
68}
69
70static void final_check(const struct ebt_u_entry *entry,
71 const struct ebt_entry_target *target, const char *name,
72 unsigned int hookmask, unsigned int time)
73{
74 struct ebt_arpreply_info *replyinfo =
75 (struct ebt_arpreply_info *)target->data;
76
77 if (entry->ethproto != ETH_P_ARP || entry->invflags & EBT_IPROTO)
78 print_error("For ARP replying the protocol must be "
79 "specified as ARP");
80 if (time == 0 && mac_supplied == 0)
81 print_error("No arpreply mac supplied");
82 if (BASE_CHAIN && replyinfo->target == EBT_RETURN)
83 print_error("--arpreply-target RETURN not allowed on "
84 "base chain");
85 CLEAR_BASE_CHAIN_BIT;
86 if (strcmp(name, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING))
87 print_error("arpreply only allowed in PREROUTING");
88}
89
90static void print(const struct ebt_u_entry *entry,
91 const struct ebt_entry_target *target)
92{
93 struct ebt_arpreply_info *replyinfo =
94 (struct ebt_arpreply_info *)target->data;
95
96 printf("--arpreply-mac ");
97 print_mac(replyinfo->mac);
98 if (replyinfo->target == EBT_DROP)
99 return;
100 printf(" --arpreply-target %s", TARGET_NAME(replyinfo->target));
101}
102
103static int compare(const struct ebt_entry_target *t1,
104 const struct ebt_entry_target *t2)
105{
106 struct ebt_arpreply_info *replyinfo1 =
107 (struct ebt_arpreply_info *)t1->data;
108 struct ebt_arpreply_info *replyinfo2 =
109 (struct ebt_arpreply_info *)t2->data;
110
111 return memcmp(replyinfo1->mac, replyinfo2->mac, ETH_ALEN) == 0
112 && replyinfo1->target == replyinfo2->target;
113}
114
115static struct ebt_u_target arpreply_target =
116{
Bart De Schuymer7cf1cca2003-08-30 16:20:19 +0000117 .name = EBT_ARPREPLY_TARGET,
118 .size = sizeof(struct ebt_arpreply_info),
119 .help = print_help,
120 .init = init,
121 .parse = parse,
122 .final_check = final_check,
123 .print = print,
124 .compare = compare,
125 .extra_ops = opts,
Bart De Schuymer5a824802003-08-14 19:24:25 +0000126};
127
128static void _init(void) __attribute__ ((constructor));
129static void _init(void)
130{
131 register_target(&arpreply_target);
132}