• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Arturo Borrero Gonzalez <arturo@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 
arpmangle_print_help(void)17 static void arpmangle_print_help(void)
18 {
19 	printf(
20 	"mangle target options:\n"
21 	"--mangle-ip-s IP address\n"
22 	"--mangle-ip-d IP address\n"
23 	"--mangle-mac-s MAC address\n"
24 	"--mangle-mac-d MAC address\n"
25 	"--mangle-target target (DROP, CONTINUE or ACCEPT -- default is ACCEPT)\n");
26 }
27 
28 /* internal use only, explicitly not covered by ARPT_MANGLE_MASK */
29 #define ARPT_MANGLE_TARGET	0x10
30 
31 static const struct xt_option_entry arpmangle_opts[] = {
32 { .name = "mangle-ip-s", .id = ARPT_MANGLE_SIP, .type = XTTYPE_HOSTMASK },
33 { .name = "mangle-ip-d", .id = ARPT_MANGLE_TIP, .type = XTTYPE_HOSTMASK },
34 { .name = "mangle-mac-s", .id = ARPT_MANGLE_SDEV, .type = XTTYPE_ETHERMAC },
35 { .name = "mangle-mac-d", .id = ARPT_MANGLE_TDEV, .type = XTTYPE_ETHERMAC },
36 { .name = "mangle-target", .id = ARPT_MANGLE_TARGET, .type = XTTYPE_STRING },
37 XTOPT_TABLEEND,
38 };
39 
arpmangle_init(struct xt_entry_target * target)40 static void arpmangle_init(struct xt_entry_target *target)
41 {
42 	struct arpt_mangle *mangle = (struct arpt_mangle *)target->data;
43 
44 	mangle->target = NF_ACCEPT;
45 }
46 
assert_hopts(const struct arpt_entry * e,const char * optname)47 static void assert_hopts(const struct arpt_entry *e, const char *optname)
48 {
49 	if (e->arp.arhln_mask == 0)
50 		xtables_error(PARAMETER_PROBLEM, "no --h-length defined");
51 	if (e->arp.invflags & IPT_INV_ARPHLN)
52 		xtables_error(PARAMETER_PROBLEM,
53 			      "! hln not allowed for --%s", optname);
54 	if (e->arp.arhln != 6)
55 		xtables_error(PARAMETER_PROBLEM, "only --h-length 6 supported");
56 }
57 
arpmangle_parse(struct xt_option_call * cb)58 static void arpmangle_parse(struct xt_option_call *cb)
59 {
60 	const struct arpt_entry *e = cb->xt_entry;
61 	struct arpt_mangle *mangle = cb->data;
62 
63 	xtables_option_parse(cb);
64 	mangle->flags |= (cb->entry->id & ARPT_MANGLE_MASK);
65 	switch (cb->entry->id) {
66 	case ARPT_MANGLE_SIP:
67 		mangle->u_s.src_ip = cb->val.haddr.in;
68 		break;
69 	case ARPT_MANGLE_TIP:
70 		mangle->u_t.tgt_ip = cb->val.haddr.in;
71 		break;
72 	case ARPT_MANGLE_SDEV:
73 		assert_hopts(e, cb->entry->name);
74 		memcpy(mangle->src_devaddr, cb->val.ethermac, ETH_ALEN);
75 	case ARPT_MANGLE_TDEV:
76 		assert_hopts(e, cb->entry->name);
77 		memcpy(mangle->tgt_devaddr, cb->val.ethermac, ETH_ALEN);
78 		break;
79 	case ARPT_MANGLE_TARGET:
80 		if (!strcmp(cb->arg, "DROP"))
81 			mangle->target = NF_DROP;
82 		else if (!strcmp(cb->arg, "ACCEPT"))
83 			mangle->target = NF_ACCEPT;
84 		else if (!strcmp(cb->arg, "CONTINUE"))
85 			mangle->target = XT_CONTINUE;
86 		else
87 			xtables_error(PARAMETER_PROBLEM,
88 				      "bad target for --mangle-target");
89 		break;
90 	}
91 }
92 
ipaddr_to(const struct in_addr * addrp,int numeric)93 static const char *ipaddr_to(const struct in_addr *addrp, int numeric)
94 {
95 	if (numeric)
96 		return xtables_ipaddr_to_numeric(addrp);
97 	else
98 		return xtables_ipaddr_to_anyname(addrp);
99 }
100 
101 static void
arpmangle_print(const void * ip,const struct xt_entry_target * target,int numeric)102 arpmangle_print(const void *ip, const struct xt_entry_target *target,
103 		int numeric)
104 {
105 	struct arpt_mangle *m = (struct arpt_mangle *)(target->data);
106 
107 	if (m->flags & ARPT_MANGLE_SIP) {
108 		printf(" --mangle-ip-s %s",
109 		       ipaddr_to(&(m->u_s.src_ip), numeric));
110 	}
111 	if (m->flags & ARPT_MANGLE_SDEV) {
112 		printf(" --mangle-mac-s ");
113 		xtables_print_mac((unsigned char *)m->src_devaddr);
114 	}
115 	if (m->flags & ARPT_MANGLE_TIP) {
116 		printf(" --mangle-ip-d %s",
117 		       ipaddr_to(&(m->u_t.tgt_ip), numeric));
118 	}
119 	if (m->flags & ARPT_MANGLE_TDEV) {
120 		printf(" --mangle-mac-d ");
121 		xtables_print_mac((unsigned char *)m->tgt_devaddr);
122 	}
123 	if (m->target != NF_ACCEPT) {
124 		printf(" --mangle-target %s",
125 		       m->target == NF_DROP ? "DROP" : "CONTINUE");
126 	}
127 }
128 
arpmangle_save(const void * ip,const struct xt_entry_target * target)129 static void arpmangle_save(const void *ip, const struct xt_entry_target *target)
130 {
131 	arpmangle_print(ip, target, 0);
132 }
133 
print_devaddr_xlate(const char * macaddress,struct xt_xlate * xl)134 static void print_devaddr_xlate(const char *macaddress, struct xt_xlate *xl)
135 {
136 	unsigned int i;
137 
138 	xt_xlate_add(xl, "%02x", macaddress[0]);
139 	for (i = 1; i < ETH_ALEN; ++i)
140 		xt_xlate_add(xl, ":%02x", macaddress[i]);
141 }
142 
arpmangle_xlate(struct xt_xlate * xl,const struct xt_xlate_tg_params * params)143 static int arpmangle_xlate(struct xt_xlate *xl,
144 			 const struct xt_xlate_tg_params *params)
145 {
146 	const struct arpt_mangle *m = (const void *)params->target->data;
147 
148 	if (m->flags & ARPT_MANGLE_SIP)
149 		xt_xlate_add(xl, "arp saddr ip set %s ",
150 			     xtables_ipaddr_to_numeric(&m->u_s.src_ip));
151 
152 	if (m->flags & ARPT_MANGLE_SDEV) {
153 		xt_xlate_add(xl, "arp %caddr ether set ", 's');
154 		print_devaddr_xlate(m->src_devaddr, xl);
155 	}
156 
157 	if (m->flags & ARPT_MANGLE_TIP)
158 		xt_xlate_add(xl, "arp daddr ip set %s ",
159 			     xtables_ipaddr_to_numeric(&m->u_t.tgt_ip));
160 
161 	if (m->flags & ARPT_MANGLE_TDEV) {
162 		xt_xlate_add(xl, "arp %caddr ether set ", 'd');
163 		print_devaddr_xlate(m->tgt_devaddr, xl);
164 	}
165 
166 	switch (m->target) {
167 	case NF_ACCEPT:
168 		xt_xlate_add(xl, "accept");
169 		break;
170 	case NF_DROP:
171 		xt_xlate_add(xl, "drop");
172 		break;
173 	default:
174 		break;
175 	}
176 
177 	return 1;
178 }
179 
180 static struct xtables_target arpmangle_target = {
181 	.name		= "mangle",
182 	.revision	= 0,
183 	.version	= XTABLES_VERSION,
184 	.family		= NFPROTO_ARP,
185 	.size		= XT_ALIGN(sizeof(struct arpt_mangle)),
186 	.userspacesize	= XT_ALIGN(sizeof(struct arpt_mangle)),
187 	.help		= arpmangle_print_help,
188 	.init		= arpmangle_init,
189 	.x6_parse	= arpmangle_parse,
190 	.print		= arpmangle_print,
191 	.save		= arpmangle_save,
192 	.x6_options	= arpmangle_opts,
193 	.xlate		= arpmangle_xlate,
194 };
195 
_init(void)196 void _init(void)
197 {
198 	xtables_register_target(&arpmangle_target);
199 }
200