forked from NLnetLabs/unbound
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interface.i
1705 lines (1503 loc) · 54.6 KB
/
interface.i
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* interface.i: unbound python module
*/
%begin %{
/* store state of warning output, restored at later pop */
#pragma GCC diagnostic push
/* ignore warnings for pragma below, where for older GCC it can produce a
warning if the cast-function-type warning is absent. */
#pragma GCC diagnostic ignored "-Wpragmas"
/* ignore gcc8 METH_NOARGS function cast warnings for swig function pointers */
#pragma GCC diagnostic ignored "-Wcast-function-type"
%}
%module unboundmodule
%{
/* restore state of warning output, remove the functioncast ignore */
#pragma GCC diagnostic pop
/**
* \file
* This is the interface between the unbound server and a python module
* called to perform operations on queries.
*/
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#include <stdarg.h>
#include "config.h"
#include "util/log.h"
#include "util/module.h"
#include "util/netevent.h"
#include "util/regional.h"
#include "util/config_file.h"
#include "util/data/msgreply.h"
#include "util/data/packed_rrset.h"
#include "util/data/dname.h"
#include "util/storage/lruhash.h"
#include "services/cache/dns.h"
#include "services/mesh.h"
#include "iterator/iter_delegpt.h"
#include "iterator/iter_hints.h"
#include "iterator/iter_utils.h"
#include "sldns/wire2str.h"
#include "sldns/str2wire.h"
#include "sldns/pkthdr.h"
%}
%include "stdint.i" /* uint_16_t can be known type now */
%inline %{
/* converts [len][data][len][data][0] string to a List of labels (PyBytes) */
PyObject* GetNameAsLabelList(const char* name, int len) {
PyObject* list;
int cnt=0, i;
i = 0;
while (i < len) {
i += ((unsigned int)name[i]) + 1;
cnt++;
}
list = PyList_New(cnt);
i = 0; cnt = 0;
while (i < len) {
char buf[LDNS_MAX_LABELLEN+1];
if(((unsigned int)name[i])+1 <= (unsigned int)sizeof(buf) &&
i+(int)((unsigned int)name[i]) < len) {
memmove(buf, name + i + 1, (unsigned int)name[i]);
buf[(unsigned int)name[i]] = 0;
PyList_SetItem(list, cnt, PyString_FromString(buf));
}
i += ((unsigned int)name[i]) + 1;
cnt++;
}
return list;
}
%}
/* ************************************************************************************ *
Structure query_info
* ************************************************************************************ */
/* Query info */
%ignore query_info::qname;
%ignore query_info::qname_len;
struct query_info {
%immutable;
char* qname;
size_t qname_len;
uint16_t qtype;
uint16_t qclass;
%mutable;
};
%inline %{
enum enum_rr_class {
RR_CLASS_IN = 1,
RR_CLASS_CH = 3,
RR_CLASS_HS = 4,
RR_CLASS_NONE = 254,
RR_CLASS_ANY = 255,
};
enum enum_rr_type {
RR_TYPE_A = 1,
RR_TYPE_NS = 2,
RR_TYPE_MD = 3,
RR_TYPE_MF = 4,
RR_TYPE_CNAME = 5,
RR_TYPE_SOA = 6,
RR_TYPE_MB = 7,
RR_TYPE_MG = 8,
RR_TYPE_MR = 9,
RR_TYPE_NULL = 10,
RR_TYPE_WKS = 11,
RR_TYPE_PTR = 12,
RR_TYPE_HINFO = 13,
RR_TYPE_MINFO = 14,
RR_TYPE_MX = 15,
RR_TYPE_TXT = 16,
RR_TYPE_RP = 17,
RR_TYPE_AFSDB = 18,
RR_TYPE_X25 = 19,
RR_TYPE_ISDN = 20,
RR_TYPE_RT = 21,
RR_TYPE_NSAP = 22,
RR_TYPE_NSAP_PTR = 23,
RR_TYPE_SIG = 24,
RR_TYPE_KEY = 25,
RR_TYPE_PX = 26,
RR_TYPE_GPOS = 27,
RR_TYPE_AAAA = 28,
RR_TYPE_LOC = 29,
RR_TYPE_NXT = 30,
RR_TYPE_EID = 31,
RR_TYPE_NIMLOC = 32,
RR_TYPE_SRV = 33,
RR_TYPE_ATMA = 34,
RR_TYPE_NAPTR = 35,
RR_TYPE_KX = 36,
RR_TYPE_CERT = 37,
RR_TYPE_A6 = 38,
RR_TYPE_DNAME = 39,
RR_TYPE_SINK = 40,
RR_TYPE_OPT = 41,
RR_TYPE_APL = 42,
RR_TYPE_DS = 43,
RR_TYPE_SSHFP = 44,
RR_TYPE_IPSECKEY = 45,
RR_TYPE_RRSIG = 46,
RR_TYPE_NSEC = 47,
RR_TYPE_DNSKEY = 48,
RR_TYPE_DHCID = 49,
RR_TYPE_NSEC3 = 50,
RR_TYPE_NSEC3PARAMS = 51,
RR_TYPE_UINFO = 100,
RR_TYPE_UID = 101,
RR_TYPE_GID = 102,
RR_TYPE_UNSPEC = 103,
RR_TYPE_TSIG = 250,
RR_TYPE_IXFR = 251,
RR_TYPE_AXFR = 252,
RR_TYPE_MAILB = 253,
RR_TYPE_MAILA = 254,
RR_TYPE_ANY = 255,
RR_TYPE_DLV = 32769,
};
PyObject* _get_qname(struct query_info* q) {
return PyBytes_FromStringAndSize((char*)q->qname, q->qname_len);
}
PyObject* _get_qname_components(struct query_info* q) {
return GetNameAsLabelList((const char*)q->qname, q->qname_len);
}
%}
%inline %{
PyObject* dnameAsStr(PyObject* dname) {
char buf[LDNS_MAX_DOMAINLEN+1];
buf[0] = '\0';
dname_str((uint8_t*)PyBytes_AsString(dname), buf);
return PyString_FromString(buf);
}
%}
%extend query_info {
%pythoncode %{
def _get_qtype_str(self): return sldns_wire2str_type(self.qtype)
qtype_str = property(_get_qtype_str)
def _get_qclass_str(self): return sldns_wire2str_class(self.qclass)
qclass_str = property(_get_qclass_str)
qname = property(_unboundmodule._get_qname)
qname_list = property(_unboundmodule._get_qname_components)
def _get_qname_str(self): return dnameAsStr(self.qname)
qname_str = property(_get_qname_str)
%}
}
/* ************************************************************************************ *
Structure packed_rrset_key
* ************************************************************************************ */
%ignore packed_rrset_key::dname;
%ignore packed_rrset_key::dname_len;
/* RRsets */
struct packed_rrset_key {
%immutable;
char* dname;
size_t dname_len;
uint32_t flags;
uint16_t type; /* rrset type in network format */
uint16_t rrset_class; /* rrset class in network format */
%mutable;
};
/**
* This subroutine converts values between the host and network byte order.
* Specifically, ntohs() converts 16-bit quantities from network byte order to
* host byte order.
*/
uint16_t ntohs(uint16_t netshort);
%inline %{
PyObject* _get_dname(struct packed_rrset_key* k) {
return PyBytes_FromStringAndSize((char*)k->dname, k->dname_len);
}
PyObject* _get_dname_components(struct packed_rrset_key* k) {
return GetNameAsLabelList((char*)k->dname, k->dname_len);
}
%}
%extend packed_rrset_key {
%pythoncode %{
def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type))
type_str = property(_get_type_str)
def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class))
rrset_class_str = property(_get_class_str)
dname = property(_unboundmodule._get_dname)
dname_list = property(_unboundmodule._get_dname_components)
def _get_dname_str(self): return dnameAsStr(self.dname)
dname_str = property(_get_dname_str)
%}
}
#if defined(SWIGWORDSIZE64)
typedef long int rrset_id_type;
#else
typedef long long int rrset_id_type;
#endif
struct ub_packed_rrset_key {
struct lruhash_entry entry;
rrset_id_type id;
struct packed_rrset_key rk;
};
struct lruhash_entry {
lock_rw_type lock;
struct lruhash_entry* overflow_next;
struct lruhash_entry* lru_next;
struct lruhash_entry* lru_prev;
hashvalue_type hash;
void* key;
struct packed_rrset_data* data;
};
%ignore packed_rrset_data::rr_len;
%ignore packed_rrset_data::rr_ttl;
%ignore packed_rrset_data::rr_data;
struct packed_rrset_data {
/* TTL (in seconds like time()) */
uint32_t ttl;
/* number of rrs */
size_t count;
/* number of rrsigs */
size_t rrsig_count;
enum rrset_trust trust;
enum sec_status security;
/* length of every rr's rdata */
size_t* rr_len;
/* ttl of every rr */
uint32_t *rr_ttl;
/* array of pointers to every rr's rdata. The rr_data[i] rdata is stored in
* uncompressed wireformat. */
uint8_t** rr_data;
};
%pythoncode %{
class RRSetData_RRLen:
def __init__(self, obj): self.obj = obj
def __getitem__(self, index): return _unboundmodule._get_data_rr_len(self.obj, index)
def __len__(self): return self.obj.count + self.obj.rrsig_count
class RRSetData_RRTTL:
def __init__(self, obj): self.obj = obj
def __getitem__(self, index): return _unboundmodule._get_data_rr_ttl(self.obj, index)
def __setitem__(self, index, value): _unboundmodule._set_data_rr_ttl(self.obj, index, value)
def __len__(self): return self.obj.count + self.obj.rrsig_count
class RRSetData_RRData:
def __init__(self, obj): self.obj = obj
def __getitem__(self, index): return _unboundmodule._get_data_rr_data(self.obj, index)
def __len__(self): return self.obj.count + self.obj.rrsig_count
%}
%inline %{
PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
if ((d != NULL) && (idx >= 0) &&
((size_t)idx < (d->count+d->rrsig_count)))
return PyInt_FromLong(d->rr_len[idx]);
return Py_None;
}
void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
{
if ((d != NULL) && (idx >= 0) &&
((size_t)idx < (d->count+d->rrsig_count)))
d->rr_ttl[idx] = ttl;
}
PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
if ((d != NULL) && (idx >= 0) &&
((size_t)idx < (d->count+d->rrsig_count)))
return PyInt_FromLong(d->rr_ttl[idx]);
return Py_None;
}
PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
if ((d != NULL) && (idx >= 0) &&
((size_t)idx < (d->count+d->rrsig_count)))
return PyBytes_FromStringAndSize((char*)d->rr_data[idx],
d->rr_len[idx]);
return Py_None;
}
%}
%extend packed_rrset_data {
%pythoncode %{
def _get_data_rr_len(self): return RRSetData_RRLen(self)
rr_len = property(_get_data_rr_len)
def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
rr_ttl = property(_get_data_rr_ttl)
def _get_data_rr_data(self): return RRSetData_RRData(self)
rr_data = property(_get_data_rr_data)
%}
}
/* ************************************************************************************ *
Structure reply_info
* ************************************************************************************ */
/* Messages */
%ignore reply_info::rrsets;
%ignore reply_info::ref;
struct reply_info {
uint16_t flags;
uint16_t qdcount;
uint32_t ttl;
uint32_t prefetch_ttl;
uint16_t authoritative;
enum sec_status security;
size_t an_numrrsets;
size_t ns_numrrsets;
size_t ar_numrrsets;
size_t rrset_count; /* an_numrrsets + ns_numrrsets + ar_numrrsets */
struct ub_packed_rrset_key** rrsets;
struct rrset_ref ref[1]; /* ? */
};
struct rrset_ref {
struct ub_packed_rrset_key* key;
rrset_id_type id;
};
struct dns_msg {
struct query_info qinfo;
struct reply_info *rep;
};
%pythoncode %{
class ReplyInfo_RRSet:
def __init__(self, obj): self.obj = obj
def __getitem__(self, index): return _unboundmodule._rrset_rrsets_get(self.obj, index)
def __len__(self): return self.obj.rrset_count
class ReplyInfo_Ref:
def __init__(self, obj): self.obj = obj
def __getitem__(self, index): return _unboundmodule._rrset_ref_get(self.obj, index)
def __len__(self): return self.obj.rrset_count
%}
%inline %{
struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) {
if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count))
return r->rrsets[idx];
return NULL;
}
struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) {
if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) {
/* printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key); */
return &(r->ref[idx]);
/* return &(r->ref[idx]); */
}
/* printf("_rrset_ref_get: NULL\n"); */
return NULL;
}
%}
%extend reply_info {
%pythoncode %{
def _rrset_ref_get(self): return ReplyInfo_Ref(self)
ref = property(_rrset_ref_get)
def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
rrsets = property(_rrset_rrsets_get)
%}
}
/* ************************************************************************************ *
Structure sockaddr_storage
* ************************************************************************************ */
struct sockaddr_storage {};
%inline %{
static size_t _sockaddr_storage_len(const struct sockaddr_storage *ss) {
if (ss == NULL) {
return 0;
}
switch (ss->ss_family) {
case AF_INET: return sizeof(struct sockaddr_in);
case AF_INET6: return sizeof(struct sockaddr_in6);
#ifdef HAVE_SYS_UN_H
case AF_UNIX: return sizeof(struct sockaddr_un);
#endif
default:
return 0;
}
}
PyObject *_sockaddr_storage_family(const struct sockaddr_storage *ss) {
if (ss == NULL) {
return Py_None;
}
switch (ss->ss_family) {
case AF_INET: return PyUnicode_FromString("ip4");
case AF_INET6: return PyUnicode_FromString("ip6");
case AF_UNIX: return PyUnicode_FromString("unix");
default:
return Py_None;
}
}
PyObject *_sockaddr_storage_addr(const struct sockaddr_storage *ss) {
const struct sockaddr *sa;
size_t sa_len;
char name[NI_MAXHOST] = {0};
if (ss == NULL) {
return Py_None;
}
sa = (struct sockaddr *)ss;
sa_len = _sockaddr_storage_len(ss);
if (sa_len == 0) {
return Py_None;
}
if (getnameinfo(sa, sa_len, name, sizeof(name), NULL, 0, NI_NUMERICHOST) != 0) {
return Py_None;
}
return PyUnicode_FromString(name);
}
PyObject *_sockaddr_storage_raw_addr(const struct sockaddr_storage *ss) {
size_t sa_len;
if (ss == NULL) {
return Py_None;
}
sa_len = _sockaddr_storage_len(ss);
if (sa_len == 0) {
return Py_None;
}
if (ss->ss_family == AF_INET) {
const struct sockaddr_in *sa = (struct sockaddr_in *)ss;
const struct in_addr *raw = (struct in_addr *)&sa->sin_addr;
return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
}
if (ss->ss_family == AF_INET6) {
const struct sockaddr_in6 *sa = (struct sockaddr_in6 *)ss;
const struct in6_addr *raw = (struct in6_addr *)&sa->sin6_addr;
return PyBytes_FromStringAndSize((const char *)raw, sizeof(*raw));
}
#ifdef HAVE_SYS_UN_H
if (ss->ss_family == AF_UNIX) {
const struct sockaddr_un *sa = (struct sockaddr_un *)ss;
return PyBytes_FromString(sa->sun_path);
}
#endif
return Py_None;
}
PyObject *_sockaddr_storage_port(const struct sockaddr_storage *ss) {
if (ss == NULL) {
return Py_None;
}
if (ss->ss_family == AF_INET) {
const struct sockaddr_in *sa4 = (struct sockaddr_in *)ss;
return PyInt_FromLong(ntohs(sa4->sin_port));
}
if (ss->ss_family == AF_INET6) {
const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
return PyInt_FromLong(ntohs(sa6->sin6_port));
}
return Py_None;
}
PyObject *_sockaddr_storage_flowinfo(const struct sockaddr_storage *ss) {
const struct sockaddr_in6 *sa6;
if (ss == NULL || ss->ss_family != AF_INET6) {
return Py_None;
}
sa6 = (struct sockaddr_in6 *)ss;
return PyInt_FromLong(ntohl(sa6->sin6_flowinfo));
}
PyObject *_sockaddr_storage_scope_id(const struct sockaddr_storage *ss) {
const struct sockaddr_in6 *sa6;
if (ss == NULL || ss->ss_family != AF_INET6) {
return Py_None;
}
sa6 = (struct sockaddr_in6 *)ss;
return PyInt_FromLong(ntohl(sa6->sin6_scope_id));
}
%}
%extend sockaddr_storage {
%pythoncode %{
def _family_get(self): return _sockaddr_storage_family(self)
family = property(_family_get)
def _addr_get(self): return _sockaddr_storage_addr(self)
addr = property(_addr_get)
def _raw_addr_get(self): return _sockaddr_storage_raw_addr(self)
raw_addr = property(_raw_addr_get)
def _port_get(self): return _sockaddr_storage_port(self)
port = property(_port_get)
def _flowinfo_get(self): return _sockaddr_storage_flowinfo(self)
flowinfo = property(_flowinfo_get)
def _scope_id_get(self): return _sockaddr_storage_scope_id(self)
scope_id = property(_scope_id_get)
%}
}
/* ************************************************************************************ *
Structure mesh_state
* ************************************************************************************ */
struct mesh_state {
struct mesh_reply* reply_list;
};
struct mesh_reply {
struct mesh_reply* next;
struct comm_reply query_reply;
};
%rename(_addr) comm_reply::client_addr;
struct comm_reply {
struct sockaddr_storage client_addr;
};
%extend comm_reply {
%pythoncode %{
def _addr_get(self): return _sockaddr_storage_addr(self._addr)
addr = property(_addr_get)
def _port_get(self): return _sockaddr_storage_port(self._addr)
port = property(_port_get)
def _family_get(self): return _sockaddr_storage_family(self._addr)
family = property(_family_get)
%}
}
/* ************************************************************************************ *
Structure edns_option
* ************************************************************************************ */
/* Rename the members to follow the python convention of marking them as
* private. Access to the opt_code and opt_data members is given by the later
* python defined code and data members respectively. */
%rename(_next) edns_option::next;
%rename(_opt_code) edns_option::opt_code;
%rename(_opt_len) edns_option::opt_len;
%rename(_opt_data) edns_option::opt_data;
struct edns_option {
struct edns_option* next;
uint16_t opt_code;
size_t opt_len;
uint8_t* opt_data;
};
%inline %{
PyObject* _edns_option_opt_code_get(struct edns_option* option) {
uint16_t opt_code = option->opt_code;
return PyInt_FromLong(opt_code);
}
PyObject* _edns_option_opt_data_get(struct edns_option* option) {
return PyByteArray_FromStringAndSize((void*)option->opt_data,
option->opt_len);
}
%}
%extend edns_option {
%pythoncode %{
def _opt_code_get(self): return _edns_option_opt_code_get(self)
code = property(_opt_code_get)
def _opt_data_get(self): return _edns_option_opt_data_get(self)
data = property(_opt_data_get)
%}
}
/* ************************************************************************************ *
Structure edns_data
* ************************************************************************************ */
/* This is ignored because we will pass a double pointer of this to Python
* with custom getmethods. This is done to bypass Swig's behavior to pass NULL
* pointers as None. */
%ignore edns_data::opt_list;
struct edns_data {
int edns_present;
uint8_t ext_rcode;
uint8_t edns_version;
uint16_t bits;
uint16_t udp_size;
struct edns_option* opt_list_in;
struct edns_option* opt_list_out;
struct edns_option* opt_list_inplace_cb_out;
uint16_t padding_block_size;
};
%inline %{
struct edns_option** _edns_data_opt_list_get(struct edns_data* edns) {
return &edns->opt_list_in;
}
%}
%extend edns_data {
%pythoncode %{
def _opt_list_iter(self): return EdnsOptsListIter(self.opt_list)
opt_list_iter = property(_opt_list_iter)
def _opt_list(self): return _edns_data_opt_list_get(self)
opt_list = property(_opt_list)
%}
}
/* ************************************************************************************ *
Structure module_env
* ************************************************************************************ */
%rename(_now) module_env::now;
%rename(_now_tv) module_env::now_tv;
struct module_env {
struct config_file* cfg;
struct slabhash* msg_cache;
struct rrset_cache* rrset_cache;
struct infra_cache* infra_cache;
struct key_cache* key_cache;
/* --- services --- */
struct outbound_entry* (*send_query)(struct query_info* qinfo,
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
int check_ratelimit,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream,
char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
void (*detach_subs)(struct module_qstate* qstate);
int (*attach_sub)(struct module_qstate* qstate,
struct query_info* qinfo, uint16_t qflags, int prime,
int valrec, struct module_qstate** newq);
void (*kill_sub)(struct module_qstate* newq);
int (*detect_cycle)(struct module_qstate* qstate,
struct query_info* qinfo, uint16_t flags, int prime,
int valrec);
struct regional* scratch;
struct sldns_buffer* scratch_buffer;
struct worker* worker;
struct mesh_area* mesh;
struct alloc_cache* alloc;
struct ub_randstate* rnd;
time_t* now;
struct timeval* now_tv;
int need_to_validate;
struct val_anchors* anchors;
struct val_neg_cache* neg_cache;
struct comm_timer* probe_timer;
struct iter_forwards* fwds;
struct iter_hints* hints;
void* modinfo[MAX_MODULE];
void* inplace_cb_lists[inplace_cb_types_total];
struct edns_known_option* edns_known_options;
size_t edns_known_options_num;
};
%inline %{
PyObject* _module_env_now_get(struct module_env* env) {
double ts = env->now_tv->tv_sec + env->now_tv->tv_usec / 1e6;
return PyFloat_FromDouble(ts);
}
%}
%extend module_env {
%pythoncode %{
def _now_get(self): return _module_env_now_get(self)
now = property(_now_get)
%}
}
/* ************************************************************************************ *
Structure module_qstate
* ************************************************************************************ */
%ignore module_qstate::ext_state;
%ignore module_qstate::minfo;
/* These are ignored because we will pass a double pointer of them to Python
* with custom getmethods. This is done to bypass Swig's behavior to pass NULL
* pointers as None. */
%ignore module_qstate::edns_opts_front_in;
%ignore module_qstate::edns_opts_back_out;
%ignore module_qstate::edns_opts_back_in;
%ignore module_qstate::edns_opts_front_out;
/* Query state */
struct module_qstate {
struct query_info qinfo;
uint16_t query_flags; /* See QF_BIT_xx constants */
int is_priming;
int is_valrec;
struct comm_reply* reply;
struct dns_msg* return_msg;
int return_rcode;
struct regional* region; /* unwrapped */
int curmod;
enum module_ext_state ext_state[MAX_MODULE];
void* minfo[MAX_MODULE];
time_t prefetch_leeway;
struct module_env* env; /* unwrapped */
struct mesh_state* mesh_info;
struct edns_option* edns_opts_front_in;
struct edns_option* edns_opts_back_out;
struct edns_option* edns_opts_back_in;
struct edns_option* edns_opts_front_out;
int no_cache_lookup;
int no_cache_store;
};
%constant int MODULE_COUNT = MAX_MODULE;
%constant int QF_BIT_CD = 0x0010;
%constant int QF_BIT_AD = 0x0020;
%constant int QF_BIT_Z = 0x0040;
%constant int QF_BIT_RA = 0x0080;
%constant int QF_BIT_RD = 0x0100;
%constant int QF_BIT_TC = 0x0200;
%constant int QF_BIT_AA = 0x0400;
%constant int QF_BIT_QR = 0x8000;
%inline %{
enum enum_return_rcode {
RCODE_NOERROR = 0,
RCODE_FORMERR = 1,
RCODE_SERVFAIL = 2,
RCODE_NXDOMAIN = 3,
RCODE_NOTIMPL = 4,
RCODE_REFUSED = 5,
RCODE_YXDOMAIN = 6,
RCODE_YXRRSET = 7,
RCODE_NXRRSET = 8,
RCODE_NOTAUTH = 9,
RCODE_NOTZONE = 10
};
%}
%pythoncode %{
class ExtState:
def __init__(self, obj): self.obj = obj
def __str__(self):
return ", ".join([_unboundmodule.strextstate(_unboundmodule._ext_state_get(self.obj,a)) for a in range(0, _unboundmodule.MODULE_COUNT)])
def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index)
def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value)
def __len__(self): return _unboundmodule.MODULE_COUNT
class EdnsOptsListIter:
def __init__(self, obj):
self._current = obj
self._temp = None
def __iter__(self): return self
def __next__(self):
"""Python 3 compatibility"""
return self._get_next()
def next(self):
"""Python 2 compatibility"""
return self._get_next()
def _get_next(self):
if not edns_opt_list_is_empty(self._current):
self._temp = self._current
self._current = _p_p_edns_option_get_next(self._current)
return _dereference_edns_option(self._temp)
else:
raise StopIteration
%}
%inline %{
enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) {
if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
return q->ext_state[idx];
}
return 0;
}
void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
q->ext_state[idx] = state;
}
}
int edns_opt_list_is_empty(struct edns_option** opt) {
if (!opt || !(*opt)) return 1;
return 0;
}
struct edns_option* _dereference_edns_option(struct edns_option** opt) {
if (!opt) return NULL;
return *opt;
}
struct edns_option** _p_p_edns_option_get_next(struct edns_option** opt) {
return &(*opt)->next;
}
struct edns_option** _edns_opts_front_in_get(struct module_qstate* q) {
return &q->edns_opts_front_in;
}
struct edns_option** _edns_opts_back_out_get(struct module_qstate* q) {
return &q->edns_opts_back_out;
}
struct edns_option** _edns_opts_back_in_get(struct module_qstate* q) {
return &q->edns_opts_back_in;
}
struct edns_option** _edns_opts_front_out_get(struct module_qstate* q) {
return &q->edns_opts_front_out;
}
%}
%extend module_qstate {
%pythoncode %{
def set_ext_state(self, id, state):
"""Sets the ext state"""
_unboundmodule._ext_state_set(self, id, state)
def __ext_state_get(self): return ExtState(self)
ext_state = property(__ext_state_get) #, __ext_state_set
def _edns_opts_front_in_iter(self): return EdnsOptsListIter(self.edns_opts_front_in)
edns_opts_front_in_iter = property(_edns_opts_front_in_iter)
def _edns_opts_back_out_iter(self): return EdnsOptsListIter(self.edns_opts_back_out)
edns_opts_back_out_iter = property(_edns_opts_back_out_iter)
def _edns_opts_back_in_iter(self): return EdnsOptsListIter(self.edns_opts_back_in)
edns_opts_back_in_iter = property(_edns_opts_back_in_iter)
def _edns_opts_front_out_iter(self): return EdnsOptsListIter(self.edns_opts_front_out)
edns_opts_front_out_iter = property(_edns_opts_front_out_iter)
def _edns_opts_front_in(self): return _edns_opts_front_in_get(self)
edns_opts_front_in = property(_edns_opts_front_in)
def _edns_opts_back_out(self): return _edns_opts_back_out_get(self)
edns_opts_back_out = property(_edns_opts_back_out)
def _edns_opts_back_in(self): return _edns_opts_back_in_get(self)
edns_opts_back_in = property(_edns_opts_back_in)
def _edns_opts_front_out(self): return _edns_opts_front_out_get(self)
edns_opts_front_out = property(_edns_opts_front_out)
%}
}
/* ************************************************************************************ *
Structure config_strlist
* ************************************************************************************ */
struct config_strlist {
struct config_strlist* next;
char* str;
};
/* ************************************************************************************ *
Structure config_str2list
* ************************************************************************************ */
struct config_str2list {
struct config_str2list* next;
char* str;
char* str2;
};
/* ************************************************************************************ *
Structure config_file
* ************************************************************************************ */
struct config_file {
int verbosity;
int stat_interval;
int stat_cumulative;
int stat_extended;
int num_threads;
int port;
int do_ip4;
int do_ip6;
int do_udp;
int do_tcp;
int outgoing_num_ports;
size_t outgoing_num_tcp;
size_t incoming_num_tcp;
int* outgoing_avail_ports;
size_t msg_buffer_size;
size_t msg_cache_size;
size_t msg_cache_slabs;
size_t num_queries_per_thread;
size_t jostle_time;
size_t rrset_cache_size;
size_t rrset_cache_slabs;
int host_ttl;
size_t infra_cache_slabs;
size_t infra_cache_numhosts;
char* target_fetch_policy;
int if_automatic;
int num_ifs;
char **ifs;
int num_out_ifs;
char **out_ifs;
struct config_strlist* root_hints;
struct config_stub* stubs;
struct config_stub* forwards;
struct config_strlist* donotqueryaddrs;
struct config_str2list* acls;
int donotquery_localhost;
int harden_short_bufsize;
int harden_large_queries;
int harden_glue;
int harden_dnssec_stripped;
int harden_referral_path;
int use_caps_bits_for_id;
struct config_strlist* private_address;
struct config_strlist* private_domain;
size_t unwanted_threshold;