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];
152 parse_rtattr_nested(tb
, TCA_NAT_MAX
, arg
);
154 if (tb
[TCA_NAT_PARMS
] == NULL
) {
155 print_string(PRINT_FP
, NULL
, "%s", "[NULL nat parameters]");
158 sel
= RTA_DATA(tb
[TCA_NAT_PARMS
]);
160 len
= ffs(sel
->mask
);
161 len
= len
? 33 - len
: 0;
163 print_string(PRINT_ANY
, "type", " %s ", "nat");
164 print_string(PRINT_ANY
, "direction", "%s",
165 sel
->flags
& TCA_NAT_FLAG_EGRESS
? "egress" : "ingress");
167 snprintf(buf2
, sizeof(buf2
), "%s/%d",
168 format_host_r(AF_INET
, 4, &sel
->old_addr
, buf1
, sizeof(buf1
)),
170 print_string(PRINT_ANY
, "old_addr", " %s", buf2
);
171 print_string(PRINT_ANY
, "new_addr", " %s",
172 format_host_r(AF_INET
, 4, &sel
->new_addr
, buf1
, sizeof(buf1
)));
174 print_action_control(f
, " ", sel
->action
, "");
175 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
176 print_uint(PRINT_ANY
, "index", "\t index %u", sel
->index
);
177 print_int(PRINT_ANY
, "ref", " ref %d", sel
->refcnt
);
178 print_int(PRINT_ANY
, "bind", " bind %d", sel
->bindcnt
);
181 if (tb
[TCA_NAT_TM
]) {
182 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_NAT_TM
]);
188 print_string(PRINT_FP
, NULL
, "%s", _SL_
);
193 struct action_util nat_action_util
= {
195 .parse_aopt
= parse_nat
,
196 .print_aopt
= print_nat
,