]> sourceware.org Git - systemtap.git/blame - tapset-netfilter.cxx
Add multiarch testing to testsuite/systemtap.base/callee.exp.
[systemtap.git] / tapset-netfilter.cxx
CommitLineData
cc0901e0 1// tapset for netfilter hooks
4d914c37 2// Copyright (C) 2012-2014 Red Hat Inc.
92318adc
CM
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
8
9
10#include "session.h"
11#include "tapsets.h"
12#include "translate.h"
13#include "util.h"
92318adc
CM
14#include <cstring>
15#include <string>
180132ef 16#include <limits.h>
92318adc 17
92318adc
CM
18using namespace std;
19using namespace __gnu_cxx;
20
cc0901e0
FCE
21static const string TOK_NETFILTER("netfilter");
22static const string TOK_HOOK("hook");
b21055f0
FCE
23static const string TOK_PF("pf");
24static const string TOK_PRIORITY("priority");
92318adc
CM
25
26// ------------------------------------------------------------------------
cc0901e0 27// netfilter derived probes
92318adc
CM
28// ------------------------------------------------------------------------
29
30
cc0901e0 31struct netfilter_derived_probe: public derived_probe
92318adc 32{
b32b98b1 33 string hook;
b21055f0 34 string pf;
b32b98b1 35 string priority;
ddbda7ee 36 unsigned nf_index;
b21055f0
FCE
37
38 set<string> context_vars;
f1eff87e
CM
39
40 netfilter_derived_probe (systemtap_session &, probe* p,
41 probe_point* l, string h,
2398e3c6 42 string protof, string pri);
92318adc 43 virtual void join_group (systemtap_session& s);
92318adc
CM
44};
45
46
cc0901e0 47struct netfilter_derived_probe_group: public generic_dpg<netfilter_derived_probe>
92318adc 48{
92318adc
CM
49public:
50 void emit_module_decls (systemtap_session& s);
51 void emit_module_init (systemtap_session& s);
52 void emit_module_exit (systemtap_session& s);
53};
54
f1eff87e
CM
55struct netfilter_var_expanding_visitor: public var_expanding_visitor
56{
70719cbf 57 netfilter_var_expanding_visitor(systemtap_session& s);
f1eff87e
CM
58
59 systemtap_session& sess;
b21055f0 60 set<string> context_vars;
f1eff87e
CM
61
62 void visit_target_symbol (target_symbol* e);
63};
92318adc 64
f1eff87e
CM
65netfilter_derived_probe::netfilter_derived_probe (systemtap_session &s, probe* p,
66 probe_point* l, string h,
2398e3c6
CM
67 string protof, string pri):
68 derived_probe (p, l), hook (h), pf (protof), priority (pri)
92318adc 69{
ddbda7ee
FCE
70 static unsigned nf_index_ctr = 0;
71 this->nf_index = nf_index_ctr++; // PR14137: need to generate unique
72 // identifier, since p->name may be
73 // shared in c_unparser::emit_probe()
cf9a931b 74
a0e481c6
CM
75 bool hook_error = false;
76 bool pf_error = false;
cf9a931b 77
a0e481c6 78 // Map the strings passed in to the actual values defined in netfilter_*.h
2398e3c6
CM
79 // NOTE: We need to hard code all the following
80 // constants rather than just include the
81 // appropriate kernel headers because in different
82 // versions of the kernel, certain constants are not
83 // defined. This was the best method at the time to
84 // get them to compile properly.
cf9a931b 85
a0e481c6
CM
86 // Validate hook, pf, priority
87 if(pf == "NFPROTO_IPV4")
88 {
2398e3c6
CM
89 // Protocol Family
90 pf = "2";
91
92 // Hook
93 if (hook == "NF_INET_PRE_ROUTING") hook = "0";
94 else if (hook == "NF_INET_LOCAL_IN") hook = "1";
95 else if (hook == "NF_INET_FORWARD") hook = "2";
96 else if (hook == "NF_INET_LOCAL_OUT") hook = "3";
97 else if (hook == "NF_INET_POST_ROUTING") hook = "4";
98 else if (hook == "NF_IP_PRE_ROUTING") hook = "0";
99 else if (hook == "NF_IP_LOCAL_IN") hook = "1";
100 else if (hook == "NF_IP_FORWARD") hook = "2";
101 else if (hook == "NF_IP_LOCAL_OUT") hook = "3";
102 else if (hook == "NF_IP_POST_ROUTING") hook = "4";
103 else hook_error = true;
104
105 // Priority
106 if (priority == "NF_IP_PRI_FIRST") priority = lex_cast(INT_MIN);
107 else if (priority == "NF_IP_PRI_CONNTRACK_DEFRAG") priority = "-400";
108 else if (priority == "NF_IP_PRI_RAW") priority = "-300";
109 else if (priority == "NF_IP_PRI_SELINUX_FIRST") priority = "-225";
110 else if (priority == "NF_IP_PRI_CONNTRACK") priority = "-200";
111 else if (priority == "NF_IP_PRI_MANGLE") priority = "-150";
112 else if (priority == "NF_IP_PRI_NAT_DST") priority = "-100";
113 else if (priority == "NF_IP_PRI_FILTER") priority = "0";
114 else if (priority == "NF_IP_PRI_SECURITY") priority = "50";
115 else if (priority == "NF_IP_PRI_NAT_SRC") priority = "100";
116 else if (priority == "NF_IP_PRI_SELINUX_LAST") priority = "225";
117 else if (priority == "NF_IP_PRI_CONNTRACK_CONFIRM") priority = lex_cast(INT_MAX);
118 else if (priority == "NF_IP_PRI_LAST") priority = lex_cast(INT_MAX);
a0e481c6
CM
119 }
120 else if(pf=="NFPROTO_IPV6")
121 {
2398e3c6
CM
122 // Protocol Family
123 pf = "10";
124
125 // Hook
126 if (hook == "NF_IP6_PRE_ROUTING") hook = "0";
127 else if (hook == "NF_IP6_LOCAL_IN") hook = "1";
128 else if (hook == "NF_IP6_FORWARD") hook = "2";
129 else if (hook == "NF_IP6_LOCAL_OUT") hook = "3";
130 else if (hook == "NF_IP6_POST_ROUTING") hook = "4";
131 else hook_error = true;
132
133 // Priority
134 if (priority == "NF_IP6_PRI_FIRST") priority = lex_cast(INT_MIN);
135 else if (priority == "NF_IP6_PRI_CONNTRACK_DEFRAG") priority = "-400";
136 else if (priority == "NF_IP6_PRI_RAW") priority = "-300";
137 else if (priority == "NF_IP6_PRI_SELINUX_FIRST") priority = "-225";
138 else if (priority == "NF_IP6_PRI_CONNTRACK") priority = "-200";
139 else if (priority == "NF_IP6_PRI_MANGLE") priority = "-150";
140 else if (priority == "NF_IP6_PRI_NAT_DST") priority = "-100";
141 else if (priority == "NF_IP6_PRI_FILTER") priority = "0";
142 else if (priority == "NF_IP6_PRI_SECURITY") priority = "50";
143 else if (priority == "NF_IP6_PRI_NAT_SRC") priority = "100";
144 else if (priority == "NF_IP6_PRI_SELINUX_LAST") priority = "225";
145 else if (priority == "NF_IP6_PRI_LAST") priority = lex_cast(INT_MAX);
a0e481c6
CM
146 }
147 else if (pf == "NFPROTO_ARP")
2398e3c6
CM
148 {
149 // Protocol Family
150 pf = "3";
151
152 // Hook
153 if (hook == "NF_ARP_IN") hook = "0";
154 else if (hook == "NF_ARP_OUT") hook = "1";
155 else if (hook == "NF_ARP_FORWARD") hook = "2";
156 else hook_error = true;
a0e481c6
CM
157 }
158 else if (pf == "NFPROTO_BRIDGE")
159 {
2398e3c6
CM
160 // Protocol Family
161 pf = "7";
162
163 // Hook
164 if (hook == "NF_BR_PRE_ROUTING") hook = "0";
165 else if (hook == "NF_BR_LOCAL_IN") hook = "1";
166 else if (hook == "NF_BR_FORWARD") hook = "2";
167 else if (hook == "NF_BR_LOCAL_OUT") hook = "3";
168 else if (hook == "NF_BR_POST_ROUTING") hook = "4";
169 else hook_error = true;
a0e481c6
CM
170 }
171 else
172 pf_error = true;
cf9a931b 173
a0e481c6
CM
174 // If not running in guru mode, we need more strict checks on hook name,
175 // protocol family and priority to avoid people putting in wacky embedded c
176 // nastiness. Otherwise, and if it didn't match any of the above lists,
177 // pass the string in as is.
178 if(!s.guru_mode)
179 {
cf9a931b
CM
180 // At this point the priority should be a 32 bit integer encoded as a string.
181 // Ensure that this is the case.
182 try
183 {
184 int prio = lex_cast<int32_t>(priority);
b21055f0
FCE
185 (void) prio;
186 }
187 catch (const runtime_error&)
188 {
dc09353a 189 throw SEMANTIC_ERROR
cf9a931b
CM
190 (_F("unsupported netfilter priority \"%s\" for protocol family \"%s\"; need stap -g",
191 priority.c_str(), pf.c_str()));
b21055f0 192 }
cf9a931b
CM
193
194 // Complain and abort if there were any hook name errors
195 if (hook_error)
dc09353a 196 throw SEMANTIC_ERROR
cf9a931b
CM
197 (_F("unsupported netfilter hook \"%s\" for protocol family \"%s\"; need stap -g",
198 hook.c_str(), pf.c_str()));
199
a0e481c6
CM
200 // Complain and abort if there were any pf errors
201 if (pf_error)
dc09353a 202 throw SEMANTIC_ERROR
a0e481c6
CM
203 (_F("unsupported netfilter protocol family \"%s\"; need stap -g", pf.c_str()));
204 }
205
f1eff87e 206 // Expand local variables in the probe body
70719cbf 207 netfilter_var_expanding_visitor v (s);
f1eff87e 208 v.replace (this->body);
b21055f0
FCE
209
210 // Create probe-local vardecls, before symbol resolution might make
69aa668e 211 // one for us, so that we can set the all-important synthetic flag.
b21055f0
FCE
212 for (set<string>::iterator it = v.context_vars.begin();
213 it != v.context_vars.end();
214 it++)
215 {
216 string name = *it;
217 this->context_vars.insert(name);
218 vardecl *v = new vardecl;
219 v->name = name;
220 v->tok = this->tok; /* XXX: but really the $context var. */
221 v->set_arity (0, this->tok);
222 v->type = pe_long;
69aa668e 223 v->synthetic = true; // suppress rvalue or lvalue optimizations
b21055f0
FCE
224 this->locals.push_back (v);
225 }
92318adc
CM
226}
227
92318adc 228void
cc0901e0 229netfilter_derived_probe::join_group (systemtap_session& s)
92318adc 230{
cc0901e0 231 if (! s.netfilter_derived_probes)
b21055f0 232 s.netfilter_derived_probes = new netfilter_derived_probe_group ();
cc0901e0 233 s.netfilter_derived_probes->enroll (this);
ca6d3b0f 234 this->group = s.netfilter_derived_probes;
92318adc
CM
235}
236
237
238void
cc0901e0 239netfilter_derived_probe_group::emit_module_decls (systemtap_session& s)
92318adc
CM
240{
241 if (probes.empty()) return;
242
cc0901e0
FCE
243 // Here we emit any global data structures and functions, including callback functions
244 // to be invoked by netfilter.
b32b98b1 245 //
cc0901e0
FCE
246 // For other kernel callbacks, a token is passed back to help identify a particular
247 // probe-point registration. For netfilter, nope, so once we're in a notification callback,
248 // we can't find out exactly on whose (which probe point's) behalf we were called.
b32b98b1 249 //
cc0901e0
FCE
250 // So, we just emit one netfilter callback function per systemtap probe, each with its
251 // own nf_hook_ops structure. Note that the translator already emits a stp_probes[] array,
252 // pre-filled with probe names and handler functions and that sort of stuff.
b32b98b1 253
cc0901e0 254 s.op->newline() << "/* ---- netfilter probes ---- */";
92318adc
CM
255
256 s.op->newline() << "#include <linux/netfilter.h>";
92318adc
CM
257 s.op->newline() << "#include <linux/skbuff.h>";
258 s.op->newline() << "#include <linux/udp.h>";
259 s.op->newline() << "#include <linux/tcp.h>";
260 s.op->newline() << "#include <linux/ip.h>";
cc0901e0
FCE
261
262 for (unsigned i=0; i < probes.size(); i++)
263 {
264 netfilter_derived_probe *np = probes[i];
ddbda7ee 265 s.op->newline() << "static unsigned int enter_netfilter_probe_" << np->nf_index;
5bac1073 266
502f3816
DS
267 // Previous to kernel 2.6.22, the hookfunction definition takes
268 // a struct sk_buff **skb, whereas currently it uses a *skb. We
269 // need emit the right version so this will compile on RHEL5,
270 // for example.
2736131d
DS
271 s.op->newline() << "#if defined(STAPCONF_NETFILTER_V44)";
272 s.op->newline() << "(void *priv, struct sk_buff *nf_skb, const struct nf_hook_state *nf_state)";
273 s.op->newline() << "{";
274 s.op->newline() << "#elif defined(STAPCONF_NETFILTER_V41)";
502f3816
DS
275 s.op->newline() << "(const struct nf_hook_ops *nf_ops, struct sk_buff *nf_skb, const struct nf_hook_state *nf_state)";
276 s.op->newline() << "{";
277 s.op->newline() << "#elif defined(STAPCONF_NETFILTER_V313)";
4d914c37
FCE
278
279 s.op->newline() << "(const struct nf_hook_ops *nf_ops, struct sk_buff *nf_skb, const struct net_device *nf_in, const struct net_device *nf_out, int (*nf_okfn)(struct sk_buff *))";
280 s.op->newline() << "{";
281
7cfb10ec
MC
282 s.op->newline() << "#elif defined(STAPCONF_NETFILTER_V313B)";
283
284 s.op->newline() << "(const struct nf_hook_ops *nf_ops, struct sk_buff *nf_skb, const struct net_device *nf_in, const struct net_device *nf_out, const struct nf_hook_state *nf_state)";
285 s.op->newline() << "{";
286
4d914c37
FCE
287 s.op->newline() << "#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)";
288
b21055f0 289 s.op->newline() << "(unsigned int nf_hooknum, struct sk_buff *nf_skb, const struct net_device *nf_in, const struct net_device *nf_out, int (*nf_okfn)(struct sk_buff *))";
cc0901e0 290 s.op->newline() << "{";
5bac1073
CM
291
292 s.op->newline() << "#else";
293
294 s.op->newline() << "(unsigned int nf_hooknum, struct sk_buff **nf_pskb, const struct net_device *nf_in, const struct net_device *nf_out, int (*nf_okfn)(struct sk_buff *))";
295 s.op->newline() << "{";
296 s.op->newline(1) << "struct sk_buff *nf_skb = nf_pskb ? *nf_pskb : NULL;";
297
298 s.op->newline(-1) << "#endif";
7c3e97f4 299 s.op->newline(1) << "const struct stap_probe * const stp = & stap_probes[" << np->session_index << "];";
b21055f0 300 s.op->newline() << "int nf_verdict = NF_ACCEPT;"; // default NF_ACCEPT, to be used by $verdict context var
2736131d
DS
301 s.op->newline() << "#if defined(STAPCONF_NETFILTER_V44)";
302 s.op->newline() << "unsigned int nf_hooknum = nf_state->hook;";
303 s.op->newline() << "#elif defined(STAPCONF_NETFILTER_V313) || defined(STAPCONF_NETFILTER_V313B) || defined(STAPCONF_NETFILTER_V41)";
4d914c37
FCE
304 s.op->newline() << "unsigned int nf_hooknum = nf_ops->hooknum;";
305 s.op->newline() << "#endif";
2736131d 306 s.op->newline() << "#if defined(STAPCONF_NETFILTER_V41) || defined(STAPCONF_NETFILTER_V44)";
502f3816
DS
307 s.op->newline() << "struct net_device *nf_in = nf_state->in;";
308 s.op->newline() << "struct net_device *nf_out = nf_state->out;";
2736131d
DS
309 s.op->newline() << "#endif";
310 s.op->newline() << "#if defined(STAPCONF_NETFILTER_V44)";
311 s.op->newline() << "int (*nf_okfn)(struct net *, struct sock *, struct sk_buff *) = nf_state->okfn;";
312 s.op->newline() << "#elif defined(STAPCONF_NETFILTER_V41)";
502f3816
DS
313 s.op->newline() << "int (*nf_okfn)(struct sock *, struct sk_buff *) = nf_state->okfn;";
314 s.op->newline() << "#endif";
71db462b 315 common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "stp",
cda141c2 316 "stp_probe_type_netfilter",
cc0901e0 317 false);
f1eff87e 318
b21055f0
FCE
319 // Copy or pretend-to-touch each incoming parameter.
320
1341a03c 321 string c_p = "c->probe_locals." + lex_cast(np->name()); // this is where the $context vars show up
ddbda7ee
FCE
322 // NB: PR14137: this should be the potentially shared name,
323 // since the generated probe handler body refers to that name.
b21055f0
FCE
324
325 if (np->context_vars.find("__nf_hooknum") != np->context_vars.end())
0386bbcf 326 s.op->newline() << c_p + "." + s.up->c_localname("__nf_hooknum") + " = (int64_t)(uintptr_t) nf_hooknum;";
b21055f0
FCE
327 else
328 s.op->newline() << "(void) nf_hooknum;";
329 if (np->context_vars.find("__nf_skb") != np->context_vars.end())
0386bbcf 330 s.op->newline() << c_p + "." + s.up->c_localname("__nf_skb") + " = (int64_t)(uintptr_t) nf_skb;";
b21055f0
FCE
331 else
332 s.op->newline() << "(void) nf_skb;";
333 if (np->context_vars.find("__nf_in") != np->context_vars.end())
0386bbcf 334 s.op->newline() << c_p + "." + s.up->c_localname("__nf_in") + " = (int64_t)(uintptr_t) nf_in;";
b21055f0
FCE
335 else
336 s.op->newline() << "(void) nf_in;";
337 if (np->context_vars.find("__nf_out") != np->context_vars.end())
5eb65d05 338 s.op->newline() << c_p + "." + s.up->c_localname("__nf_out") + " = (int64_t)(uintptr_t) nf_out;";
b21055f0
FCE
339 else
340 s.op->newline() << "(void) nf_out;";
341 if (np->context_vars.find("__nf_verdict") != np->context_vars.end())
0386bbcf 342 s.op->newline() << c_p + "." + s.up->c_localname("__nf_verdict") + " = (int64_t) nf_verdict;";
b21055f0
FCE
343 else
344 s.op->newline() << "(void) nf_out;";
345
346 // Invoke the probe handler
cc0901e0 347 s.op->newline() << "(*stp->ph) (c);";
f1eff87e 348
ef1337ee 349 common_probe_entryfn_epilogue (s, false, otf_safe_context(s));
cc0901e0 350
b21055f0 351 if (np->context_vars.find("__nf_verdict") != np->context_vars.end())
6b5871b0 352 s.op->newline() << "if (c != NULL) nf_verdict = (int) "+c_p+"." + s.up->c_localname("__nf_verdict") + ";";
b21055f0
FCE
353
354 s.op->newline() << "return nf_verdict;";
f1eff87e
CM
355 s.op->newline(-1) << "}";
356
cc0901e0 357 // now emit the nf_hook_ops struct for this probe.
ddbda7ee
FCE
358 s.op->newline() << "static struct nf_hook_ops netfilter_opts_" << np->nf_index << " = {";
359 s.op->newline() << ".hook = enter_netfilter_probe_" << np->nf_index << ",";
2736131d 360 s.op->newline() << "#ifndef STAPCONF_NETFILTER_V44";
cc0901e0 361 s.op->newline() << ".owner = THIS_MODULE,";
2736131d 362 s.op->newline() << "#endif";
b21055f0
FCE
363
364 // XXX: if these strings/numbers are not range-limited / validated before we get here,
365 // ie during the netfilter_derived_probe ctor, then we will emit potential trash here,
366 // leading to all kinds of horror. Like zombie women eating roach-filled walnuts. Dogs
367 // and cats living together. Foreign foods taking over the refrigerator. Don't let this
368 // happen to you!
b32b98b1 369 s.op->newline() << ".hooknum = " << np->hook << ",";
b21055f0 370 s.op->newline() << ".pf = " << np->pf << ",";
b32b98b1
CM
371 s.op->newline() << ".priority = " << np->priority << ",";
372 s.op->newline() << "};";
cc0901e0
FCE
373 }
374 s.op->newline();
92318adc
CM
375}
376
377
378void
cc0901e0 379netfilter_derived_probe_group::emit_module_init (systemtap_session& s)
92318adc
CM
380{
381 if (probes.empty()) return;
382
cc0901e0
FCE
383 // We register (do not execute) the probes here.
384 // NB: since we anticipate only a few netfilter/hook type probes, there is no need to
385 // emit an initialization loop into the generated C code. We can simply unroll it.
b32b98b1 386 for (unsigned i=0; i < probes.size(); i++)
cc0901e0
FCE
387 {
388 netfilter_derived_probe *np = probes[i];
ddbda7ee 389 s.op->newline() << "rc = nf_register_hook (& netfilter_opts_" << np->nf_index << ");";
cc0901e0
FCE
390 if (i > 0) // unregister others upon failure
391 {
392 s.op->newline() << "if (rc < 0) {";
ddbda7ee 393 s.op->indent(1);
c1b601a8 394 for (int j=i-1; j>=0; j--) // XXX: j must be signed for loop to work
cc0901e0
FCE
395 {
396 netfilter_derived_probe *np2 = probes[j];
ddbda7ee 397 s.op->newline() << "nf_unregister_hook (& netfilter_opts_" << np2->nf_index << ");";
cc0901e0
FCE
398 }
399 s.op->newline(-1) << "}";
400 }
401 }
92318adc
CM
402}
403
404
405void
cc0901e0 406netfilter_derived_probe_group::emit_module_exit (systemtap_session& s)
92318adc 407{
cc0901e0 408 if (probes.empty()) return;
b32b98b1 409
cc0901e0 410 // We register (do not execute) the probes here.
b32b98b1 411 for (unsigned i=0; i < probes.size(); i++)
cc0901e0
FCE
412 {
413 netfilter_derived_probe *np = probes[i];
ddbda7ee 414 s.op->newline() << "nf_unregister_hook (& netfilter_opts_" << np->nf_index << ");";
cc0901e0 415 }
92318adc
CM
416}
417
b21055f0 418
70719cbf
JS
419netfilter_var_expanding_visitor::netfilter_var_expanding_visitor (systemtap_session& s):
420 sess (s)
f1eff87e 421{
f1eff87e
CM
422}
423
b21055f0 424
f1eff87e
CM
425void
426netfilter_var_expanding_visitor::visit_target_symbol (target_symbol* e)
427{
428 try
429 {
430 assert(e->name.size() > 0 && e->name[0] == '$');
431
f1eff87e 432 if (e->addressof)
dc09353a 433 throw SEMANTIC_ERROR(_("cannot take address of netfilter hook context variable"), e->tok);
b21055f0
FCE
434
435 // We map all $context variables to similarly named probe locals.
436 // See emit_module_decls for how the parameters & result are handled.
437 string c_var;
438 bool lvalue_ok = false;
6f636710 439 bool need_guru = false;
b21055f0
FCE
440 if (e->name == "$hooknum") { c_var = "__nf_hooknum"; }
441 else if (e->name == "$skb") { c_var = "__nf_skb"; }
442 else if (e->name == "$in") { c_var = "__nf_in"; }
443 else if (e->name == "$out") { c_var = "__nf_out"; }
444 else if (e->name == "$okfn") { c_var = "__nf_okfn"; }
6f636710 445 else if (e->name == "$verdict") { c_var = "__nf_verdict"; lvalue_ok = true; need_guru = true; }
b21055f0
FCE
446 // XXX: also support $$vars / $$parms
447 else
dc09353a 448 throw SEMANTIC_ERROR(_("unsupported context variable"), e->tok);
b21055f0
FCE
449
450 if (! lvalue_ok && is_active_lvalue (e))
dc09353a 451 throw SEMANTIC_ERROR(_("write to netfilter parameter not permitted"), e->tok);
b21055f0 452
6f636710
CM
453 // Writing to variables like $verdict requires guru mode, for obvious reasons
454 if(need_guru && !sess.guru_mode)
dc09353a 455 throw SEMANTIC_ERROR(_("write to netfilter verdict requires guru mode; need stap -g"), e->tok);
6f636710 456
b21055f0
FCE
457 context_vars.insert (c_var);
458
459 // Synthesize a symbol to reference those variables
460 symbol* sym = new symbol;
461 sym->type = pe_long;
462 sym->tok = e->tok;
463 sym->name = c_var;
464 provide (sym);
f1eff87e
CM
465 }
466 catch (const semantic_error &er)
467 {
468 e->chain (er);
469 provide (e);
470 }
471}
92318adc 472// ------------------------------------------------------------------------
cc0901e0 473// unified probe builder for netfilter probes
92318adc
CM
474// ------------------------------------------------------------------------
475
476
cc0901e0 477struct netfilter_builder: public derived_probe_builder
92318adc
CM
478{
479 virtual void build(systemtap_session & sess,
480 probe * base, probe_point * location,
481 literal_map_t const & parameters,
482 vector<derived_probe *> & finished_results);
483
484 static void register_patterns(systemtap_session& s);
485};
486
cc0901e0 487
92318adc 488void
cc0901e0 489netfilter_builder::build(systemtap_session & sess,
92318adc
CM
490 probe * base,
491 probe_point * location,
492 literal_map_t const & parameters,
493 vector<derived_probe *> & finished_results)
494{
45a63356
FCE
495 interned_string hook; // no default
496 interned_string pf; // no default
497 interned_string priority = "0"; // Default: somewhere in the middle
b32b98b1
CM
498
499 if(!get_param(parameters, TOK_HOOK, hook))
dc09353a 500 throw SEMANTIC_ERROR (_("missing hooknum"));
92318adc 501
067cc66f 502 if(!get_param(parameters, TOK_PF, pf))
dc09353a 503 throw SEMANTIC_ERROR (_("missing protocol family"));
067cc66f 504
b21055f0 505 get_param(parameters, TOK_PRIORITY, priority);
b32b98b1 506
b21055f0 507 finished_results.push_back(new netfilter_derived_probe(sess, base, location, hook, pf, priority));
b32b98b1 508}
cc0901e0 509
92318adc 510void
b32b98b1 511register_tapset_netfilter(systemtap_session& s)
92318adc
CM
512{
513 match_node* root = s.pattern_root;
cc0901e0 514 derived_probe_builder *builder = new netfilter_builder();
92318adc 515
b32b98b1 516
4e8c0276 517 //netfilter.hook().pf()
b32b98b1
CM
518 root->bind(TOK_NETFILTER)->bind_str(TOK_HOOK)->bind_str(TOK_PF)->bind(builder);
519
4e8c0276
CM
520 //netfilter.pf().hook()
521 root->bind(TOK_NETFILTER)->bind_str(TOK_PF)->bind_str(TOK_HOOK)->bind(builder);
b32b98b1 522
4e8c0276 523 //netfilter.hook().pf().priority()
b21055f0 524 root->bind(TOK_NETFILTER)->bind_str(TOK_HOOK)->bind_str(TOK_PF)->bind_str(TOK_PRIORITY)->bind(builder);
4e8c0276
CM
525
526 //netfilter.pf().hook().priority()
527 root->bind(TOK_NETFILTER)->bind_str(TOK_PF)->bind_str(TOK_HOOK)->bind_str(TOK_PRIORITY)->bind(builder);
92318adc
CM
528}
529
530/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.149668 seconds and 5 git commands to generate.