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>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
23 #include <linux/tc_act/tc_nat.h>
28 fprintf(stderr
, "Usage: ... nat NAT\n"
29 "NAT := DIRECTION OLD NEW\n"
30 "DIRECTION := { ingress | egress }\n"
43 parse_nat_args(int *argc_p
, char ***argv_p
, struct tc_nat
*sel
)
46 char **argv
= *argv_p
;
52 if (matches(*argv
, "egress") == 0)
53 sel
->flags
|= TCA_NAT_FLAG_EGRESS
;
54 else if (matches(*argv
, "ingress") != 0)
59 if (get_prefix_1(&addr
, *argv
, AF_INET
))
62 sel
->old_addr
= addr
.data
[0];
63 sel
->mask
= htonl(~0u << (32 - addr
.bitlen
));
67 if (get_prefix_1(&addr
, *argv
, AF_INET
))
70 sel
->new_addr
= addr
.data
[0];
84 parse_nat(struct action_util
*a
, int *argc_p
, char ***argv_p
, int tca_id
, struct nlmsghdr
*n
)
86 struct tc_nat sel
= {};
89 char **argv
= *argv_p
;
94 if (matches(*argv
, "nat") == 0) {
96 if (parse_nat_args(&argc
, &argv
, &sel
)) {
97 fprintf(stderr
, "Illegal nat construct (%s)\n",
104 } else if (matches(*argv
, "help") == 0) {
117 parse_action_control_dflt(&argc
, &argv
, &sel
.action
, false, TC_ACT_OK
);
120 if (matches(*argv
, "index") == 0) {
122 if (get_u32(&sel
.index
, *argv
, 10)) {
123 fprintf(stderr
, "Nat: Illegal \"index\"\n");
131 tail
= addattr_nest(n
, MAX_MSG
, tca_id
);
132 addattr_l(n
, MAX_MSG
, TCA_NAT_PARMS
, &sel
, sizeof(sel
));
133 addattr_nest_end(n
, tail
);
141 print_nat(struct action_util
*au
, FILE * f
, struct rtattr
*arg
)
144 struct rtattr
*tb
[TCA_NAT_MAX
+ 1];
153 parse_rtattr_nested(tb
, TCA_NAT_MAX
, arg
);
155 if (tb
[TCA_NAT_PARMS
] == NULL
) {
156 fprintf(f
, "[NULL nat parameters]");
159 sel
= RTA_DATA(tb
[TCA_NAT_PARMS
]);
161 len
= ffs(sel
->mask
);
162 len
= len
? 33 - len
: 0;
164 fprintf(f
, " nat %s %s/%d %s", sel
->flags
& TCA_NAT_FLAG_EGRESS
?
165 "egress" : "ingress",
166 format_host_r(AF_INET
, 4, &sel
->old_addr
, buf1
, sizeof(buf1
)),
168 format_host_r(AF_INET
, 4, &sel
->new_addr
, buf2
, sizeof(buf2
)));
169 print_action_control(f
, " ", sel
->action
, "");
171 fprintf(f
, "\n\t index %u ref %d bind %d",
172 sel
->index
, sel
->refcnt
, sel
->bindcnt
);
175 if (tb
[TCA_NAT_TM
]) {
176 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_NAT_TM
]);
187 struct action_util nat_action_util
= {
189 .parse_aopt
= parse_nat
,
190 .print_aopt
= print_nat
,