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 .compat_rev
= xtables_compatible_revision
,
47 static struct xt_entry_match
*fake_xt_entry_match(int data_size
, void *data
)
49 struct xt_entry_match
*m
;
51 m
= xtables_calloc(1, XT_ALIGN(sizeof(*m
)) + data_size
);
56 memcpy(m
->data
, data
, data_size
);
58 m
->u
.user
.match_size
= data_size
;
62 static void scrub_match(struct xtables_match
*match
)
69 /* IPv4 and IPv6 share the same hooking enumeration */
70 #define HOOK_PRE_ROUTING 0
71 #define HOOK_POST_ROUTING 4
73 static __u32
em_ipt_hook(struct nlmsghdr
*n
)
75 struct tcmsg
*t
= NLMSG_DATA(n
);
77 if (t
->tcm_parent
!= TC_H_ROOT
&&
78 t
->tcm_parent
== TC_H_MAJ(TC_H_INGRESS
))
79 return HOOK_PRE_ROUTING
;
81 return HOOK_POST_ROUTING
;
84 static int em_ipt_parse_eopt_argv(struct nlmsghdr
*n
,
85 struct tcf_ematch_hdr
*hdr
,
86 int argc
, char **argv
)
88 struct xtables_globals tmp_tcipt_globals
= em_tc_ipt_globals
;
89 struct xtables_match
*match
= NULL
;
90 __u8 nfproto
= NFPROTO_IPV4
;
96 c
= getopt_long(argc
, argv
, "6m:", tmp_tcipt_globals
.opts
,
103 xtables_init_all(&tmp_tcipt_globals
, nfproto
);
105 match
= xtables_find_match(optarg
, XTF_TRY_LOAD
, NULL
);
106 if (!match
|| !match
->x6_parse
) {
107 fprintf(stderr
, " failed to find match %s\n\n",
112 match
->m
= fake_xt_entry_match(match
->size
, NULL
);
114 printf(" %s error\n", match
->name
);
119 match
->init(match
->m
);
121 opts
= xtables_options_xfrm(tmp_tcipt_globals
.orig_opts
,
122 tmp_tcipt_globals
.opts
,
124 &match
->option_offset
);
130 tmp_tcipt_globals
.opts
= opts
;
134 nfproto
= NFPROTO_IPV6
;
139 fprintf(stderr
, "failed to find match %s\n\n",
144 xtables_option_mpcall(c
, argv
, 0, match
, NULL
);
150 fprintf(stderr
, " failed to parse parameters (%s)\n", *argv
);
154 /* check that we passed the correct parameters to the match */
155 xtables_option_mfcall(match
);
157 addraw_l(n
, MAX_MSG
, hdr
, sizeof(*hdr
));
158 addattr32(n
, MAX_MSG
, TCA_EM_IPT_HOOK
, em_ipt_hook(n
));
159 addattrstrz(n
, MAX_MSG
, TCA_EM_IPT_MATCH_NAME
, match
->name
);
160 addattr8(n
, MAX_MSG
, TCA_EM_IPT_MATCH_REVISION
, match
->revision
);
161 addattr8(n
, MAX_MSG
, TCA_EM_IPT_NFPROTO
, nfproto
);
162 addattr_l(n
, MAX_MSG
, TCA_EM_IPT_MATCH_DATA
, match
->m
->data
,
165 xtables_free_opts(1);
171 static int em_ipt_print_epot(FILE *fd
, struct tcf_ematch_hdr
*hdr
, void *data
,
174 struct rtattr
*tb
[TCA_EM_IPT_MAX
+ 1];
175 struct xtables_match
*match
;
179 if (parse_rtattr(tb
, TCA_EM_IPT_MAX
, data
, data_len
) < 0)
182 nfproto
= rta_getattr_u8(tb
[TCA_EM_IPT_NFPROTO
]);
184 xtables_init_all(&em_tc_ipt_globals
, nfproto
);
186 mname
= rta_getattr_str(tb
[TCA_EM_IPT_MATCH_NAME
]);
187 match
= xtables_find_match(mname
, XTF_TRY_LOAD
, NULL
);
191 match
->m
= fake_xt_entry_match(RTA_PAYLOAD(tb
[TCA_EM_IPT_MATCH_DATA
]),
192 RTA_DATA(tb
[TCA_EM_IPT_MATCH_DATA
]));
196 match
->print(NULL
, match
->m
, 0);
202 struct ematch_util ipt_ematch_util
= {
204 .kind_num
= TCF_EM_IPT
,
205 .parse_eopt_argv
= em_ipt_parse_eopt_argv
,
206 .print_eopt
= em_ipt_print_epot
,
207 .print_usage
= em_ipt_print_usage