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