4 * This program is free software; you can redistribute 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: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
21 #include <linux/if.h> /* IFNAMSIZ */
25 static void explain(void)
28 "Usage: ... fw [ classid CLASSID ] [ indev DEV ] [ action ACTION_SPEC ]\n"
29 " CLASSID := Push matching packets to the class identified by CLASSID with format X:Y\n"
30 " CLASSID is parsed as hexadecimal input.\n"
31 " DEV := specify device for incoming device classification.\n"
32 " ACTION_SPEC := Apply an action on matching packets.\n"
33 " NOTE: handle is represented as HANDLE[/FWMASK].\n"
34 " FWMASK is 0xffffffff by default.\n");
37 static int fw_parse_opt(struct filter_util
*qu
, char *handle
, int argc
, char **argv
, struct nlmsghdr
*n
)
39 struct tcmsg
*t
= NLMSG_DATA(n
);
47 if ((slash
= strchr(handle
, '/')) != NULL
)
49 if (get_u32(&t
->tcm_handle
, handle
, 0)) {
50 fprintf(stderr
, "Illegal \"handle\"\n");
54 if (get_u32(&mask
, slash
+1, 0)) {
55 fprintf(stderr
, "Illegal \"handle\" mask\n");
65 tail
= addattr_nest(n
, 4096, TCA_OPTIONS
);
68 addattr32(n
, MAX_MSG
, TCA_FW_MASK
, mask
);
71 if (matches(*argv
, "classid") == 0 ||
72 matches(*argv
, "flowid") == 0) {
76 if (get_tc_classid(&handle
, *argv
)) {
77 fprintf(stderr
, "Illegal \"classid\"\n");
80 addattr_l(n
, 4096, TCA_FW_CLASSID
, &handle
, 4);
81 } else if (matches(*argv
, "police") == 0) {
83 if (parse_police(&argc
, &argv
, TCA_FW_POLICE
, n
)) {
84 fprintf(stderr
, "Illegal \"police\"\n");
88 } else if (matches(*argv
, "action") == 0) {
90 if (parse_action(&argc
, &argv
, TCA_FW_ACT
, n
)) {
91 fprintf(stderr
, "Illegal fw \"action\"\n");
95 } else if (strcmp(*argv
, "indev") == 0) {
96 char d
[IFNAMSIZ
+1] = {};
101 fprintf(stderr
, "Illegal indev\n");
104 strncpy(d
, *argv
, sizeof(d
) - 1);
105 addattr_l(n
, MAX_MSG
, TCA_FW_INDEV
, d
, strlen(d
) + 1);
106 } else if (strcmp(*argv
, "help") == 0) {
110 fprintf(stderr
, "What is \"%s\"?\n", *argv
);
116 addattr_nest_end(n
, tail
);
120 static int fw_print_opt(struct filter_util
*qu
, FILE *f
, struct rtattr
*opt
, __u32 handle
)
122 struct rtattr
*tb
[TCA_FW_MAX
+1];
127 parse_rtattr_nested(tb
, TCA_FW_MAX
, opt
);
129 if (handle
|| tb
[TCA_FW_MASK
]) {
130 __u32 mark
= 0, mask
= 0;
134 if (tb
[TCA_FW_MASK
] &&
135 (mask
= rta_getattr_u32(tb
[TCA_FW_MASK
])) != 0xFFFFFFFF)
136 fprintf(f
, "handle 0x%x/0x%x ", mark
, mask
);
138 fprintf(f
, "handle 0x%x ", handle
);
141 if (tb
[TCA_FW_CLASSID
]) {
143 fprintf(f
, "classid %s ", sprint_tc_classid(rta_getattr_u32(tb
[TCA_FW_CLASSID
]), b1
));
146 if (tb
[TCA_FW_POLICE
])
147 tc_print_police(f
, tb
[TCA_FW_POLICE
]);
148 if (tb
[TCA_FW_INDEV
]) {
149 struct rtattr
*idev
= tb
[TCA_FW_INDEV
];
151 fprintf(f
, "input dev %s ", rta_getattr_str(idev
));
154 if (tb
[TCA_FW_ACT
]) {
156 tc_print_action(f
, tb
[TCA_FW_ACT
], 0);
161 struct filter_util fw_filter_util
= {
163 .parse_fopt
= fw_parse_opt
,
164 .print_fopt
= fw_print_opt
,