1 /* 2 * interface.i: unbound python module 3 */ 4 5 %module unboundmodule 6 %{ 7 /** 8 * \file 9 * This is the interface between the unbound server and a python module 10 * called to perform operations on queries. 11 */ 12 #include <sys/types.h> 13 #include <sys/socket.h> 14 #include <netinet/in.h> 15 #include <arpa/inet.h> 16 #include <stdarg.h> 17 #include "config.h" 18 #include "util/log.h" 19 #include "util/module.h" 20 #include "util/netevent.h" 21 #include "util/regional.h" 22 #include "util/config_file.h" 23 #include "util/data/msgreply.h" 24 #include "util/data/packed_rrset.h" 25 #include "util/data/dname.h" 26 #include "util/storage/lruhash.h" 27 #include "services/cache/dns.h" 28 #include "services/mesh.h" 29 #include "iterator/iter_delegpt.h" 30 #include "iterator/iter_hints.h" 31 #include "iterator/iter_utils.h" 32 #include "sldns/wire2str.h" 33 #include "sldns/str2wire.h" 34 #include "sldns/pkthdr.h" 35 %} 36 37 %include "stdint.i" // uint_16_t can be known type now 38 39 %inline %{ 40 //converts [len][data][len][data][0] string to a List of labels (PyBytes) 41 PyObject* GetNameAsLabelList(const char* name, int len) { 42 PyObject* list; 43 int cnt=0, i; 44 45 i = 0; 46 while (i < len) { 47 i += name[i] + 1; 48 cnt++; 49 } 50 51 list = PyList_New(cnt); 52 i = 0; cnt = 0; 53 while (i < len) { 54 PyList_SetItem(list, cnt, PyBytes_FromStringAndSize(name + i + 1, name[i])); 55 i += name[i] + 1; 56 cnt++; 57 } 58 return list; 59 } 60 %} 61 62 /* ************************************************************************************ * 63 Structure query_info 64 * ************************************************************************************ */ 65 /* Query info */ 66 %ignore query_info::qname; 67 %ignore query_info::qname_len; 68 69 70 struct query_info { 71 %immutable; 72 char* qname; 73 size_t qname_len; 74 uint16_t qtype; 75 uint16_t qclass; 76 %mutable; 77 }; 78 79 %inline %{ 80 enum enum_rr_class { 81 RR_CLASS_IN = 1, 82 RR_CLASS_CH = 3, 83 RR_CLASS_HS = 4, 84 RR_CLASS_NONE = 254, 85 RR_CLASS_ANY = 255, 86 }; 87 88 enum enum_rr_type { 89 RR_TYPE_A = 1, 90 RR_TYPE_NS = 2, 91 RR_TYPE_MD = 3, 92 RR_TYPE_MF = 4, 93 RR_TYPE_CNAME = 5, 94 RR_TYPE_SOA = 6, 95 RR_TYPE_MB = 7, 96 RR_TYPE_MG = 8, 97 RR_TYPE_MR = 9, 98 RR_TYPE_NULL = 10, 99 RR_TYPE_WKS = 11, 100 RR_TYPE_PTR = 12, 101 RR_TYPE_HINFO = 13, 102 RR_TYPE_MINFO = 14, 103 RR_TYPE_MX = 15, 104 RR_TYPE_TXT = 16, 105 RR_TYPE_RP = 17, 106 RR_TYPE_AFSDB = 18, 107 RR_TYPE_X25 = 19, 108 RR_TYPE_ISDN = 20, 109 RR_TYPE_RT = 21, 110 RR_TYPE_NSAP = 22, 111 RR_TYPE_NSAP_PTR = 23, 112 RR_TYPE_SIG = 24, 113 RR_TYPE_KEY = 25, 114 RR_TYPE_PX = 26, 115 RR_TYPE_GPOS = 27, 116 RR_TYPE_AAAA = 28, 117 RR_TYPE_LOC = 29, 118 RR_TYPE_NXT = 30, 119 RR_TYPE_EID = 31, 120 RR_TYPE_NIMLOC = 32, 121 RR_TYPE_SRV = 33, 122 RR_TYPE_ATMA = 34, 123 RR_TYPE_NAPTR = 35, 124 RR_TYPE_KX = 36, 125 RR_TYPE_CERT = 37, 126 RR_TYPE_A6 = 38, 127 RR_TYPE_DNAME = 39, 128 RR_TYPE_SINK = 40, 129 RR_TYPE_OPT = 41, 130 RR_TYPE_APL = 42, 131 RR_TYPE_DS = 43, 132 RR_TYPE_SSHFP = 44, 133 RR_TYPE_IPSECKEY = 45, 134 RR_TYPE_RRSIG = 46, 135 RR_TYPE_NSEC = 47, 136 RR_TYPE_DNSKEY = 48, 137 RR_TYPE_DHCID = 49, 138 RR_TYPE_NSEC3 = 50, 139 RR_TYPE_NSEC3PARAMS = 51, 140 RR_TYPE_UINFO = 100, 141 RR_TYPE_UID = 101, 142 RR_TYPE_GID = 102, 143 RR_TYPE_UNSPEC = 103, 144 RR_TYPE_TSIG = 250, 145 RR_TYPE_IXFR = 251, 146 RR_TYPE_AXFR = 252, 147 RR_TYPE_MAILB = 253, 148 RR_TYPE_MAILA = 254, 149 RR_TYPE_ANY = 255, 150 RR_TYPE_DLV = 32769, 151 }; 152 153 PyObject* _get_qname(struct query_info* q) { 154 return PyBytes_FromStringAndSize((char*)q->qname, q->qname_len); 155 } 156 157 PyObject* _get_qname_components(struct query_info* q) { 158 return GetNameAsLabelList((const char*)q->qname, q->qname_len); 159 } 160 %} 161 162 %inline %{ 163 PyObject* dnameAsStr(const char* dname) { 164 char buf[LDNS_MAX_DOMAINLEN+1]; 165 buf[0] = '\0'; 166 dname_str((uint8_t*)dname, buf); 167 return PyBytes_FromString(buf); 168 } 169 %} 170 171 %extend query_info { 172 %pythoncode %{ 173 def _get_qtype_str(self): return sldns_wire2str_type(self.qtype) 174 __swig_getmethods__["qtype_str"] = _get_qtype_str 175 if _newclass:qtype_str = _swig_property(_get_qtype_str) 176 177 def _get_qclass_str(self): return sldns_wire2str_class(self.qclass) 178 __swig_getmethods__["qclass_str"] = _get_qclass_str 179 if _newclass:qclass_str = _swig_property(_get_qclass_str) 180 181 __swig_getmethods__["qname"] = _unboundmodule._get_qname 182 if _newclass:qname = _swig_property(_unboundmodule._get_qname) 183 184 __swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components 185 if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components) 186 187 def _get_qname_str(self): return dnameAsStr(self.qname) 188 __swig_getmethods__["qname_str"] = _get_qname_str 189 if _newclass:qname_str = _swig_property(_get_qname_str) 190 %} 191 } 192 193 /* ************************************************************************************ * 194 Structure packed_rrset_key 195 * ************************************************************************************ */ 196 %ignore packed_rrset_key::dname; 197 %ignore packed_rrset_key::dname_len; 198 199 /* RRsets */ 200 struct packed_rrset_key { 201 %immutable; 202 char* dname; 203 size_t dname_len; 204 uint32_t flags; 205 uint16_t type; //rrset type in network format 206 uint16_t rrset_class; //rrset class in network format 207 %mutable; 208 }; 209 210 //This subroutine converts values between the host and network byte order. 211 //Specifically, ntohs() converts 16-bit quantities from network byte order to host byte order. 212 uint16_t ntohs(uint16_t netshort); 213 214 %inline %{ 215 PyObject* _get_dname(struct packed_rrset_key* k) { 216 return PyBytes_FromStringAndSize((char*)k->dname, k->dname_len); 217 } 218 PyObject* _get_dname_components(struct packed_rrset_key* k) { 219 return GetNameAsLabelList((char*)k->dname, k->dname_len); 220 } 221 %} 222 223 %extend packed_rrset_key { 224 %pythoncode %{ 225 def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type)) 226 __swig_getmethods__["type_str"] = _get_type_str 227 if _newclass:type_str = _swig_property(_get_type_str) 228 229 def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class)) 230 __swig_getmethods__["rrset_class_str"] = _get_class_str 231 if _newclass:rrset_class_str = _swig_property(_get_class_str) 232 233 __swig_getmethods__["dname"] = _unboundmodule._get_dname 234 if _newclass:dname = _swig_property(_unboundmodule._get_dname) 235 236 __swig_getmethods__["dname_list"] = _unboundmodule._get_dname_components 237 if _newclass:dname_list = _swig_property(_unboundmodule._get_dname_components) 238 239 def _get_dname_str(self): return dnameAsStr(self.dname) 240 __swig_getmethods__["dname_str"] = _get_dname_str 241 if _newclass:dname_str = _swig_property(_get_dname_str) 242 %} 243 } 244 245 #if defined(SWIGWORDSIZE64) 246 typedef long int rrset_id_t; 247 #else 248 typedef long long int rrset_id_t; 249 #endif 250 251 struct ub_packed_rrset_key { 252 struct lruhash_entry entry; 253 rrset_id_t id; 254 struct packed_rrset_key rk; 255 }; 256 257 struct lruhash_entry { 258 lock_rw_t lock; 259 struct lruhash_entry* overflow_next; 260 struct lruhash_entry* lru_next; 261 struct lruhash_entry* lru_prev; 262 hashvalue_t hash; 263 void* key; 264 struct packed_rrset_data* data; 265 }; 266 267 %ignore packed_rrset_data::rr_len; 268 %ignore packed_rrset_data::rr_ttl; 269 %ignore packed_rrset_data::rr_data; 270 271 struct packed_rrset_data { 272 uint32_t ttl; //TTL (in seconds like time()) 273 274 size_t count; //number of rrs 275 size_t rrsig_count; //number of rrsigs 276 277 enum rrset_trust trust; 278 enum sec_status security; 279 280 size_t* rr_len; //length of every rr's rdata 281 uint32_t *rr_ttl; //ttl of every rr 282 uint8_t** rr_data; //array of pointers to every rr's rdata; The rr_data[i] rdata is stored in uncompressed wireformat. 283 }; 284 285 %pythoncode %{ 286 class RRSetData_RRLen: 287 def __init__(self, obj): self.obj = obj 288 def __getitem__(self, index): return _unboundmodule._get_data_rr_len(self.obj, index) 289 def __len__(self): return obj.count + obj.rrsig_count 290 class RRSetData_RRTTL: 291 def __init__(self, obj): self.obj = obj 292 def __getitem__(self, index): return _unboundmodule._get_data_rr_ttl(self.obj, index) 293 def __setitem__(self, index, value): _unboundmodule._set_data_rr_ttl(self.obj, index, value) 294 def __len__(self): return obj.count + obj.rrsig_count 295 class RRSetData_RRData: 296 def __init__(self, obj): self.obj = obj 297 def __getitem__(self, index): return _unboundmodule._get_data_rr_data(self.obj, index) 298 def __len__(self): return obj.count + obj.rrsig_count 299 %} 300 301 %inline %{ 302 PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) { 303 if ((d != NULL) && (idx >= 0) && 304 ((size_t)idx < (d->count+d->rrsig_count))) 305 return PyInt_FromLong(d->rr_len[idx]); 306 return Py_None; 307 } 308 void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl) 309 { 310 if ((d != NULL) && (idx >= 0) && 311 ((size_t)idx < (d->count+d->rrsig_count))) 312 d->rr_ttl[idx] = ttl; 313 } 314 PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) { 315 if ((d != NULL) && (idx >= 0) && 316 ((size_t)idx < (d->count+d->rrsig_count))) 317 return PyInt_FromLong(d->rr_ttl[idx]); 318 return Py_None; 319 } 320 PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) { 321 if ((d != NULL) && (idx >= 0) && 322 ((size_t)idx < (d->count+d->rrsig_count))) 323 return PyBytes_FromStringAndSize((char*)d->rr_data[idx], 324 d->rr_len[idx]); 325 return Py_None; 326 } 327 %} 328 329 %extend packed_rrset_data { 330 %pythoncode %{ 331 def _get_data_rr_len(self): return RRSetData_RRLen(self) 332 __swig_getmethods__["rr_len"] = _get_data_rr_len 333 if _newclass:rr_len = _swig_property(_get_data_rr_len) 334 def _get_data_rr_ttl(self): return RRSetData_RRTTL(self) 335 __swig_getmethods__["rr_ttl"] =_get_data_rr_ttl 336 if _newclass:rr_len = _swig_property(_get_data_rr_ttl) 337 def _get_data_rr_data(self): return RRSetData_RRData(self) 338 __swig_getmethods__["rr_data"] = _get_data_rr_data 339 if _newclass:rr_len = _swig_property(_get_data_rr_data) 340 %} 341 } 342 343 /* ************************************************************************************ * 344 Structure reply_info 345 * ************************************************************************************ */ 346 /* Messages */ 347 %ignore reply_info::rrsets; 348 %ignore reply_info::ref; 349 350 struct reply_info { 351 uint16_t flags; 352 uint16_t qdcount; 353 uint32_t ttl; 354 uint32_t prefetch_ttl; 355 356 uint16_t authoritative; 357 enum sec_status security; 358 359 size_t an_numrrsets; 360 size_t ns_numrrsets; 361 size_t ar_numrrsets; 362 size_t rrset_count; // an_numrrsets + ns_numrrsets + ar_numrrsets 363 364 struct ub_packed_rrset_key** rrsets; 365 struct rrset_ref ref[1]; //? 366 }; 367 368 struct rrset_ref { 369 struct ub_packed_rrset_key* key; 370 rrset_id_t id; 371 }; 372 373 struct dns_msg { 374 struct query_info qinfo; 375 struct reply_info *rep; 376 }; 377 378 %pythoncode %{ 379 class ReplyInfo_RRSet: 380 def __init__(self, obj): self.obj = obj 381 def __getitem__(self, index): return _unboundmodule._rrset_rrsets_get(self.obj, index) 382 def __len__(self): return obj.rrset_count 383 384 class ReplyInfo_Ref: 385 def __init__(self, obj): self.obj = obj 386 def __getitem__(self, index): return _unboundmodule._rrset_ref_get(self.obj, index) 387 def __len__(self): return obj.rrset_count 388 %} 389 390 %inline %{ 391 struct ub_packed_rrset_key* _rrset_rrsets_get(struct reply_info* r, int idx) { 392 if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) 393 return r->rrsets[idx]; 394 return NULL; 395 } 396 397 struct rrset_ref* _rrset_ref_get(struct reply_info* r, int idx) { 398 if ((r != NULL) && (idx >= 0) && ((size_t)idx < r->rrset_count)) { 399 //printf("_rrset_ref_get: %lX key:%lX\n", r->ref + idx, r->ref[idx].key); 400 return &(r->ref[idx]); 401 // return &(r->ref[idx]); 402 } 403 //printf("_rrset_ref_get: NULL\n"); 404 return NULL; 405 } 406 %} 407 408 %extend reply_info { 409 %pythoncode %{ 410 def _rrset_ref_get(self): return ReplyInfo_Ref(self) 411 __swig_getmethods__["ref"] = _rrset_ref_get 412 if _newclass:ref = _swig_property(_rrset_ref_get) 413 414 def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self) 415 __swig_getmethods__["rrsets"] = _rrset_rrsets_get 416 if _newclass:rrsets = _swig_property(_rrset_rrsets_get) 417 %} 418 } 419 420 /* ************************************************************************************ * 421 Structure mesh_state 422 * ************************************************************************************ */ 423 struct mesh_state { 424 struct mesh_reply* reply_list; 425 }; 426 427 struct mesh_reply { 428 struct mesh_reply* next; 429 struct comm_reply query_reply; 430 }; 431 432 struct comm_reply { 433 434 }; 435 436 %inline %{ 437 438 PyObject* _comm_reply_addr_get(struct comm_reply* reply) { 439 char dest[64]; 440 reply_addr2str(reply, dest, 64); 441 if (dest[0] == 0) 442 return Py_None; 443 return PyBytes_FromString(dest); 444 } 445 446 PyObject* _comm_reply_family_get(struct comm_reply* reply) { 447 448 int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family; 449 450 switch(af) { 451 case AF_INET: return PyBytes_FromString("ip4"); 452 case AF_INET6: return PyBytes_FromString("ip6"); 453 case AF_UNIX: return PyBytes_FromString("unix"); 454 } 455 456 return Py_None; 457 } 458 459 PyObject* _comm_reply_port_get(struct comm_reply* reply) { 460 uint16_t port; 461 port = ntohs(((struct sockaddr_in*)&(reply->addr))->sin_port); 462 return PyInt_FromLong(port); 463 } 464 465 %} 466 467 %extend comm_reply { 468 %pythoncode %{ 469 def _addr_get(self): return _comm_reply_addr_get(self) 470 __swig_getmethods__["addr"] = _addr_get 471 if _newclass:addr = _swig_property(_addr_get) 472 473 def _port_get(self): return _comm_reply_port_get(self) 474 __swig_getmethods__["port"] = _port_get 475 if _newclass:port = _swig_property(_port_get) 476 477 def _family_get(self): return _comm_reply_family_get(self) 478 __swig_getmethods__["family"] = _family_get 479 if _newclass:family = _swig_property(_family_get) 480 %} 481 } 482 /* ************************************************************************************ * 483 Structure module_qstate 484 * ************************************************************************************ */ 485 %ignore module_qstate::ext_state; 486 %ignore module_qstate::minfo; 487 488 /* Query state */ 489 struct module_qstate { 490 struct query_info qinfo; 491 uint16_t query_flags; //See QF_BIT_xx constants 492 int is_priming; 493 494 struct comm_reply* reply; 495 struct dns_msg* return_msg; 496 int return_rcode; 497 struct regional* region; /* unwrapped */ 498 499 int curmod; 500 501 enum module_ext_state ext_state[MAX_MODULE]; 502 void* minfo[MAX_MODULE]; 503 504 struct module_env* env; /* unwrapped */ 505 struct mesh_state* mesh_info; 506 }; 507 508 %constant int MODULE_COUNT = MAX_MODULE; 509 510 %constant int QF_BIT_CD = 0x0010; 511 %constant int QF_BIT_AD = 0x0020; 512 %constant int QF_BIT_Z = 0x0040; 513 %constant int QF_BIT_RA = 0x0080; 514 %constant int QF_BIT_RD = 0x0100; 515 %constant int QF_BIT_TC = 0x0200; 516 %constant int QF_BIT_AA = 0x0400; 517 %constant int QF_BIT_QR = 0x8000; 518 519 %inline %{ 520 enum enum_return_rcode { 521 RCODE_NOERROR = 0, 522 RCODE_FORMERR = 1, 523 RCODE_SERVFAIL = 2, 524 RCODE_NXDOMAIN = 3, 525 RCODE_NOTIMPL = 4, 526 RCODE_REFUSED = 5, 527 RCODE_YXDOMAIN = 6, 528 RCODE_YXRRSET = 7, 529 RCODE_NXRRSET = 8, 530 RCODE_NOTAUTH = 9, 531 RCODE_NOTZONE = 10 532 }; 533 %} 534 535 %pythoncode %{ 536 class ExtState: 537 def __init__(self, obj): self.obj = obj 538 def __str__(self): 539 return ", ".join([_unboundmodule.strextstate(_unboundmodule._ext_state_get(self.obj,a)) for a in range(0, _unboundmodule.MODULE_COUNT)]) 540 def __getitem__(self, index): return _unboundmodule._ext_state_get(self.obj, index) 541 def __setitem__(self, index, value): _unboundmodule._ext_state_set(self.obj, index, value) 542 def __len__(self): return _unboundmodule.MODULE_COUNT 543 %} 544 545 %inline %{ 546 enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) { 547 if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) { 548 return q->ext_state[idx]; 549 } 550 return 0; 551 } 552 553 void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) { 554 if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) { 555 q->ext_state[idx] = state; 556 } 557 } 558 %} 559 560 %extend module_qstate { 561 %pythoncode %{ 562 def set_ext_state(self, id, state): 563 """Sets the ext state""" 564 _unboundmodule._ext_state_set(self, id, state) 565 566 def __ext_state_get(self): return ExtState(self) 567 __swig_getmethods__["ext_state"] = __ext_state_get 568 if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set) 569 %} 570 } 571 572 /* ************************************************************************************ * 573 Structure config_strlist 574 * ************************************************************************************ */ 575 struct config_strlist { 576 struct config_strlist* next; 577 char* str; 578 }; 579 580 /* ************************************************************************************ * 581 Structure config_str2list 582 * ************************************************************************************ */ 583 struct config_str2list { 584 struct config_str2list* next; 585 char* str; 586 char* str2; 587 }; 588 589 /* ************************************************************************************ * 590 Structure config_file 591 * ************************************************************************************ */ 592 struct config_file { 593 int verbosity; 594 int stat_interval; 595 int stat_cumulative; 596 int stat_extended; 597 int num_threads; 598 int port; 599 int do_ip4; 600 int do_ip6; 601 int do_udp; 602 int do_tcp; 603 int outgoing_num_ports; 604 size_t outgoing_num_tcp; 605 size_t incoming_num_tcp; 606 int* outgoing_avail_ports; 607 size_t msg_buffer_size; 608 size_t msg_cache_size; 609 size_t msg_cache_slabs; 610 size_t num_queries_per_thread; 611 size_t jostle_time; 612 size_t rrset_cache_size; 613 size_t rrset_cache_slabs; 614 int host_ttl; 615 size_t infra_cache_slabs; 616 size_t infra_cache_numhosts; 617 char* target_fetch_policy; 618 int if_automatic; 619 int num_ifs; 620 char **ifs; 621 int num_out_ifs; 622 char **out_ifs; 623 struct config_strlist* root_hints; 624 struct config_stub* stubs; 625 struct config_stub* forwards; 626 struct config_strlist* donotqueryaddrs; 627 struct config_str2list* acls; 628 int donotquery_localhost; 629 int harden_short_bufsize; 630 int harden_large_queries; 631 int harden_glue; 632 int harden_dnssec_stripped; 633 int harden_referral_path; 634 int use_caps_bits_for_id; 635 struct config_strlist* private_address; 636 struct config_strlist* private_domain; 637 size_t unwanted_threshold; 638 char* chrootdir; 639 char* username; 640 char* directory; 641 char* logfile; 642 char* pidfile; 643 int use_syslog; 644 int hide_identity; 645 int hide_version; 646 char* identity; 647 char* version; 648 char* module_conf; 649 struct config_strlist* trust_anchor_file_list; 650 struct config_strlist* trust_anchor_list; 651 struct config_strlist* trusted_keys_file_list; 652 char* dlv_anchor_file; 653 struct config_strlist* dlv_anchor_list; 654 int max_ttl; 655 int32_t val_date_override; 656 int bogus_ttl; 657 int val_clean_additional; 658 int val_permissive_mode; 659 char* val_nsec3_key_iterations; 660 size_t key_cache_size; 661 size_t key_cache_slabs; 662 size_t neg_cache_size; 663 struct config_str2list* local_zones; 664 struct config_strlist* local_zones_nodefault; 665 struct config_strlist* local_data; 666 int remote_control_enable; 667 struct config_strlist* control_ifs; 668 int control_port; 669 char* server_key_file; 670 char* server_cert_file; 671 char* control_key_file; 672 char* control_cert_file; 673 int do_daemonize; 674 char* python_script; 675 }; 676 677 /* ************************************************************************************ * 678 ASN: Adding structures related to forwards_lookup and dns_cache_find_delegation 679 * ************************************************************************************ */ 680 struct delegpt_ns { 681 struct delegpt_ns* next; 682 int resolved; 683 uint8_t got4; 684 uint8_t got6; 685 uint8_t lame; 686 uint8_t done_pside4; 687 uint8_t done_pside6; 688 }; 689 690 struct delegpt_addr { 691 struct delegpt_addr* next_result; 692 struct delegpt_addr* next_usable; 693 struct delegpt_addr* next_target; 694 int attempts; 695 int sel_rtt; 696 int bogus; 697 int lame; 698 }; 699 700 struct delegpt { 701 int namelabs; 702 struct delegpt_ns* nslist; 703 struct delegpt_addr* target_list; 704 struct delegpt_addr* usable_list; 705 struct delegpt_addr* result_list; 706 int bogus; 707 uint8_t has_parent_side_NS; 708 uint8_t dp_type_mlc; 709 }; 710 711 712 %inline %{ 713 PyObject* _get_dp_dname(struct delegpt* dp) { 714 return PyBytes_FromStringAndSize((char*)dp->name, dp->namelen); 715 } 716 PyObject* _get_dp_dname_components(struct delegpt* dp) { 717 return GetNameAsLabelList((char*)dp->name, dp->namelen); 718 } 719 PyObject* _get_dpns_dname(struct delegpt_ns* dpns) { 720 return PyBytes_FromStringAndSize((char*)dpns->name, dpns->namelen); 721 } 722 PyObject* _get_dpns_dname_components(struct delegpt_ns* dpns) { 723 return GetNameAsLabelList((char*)dpns->name, dpns->namelen); 724 } 725 726 PyObject* _delegpt_addr_addr_get(struct delegpt_addr* target) { 727 char dest[64]; 728 delegpt_addr_addr2str(target, dest, 64); 729 if (dest[0] == 0) 730 return Py_None; 731 return PyBytes_FromString(dest); 732 } 733 734 %} 735 736 %extend delegpt { 737 %pythoncode %{ 738 __swig_getmethods__["dname"] = _unboundmodule._get_dp_dname 739 if _newclass:dname = _swig_property(_unboundmodule._get_dp_dname) 740 741 __swig_getmethods__["dname_list"] = _unboundmodule._get_dp_dname_components 742 if _newclass:dname_list = _swig_property(_unboundmodule._get_dp_dname_components) 743 744 def _get_dname_str(self): return dnameAsStr(self.dname) 745 __swig_getmethods__["dname_str"] = _get_dname_str 746 if _newclass:dname_str = _swig_property(_get_dname_str) 747 %} 748 } 749 %extend delegpt_ns { 750 %pythoncode %{ 751 __swig_getmethods__["dname"] = _unboundmodule._get_dpns_dname 752 if _newclass:dname = _swig_property(_unboundmodule._get_dpns_dname) 753 754 __swig_getmethods__["dname_list"] = _unboundmodule._get_dpns_dname_components 755 if _newclass:dname_list = _swig_property(_unboundmodule._get_dpns_dname_components) 756 757 def _get_dname_str(self): return dnameAsStr(self.dname) 758 __swig_getmethods__["dname_str"] = _get_dname_str 759 if _newclass:dname_str = _swig_property(_get_dname_str) 760 %} 761 } 762 %extend delegpt_addr { 763 %pythoncode %{ 764 def _addr_get(self): return _delegpt_addr_addr_get(self) 765 __swig_getmethods__["addr"] = _addr_get 766 if _newclass:addr = _swig_property(_addr_get) 767 %} 768 } 769 770 /* ************************************************************************************ * 771 Enums 772 * ************************************************************************************ */ 773 %rename ("MODULE_STATE_INITIAL") "module_state_initial"; 774 %rename ("MODULE_WAIT_REPLY") "module_wait_reply"; 775 %rename ("MODULE_WAIT_MODULE") "module_wait_module"; 776 %rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery"; 777 %rename ("MODULE_ERROR") "module_error"; 778 %rename ("MODULE_FINISHED") "module_finished"; 779 780 enum module_ext_state { 781 module_state_initial = 0, 782 module_wait_reply, 783 module_wait_module, 784 module_wait_subquery, 785 module_error, 786 module_finished 787 }; 788 789 %rename ("MODULE_EVENT_NEW") "module_event_new"; 790 %rename ("MODULE_EVENT_PASS") "module_event_pass"; 791 %rename ("MODULE_EVENT_REPLY") "module_event_reply"; 792 %rename ("MODULE_EVENT_NOREPLY") "module_event_noreply"; 793 %rename ("MODULE_EVENT_CAPSFAIL") "module_event_capsfail"; 794 %rename ("MODULE_EVENT_MODDONE") "module_event_moddone"; 795 %rename ("MODULE_EVENT_ERROR") "module_event_error"; 796 797 enum module_ev { 798 module_event_new = 0, 799 module_event_pass, 800 module_event_reply, 801 module_event_noreply, 802 module_event_capsfail, 803 module_event_moddone, 804 module_event_error 805 }; 806 807 enum sec_status { 808 sec_status_unchecked = 0, 809 sec_status_bogus, 810 sec_status_indeterminate, 811 sec_status_insecure, 812 sec_status_secure 813 }; 814 815 enum verbosity_value { 816 NO_VERBOSE = 0, 817 VERB_OPS, 818 VERB_DETAIL, 819 VERB_QUERY, 820 VERB_ALGO 821 }; 822 823 %constant uint16_t PKT_QR = 1; /* QueRy - query flag */ 824 %constant uint16_t PKT_AA = 2; /* Authoritative Answer - server flag */ 825 %constant uint16_t PKT_TC = 4; /* TrunCated - server flag */ 826 %constant uint16_t PKT_RD = 8; /* Recursion Desired - query flag */ 827 %constant uint16_t PKT_CD = 16; /* Checking Disabled - query flag */ 828 %constant uint16_t PKT_RA = 32; /* Recursion Available - server flag */ 829 %constant uint16_t PKT_AD = 64; /* Authenticated Data - server flag */ 830 831 %{ 832 int checkList(PyObject *l) 833 { 834 PyObject* item; 835 int i; 836 837 if (l == Py_None) 838 return 1; 839 840 if (PyList_Check(l)) 841 { 842 for (i=0; i < PyList_Size(l); i++) 843 { 844 item = PyList_GetItem(l, i); 845 if (!PyBytes_Check(item)) 846 return 0; 847 } 848 return 1; 849 } 850 851 return 0; 852 } 853 854 int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec, 855 size_t count_offset) 856 { 857 PyObject* item; 858 int i; 859 size_t len; 860 861 for (i=0; i < PyList_Size(l); i++) 862 { 863 item = PyList_GetItem(l, i); 864 865 len = sldns_buffer_remaining(qb); 866 if(qsec) { 867 if(sldns_str2wire_rr_question_buf(PyBytes_AsString(item), 868 sldns_buffer_current(qb), &len, NULL, NULL, 0, NULL, 0) 869 != 0) 870 return 0; 871 } else { 872 if(sldns_str2wire_rr_buf(PyBytes_AsString(item), 873 sldns_buffer_current(qb), &len, NULL, default_ttl, 874 NULL, 0, NULL, 0) != 0) 875 return 0; 876 } 877 sldns_buffer_skip(qb, len); 878 879 sldns_buffer_write_u16_at(qb, count_offset, 880 sldns_buffer_read_u16_at(qb, count_offset)+1); 881 } 882 return 1; 883 } 884 885 int set_return_msg(struct module_qstate* qstate, 886 const char* rr_name, sldns_rr_type rr_type, sldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl, 887 PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional) 888 { 889 sldns_buffer *qb = 0; 890 int res = 1; 891 size_t l; 892 uint16_t PKT_QR = 1; 893 uint16_t PKT_AA = 2; 894 uint16_t PKT_TC = 4; 895 uint16_t PKT_RD = 8; 896 uint16_t PKT_CD = 16; 897 uint16_t PKT_RA = 32; 898 uint16_t PKT_AD = 64; 899 900 if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional))) 901 return 0; 902 if ((qb = sldns_buffer_new(LDNS_RR_BUF_SIZE)) == 0) return 0; 903 904 /* write header */ 905 sldns_buffer_write_u16(qb, 0); /* ID */ 906 sldns_buffer_write_u16(qb, 0); /* flags */ 907 sldns_buffer_write_u16(qb, 1); /* qdcount */ 908 sldns_buffer_write_u16(qb, 0); /* ancount */ 909 sldns_buffer_write_u16(qb, 0); /* nscount */ 910 sldns_buffer_write_u16(qb, 0); /* arcount */ 911 if ((flags&PKT_QR)) LDNS_QR_SET(sldns_buffer_begin(qb)); 912 if ((flags&PKT_AA)) LDNS_AA_SET(sldns_buffer_begin(qb)); 913 if ((flags&PKT_TC)) LDNS_TC_SET(sldns_buffer_begin(qb)); 914 if ((flags&PKT_RD)) LDNS_RD_SET(sldns_buffer_begin(qb)); 915 if ((flags&PKT_CD)) LDNS_CD_SET(sldns_buffer_begin(qb)); 916 if ((flags&PKT_RA)) LDNS_RA_SET(sldns_buffer_begin(qb)); 917 if ((flags&PKT_AD)) LDNS_AD_SET(sldns_buffer_begin(qb)); 918 919 /* write the query */ 920 l = sldns_buffer_remaining(qb); 921 if(sldns_str2wire_dname_buf(rr_name, sldns_buffer_current(qb), &l) != 0) { 922 sldns_buffer_free(qb); 923 return 0; 924 } 925 sldns_buffer_skip(qb, l); 926 if (rr_type == 0) { rr_type = LDNS_RR_TYPE_A; } 927 if (rr_class == 0) { rr_class = LDNS_RR_CLASS_IN; } 928 sldns_buffer_write_u16(qb, rr_type); 929 sldns_buffer_write_u16(qb, rr_class); 930 931 /* write RR sections */ 932 if(res && !pushRRList(qb, question, default_ttl, 1, LDNS_QDCOUNT_OFF)) 933 res = 0; 934 if(res && !pushRRList(qb, answer, default_ttl, 0, LDNS_ANCOUNT_OFF)) 935 res = 0; 936 if(res && !pushRRList(qb, authority, default_ttl, 0, LDNS_NSCOUNT_OFF)) 937 res = 0; 938 if(res && !pushRRList(qb, additional, default_ttl, 0, LDNS_ARCOUNT_OFF)) 939 res = 0; 940 941 if (res) res = createResponse(qstate, qb); 942 943 if (qb) sldns_buffer_free(qb); 944 return res; 945 } 946 %} 947 948 int set_return_msg(struct module_qstate* qstate, 949 const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl, 950 PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional); 951 952 %pythoncode %{ 953 class DNSMessage: 954 def __init__(self, rr_name, rr_type, rr_class = RR_CLASS_IN, query_flags = 0, default_ttl = 0): 955 """Query flags is a combination of PKT_xx contants""" 956 self.rr_name = rr_name 957 self.rr_type = rr_type 958 self.rr_class = rr_class 959 self.default_ttl = default_ttl 960 self.query_flags = query_flags 961 self.question = [] 962 self.answer = [] 963 self.authority = [] 964 self.additional = [] 965 966 def set_return_msg(self, qstate): 967 """Returns 1 if OK""" 968 status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class, 969 self.query_flags, self.default_ttl, 970 self.question, self.answer, self.authority, self.additional) 971 972 if (status) and (PKT_AA & self.query_flags): 973 qstate.return_msg.rep.authoritative = 1 974 975 return status 976 977 %} 978 /* ************************************************************************************ * 979 ASN: Delegation pointer related functions 980 * ************************************************************************************ */ 981 982 /* Functions which we will need to lookup delegations */ 983 struct delegpt* dns_cache_find_delegation(struct module_env* env, 984 uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, 985 struct regional* region, struct dns_msg** msg, uint32_t timenow); 986 int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, 987 struct delegpt* dp); 988 struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints, 989 uint8_t* qname, uint16_t qclass, struct delegpt* dp); 990 991 /* Custom function to perform logic similar to the one in daemon/cachedump.c */ 992 struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen); 993 994 %{ 995 #define BIT_RD 0x100 996 997 struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen) 998 { 999 struct delegpt *dp; 1000 struct dns_msg *msg = NULL; 1001 struct regional* region = qstate->env->scratch; 1002 char b[260]; 1003 struct query_info qinfo; 1004 struct iter_hints_stub* stub; 1005 uint32_t timenow = *qstate->env->now; 1006 1007 regional_free_all(region); 1008 qinfo.qname = (uint8_t*)nm; 1009 qinfo.qname_len = nmlen; 1010 qinfo.qtype = LDNS_RR_TYPE_A; 1011 qinfo.qclass = LDNS_RR_CLASS_IN; 1012 1013 while(1) { 1014 dp = dns_cache_find_delegation(qstate->env, (uint8_t*)nm, nmlen, qinfo.qtype, qinfo.qclass, region, &msg, timenow); 1015 if(!dp) 1016 return NULL; 1017 if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) { 1018 if (dname_is_root((uint8_t*)nm)) 1019 return NULL; 1020 nm = (char*)dp->name; 1021 nmlen = dp->namelen; 1022 dname_remove_label((uint8_t**)&nm, &nmlen); 1023 dname_str((uint8_t*)nm, b); 1024 continue; 1025 } 1026 stub = hints_lookup_stub(qstate->env->hints, qinfo.qname, qinfo.qclass, dp); 1027 if (stub) { 1028 return stub->dp; 1029 } else { 1030 return dp; 1031 } 1032 } 1033 return NULL; 1034 } 1035 %} 1036 1037 /* ************************************************************************************ * 1038 Functions 1039 * ************************************************************************************ */ 1040 1041 // Various debuging functions 1042 void verbose(enum verbosity_value level, const char* format, ...); 1043 void log_info(const char* format, ...); 1044 void log_err(const char* format, ...); 1045 void log_warn(const char* format, ...); 1046 void log_hex(const char* msg, void* data, size_t length); 1047 void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep); 1048 void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf); 1049 void regional_log_stats(struct regional *r); 1050 1051 // Free allocated memory from marked sources returning corresponding types 1052 %typemap(newfree, noblock = 1) char * { 1053 free($1); 1054 } 1055 1056 // Mark as source returning newly allocated memory 1057 %newobject sldns_wire2str_type; 1058 %newobject sldns_wire2str_class; 1059 1060 // LDNS functions 1061 char *sldns_wire2str_type(const uint16_t atype); 1062 char *sldns_wire2str_class(const uint16_t aclass); 1063 1064 // Functions from pythonmod_utils 1065 int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, struct reply_info* msgrep, int is_referral); 1066 void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo); 1067 1068 // Module conversion functions 1069 const char* strextstate(enum module_ext_state s); 1070 const char* strmodulevent(enum module_ev e); 1071 1072