4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Herbert Xu <herbert@gondor.apana.org.au>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
24 #include <linux/tc_act/tc_nat.h>
29 fprintf(stderr
, "Usage: ... nat NAT\n"
30 "NAT := DIRECTION OLD NEW\n"
31 "DIRECTION := { ingress | egress }\n"
44 parse_nat_args(int *argc_p
, char ***argv_p
, struct tc_nat
*sel
)
47 char **argv
= *argv_p
;
53 if (matches(*argv
, "egress") == 0)
54 sel
->flags
|= TCA_NAT_FLAG_EGRESS
;
55 else if (matches(*argv
, "ingress") != 0)
60 if (get_prefix_1(&addr
, *argv
, AF_INET
))
63 sel
->old_addr
= addr
.data
[0];
64 sel
->mask
= htonl(~0u << (32 - addr
.bitlen
));
68 if (get_prefix_1(&addr
, *argv
, AF_INET
))
71 sel
->new_addr
= addr
.data
[0];
85 parse_nat(struct action_util
*a
, int *argc_p
, char ***argv_p
, int tca_id
, struct nlmsghdr
*n
)
87 struct tc_nat sel
= {};
90 char **argv
= *argv_p
;
95 if (matches(*argv
, "nat") == 0) {
97 if (parse_nat_args(&argc
, &argv
, &sel
)) {
98 fprintf(stderr
, "Illegal nat construct (%s)\n",
105 } else if (matches(*argv
, "help") == 0) {
118 parse_action_control_dflt(&argc
, &argv
, &sel
.action
, false, TC_ACT_OK
);
121 if (matches(*argv
, "index") == 0) {
123 if (get_u32(&sel
.index
, *argv
, 10)) {
124 fprintf(stderr
, "Nat: Illegal \"index\"\n");
132 tail
= NLMSG_TAIL(n
);
133 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
134 addattr_l(n
, MAX_MSG
, TCA_NAT_PARMS
, &sel
, sizeof(sel
));
135 tail
->rta_len
= (char *)NLMSG_TAIL(n
) - (char *)tail
;
143 print_nat(struct action_util
*au
, FILE * f
, struct rtattr
*arg
)
146 struct rtattr
*tb
[TCA_NAT_MAX
+ 1];
155 parse_rtattr_nested(tb
, TCA_NAT_MAX
, arg
);
157 if (tb
[TCA_NAT_PARMS
] == NULL
) {
158 fprintf(f
, "[NULL nat parameters]");
161 sel
= RTA_DATA(tb
[TCA_NAT_PARMS
]);
163 len
= ffs(sel
->mask
);
164 len
= len
? 33 - len
: 0;
166 fprintf(f
, " nat %s %s/%d %s", sel
->flags
& TCA_NAT_FLAG_EGRESS
?
167 "egress" : "ingress",
168 format_host_r(AF_INET
, 4, &sel
->old_addr
, buf1
, sizeof(buf1
)),
170 format_host_r(AF_INET
, 4, &sel
->new_addr
, buf2
, sizeof(buf2
)));
171 print_action_control(f
, " ", sel
->action
, "");
174 if (tb
[TCA_NAT_TM
]) {
175 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_NAT_TM
]);
184 struct action_util nat_action_util
= {
186 .parse_aopt
= parse_nat
,
187 .print_aopt
= print_nat
,