]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/em_ipt.c
Merge branch 'main' into next
[mirror_iproute2.git] / tc / em_ipt.c
CommitLineData
dd296215 1/*
69df9bf9 2 * em_ipt.c IPtables extensions matching Ematch
dd296215
EB
3 *
4 * (C) 2018 Eyal Birger <eyal.birger@gmail.com>
5 *
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.
9 */
10
11#include <getopt.h>
12
13#include <linux/tc_ematch/tc_em_ipt.h>
14#include <linux/pkt_cls.h>
15#include <xtables.h>
16#include "m_ematch.h"
17
18static void em_ipt_print_usage(FILE *fd)
19{
20 fprintf(fd,
21 "Usage: ipt([-6] -m MATCH_NAME [MATCH_OPTS])\n"
22 "Example: 'ipt(-m policy --reqid 1 --pol ipsec --dir in)'\n");
23}
24
25static struct option original_opts[] = {
26 {
27 .name = "match",
28 .has_arg = 1,
29 .val = 'm'
30 },
31 {
32 .name = "ipv6",
33 .val = '6'
34 },
35 {}
36};
37
38static struct xtables_globals em_tc_ipt_globals = {
39 .option_offset = 0,
40 .program_name = "tc-em-ipt",
41 .program_version = "0.1",
42 .orig_opts = original_opts,
43 .opts = original_opts,
17504be8 44#if (XTABLES_VERSION_CODE >= 11)
dd296215 45 .compat_rev = xtables_compatible_revision,
17504be8 46#endif
dd296215
EB
47};
48
49static struct xt_entry_match *fake_xt_entry_match(int data_size, void *data)
50{
51 struct xt_entry_match *m;
52
53 m = xtables_calloc(1, XT_ALIGN(sizeof(*m)) + data_size);
54 if (!m)
55 return NULL;
56
57 if (data)
58 memcpy(m->data, data, data_size);
59
60 m->u.user.match_size = data_size;
61 return m;
62}
63
64static void scrub_match(struct xtables_match *match)
65{
66 match->mflags = 0;
67 free(match->m);
68 match->m = NULL;
69}
70
71/* IPv4 and IPv6 share the same hooking enumeration */
72#define HOOK_PRE_ROUTING 0
73#define HOOK_POST_ROUTING 4
74
75static __u32 em_ipt_hook(struct nlmsghdr *n)
76{
77 struct tcmsg *t = NLMSG_DATA(n);
78
79 if (t->tcm_parent != TC_H_ROOT &&
80 t->tcm_parent == TC_H_MAJ(TC_H_INGRESS))
81 return HOOK_PRE_ROUTING;
82
83 return HOOK_POST_ROUTING;
84}
85
86static int em_ipt_parse_eopt_argv(struct nlmsghdr *n,
87 struct tcf_ematch_hdr *hdr,
88 int argc, char **argv)
89{
90 struct xtables_globals tmp_tcipt_globals = em_tc_ipt_globals;
91 struct xtables_match *match = NULL;
92 __u8 nfproto = NFPROTO_IPV4;
93
94 while (1) {
95 struct option *opts;
96 int c;
97
98 c = getopt_long(argc, argv, "6m:", tmp_tcipt_globals.opts,
99 NULL);
100 if (c == -1)
101 break;
102
103 switch (c) {
104 case 'm':
105 xtables_init_all(&tmp_tcipt_globals, nfproto);
106
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",
110 optarg);
111 return -1;
112 }
113
114 match->m = fake_xt_entry_match(match->size, NULL);
115 if (!match->m) {
116 printf(" %s error\n", match->name);
117 return -1;
118 }
119
120 if (match->init)
121 match->init(match->m);
122
123 opts = xtables_options_xfrm(tmp_tcipt_globals.orig_opts,
124 tmp_tcipt_globals.opts,
125 match->x6_options,
126 &match->option_offset);
127 if (!opts) {
128 scrub_match(match);
129 return -1;
130 }
131
132 tmp_tcipt_globals.opts = opts;
133 break;
134
135 case '6':
136 nfproto = NFPROTO_IPV6;
137 break;
138
139 default:
140 if (!match) {
141 fprintf(stderr, "failed to find match %s\n\n",
142 optarg);
143 return -1;
144
145 }
146 xtables_option_mpcall(c, argv, 0, match, NULL);
147 break;
148 }
149 }
150
151 if (!match) {
152 fprintf(stderr, " failed to parse parameters (%s)\n", *argv);
153 return -1;
154 }
155
156 /* check that we passed the correct parameters to the match */
157 xtables_option_mfcall(match);
158
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,
165 match->size);
166
167 xtables_free_opts(1);
168
169 scrub_match(match);
170 return 0;
171}
172
173static int em_ipt_print_epot(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
174 int data_len)
175{
176 struct rtattr *tb[TCA_EM_IPT_MAX + 1];
177 struct xtables_match *match;
178 const char *mname;
179 __u8 nfproto;
180
181 if (parse_rtattr(tb, TCA_EM_IPT_MAX, data, data_len) < 0)
182 return -1;
183
184 nfproto = rta_getattr_u8(tb[TCA_EM_IPT_NFPROTO]);
185
186 xtables_init_all(&em_tc_ipt_globals, nfproto);
187
188 mname = rta_getattr_str(tb[TCA_EM_IPT_MATCH_NAME]);
189 match = xtables_find_match(mname, XTF_TRY_LOAD, NULL);
190 if (!match)
191 return -1;
192
193 match->m = fake_xt_entry_match(RTA_PAYLOAD(tb[TCA_EM_IPT_MATCH_DATA]),
194 RTA_DATA(tb[TCA_EM_IPT_MATCH_DATA]));
195 if (!match->m)
196 return -1;
197
198 match->print(NULL, match->m, 0);
199
200 scrub_match(match);
201 return 0;
202}
203
204struct ematch_util ipt_ematch_util = {
205 .kind = "ipt",
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
210};