2 * em_ipt.c IPtables extenstions matching Ematch
4 * (C) 2018 Eyal Birger <eyal.birger@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
13 #include <linux/tc_ematch/tc_em_ipt.h>
14 #include <linux/pkt_cls.h>
18 static void em_ipt_print_usage(FILE *fd
)
21 "Usage: ipt([-6] -m MATCH_NAME [MATCH_OPTS])\n"
22 "Example: 'ipt(-m policy --reqid 1 --pol ipsec --dir in)'\n");
25 static struct option original_opts
[] = {
38 static struct xtables_globals em_tc_ipt_globals
= {
40 .program_name
= "tc-em-ipt",
41 .program_version
= "0.1",
42 .orig_opts
= original_opts
,
43 .opts
= original_opts
,
44 #if (XTABLES_VERSION_CODE >= 11)
45 .compat_rev
= xtables_compatible_revision
,
49 static struct xt_entry_match
*fake_xt_entry_match(int data_size
, void *data
)
51 struct xt_entry_match
*m
;
53 m
= xtables_calloc(1, XT_ALIGN(sizeof(*m
)) + data_size
);
58 memcpy(m
->data
, data
, data_size
);
60 m
->u
.user
.match_size
= data_size
;
64 static void scrub_match(struct xtables_match
*match
)
71 /* IPv4 and IPv6 share the same hooking enumeration */
72 #define HOOK_PRE_ROUTING 0
73 #define HOOK_POST_ROUTING 4
75 static __u32
em_ipt_hook(struct nlmsghdr
*n
)
77 struct tcmsg
*t
= NLMSG_DATA(n
);
79 if (t
->tcm_parent
!= TC_H_ROOT
&&
80 t
->tcm_parent
== TC_H_MAJ(TC_H_INGRESS
))
81 return HOOK_PRE_ROUTING
;
83 return HOOK_POST_ROUTING
;
86 static int em_ipt_parse_eopt_argv(struct nlmsghdr
*n
,
87 struct tcf_ematch_hdr
*hdr
,
88 int argc
, char **argv
)
90 struct xtables_globals tmp_tcipt_globals
= em_tc_ipt_globals
;
91 struct xtables_match
*match
= NULL
;
92 __u8 nfproto
= NFPROTO_IPV4
;
98 c
= getopt_long(argc
, argv
, "6m:", tmp_tcipt_globals
.opts
,
105 xtables_init_all(&tmp_tcipt_globals
, nfproto
);
107 match
= xtables_find_match(optarg
, XTF_TRY_LOAD
, NULL
);
108 if (!match
|| !match
->x6_parse
) {
109 fprintf(stderr
, " failed to find match %s\n\n",
114 match
->m
= fake_xt_entry_match(match
->size
, NULL
);
116 printf(" %s error\n", match
->name
);
121 match
->init(match
->m
);
123 opts
= xtables_options_xfrm(tmp_tcipt_globals
.orig_opts
,
124 tmp_tcipt_globals
.opts
,
126 &match
->option_offset
);
132 tmp_tcipt_globals
.opts
= opts
;
136 nfproto
= NFPROTO_IPV6
;
141 fprintf(stderr
, "failed to find match %s\n\n",
146 xtables_option_mpcall(c
, argv
, 0, match
, NULL
);
152 fprintf(stderr
, " failed to parse parameters (%s)\n", *argv
);
156 /* check that we passed the correct parameters to the match */
157 xtables_option_mfcall(match
);
159 addraw_l(n
, MAX_MSG
, hdr
, sizeof(*hdr
));
160 addattr32(n
, MAX_MSG
, TCA_EM_IPT_HOOK
, em_ipt_hook(n
));
161 addattrstrz(n
, MAX_MSG
, TCA_EM_IPT_MATCH_NAME
, match
->name
);
162 addattr8(n
, MAX_MSG
, TCA_EM_IPT_MATCH_REVISION
, match
->revision
);
163 addattr8(n
, MAX_MSG
, TCA_EM_IPT_NFPROTO
, nfproto
);
164 addattr_l(n
, MAX_MSG
, TCA_EM_IPT_MATCH_DATA
, match
->m
->data
,
167 xtables_free_opts(1);
173 static int em_ipt_print_epot(FILE *fd
, struct tcf_ematch_hdr
*hdr
, void *data
,
176 struct rtattr
*tb
[TCA_EM_IPT_MAX
+ 1];
177 struct xtables_match
*match
;
181 if (parse_rtattr(tb
, TCA_EM_IPT_MAX
, data
, data_len
) < 0)
184 nfproto
= rta_getattr_u8(tb
[TCA_EM_IPT_NFPROTO
]);
186 xtables_init_all(&em_tc_ipt_globals
, nfproto
);
188 mname
= rta_getattr_str(tb
[TCA_EM_IPT_MATCH_NAME
]);
189 match
= xtables_find_match(mname
, XTF_TRY_LOAD
, NULL
);
193 match
->m
= fake_xt_entry_match(RTA_PAYLOAD(tb
[TCA_EM_IPT_MATCH_DATA
]),
194 RTA_DATA(tb
[TCA_EM_IPT_MATCH_DATA
]));
198 match
->print(NULL
, match
->m
, 0);
204 struct ematch_util ipt_ematch_util
= {
206 .kind_num
= TCF_EM_IPT
,
207 .parse_eopt_argv
= em_ipt_parse_eopt_argv
,
208 .print_eopt
= em_ipt_print_epot
,
209 .print_usage
= em_ipt_print_usage