xref: /aosp_15_r20/external/iptables/libiptc/libip6tc.c (revision a71a954618bbadd4a345637e5edcf36eec826889)
1*a71a9546SAutomerger Merge Worker /* Library which manipulates firewall rules.  Version 0.1. */
2*a71a9546SAutomerger Merge Worker 
3*a71a9546SAutomerger Merge Worker /* Architecture of firewall rules is as follows:
4*a71a9546SAutomerger Merge Worker  *
5*a71a9546SAutomerger Merge Worker  * Chains go INPUT, FORWARD, OUTPUT then user chains.
6*a71a9546SAutomerger Merge Worker  * Each user chain starts with an ERROR node.
7*a71a9546SAutomerger Merge Worker  * Every chain ends with an unconditional jump: a RETURN for user chains,
8*a71a9546SAutomerger Merge Worker  * and a POLICY for built-ins.
9*a71a9546SAutomerger Merge Worker  */
10*a71a9546SAutomerger Merge Worker 
11*a71a9546SAutomerger Merge Worker /* (C)1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
12*a71a9546SAutomerger Merge Worker    COPYING for details). */
13*a71a9546SAutomerger Merge Worker 
14*a71a9546SAutomerger Merge Worker #include <assert.h>
15*a71a9546SAutomerger Merge Worker #include <string.h>
16*a71a9546SAutomerger Merge Worker #include <errno.h>
17*a71a9546SAutomerger Merge Worker #include <stdlib.h>
18*a71a9546SAutomerger Merge Worker #include <stdio.h>
19*a71a9546SAutomerger Merge Worker #include <unistd.h>
20*a71a9546SAutomerger Merge Worker #include <arpa/inet.h>
21*a71a9546SAutomerger Merge Worker 
22*a71a9546SAutomerger Merge Worker #ifdef DEBUG_CONNTRACK
23*a71a9546SAutomerger Merge Worker #define inline
24*a71a9546SAutomerger Merge Worker #endif
25*a71a9546SAutomerger Merge Worker 
26*a71a9546SAutomerger Merge Worker #if !defined(__BIONIC__) && (!defined(__GLIBC__) || (__GLIBC__ < 2))
27*a71a9546SAutomerger Merge Worker typedef unsigned int socklen_t;
28*a71a9546SAutomerger Merge Worker #endif
29*a71a9546SAutomerger Merge Worker 
30*a71a9546SAutomerger Merge Worker #include "libiptc/libip6tc.h"
31*a71a9546SAutomerger Merge Worker 
32*a71a9546SAutomerger Merge Worker #define HOOK_PRE_ROUTING	NF_IP6_PRE_ROUTING
33*a71a9546SAutomerger Merge Worker #define HOOK_LOCAL_IN		NF_IP6_LOCAL_IN
34*a71a9546SAutomerger Merge Worker #define HOOK_FORWARD		NF_IP6_FORWARD
35*a71a9546SAutomerger Merge Worker #define HOOK_LOCAL_OUT		NF_IP6_LOCAL_OUT
36*a71a9546SAutomerger Merge Worker #define HOOK_POST_ROUTING	NF_IP6_POST_ROUTING
37*a71a9546SAutomerger Merge Worker 
38*a71a9546SAutomerger Merge Worker #define STRUCT_ENTRY_TARGET	struct xt_entry_target
39*a71a9546SAutomerger Merge Worker #define STRUCT_ENTRY		struct ip6t_entry
40*a71a9546SAutomerger Merge Worker #define STRUCT_ENTRY_MATCH	struct xt_entry_match
41*a71a9546SAutomerger Merge Worker #define STRUCT_GETINFO		struct ip6t_getinfo
42*a71a9546SAutomerger Merge Worker #define STRUCT_GET_ENTRIES	struct ip6t_get_entries
43*a71a9546SAutomerger Merge Worker #define STRUCT_COUNTERS		struct xt_counters
44*a71a9546SAutomerger Merge Worker #define STRUCT_COUNTERS_INFO	struct xt_counters_info
45*a71a9546SAutomerger Merge Worker #define STRUCT_STANDARD_TARGET	struct xt_standard_target
46*a71a9546SAutomerger Merge Worker #define STRUCT_REPLACE		struct ip6t_replace
47*a71a9546SAutomerger Merge Worker 
48*a71a9546SAutomerger Merge Worker #define ENTRY_ITERATE		IP6T_ENTRY_ITERATE
49*a71a9546SAutomerger Merge Worker #define TABLE_MAXNAMELEN	XT_TABLE_MAXNAMELEN
50*a71a9546SAutomerger Merge Worker #define FUNCTION_MAXNAMELEN	XT_FUNCTION_MAXNAMELEN
51*a71a9546SAutomerger Merge Worker 
52*a71a9546SAutomerger Merge Worker #define GET_TARGET		ip6t_get_target
53*a71a9546SAutomerger Merge Worker 
54*a71a9546SAutomerger Merge Worker #define ERROR_TARGET		XT_ERROR_TARGET
55*a71a9546SAutomerger Merge Worker #define NUMHOOKS		NF_IP6_NUMHOOKS
56*a71a9546SAutomerger Merge Worker 
57*a71a9546SAutomerger Merge Worker #define IPT_CHAINLABEL		xt_chainlabel
58*a71a9546SAutomerger Merge Worker 
59*a71a9546SAutomerger Merge Worker #define TC_DUMP_ENTRIES		dump_entries6
60*a71a9546SAutomerger Merge Worker #define TC_IS_CHAIN		ip6tc_is_chain
61*a71a9546SAutomerger Merge Worker #define TC_FIRST_CHAIN		ip6tc_first_chain
62*a71a9546SAutomerger Merge Worker #define TC_NEXT_CHAIN		ip6tc_next_chain
63*a71a9546SAutomerger Merge Worker #define TC_FIRST_RULE		ip6tc_first_rule
64*a71a9546SAutomerger Merge Worker #define TC_NEXT_RULE		ip6tc_next_rule
65*a71a9546SAutomerger Merge Worker #define TC_GET_TARGET		ip6tc_get_target
66*a71a9546SAutomerger Merge Worker #define TC_BUILTIN		ip6tc_builtin
67*a71a9546SAutomerger Merge Worker #define TC_GET_POLICY		ip6tc_get_policy
68*a71a9546SAutomerger Merge Worker #define TC_INSERT_ENTRY		ip6tc_insert_entry
69*a71a9546SAutomerger Merge Worker #define TC_REPLACE_ENTRY	ip6tc_replace_entry
70*a71a9546SAutomerger Merge Worker #define TC_APPEND_ENTRY		ip6tc_append_entry
71*a71a9546SAutomerger Merge Worker #define TC_CHECK_ENTRY		ip6tc_check_entry
72*a71a9546SAutomerger Merge Worker #define TC_DELETE_ENTRY		ip6tc_delete_entry
73*a71a9546SAutomerger Merge Worker #define TC_DELETE_NUM_ENTRY	ip6tc_delete_num_entry
74*a71a9546SAutomerger Merge Worker #define TC_FLUSH_ENTRIES	ip6tc_flush_entries
75*a71a9546SAutomerger Merge Worker #define TC_ZERO_ENTRIES		ip6tc_zero_entries
76*a71a9546SAutomerger Merge Worker #define TC_ZERO_COUNTER		ip6tc_zero_counter
77*a71a9546SAutomerger Merge Worker #define TC_READ_COUNTER		ip6tc_read_counter
78*a71a9546SAutomerger Merge Worker #define TC_SET_COUNTER		ip6tc_set_counter
79*a71a9546SAutomerger Merge Worker #define TC_CREATE_CHAIN		ip6tc_create_chain
80*a71a9546SAutomerger Merge Worker #define TC_GET_REFERENCES	ip6tc_get_references
81*a71a9546SAutomerger Merge Worker #define TC_DELETE_CHAIN		ip6tc_delete_chain
82*a71a9546SAutomerger Merge Worker #define TC_RENAME_CHAIN		ip6tc_rename_chain
83*a71a9546SAutomerger Merge Worker #define TC_SET_POLICY		ip6tc_set_policy
84*a71a9546SAutomerger Merge Worker #define TC_GET_RAW_SOCKET	ip6tc_get_raw_socket
85*a71a9546SAutomerger Merge Worker #define TC_INIT			ip6tc_init
86*a71a9546SAutomerger Merge Worker #define TC_FREE			ip6tc_free
87*a71a9546SAutomerger Merge Worker #define TC_COMMIT		ip6tc_commit
88*a71a9546SAutomerger Merge Worker #define TC_STRERROR		ip6tc_strerror
89*a71a9546SAutomerger Merge Worker #define TC_NUM_RULES		ip6tc_num_rules
90*a71a9546SAutomerger Merge Worker #define TC_GET_RULE		ip6tc_get_rule
91*a71a9546SAutomerger Merge Worker #define TC_OPS			ip6tc_ops
92*a71a9546SAutomerger Merge Worker 
93*a71a9546SAutomerger Merge Worker #define TC_AF			AF_INET6
94*a71a9546SAutomerger Merge Worker #define TC_IPPROTO		IPPROTO_IPV6
95*a71a9546SAutomerger Merge Worker 
96*a71a9546SAutomerger Merge Worker #define SO_SET_REPLACE		IP6T_SO_SET_REPLACE
97*a71a9546SAutomerger Merge Worker #define SO_SET_ADD_COUNTERS	IP6T_SO_SET_ADD_COUNTERS
98*a71a9546SAutomerger Merge Worker #define SO_GET_INFO		IP6T_SO_GET_INFO
99*a71a9546SAutomerger Merge Worker #define SO_GET_ENTRIES		IP6T_SO_GET_ENTRIES
100*a71a9546SAutomerger Merge Worker #define SO_GET_VERSION		IP6T_SO_GET_VERSION
101*a71a9546SAutomerger Merge Worker 
102*a71a9546SAutomerger Merge Worker #define STANDARD_TARGET		XT_STANDARD_TARGET
103*a71a9546SAutomerger Merge Worker #define LABEL_RETURN		IP6TC_LABEL_RETURN
104*a71a9546SAutomerger Merge Worker #define LABEL_ACCEPT		IP6TC_LABEL_ACCEPT
105*a71a9546SAutomerger Merge Worker #define LABEL_DROP		IP6TC_LABEL_DROP
106*a71a9546SAutomerger Merge Worker #define LABEL_QUEUE		IP6TC_LABEL_QUEUE
107*a71a9546SAutomerger Merge Worker 
108*a71a9546SAutomerger Merge Worker #define ALIGN			XT_ALIGN
109*a71a9546SAutomerger Merge Worker #define RETURN			XT_RETURN
110*a71a9546SAutomerger Merge Worker 
111*a71a9546SAutomerger Merge Worker #include "libiptc.c"
112*a71a9546SAutomerger Merge Worker 
113*a71a9546SAutomerger Merge Worker #define BIT6(a, l) \
114*a71a9546SAutomerger Merge Worker  ((ntohl(a->s6_addr32[(l) / 32]) >> (31 - ((l) & 31))) & 1)
115*a71a9546SAutomerger Merge Worker 
116*a71a9546SAutomerger Merge Worker static int
ipv6_prefix_length(const struct in6_addr * a)117*a71a9546SAutomerger Merge Worker ipv6_prefix_length(const struct in6_addr *a)
118*a71a9546SAutomerger Merge Worker {
119*a71a9546SAutomerger Merge Worker 	int l, i;
120*a71a9546SAutomerger Merge Worker 	for (l = 0; l < 128; l++) {
121*a71a9546SAutomerger Merge Worker 		if (BIT6(a, l) == 0)
122*a71a9546SAutomerger Merge Worker 			break;
123*a71a9546SAutomerger Merge Worker 	}
124*a71a9546SAutomerger Merge Worker 	for (i = l + 1; i < 128; i++) {
125*a71a9546SAutomerger Merge Worker 		if (BIT6(a, i) == 1)
126*a71a9546SAutomerger Merge Worker 			return -1;
127*a71a9546SAutomerger Merge Worker 	}
128*a71a9546SAutomerger Merge Worker 	return l;
129*a71a9546SAutomerger Merge Worker }
130*a71a9546SAutomerger Merge Worker 
131*a71a9546SAutomerger Merge Worker static int
dump_entry(struct ip6t_entry * e,struct xtc_handle * const handle)132*a71a9546SAutomerger Merge Worker dump_entry(struct ip6t_entry *e, struct xtc_handle *const handle)
133*a71a9546SAutomerger Merge Worker {
134*a71a9546SAutomerger Merge Worker 	size_t i;
135*a71a9546SAutomerger Merge Worker 	char buf[40];
136*a71a9546SAutomerger Merge Worker 	int len;
137*a71a9546SAutomerger Merge Worker 	struct xt_entry_target *t;
138*a71a9546SAutomerger Merge Worker 
139*a71a9546SAutomerger Merge Worker 	printf("Entry %u (%lu):\n", iptcb_entry2index(handle, e),
140*a71a9546SAutomerger Merge Worker 	       iptcb_entry2offset(handle, e));
141*a71a9546SAutomerger Merge Worker 	puts("SRC IP: ");
142*a71a9546SAutomerger Merge Worker 	inet_ntop(AF_INET6, &e->ipv6.src, buf, sizeof buf);
143*a71a9546SAutomerger Merge Worker 	puts(buf);
144*a71a9546SAutomerger Merge Worker 	putchar('/');
145*a71a9546SAutomerger Merge Worker 	len = ipv6_prefix_length(&e->ipv6.smsk);
146*a71a9546SAutomerger Merge Worker 	if (len != -1)
147*a71a9546SAutomerger Merge Worker 		printf("%d", len);
148*a71a9546SAutomerger Merge Worker 	else {
149*a71a9546SAutomerger Merge Worker 		inet_ntop(AF_INET6, &e->ipv6.smsk, buf, sizeof buf);
150*a71a9546SAutomerger Merge Worker 		puts(buf);
151*a71a9546SAutomerger Merge Worker 	}
152*a71a9546SAutomerger Merge Worker 	putchar('\n');
153*a71a9546SAutomerger Merge Worker 
154*a71a9546SAutomerger Merge Worker 	puts("DST IP: ");
155*a71a9546SAutomerger Merge Worker 	inet_ntop(AF_INET6, &e->ipv6.dst, buf, sizeof buf);
156*a71a9546SAutomerger Merge Worker 	puts(buf);
157*a71a9546SAutomerger Merge Worker 	putchar('/');
158*a71a9546SAutomerger Merge Worker 	len = ipv6_prefix_length(&e->ipv6.dmsk);
159*a71a9546SAutomerger Merge Worker 	if (len != -1)
160*a71a9546SAutomerger Merge Worker 		printf("%d", len);
161*a71a9546SAutomerger Merge Worker 	else {
162*a71a9546SAutomerger Merge Worker 		inet_ntop(AF_INET6, &e->ipv6.dmsk, buf, sizeof buf);
163*a71a9546SAutomerger Merge Worker 		puts(buf);
164*a71a9546SAutomerger Merge Worker 	}
165*a71a9546SAutomerger Merge Worker 	putchar('\n');
166*a71a9546SAutomerger Merge Worker 
167*a71a9546SAutomerger Merge Worker 	printf("Interface: `%s'/", e->ipv6.iniface);
168*a71a9546SAutomerger Merge Worker 	for (i = 0; i < IFNAMSIZ; i++)
169*a71a9546SAutomerger Merge Worker 		printf("%c", e->ipv6.iniface_mask[i] ? 'X' : '.');
170*a71a9546SAutomerger Merge Worker 	printf("to `%s'/", e->ipv6.outiface);
171*a71a9546SAutomerger Merge Worker 	for (i = 0; i < IFNAMSIZ; i++)
172*a71a9546SAutomerger Merge Worker 		printf("%c", e->ipv6.outiface_mask[i] ? 'X' : '.');
173*a71a9546SAutomerger Merge Worker 	printf("\nProtocol: %u\n", e->ipv6.proto);
174*a71a9546SAutomerger Merge Worker 	if (e->ipv6.flags & IP6T_F_TOS)
175*a71a9546SAutomerger Merge Worker 		printf("TOS: %u\n", e->ipv6.tos);
176*a71a9546SAutomerger Merge Worker 	printf("Flags: %02X\n", e->ipv6.flags);
177*a71a9546SAutomerger Merge Worker 	printf("Invflags: %02X\n", e->ipv6.invflags);
178*a71a9546SAutomerger Merge Worker 	printf("Counters: %llu packets, %llu bytes\n",
179*a71a9546SAutomerger Merge Worker 	       (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
180*a71a9546SAutomerger Merge Worker 	printf("Cache: %08X\n", e->nfcache);
181*a71a9546SAutomerger Merge Worker 
182*a71a9546SAutomerger Merge Worker 	IP6T_MATCH_ITERATE(e, print_match);
183*a71a9546SAutomerger Merge Worker 
184*a71a9546SAutomerger Merge Worker 	t = ip6t_get_target(e);
185*a71a9546SAutomerger Merge Worker 	printf("Target name: `%s' [%u]\n", t->u.user.name, t->u.target_size);
186*a71a9546SAutomerger Merge Worker 	if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0) {
187*a71a9546SAutomerger Merge Worker 		const unsigned char *data = t->data;
188*a71a9546SAutomerger Merge Worker 		int pos = *(const int *)data;
189*a71a9546SAutomerger Merge Worker 		if (pos < 0)
190*a71a9546SAutomerger Merge Worker 			printf("verdict=%s\n",
191*a71a9546SAutomerger Merge Worker 			       pos == -NF_ACCEPT-1 ? "NF_ACCEPT"
192*a71a9546SAutomerger Merge Worker 			       : pos == -NF_DROP-1 ? "NF_DROP"
193*a71a9546SAutomerger Merge Worker 			       : pos == XT_RETURN ? "RETURN"
194*a71a9546SAutomerger Merge Worker 			       : "UNKNOWN");
195*a71a9546SAutomerger Merge Worker 		else
196*a71a9546SAutomerger Merge Worker 			printf("verdict=%u\n", pos);
197*a71a9546SAutomerger Merge Worker 	} else if (strcmp(t->u.user.name, XT_ERROR_TARGET) == 0)
198*a71a9546SAutomerger Merge Worker 		printf("error=`%s'\n", t->data);
199*a71a9546SAutomerger Merge Worker 
200*a71a9546SAutomerger Merge Worker 	printf("\n");
201*a71a9546SAutomerger Merge Worker 	return 0;
202*a71a9546SAutomerger Merge Worker }
203*a71a9546SAutomerger Merge Worker 
204*a71a9546SAutomerger Merge Worker static unsigned char *
is_same(const STRUCT_ENTRY * a,const STRUCT_ENTRY * b,unsigned char * matchmask)205*a71a9546SAutomerger Merge Worker is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b,
206*a71a9546SAutomerger Merge Worker 	unsigned char *matchmask)
207*a71a9546SAutomerger Merge Worker {
208*a71a9546SAutomerger Merge Worker 	unsigned int i;
209*a71a9546SAutomerger Merge Worker 	unsigned char *mptr;
210*a71a9546SAutomerger Merge Worker 
211*a71a9546SAutomerger Merge Worker 	/* Always compare head structures: ignore mask here. */
212*a71a9546SAutomerger Merge Worker 	if (memcmp(&a->ipv6.src, &b->ipv6.src, sizeof(struct in6_addr))
213*a71a9546SAutomerger Merge Worker 	    || memcmp(&a->ipv6.dst, &b->ipv6.dst, sizeof(struct in6_addr))
214*a71a9546SAutomerger Merge Worker 	    || memcmp(&a->ipv6.smsk, &b->ipv6.smsk, sizeof(struct in6_addr))
215*a71a9546SAutomerger Merge Worker 	    || memcmp(&a->ipv6.dmsk, &b->ipv6.dmsk, sizeof(struct in6_addr))
216*a71a9546SAutomerger Merge Worker 	    || a->ipv6.proto != b->ipv6.proto
217*a71a9546SAutomerger Merge Worker 	    || a->ipv6.tos != b->ipv6.tos
218*a71a9546SAutomerger Merge Worker 	    || a->ipv6.flags != b->ipv6.flags
219*a71a9546SAutomerger Merge Worker 	    || a->ipv6.invflags != b->ipv6.invflags)
220*a71a9546SAutomerger Merge Worker 		return NULL;
221*a71a9546SAutomerger Merge Worker 
222*a71a9546SAutomerger Merge Worker 	for (i = 0; i < IFNAMSIZ; i++) {
223*a71a9546SAutomerger Merge Worker 		if (a->ipv6.iniface_mask[i] != b->ipv6.iniface_mask[i])
224*a71a9546SAutomerger Merge Worker 			return NULL;
225*a71a9546SAutomerger Merge Worker 		if ((a->ipv6.iniface[i] & a->ipv6.iniface_mask[i])
226*a71a9546SAutomerger Merge Worker 		    != (b->ipv6.iniface[i] & b->ipv6.iniface_mask[i]))
227*a71a9546SAutomerger Merge Worker 			return NULL;
228*a71a9546SAutomerger Merge Worker 		if (a->ipv6.outiface_mask[i] != b->ipv6.outiface_mask[i])
229*a71a9546SAutomerger Merge Worker 			return NULL;
230*a71a9546SAutomerger Merge Worker 		if ((a->ipv6.outiface[i] & a->ipv6.outiface_mask[i])
231*a71a9546SAutomerger Merge Worker 		    != (b->ipv6.outiface[i] & b->ipv6.outiface_mask[i]))
232*a71a9546SAutomerger Merge Worker 			return NULL;
233*a71a9546SAutomerger Merge Worker 	}
234*a71a9546SAutomerger Merge Worker 
235*a71a9546SAutomerger Merge Worker 	if (a->target_offset != b->target_offset
236*a71a9546SAutomerger Merge Worker 	    || a->next_offset != b->next_offset)
237*a71a9546SAutomerger Merge Worker 		return NULL;
238*a71a9546SAutomerger Merge Worker 
239*a71a9546SAutomerger Merge Worker 	mptr = matchmask + sizeof(STRUCT_ENTRY);
240*a71a9546SAutomerger Merge Worker 	if (IP6T_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
241*a71a9546SAutomerger Merge Worker 		return NULL;
242*a71a9546SAutomerger Merge Worker 	mptr += XT_ALIGN(sizeof(struct xt_entry_target));
243*a71a9546SAutomerger Merge Worker 
244*a71a9546SAutomerger Merge Worker 	return mptr;
245*a71a9546SAutomerger Merge Worker }
246*a71a9546SAutomerger Merge Worker 
247*a71a9546SAutomerger Merge Worker #if 0
248*a71a9546SAutomerger Merge Worker /* All zeroes == unconditional rule. */
249*a71a9546SAutomerger Merge Worker static inline int
250*a71a9546SAutomerger Merge Worker unconditional(const struct ip6t_ip6 *ipv6)
251*a71a9546SAutomerger Merge Worker {
252*a71a9546SAutomerger Merge Worker 	unsigned int i;
253*a71a9546SAutomerger Merge Worker 
254*a71a9546SAutomerger Merge Worker 	for (i = 0; i < sizeof(*ipv6); i++)
255*a71a9546SAutomerger Merge Worker 		if (((char *)ipv6)[i])
256*a71a9546SAutomerger Merge Worker 			break;
257*a71a9546SAutomerger Merge Worker 
258*a71a9546SAutomerger Merge Worker 	return (i == sizeof(*ipv6));
259*a71a9546SAutomerger Merge Worker }
260*a71a9546SAutomerger Merge Worker #endif
261