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) {
119 if (matches(*argv
, "reclassify") == 0) {
120 sel
.action
= TC_ACT_RECLASSIFY
;
123 } else if (matches(*argv
, "pipe") == 0) {
124 sel
.action
= TC_ACT_PIPE
;
127 } else if (matches(*argv
, "drop") == 0 ||
128 matches(*argv
, "shot") == 0) {
129 sel
.action
= TC_ACT_SHOT
;
132 } else if (matches(*argv
, "continue") == 0) {
133 sel
.action
= TC_ACT_UNSPEC
;
136 } else if (matches(*argv
, "pass") == 0 ||
137 matches(*argv
, "ok") == 0) {
138 sel
.action
= TC_ACT_OK
;
145 if (matches(*argv
, "index") == 0) {
147 if (get_u32(&sel
.index
, *argv
, 10)) {
148 fprintf(stderr
, "Nat: Illegal \"index\"\n");
156 tail
= NLMSG_TAIL(n
);
157 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
158 addattr_l(n
, MAX_MSG
, TCA_NAT_PARMS
, &sel
, sizeof(sel
));
159 tail
->rta_len
= (char *)NLMSG_TAIL(n
) - (char *)tail
;
167 print_nat(struct action_util
*au
, FILE * f
, struct rtattr
*arg
)
170 struct rtattr
*tb
[TCA_NAT_MAX
+ 1];
180 parse_rtattr_nested(tb
, TCA_NAT_MAX
, arg
);
182 if (tb
[TCA_NAT_PARMS
] == NULL
) {
183 fprintf(f
, "[NULL nat parameters]");
186 sel
= RTA_DATA(tb
[TCA_NAT_PARMS
]);
188 len
= ffs(sel
->mask
);
189 len
= len
? 33 - len
: 0;
191 fprintf(f
, " nat %s %s/%d %s %s", sel
->flags
& TCA_NAT_FLAG_EGRESS
?
192 "egress" : "ingress",
193 format_host_r(AF_INET
, 4, &sel
->old_addr
, buf1
, sizeof(buf1
)),
195 format_host_r(AF_INET
, 4, &sel
->new_addr
, buf2
, sizeof(buf2
)),
196 action_n2a(sel
->action
, buf3
, sizeof(buf3
)));
199 if (tb
[TCA_NAT_TM
]) {
200 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_NAT_TM
]);
209 struct action_util nat_action_util
= {
211 .parse_aopt
= parse_nat
,
212 .print_aopt
= print_nat
,