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