| /* |
| * Arturo Borrero Gonzalez <arturo@debian.org> adapted |
| * this code to libxtables for arptables-compat in 2015 |
| */ |
| |
| #include <stdio.h> |
| #include <netdb.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <limits.h> |
| #include <getopt.h> |
| #include <netinet/ether.h> |
| #include <xtables.h> |
| #include <linux/netfilter_arp/arpt_mangle.h> |
| #include "iptables/nft.h" |
| #include "iptables/nft-arp.h" |
| |
| static void arpmangle_print_help(void) |
| { |
| printf( |
| "mangle target options:\n" |
| "--mangle-ip-s IP address\n" |
| "--mangle-ip-d IP address\n" |
| "--mangle-mac-s MAC address\n" |
| "--mangle-mac-d MAC address\n" |
| "--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n"); |
| } |
| |
| #define MANGLE_IPS '1' |
| #define MANGLE_IPT '2' |
| #define MANGLE_DEVS '3' |
| #define MANGLE_DEVT '4' |
| #define MANGLE_TARGET '5' |
| |
| static const struct option arpmangle_opts[] = { |
| { .name = "mangle-ip-s", .has_arg = true, .val = MANGLE_IPS }, |
| { .name = "mangle-ip-d", .has_arg = true, .val = MANGLE_IPT }, |
| { .name = "mangle-mac-s", .has_arg = true, .val = MANGLE_DEVS }, |
| { .name = "mangle-mac-d", .has_arg = true, .val = MANGLE_DEVT }, |
| { .name = "mangle-target", .has_arg = true, .val = MANGLE_TARGET }, |
| XT_GETOPT_TABLEEND, |
| }; |
| |
| static void arpmangle_init(struct xt_entry_target *target) |
| { |
| struct arpt_mangle *mangle = (struct arpt_mangle *)target->data; |
| |
| mangle->target = NF_ACCEPT; |
| } |
| |
| static int |
| arpmangle_parse(int c, char **argv, int invert, unsigned int *flags, |
| const void *entry, struct xt_entry_target **target) |
| { |
| struct arpt_mangle *mangle = (struct arpt_mangle *)(*target)->data; |
| struct in_addr *ipaddr, mask; |
| struct ether_addr *macaddr; |
| const struct arpt_entry *e = (const struct arpt_entry *)entry; |
| unsigned int nr; |
| int ret = 1; |
| |
| memset(&mask, 0, sizeof(mask)); |
| |
| switch (c) { |
| case MANGLE_IPS: |
| xtables_ipparse_any(optarg, &ipaddr, &mask, &nr); |
| mangle->u_s.src_ip.s_addr = ipaddr->s_addr; |
| free(ipaddr); |
| mangle->flags |= ARPT_MANGLE_SIP; |
| break; |
| case MANGLE_IPT: |
| xtables_ipparse_any(optarg, &ipaddr, &mask, &nr); |
| mangle->u_t.tgt_ip.s_addr = ipaddr->s_addr; |
| free(ipaddr); |
| mangle->flags |= ARPT_MANGLE_TIP; |
| break; |
| case MANGLE_DEVS: |
| if (e->arp.arhln_mask == 0) |
| xtables_error(PARAMETER_PROBLEM, |
| "no --h-length defined"); |
| if (e->arp.invflags & ARPT_INV_ARPHLN) |
| xtables_error(PARAMETER_PROBLEM, |
| "! --h-length not allowed for " |
| "--mangle-mac-s"); |
| if (e->arp.arhln != 6) |
| xtables_error(PARAMETER_PROBLEM, |
| "only --h-length 6 supported"); |
| macaddr = ether_aton(optarg); |
| if (macaddr == NULL) |
| xtables_error(PARAMETER_PROBLEM, |
| "invalid source MAC"); |
| memcpy(mangle->src_devaddr, macaddr, e->arp.arhln); |
| mangle->flags |= ARPT_MANGLE_SDEV; |
| break; |
| case MANGLE_DEVT: |
| if (e->arp.arhln_mask == 0) |
| xtables_error(PARAMETER_PROBLEM, |
| "no --h-length defined"); |
| if (e->arp.invflags & ARPT_INV_ARPHLN) |
| xtables_error(PARAMETER_PROBLEM, |
| "! hln not allowed for --mangle-mac-d"); |
| if (e->arp.arhln != 6) |
| xtables_error(PARAMETER_PROBLEM, |
| "only --h-length 6 supported"); |
| macaddr = ether_aton(optarg); |
| if (macaddr == NULL) |
| xtables_error(PARAMETER_PROBLEM, "invalid target MAC"); |
| memcpy(mangle->tgt_devaddr, macaddr, e->arp.arhln); |
| mangle->flags |= ARPT_MANGLE_TDEV; |
| break; |
| case MANGLE_TARGET: |
| if (!strcmp(optarg, "DROP")) |
| mangle->target = NF_DROP; |
| else if (!strcmp(optarg, "ACCEPT")) |
| mangle->target = NF_ACCEPT; |
| else if (!strcmp(optarg, "CONTINUE")) |
| mangle->target = XT_CONTINUE; |
| else |
| xtables_error(PARAMETER_PROBLEM, |
| "bad target for --mangle-target"); |
| break; |
| default: |
| ret = 0; |
| } |
| |
| return ret; |
| } |
| |
| static void arpmangle_final_check(unsigned int flags) |
| { |
| } |
| |
| static const char *ipaddr_to(const struct in_addr *addrp, int numeric) |
| { |
| if (numeric) |
| return xtables_ipaddr_to_numeric(addrp); |
| else |
| return xtables_ipaddr_to_anyname(addrp); |
| } |
| |
| static void |
| arpmangle_print(const void *ip, const struct xt_entry_target *target, |
| int numeric) |
| { |
| struct arpt_mangle *m = (struct arpt_mangle *)(target->data); |
| |
| if (m->flags & ARPT_MANGLE_SIP) { |
| printf(" --mangle-ip-s %s", |
| ipaddr_to(&(m->u_s.src_ip), numeric)); |
| } |
| if (m->flags & ARPT_MANGLE_SDEV) { |
| printf(" --mangle-mac-s "); |
| xtables_print_mac((unsigned char *)m->src_devaddr); |
| } |
| if (m->flags & ARPT_MANGLE_TIP) { |
| printf(" --mangle-ip-d %s", |
| ipaddr_to(&(m->u_t.tgt_ip), numeric)); |
| } |
| if (m->flags & ARPT_MANGLE_TDEV) { |
| printf(" --mangle-mac-d "); |
| xtables_print_mac((unsigned char *)m->tgt_devaddr); |
| } |
| if (m->target != NF_ACCEPT) { |
| printf(" --mangle-target %s", |
| m->target == NF_DROP ? "DROP" : "CONTINUE"); |
| } |
| } |
| |
| static void arpmangle_save(const void *ip, const struct xt_entry_target *target) |
| { |
| arpmangle_print(ip, target, 0); |
| } |
| |
| static struct xtables_target arpmangle_target = { |
| .name = "mangle", |
| .revision = 0, |
| .version = XTABLES_VERSION, |
| .family = NFPROTO_ARP, |
| .size = XT_ALIGN(sizeof(struct arpt_mangle)), |
| .userspacesize = XT_ALIGN(sizeof(struct arpt_mangle)), |
| .help = arpmangle_print_help, |
| .init = arpmangle_init, |
| .parse = arpmangle_parse, |
| .final_check = arpmangle_final_check, |
| .print = arpmangle_print, |
| .save = arpmangle_save, |
| .extra_opts = arpmangle_opts, |
| }; |
| |
| void _init(void) |
| { |
| xtables_register_target(&arpmangle_target); |
| } |