]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_LuaFFI.py
Merge pull request #13592 from rgacogne/qname-suffix-rule
[thirdparty/pdns.git] / regression-tests.dnsdist / test_LuaFFI.py
1 #!/usr/bin/env python
2
3 import unittest
4 import dns
5 from dnsdisttests import DNSDistTest
6
7 class TestAdvancedLuaFFI(DNSDistTest):
8
9 _config_template = """
10 local ffi = require("ffi")
11
12 local expectingUDP = true
13
14 function luaffirulefunction(dq)
15 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
16 if qtype ~= DNSQType.A and qtype ~= DNSQType.SOA then
17 print('invalid qtype')
18 return false
19 end
20
21 local qclass = ffi.C.dnsdist_ffi_dnsquestion_get_qclass(dq)
22 if qclass ~= DNSClass.IN then
23 print('invalid qclass')
24 return false
25 end
26
27 local ret_ptr = ffi.new("char *[1]")
28 local ret_ptr_param = ffi.cast("const char **", ret_ptr)
29 local ret_size = ffi.new("size_t[1]")
30 local ret_size_param = ffi.cast("size_t*", ret_size)
31 ffi.C.dnsdist_ffi_dnsquestion_get_qname_raw(dq, ret_ptr_param, ret_size_param)
32 if ret_size[0] ~= 36 then
33 print('invalid length for the qname ')
34 print(ret_size[0])
35 return false
36 end
37
38 local expectedQname = string.char(6)..'luaffi'..string.char(8)..'advanced'..string.char(5)..'tests'..string.char(8)..'powerdns'..string.char(3)..'com'
39 if ffi.string(ret_ptr[0]) ~= expectedQname then
40 print('invalid qname')
41 print(ffi.string(ret_ptr[0]))
42 return false
43 end
44
45 local rcode = ffi.C.dnsdist_ffi_dnsquestion_get_rcode(dq)
46 if rcode ~= 0 then
47 print('invalid rcode')
48 return false
49 end
50
51 local opcode = ffi.C.dnsdist_ffi_dnsquestion_get_opcode(dq)
52 if qtype == DNSQType.A and opcode ~= DNSOpcode.Query then
53 print('invalid opcode')
54 return false
55 elseif qtype == DNSQType.SOA and opcode ~= DNSOpcode.Update then
56 print('invalid opcode')
57 return false
58 end
59
60 local tcp = ffi.C.dnsdist_ffi_dnsquestion_get_tcp(dq)
61 if expectingUDP == tcp then
62 print('invalid tcp')
63 return false
64 end
65 expectingUDP = expectingUDP == false
66
67 local dnssecok = ffi.C.dnsdist_ffi_dnsquestion_get_do(dq)
68 if dnssecok ~= false then
69 print('invalid DNSSEC OK')
70 return false
71 end
72
73 local len = ffi.C.dnsdist_ffi_dnsquestion_get_len(dq)
74 if len ~= 52 then
75 print('invalid length')
76 print(len)
77 return false
78 end
79
80 local tag = ffi.C.dnsdist_ffi_dnsquestion_get_tag(dq, 'a-tag')
81 if ffi.string(tag) ~= 'a-value' then
82 print('invalid tag value')
83 print(ffi.string(tag))
84 return false
85 end
86
87 local raw_tag_buf_size = 255
88 local raw_tag_buf = ffi.new("char [?]", raw_tag_buf_size)
89 local raw_tag_size = ffi.C.dnsdist_ffi_dnsquestion_get_tag_raw(dq, 'raw-tag', raw_tag_buf, raw_tag_buf_size)
90 if ffi.string(raw_tag_buf, raw_tag_size) ~= 'a\0b' then
91 print('invalid raw tag value')
92 print(ffi.string(raw_tag_buf, raw_tag_size))
93 return false
94 end
95
96 return true
97 end
98
99 function luaffiactionfunction(dq)
100 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
101 if qtype == DNSQType.A then
102 local str = "192.0.2.1"
103 local buf = ffi.new("char[?]", #str + 1)
104 ffi.copy(buf, str)
105 ffi.C.dnsdist_ffi_dnsquestion_set_result(dq, buf, #str)
106 return DNSAction.Spoof
107 elseif qtype == DNSQType.SOA then
108 ffi.C.dnsdist_ffi_dnsquestion_set_rcode(dq, DNSRCode.REFUSED)
109 return DNSAction.Refused
110 end
111 end
112
113 function luaffiactionsettag(dq)
114 ffi.C.dnsdist_ffi_dnsquestion_set_tag(dq, 'a-tag', 'a-value')
115 return DNSAction.None
116 end
117
118 function luaffiactionsettagraw(dq)
119 local value = "a\0b"
120 ffi.C.dnsdist_ffi_dnsquestion_set_tag_raw(dq, 'raw-tag', value, #value)
121 return DNSAction.None
122 end
123
124 addAction(AllRule(), LuaFFIAction(luaffiactionsettag))
125 addAction(AllRule(), LuaFFIAction(luaffiactionsettagraw))
126 addAction(LuaFFIRule(luaffirulefunction), LuaFFIAction(luaffiactionfunction))
127 -- newServer{address="127.0.0.1:%s"}
128 """
129
130 def testAdvancedLuaFFI(self):
131 """
132 Lua FFI: Test the Lua FFI interface
133 """
134 name = 'luaffi.advanced.tests.powerdns.com.'
135 query = dns.message.make_query(name, 'A', 'IN')
136 # dnsdist set RA = RD for spoofed responses
137 query.flags &= ~dns.flags.RD
138
139 response = dns.message.make_response(query)
140 rrset = dns.rrset.from_text(name,
141 60,
142 dns.rdataclass.IN,
143 dns.rdatatype.A,
144 '192.0.2.1')
145 response.answer.append(rrset)
146
147 for method in ("sendUDPQuery", "sendTCPQuery"):
148 sender = getattr(self, method)
149 (_, receivedResponse) = sender(query, response=None, useQueue=False)
150 self.assertEqual(receivedResponse, response)
151
152 def testAdvancedLuaFFIUpdate(self):
153 """
154 Lua FFI: Test the Lua FFI interface via an update
155 """
156 name = 'luaffi.advanced.tests.powerdns.com.'
157 query = dns.message.make_query(name, 'SOA', 'IN')
158 query.set_opcode(dns.opcode.UPDATE)
159 # dnsdist set RA = RD for spoofed responses
160 query.flags &= ~dns.flags.RD
161
162 response = dns.message.make_response(query)
163 response.set_rcode(dns.rcode.REFUSED)
164
165 for method in ("sendUDPQuery", "sendTCPQuery"):
166 sender = getattr(self, method)
167 (_, receivedResponse) = sender(query, response=None, useQueue=False)
168 self.assertEqual(receivedResponse, response)
169
170 class TestAdvancedLuaFFIPerThread(DNSDistTest):
171
172 _config_template = """
173
174 local rulefunction = [[
175 local ffi = require("ffi")
176
177 return function(dq)
178 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
179 if qtype ~= DNSQType.A and qtype ~= DNSQType.SOA then
180 print('invalid qtype')
181 return false
182 end
183
184 local qclass = ffi.C.dnsdist_ffi_dnsquestion_get_qclass(dq)
185 if qclass ~= DNSClass.IN then
186 print('invalid qclass')
187 return false
188 end
189
190 local ret_ptr = ffi.new("char *[1]")
191 local ret_ptr_param = ffi.cast("const char **", ret_ptr)
192 local ret_size = ffi.new("size_t[1]")
193 local ret_size_param = ffi.cast("size_t*", ret_size)
194 ffi.C.dnsdist_ffi_dnsquestion_get_qname_raw(dq, ret_ptr_param, ret_size_param)
195 if ret_size[0] ~= 45 then
196 print('invalid length for the qname ')
197 print(ret_size[0])
198 return false
199 end
200
201 local expectedQname = string.char(15)..'luaffiperthread'..string.char(8)..'advanced'..string.char(5)..'tests'..string.char(8)..'powerdns'..string.char(3)..'com'
202 if ffi.string(ret_ptr[0]) ~= expectedQname then
203 print('invalid qname')
204 print(ffi.string(ret_ptr[0]))
205 return false
206 end
207
208 local rcode = ffi.C.dnsdist_ffi_dnsquestion_get_rcode(dq)
209 if rcode ~= 0 then
210 print('invalid rcode')
211 return false
212 end
213
214 local opcode = ffi.C.dnsdist_ffi_dnsquestion_get_opcode(dq)
215 if qtype == DNSQType.A and opcode ~= DNSOpcode.Query then
216 print('invalid opcode')
217 return false
218 elseif qtype == DNSQType.SOA and opcode ~= DNSOpcode.Update then
219 print('invalid opcode')
220 return false
221 end
222
223 local dnssecok = ffi.C.dnsdist_ffi_dnsquestion_get_do(dq)
224 if dnssecok ~= false then
225 print('invalid DNSSEC OK')
226 return false
227 end
228
229 local len = ffi.C.dnsdist_ffi_dnsquestion_get_len(dq)
230 if len ~= 61 then
231 print('invalid length')
232 print(len)
233 return false
234 end
235
236 local tag = ffi.C.dnsdist_ffi_dnsquestion_get_tag(dq, 'a-tag')
237 if ffi.string(tag) ~= 'a-value' then
238 print('invalid tag value')
239 print(ffi.string(tag))
240 return false
241 end
242
243 return true
244 end
245 ]]
246
247 local actionfunction = [[
248 local ffi = require("ffi")
249
250 return function(dq)
251 local qtype = ffi.C.dnsdist_ffi_dnsquestion_get_qtype(dq)
252 if qtype == DNSQType.A then
253 local str = "192.0.2.1"
254 local buf = ffi.new("char[?]", #str + 1)
255 ffi.copy(buf, str)
256 ffi.C.dnsdist_ffi_dnsquestion_set_result(dq, buf, #str)
257 return DNSAction.Spoof
258 elseif qtype == DNSQType.SOA then
259 ffi.C.dnsdist_ffi_dnsquestion_set_rcode(dq, DNSRCode.REFUSED)
260 return DNSAction.Refused
261 end
262 end
263 ]]
264
265 local settagfunction = [[
266 local ffi = require("ffi")
267
268 return function(dq)
269 ffi.C.dnsdist_ffi_dnsquestion_set_tag(dq, 'a-tag', 'a-value')
270 return DNSAction.None
271 end
272 ]]
273
274 addAction(AllRule(), LuaFFIPerThreadAction(settagfunction))
275 addAction(LuaFFIPerThreadRule(rulefunction), LuaFFIPerThreadAction(actionfunction))
276 -- newServer{address="127.0.0.1:%s"}
277 """
278
279 def testAdvancedLuaPerthreadFFI(self):
280 """
281 Lua FFI: Test the Lua FFI per-thread interface
282 """
283 name = 'luaffiperthread.advanced.tests.powerdns.com.'
284 query = dns.message.make_query(name, 'A', 'IN')
285 # dnsdist set RA = RD for spoofed responses
286 query.flags &= ~dns.flags.RD
287
288 response = dns.message.make_response(query)
289 rrset = dns.rrset.from_text(name,
290 60,
291 dns.rdataclass.IN,
292 dns.rdatatype.A,
293 '192.0.2.1')
294 response.answer.append(rrset)
295
296 for method in ("sendUDPQuery", "sendTCPQuery"):
297 sender = getattr(self, method)
298 (_, receivedResponse) = sender(query, response=None, useQueue=False)
299 self.assertEqual(receivedResponse, response)
300
301 def testAdvancedLuaFFIPerThreadUpdate(self):
302 """
303 Lua FFI: Test the Lua FFI per-thread interface via an update
304 """
305 name = 'luaffiperthread.advanced.tests.powerdns.com.'
306 query = dns.message.make_query(name, 'SOA', 'IN')
307 query.set_opcode(dns.opcode.UPDATE)
308 # dnsdist set RA = RD for spoofed responses
309 query.flags &= ~dns.flags.RD
310
311 response = dns.message.make_response(query)
312 response.set_rcode(dns.rcode.REFUSED)
313
314 for method in ("sendUDPQuery", "sendTCPQuery"):
315 sender = getattr(self, method)
316 (_, receivedResponse) = sender(query, response=None, useQueue=False)
317 self.assertEqual(receivedResponse, response)