xref: /aosp_15_r20/external/iproute2/tc/m_nat.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * m_nat.c		NAT module
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  *		This program is free software; you can distribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker  *		modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker  *		as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker  *		2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * Authors:	Herbert Xu <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  *
11*de1e4e89SAndroid Build Coastguard Worker  */
12*de1e4e89SAndroid Build Coastguard Worker 
13*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
22*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
23*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
24*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_nat.h>
25*de1e4e89SAndroid Build Coastguard Worker 
26*de1e4e89SAndroid Build Coastguard Worker static void
explain(void)27*de1e4e89SAndroid Build Coastguard Worker explain(void)
28*de1e4e89SAndroid Build Coastguard Worker {
29*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: ... nat NAT\n"
30*de1e4e89SAndroid Build Coastguard Worker 			"NAT := DIRECTION OLD NEW\n"
31*de1e4e89SAndroid Build Coastguard Worker 			"DIRECTION := { ingress | egress }\n"
32*de1e4e89SAndroid Build Coastguard Worker 			"OLD := PREFIX\n"
33*de1e4e89SAndroid Build Coastguard Worker 			"NEW := ADDRESS\n");
34*de1e4e89SAndroid Build Coastguard Worker }
35*de1e4e89SAndroid Build Coastguard Worker 
36*de1e4e89SAndroid Build Coastguard Worker static void
usage(void)37*de1e4e89SAndroid Build Coastguard Worker usage(void)
38*de1e4e89SAndroid Build Coastguard Worker {
39*de1e4e89SAndroid Build Coastguard Worker 	explain();
40*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
41*de1e4e89SAndroid Build Coastguard Worker }
42*de1e4e89SAndroid Build Coastguard Worker 
43*de1e4e89SAndroid Build Coastguard Worker static int
parse_nat_args(int * argc_p,char *** argv_p,struct tc_nat * sel)44*de1e4e89SAndroid Build Coastguard Worker parse_nat_args(int *argc_p, char ***argv_p, struct tc_nat *sel)
45*de1e4e89SAndroid Build Coastguard Worker {
46*de1e4e89SAndroid Build Coastguard Worker 	int argc = *argc_p;
47*de1e4e89SAndroid Build Coastguard Worker 	char **argv = *argv_p;
48*de1e4e89SAndroid Build Coastguard Worker 	inet_prefix addr;
49*de1e4e89SAndroid Build Coastguard Worker 
50*de1e4e89SAndroid Build Coastguard Worker 	if (argc <= 0)
51*de1e4e89SAndroid Build Coastguard Worker 		return -1;
52*de1e4e89SAndroid Build Coastguard Worker 
53*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "egress") == 0)
54*de1e4e89SAndroid Build Coastguard Worker 		sel->flags |= TCA_NAT_FLAG_EGRESS;
55*de1e4e89SAndroid Build Coastguard Worker 	else if (matches(*argv, "ingress") != 0)
56*de1e4e89SAndroid Build Coastguard Worker 		goto bad_val;
57*de1e4e89SAndroid Build Coastguard Worker 
58*de1e4e89SAndroid Build Coastguard Worker 	NEXT_ARG();
59*de1e4e89SAndroid Build Coastguard Worker 
60*de1e4e89SAndroid Build Coastguard Worker 	if (get_prefix_1(&addr, *argv, AF_INET))
61*de1e4e89SAndroid Build Coastguard Worker 		goto bad_val;
62*de1e4e89SAndroid Build Coastguard Worker 
63*de1e4e89SAndroid Build Coastguard Worker 	sel->old_addr = addr.data[0];
64*de1e4e89SAndroid Build Coastguard Worker 	sel->mask = htonl(~0u << (32 - addr.bitlen));
65*de1e4e89SAndroid Build Coastguard Worker 
66*de1e4e89SAndroid Build Coastguard Worker 	NEXT_ARG();
67*de1e4e89SAndroid Build Coastguard Worker 
68*de1e4e89SAndroid Build Coastguard Worker 	if (get_prefix_1(&addr, *argv, AF_INET))
69*de1e4e89SAndroid Build Coastguard Worker 		goto bad_val;
70*de1e4e89SAndroid Build Coastguard Worker 
71*de1e4e89SAndroid Build Coastguard Worker 	sel->new_addr = addr.data[0];
72*de1e4e89SAndroid Build Coastguard Worker 
73*de1e4e89SAndroid Build Coastguard Worker 	argc--;
74*de1e4e89SAndroid Build Coastguard Worker 	argv++;
75*de1e4e89SAndroid Build Coastguard Worker 
76*de1e4e89SAndroid Build Coastguard Worker 	*argc_p = argc;
77*de1e4e89SAndroid Build Coastguard Worker 	*argv_p = argv;
78*de1e4e89SAndroid Build Coastguard Worker 	return 0;
79*de1e4e89SAndroid Build Coastguard Worker 
80*de1e4e89SAndroid Build Coastguard Worker bad_val:
81*de1e4e89SAndroid Build Coastguard Worker 	return -1;
82*de1e4e89SAndroid Build Coastguard Worker }
83*de1e4e89SAndroid Build Coastguard Worker 
84*de1e4e89SAndroid Build Coastguard Worker static int
parse_nat(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)85*de1e4e89SAndroid Build Coastguard Worker parse_nat(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
86*de1e4e89SAndroid Build Coastguard Worker {
87*de1e4e89SAndroid Build Coastguard Worker 	struct tc_nat sel = {};
88*de1e4e89SAndroid Build Coastguard Worker 
89*de1e4e89SAndroid Build Coastguard Worker 	int argc = *argc_p;
90*de1e4e89SAndroid Build Coastguard Worker 	char **argv = *argv_p;
91*de1e4e89SAndroid Build Coastguard Worker 	int ok = 0;
92*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tail;
93*de1e4e89SAndroid Build Coastguard Worker 
94*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
95*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "nat") == 0) {
96*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
97*de1e4e89SAndroid Build Coastguard Worker 			if (parse_nat_args(&argc, &argv, &sel)) {
98*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal nat construct (%s)\n",
99*de1e4e89SAndroid Build Coastguard Worker 					*argv);
100*de1e4e89SAndroid Build Coastguard Worker 				explain();
101*de1e4e89SAndroid Build Coastguard Worker 				return -1;
102*de1e4e89SAndroid Build Coastguard Worker 			}
103*de1e4e89SAndroid Build Coastguard Worker 			ok++;
104*de1e4e89SAndroid Build Coastguard Worker 			continue;
105*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "help") == 0) {
106*de1e4e89SAndroid Build Coastguard Worker 			usage();
107*de1e4e89SAndroid Build Coastguard Worker 		} else {
108*de1e4e89SAndroid Build Coastguard Worker 			break;
109*de1e4e89SAndroid Build Coastguard Worker 		}
110*de1e4e89SAndroid Build Coastguard Worker 
111*de1e4e89SAndroid Build Coastguard Worker 	}
112*de1e4e89SAndroid Build Coastguard Worker 
113*de1e4e89SAndroid Build Coastguard Worker 	if (!ok) {
114*de1e4e89SAndroid Build Coastguard Worker 		explain();
115*de1e4e89SAndroid Build Coastguard Worker 		return -1;
116*de1e4e89SAndroid Build Coastguard Worker 	}
117*de1e4e89SAndroid Build Coastguard Worker 
118*de1e4e89SAndroid Build Coastguard Worker 	parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_OK);
119*de1e4e89SAndroid Build Coastguard Worker 
120*de1e4e89SAndroid Build Coastguard Worker 	if (argc) {
121*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "index") == 0) {
122*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
123*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&sel.index, *argv, 10)) {
124*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Nat: Illegal \"index\"\n");
125*de1e4e89SAndroid Build Coastguard Worker 				return -1;
126*de1e4e89SAndroid Build Coastguard Worker 			}
127*de1e4e89SAndroid Build Coastguard Worker 			argc--;
128*de1e4e89SAndroid Build Coastguard Worker 			argv++;
129*de1e4e89SAndroid Build Coastguard Worker 		}
130*de1e4e89SAndroid Build Coastguard Worker 	}
131*de1e4e89SAndroid Build Coastguard Worker 
132*de1e4e89SAndroid Build Coastguard Worker 	tail = NLMSG_TAIL(n);
133*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
134*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_NAT_PARMS, &sel, sizeof(sel));
135*de1e4e89SAndroid Build Coastguard Worker 	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
136*de1e4e89SAndroid Build Coastguard Worker 
137*de1e4e89SAndroid Build Coastguard Worker 	*argc_p = argc;
138*de1e4e89SAndroid Build Coastguard Worker 	*argv_p = argv;
139*de1e4e89SAndroid Build Coastguard Worker 	return 0;
140*de1e4e89SAndroid Build Coastguard Worker }
141*de1e4e89SAndroid Build Coastguard Worker 
142*de1e4e89SAndroid Build Coastguard Worker static int
print_nat(struct action_util * au,FILE * f,struct rtattr * arg)143*de1e4e89SAndroid Build Coastguard Worker print_nat(struct action_util *au, FILE * f, struct rtattr *arg)
144*de1e4e89SAndroid Build Coastguard Worker {
145*de1e4e89SAndroid Build Coastguard Worker 	struct tc_nat *sel;
146*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[TCA_NAT_MAX + 1];
147*de1e4e89SAndroid Build Coastguard Worker 	char buf1[256];
148*de1e4e89SAndroid Build Coastguard Worker 	char buf2[256];
149*de1e4e89SAndroid Build Coastguard Worker 
150*de1e4e89SAndroid Build Coastguard Worker 	int len;
151*de1e4e89SAndroid Build Coastguard Worker 
152*de1e4e89SAndroid Build Coastguard Worker 	if (arg == NULL)
153*de1e4e89SAndroid Build Coastguard Worker 		return -1;
154*de1e4e89SAndroid Build Coastguard Worker 
155*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(tb, TCA_NAT_MAX, arg);
156*de1e4e89SAndroid Build Coastguard Worker 
157*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_NAT_PARMS] == NULL) {
158*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "[NULL nat parameters]");
159*de1e4e89SAndroid Build Coastguard Worker 		return -1;
160*de1e4e89SAndroid Build Coastguard Worker 	}
161*de1e4e89SAndroid Build Coastguard Worker 	sel = RTA_DATA(tb[TCA_NAT_PARMS]);
162*de1e4e89SAndroid Build Coastguard Worker 
163*de1e4e89SAndroid Build Coastguard Worker 	len = ffs(sel->mask);
164*de1e4e89SAndroid Build Coastguard Worker 	len = len ? 33 - len : 0;
165*de1e4e89SAndroid Build Coastguard Worker 
166*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, " nat %s %s/%d %s", sel->flags & TCA_NAT_FLAG_EGRESS ?
167*de1e4e89SAndroid Build Coastguard Worker 				       "egress" : "ingress",
168*de1e4e89SAndroid Build Coastguard Worker 		format_host_r(AF_INET, 4, &sel->old_addr, buf1, sizeof(buf1)),
169*de1e4e89SAndroid Build Coastguard Worker 		len,
170*de1e4e89SAndroid Build Coastguard Worker 		format_host_r(AF_INET, 4, &sel->new_addr, buf2, sizeof(buf2)));
171*de1e4e89SAndroid Build Coastguard Worker 	print_action_control(f, " ", sel->action, "");
172*de1e4e89SAndroid Build Coastguard Worker 
173*de1e4e89SAndroid Build Coastguard Worker 	if (show_stats) {
174*de1e4e89SAndroid Build Coastguard Worker 		if (tb[TCA_NAT_TM]) {
175*de1e4e89SAndroid Build Coastguard Worker 			struct tcf_t *tm = RTA_DATA(tb[TCA_NAT_TM]);
176*de1e4e89SAndroid Build Coastguard Worker 
177*de1e4e89SAndroid Build Coastguard Worker 			print_tm(f, tm);
178*de1e4e89SAndroid Build Coastguard Worker 		}
179*de1e4e89SAndroid Build Coastguard Worker 	}
180*de1e4e89SAndroid Build Coastguard Worker 
181*de1e4e89SAndroid Build Coastguard Worker 	return 0;
182*de1e4e89SAndroid Build Coastguard Worker }
183*de1e4e89SAndroid Build Coastguard Worker 
184*de1e4e89SAndroid Build Coastguard Worker struct action_util nat_action_util = {
185*de1e4e89SAndroid Build Coastguard Worker 	.id = "nat",
186*de1e4e89SAndroid Build Coastguard Worker 	.parse_aopt = parse_nat,
187*de1e4e89SAndroid Build Coastguard Worker 	.print_aopt = print_nat,
188*de1e4e89SAndroid Build Coastguard Worker };
189