1 /* 2 * Arturo Borrero Gonzalez <arturo (at) debian.org> adapted 3 * this code to libxtables for arptables-compat in 2015 4 */ 5 6 #include <stdio.h> 7 #include <netdb.h> 8 #include <string.h> 9 #include <stdlib.h> 10 #include <limits.h> 11 #include <getopt.h> 12 #include <netinet/ether.h> 13 #include <xtables.h> 14 #include <linux/netfilter_arp/arpt_mangle.h> 15 #include "iptables/nft.h" 16 #include "iptables/nft-arp.h" 17 18 static void arpmangle_print_help(void) 19 { 20 printf( 21 "mangle target options:\n" 22 "--mangle-ip-s IP address\n" 23 "--mangle-ip-d IP address\n" 24 "--mangle-mac-s MAC address\n" 25 "--mangle-mac-d MAC address\n" 26 "--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n"); 27 } 28 29 #define MANGLE_IPS '1' 30 #define MANGLE_IPT '2' 31 #define MANGLE_DEVS '3' 32 #define MANGLE_DEVT '4' 33 #define MANGLE_TARGET '5' 34 35 static struct option arpmangle_opts[] = { 36 { .name = "mangle-ip-s", .has_arg = true, .val = MANGLE_IPS }, 37 { .name = "mangle-ip-d", .has_arg = true, .val = MANGLE_IPT }, 38 { .name = "mangle-mac-s", .has_arg = true, .val = MANGLE_DEVS }, 39 { .name = "mangle-mac-d", .has_arg = true, .val = MANGLE_DEVT }, 40 { .name = "mangle-target", .has_arg = true, .val = MANGLE_TARGET }, 41 XT_GETOPT_TABLEEND, 42 }; 43 44 static void arpmangle_init(struct xt_entry_target *target) 45 { 46 struct arpt_mangle *mangle = (struct arpt_mangle *)target->data; 47 48 mangle->target = NF_ACCEPT; 49 } 50 51 static int 52 arpmangle_parse(int c, char **argv, int invert, unsigned int *flags, 53 const void *entry, struct xt_entry_target **target) 54 { 55 struct arpt_mangle *mangle = (struct arpt_mangle *)(*target)->data; 56 struct in_addr *ipaddr, mask; 57 struct ether_addr *macaddr; 58 const struct arpt_entry *e = (const struct arpt_entry *)entry; 59 unsigned int nr; 60 int ret = 1; 61 62 memset(&mask, 0, sizeof(mask)); 63 64 switch (c) { 65 case MANGLE_IPS: 66 xtables_ipparse_any(optarg, &ipaddr, &mask, &nr); 67 mangle->u_s.src_ip.s_addr = ipaddr->s_addr; 68 free(ipaddr); 69 mangle->flags |= ARPT_MANGLE_SIP; 70 break; 71 case MANGLE_IPT: 72 xtables_ipparse_any(optarg, &ipaddr, &mask, &nr); 73 mangle->u_t.tgt_ip.s_addr = ipaddr->s_addr; 74 free(ipaddr); 75 mangle->flags |= ARPT_MANGLE_TIP; 76 break; 77 case MANGLE_DEVS: 78 if (e->arp.arhln_mask == 0) 79 xtables_error(PARAMETER_PROBLEM, 80 "no --h-length defined"); 81 if (e->arp.invflags & ARPT_INV_ARPHLN) 82 xtables_error(PARAMETER_PROBLEM, 83 "! --h-length not allowed for " 84 "--mangle-mac-s"); 85 if (e->arp.arhln != 6) 86 xtables_error(PARAMETER_PROBLEM, 87 "only --h-length 6 supported"); 88 macaddr = ether_aton(optarg); 89 if (macaddr == NULL) 90 xtables_error(PARAMETER_PROBLEM, 91 "invalid source MAC"); 92 memcpy(mangle->src_devaddr, macaddr, e->arp.arhln); 93 mangle->flags |= ARPT_MANGLE_SDEV; 94 break; 95 case MANGLE_DEVT: 96 if (e->arp.arhln_mask == 0) 97 xtables_error(PARAMETER_PROBLEM, 98 "no --h-length defined"); 99 if (e->arp.invflags & ARPT_INV_ARPHLN) 100 xtables_error(PARAMETER_PROBLEM, 101 "! hln not allowed for --mangle-mac-d"); 102 if (e->arp.arhln != 6) 103 xtables_error(PARAMETER_PROBLEM, 104 "only --h-length 6 supported"); 105 macaddr = ether_aton(optarg); 106 if (macaddr == NULL) 107 xtables_error(PARAMETER_PROBLEM, "invalid target MAC"); 108 memcpy(mangle->tgt_devaddr, macaddr, e->arp.arhln); 109 mangle->flags |= ARPT_MANGLE_TDEV; 110 break; 111 case MANGLE_TARGET: 112 if (!strcmp(optarg, "DROP")) 113 mangle->target = NF_DROP; 114 else if (!strcmp(optarg, "ACCEPT")) 115 mangle->target = NF_ACCEPT; 116 else if (!strcmp(optarg, "CONTINUE")) 117 mangle->target = XT_CONTINUE; 118 else 119 xtables_error(PARAMETER_PROBLEM, 120 "bad target for --mangle-target"); 121 break; 122 default: 123 ret = 0; 124 } 125 126 return ret; 127 } 128 129 static void arpmangle_final_check(unsigned int flags) 130 { 131 } 132 133 static void print_mac(const unsigned char *mac, int l) 134 { 135 int j; 136 137 for (j = 0; j < l; j++) 138 printf("%02x%s", mac[j], 139 (j==l-1) ? "" : ":"); 140 } 141 142 static void 143 arpmangle_print(const void *ip, const struct xt_entry_target *target, 144 int numeric) 145 { 146 struct arpt_mangle *m = (struct arpt_mangle *)(target->data); 147 char buf[100]; 148 149 if (m->flags & ARPT_MANGLE_SIP) { 150 if (numeric) 151 sprintf(buf, "%s", 152 xtables_ipaddr_to_numeric(&(m->u_s.src_ip))); 153 else 154 sprintf(buf, "%s", 155 xtables_ipaddr_to_anyname(&(m->u_s.src_ip))); 156 printf("--mangle-ip-s %s ", buf); 157 } 158 if (m->flags & ARPT_MANGLE_SDEV) { 159 printf("--mangle-mac-s "); 160 print_mac((unsigned char *)m->src_devaddr, 6); 161 printf(" "); 162 } 163 if (m->flags & ARPT_MANGLE_TIP) { 164 if (numeric) 165 sprintf(buf, "%s", 166 xtables_ipaddr_to_numeric(&(m->u_t.tgt_ip))); 167 else 168 sprintf(buf, "%s", 169 xtables_ipaddr_to_anyname(&(m->u_t.tgt_ip))); 170 printf("--mangle-ip-d %s ", buf); 171 } 172 if (m->flags & ARPT_MANGLE_TDEV) { 173 printf("--mangle-mac-d "); 174 print_mac((unsigned char *)m->tgt_devaddr, 6); 175 printf(" "); 176 } 177 if (m->target != NF_ACCEPT) { 178 printf("--mangle-target "); 179 if (m->target == NF_DROP) 180 printf("DROP "); 181 else 182 printf("CONTINUE "); 183 } 184 } 185 186 static struct xtables_target arpmangle_target = { 187 .name = "mangle", 188 .revision = 0, 189 .version = XTABLES_VERSION, 190 .family = NFPROTO_ARP, 191 .size = XT_ALIGN(sizeof(struct arpt_mangle)), 192 .userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)), 193 .help = arpmangle_print_help, 194 .init = arpmangle_init, 195 .parse = arpmangle_parse, 196 .final_check = arpmangle_final_check, 197 .print = arpmangle_print, 198 .extra_opts = arpmangle_opts, 199 }; 200 201 void _init(void) 202 { 203 xtables_register_target(&arpmangle_target); 204 } 205