message.py 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954
  1. # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
  2. # Copyright (C) 2001-2017 Nominum, Inc.
  3. #
  4. # Permission to use, copy, modify, and distribute this software and its
  5. # documentation for any purpose with or without fee is hereby granted,
  6. # provided that the above copyright notice and this permission notice
  7. # appear in all copies.
  8. #
  9. # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
  10. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
  12. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  15. # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. """DNS Messages"""
  17. import contextlib
  18. import enum
  19. import io
  20. import time
  21. from typing import Any, Dict, List, Tuple, cast
  22. import dns.edns
  23. import dns.entropy
  24. import dns.enum
  25. import dns.exception
  26. import dns.flags
  27. import dns.name
  28. import dns.opcode
  29. import dns.rcode
  30. import dns.rdata
  31. import dns.rdataclass
  32. import dns.rdatatype
  33. import dns.rdtypes.ANY.OPT
  34. import dns.rdtypes.ANY.SOA
  35. import dns.rdtypes.ANY.TSIG
  36. import dns.renderer
  37. import dns.rrset
  38. import dns.tokenizer
  39. import dns.tsig
  40. import dns.ttl
  41. import dns.wire
  42. class ShortHeader(dns.exception.FormError):
  43. """The DNS packet passed to from_wire() is too short."""
  44. class TrailingJunk(dns.exception.FormError):
  45. """The DNS packet passed to from_wire() has extra junk at the end of it."""
  46. class UnknownHeaderField(dns.exception.DNSException):
  47. """The header field name was not recognized when converting from text
  48. into a message."""
  49. class BadEDNS(dns.exception.FormError):
  50. """An OPT record occurred somewhere other than
  51. the additional data section."""
  52. class BadTSIG(dns.exception.FormError):
  53. """A TSIG record occurred somewhere other than the end of
  54. the additional data section."""
  55. class UnknownTSIGKey(dns.exception.DNSException):
  56. """A TSIG with an unknown key was received."""
  57. class Truncated(dns.exception.DNSException):
  58. """The truncated flag is set."""
  59. supp_kwargs = {"message"}
  60. # We do this as otherwise mypy complains about unexpected keyword argument
  61. # idna_exception
  62. def __init__(self, *args, **kwargs):
  63. super().__init__(*args, **kwargs)
  64. def message(self):
  65. """As much of the message as could be processed.
  66. Returns a ``dns.message.Message``.
  67. """
  68. return self.kwargs["message"]
  69. class NotQueryResponse(dns.exception.DNSException):
  70. """Message is not a response to a query."""
  71. class ChainTooLong(dns.exception.DNSException):
  72. """The CNAME chain is too long."""
  73. class AnswerForNXDOMAIN(dns.exception.DNSException):
  74. """The rcode is NXDOMAIN but an answer was found."""
  75. class NoPreviousName(dns.exception.SyntaxError):
  76. """No previous name was known."""
  77. class MessageSection(dns.enum.IntEnum):
  78. """Message sections"""
  79. QUESTION = 0
  80. ANSWER = 1
  81. AUTHORITY = 2
  82. ADDITIONAL = 3
  83. @classmethod
  84. def _maximum(cls):
  85. return 3
  86. class MessageError:
  87. def __init__(self, exception: Exception, offset: int):
  88. self.exception = exception
  89. self.offset = offset
  90. DEFAULT_EDNS_PAYLOAD = 1232
  91. MAX_CHAIN = 16
  92. IndexKeyType = Tuple[
  93. int,
  94. dns.name.Name,
  95. dns.rdataclass.RdataClass,
  96. dns.rdatatype.RdataType,
  97. dns.rdatatype.RdataType | None,
  98. dns.rdataclass.RdataClass | None,
  99. ]
  100. IndexType = Dict[IndexKeyType, dns.rrset.RRset]
  101. SectionType = int | str | List[dns.rrset.RRset]
  102. class Message:
  103. """A DNS message."""
  104. _section_enum = MessageSection
  105. def __init__(self, id: int | None = None):
  106. if id is None:
  107. self.id = dns.entropy.random_16()
  108. else:
  109. self.id = id
  110. self.flags = 0
  111. self.sections: List[List[dns.rrset.RRset]] = [[], [], [], []]
  112. self.opt: dns.rrset.RRset | None = None
  113. self.request_payload = 0
  114. self.pad = 0
  115. self.keyring: Any = None
  116. self.tsig: dns.rrset.RRset | None = None
  117. self.want_tsig_sign = False
  118. self.request_mac = b""
  119. self.xfr = False
  120. self.origin: dns.name.Name | None = None
  121. self.tsig_ctx: Any | None = None
  122. self.index: IndexType = {}
  123. self.errors: List[MessageError] = []
  124. self.time = 0.0
  125. self.wire: bytes | None = None
  126. @property
  127. def question(self) -> List[dns.rrset.RRset]:
  128. """The question section."""
  129. return self.sections[0]
  130. @question.setter
  131. def question(self, v):
  132. self.sections[0] = v
  133. @property
  134. def answer(self) -> List[dns.rrset.RRset]:
  135. """The answer section."""
  136. return self.sections[1]
  137. @answer.setter
  138. def answer(self, v):
  139. self.sections[1] = v
  140. @property
  141. def authority(self) -> List[dns.rrset.RRset]:
  142. """The authority section."""
  143. return self.sections[2]
  144. @authority.setter
  145. def authority(self, v):
  146. self.sections[2] = v
  147. @property
  148. def additional(self) -> List[dns.rrset.RRset]:
  149. """The additional data section."""
  150. return self.sections[3]
  151. @additional.setter
  152. def additional(self, v):
  153. self.sections[3] = v
  154. def __repr__(self):
  155. return "<DNS message, ID " + repr(self.id) + ">"
  156. def __str__(self):
  157. return self.to_text()
  158. def to_text(
  159. self,
  160. origin: dns.name.Name | None = None,
  161. relativize: bool = True,
  162. **kw: Dict[str, Any],
  163. ) -> str:
  164. """Convert the message to text.
  165. The *origin*, *relativize*, and any other keyword
  166. arguments are passed to the RRset ``to_wire()`` method.
  167. Returns a ``str``.
  168. """
  169. s = io.StringIO()
  170. s.write(f"id {self.id}\n")
  171. s.write(f"opcode {dns.opcode.to_text(self.opcode())}\n")
  172. s.write(f"rcode {dns.rcode.to_text(self.rcode())}\n")
  173. s.write(f"flags {dns.flags.to_text(self.flags)}\n")
  174. if self.edns >= 0:
  175. s.write(f"edns {self.edns}\n")
  176. if self.ednsflags != 0:
  177. s.write(f"eflags {dns.flags.edns_to_text(self.ednsflags)}\n")
  178. s.write(f"payload {self.payload}\n")
  179. for opt in self.options:
  180. s.write(f"option {opt.to_text()}\n")
  181. for name, which in self._section_enum.__members__.items():
  182. s.write(f";{name}\n")
  183. for rrset in self.section_from_number(which):
  184. s.write(rrset.to_text(origin, relativize, **kw))
  185. s.write("\n")
  186. if self.tsig is not None:
  187. s.write(self.tsig.to_text(origin, relativize, **kw))
  188. s.write("\n")
  189. #
  190. # We strip off the final \n so the caller can print the result without
  191. # doing weird things to get around eccentricities in Python print
  192. # formatting
  193. #
  194. return s.getvalue()[:-1]
  195. def __eq__(self, other):
  196. """Two messages are equal if they have the same content in the
  197. header, question, answer, and authority sections.
  198. Returns a ``bool``.
  199. """
  200. if not isinstance(other, Message):
  201. return False
  202. if self.id != other.id:
  203. return False
  204. if self.flags != other.flags:
  205. return False
  206. for i, section in enumerate(self.sections):
  207. other_section = other.sections[i]
  208. for n in section:
  209. if n not in other_section:
  210. return False
  211. for n in other_section:
  212. if n not in section:
  213. return False
  214. return True
  215. def __ne__(self, other):
  216. return not self.__eq__(other)
  217. def is_response(self, other: "Message") -> bool:
  218. """Is *other*, also a ``dns.message.Message``, a response to this
  219. message?
  220. Returns a ``bool``.
  221. """
  222. if (
  223. other.flags & dns.flags.QR == 0
  224. or self.id != other.id
  225. or dns.opcode.from_flags(self.flags) != dns.opcode.from_flags(other.flags)
  226. ):
  227. return False
  228. if other.rcode() in {
  229. dns.rcode.FORMERR,
  230. dns.rcode.SERVFAIL,
  231. dns.rcode.NOTIMP,
  232. dns.rcode.REFUSED,
  233. }:
  234. # We don't check the question section in these cases if
  235. # the other question section is empty, even though they
  236. # still really ought to have a question section.
  237. if len(other.question) == 0:
  238. return True
  239. if dns.opcode.is_update(self.flags):
  240. # This is assuming the "sender doesn't include anything
  241. # from the update", but we don't care to check the other
  242. # case, which is that all the sections are returned and
  243. # identical.
  244. return True
  245. for n in self.question:
  246. if n not in other.question:
  247. return False
  248. for n in other.question:
  249. if n not in self.question:
  250. return False
  251. return True
  252. def section_number(self, section: List[dns.rrset.RRset]) -> int:
  253. """Return the "section number" of the specified section for use
  254. in indexing.
  255. *section* is one of the section attributes of this message.
  256. Raises ``ValueError`` if the section isn't known.
  257. Returns an ``int``.
  258. """
  259. for i, our_section in enumerate(self.sections):
  260. if section is our_section:
  261. return self._section_enum(i)
  262. raise ValueError("unknown section")
  263. def section_from_number(self, number: int) -> List[dns.rrset.RRset]:
  264. """Return the section list associated with the specified section
  265. number.
  266. *number* is a section number `int` or the text form of a section
  267. name.
  268. Raises ``ValueError`` if the section isn't known.
  269. Returns a ``list``.
  270. """
  271. section = self._section_enum.make(number)
  272. return self.sections[section]
  273. def find_rrset(
  274. self,
  275. section: SectionType,
  276. name: dns.name.Name,
  277. rdclass: dns.rdataclass.RdataClass,
  278. rdtype: dns.rdatatype.RdataType,
  279. covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
  280. deleting: dns.rdataclass.RdataClass | None = None,
  281. create: bool = False,
  282. force_unique: bool = False,
  283. idna_codec: dns.name.IDNACodec | None = None,
  284. ) -> dns.rrset.RRset:
  285. """Find the RRset with the given attributes in the specified section.
  286. *section*, an ``int`` section number, a ``str`` section name, or one of
  287. the section attributes of this message. This specifies the
  288. the section of the message to search. For example::
  289. my_message.find_rrset(my_message.answer, name, rdclass, rdtype)
  290. my_message.find_rrset(dns.message.ANSWER, name, rdclass, rdtype)
  291. my_message.find_rrset("ANSWER", name, rdclass, rdtype)
  292. *name*, a ``dns.name.Name`` or ``str``, the name of the RRset.
  293. *rdclass*, an ``int`` or ``str``, the class of the RRset.
  294. *rdtype*, an ``int`` or ``str``, the type of the RRset.
  295. *covers*, an ``int`` or ``str``, the covers value of the RRset.
  296. The default is ``dns.rdatatype.NONE``.
  297. *deleting*, an ``int``, ``str``, or ``None``, the deleting value of the
  298. RRset. The default is ``None``.
  299. *create*, a ``bool``. If ``True``, create the RRset if it is not found.
  300. The created RRset is appended to *section*.
  301. *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``,
  302. create a new RRset regardless of whether a matching RRset exists
  303. already. The default is ``False``. This is useful when creating
  304. DDNS Update messages, as order matters for them.
  305. *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
  306. encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder
  307. is used.
  308. Raises ``KeyError`` if the RRset was not found and create was
  309. ``False``.
  310. Returns a ``dns.rrset.RRset object``.
  311. """
  312. if isinstance(section, int):
  313. section_number = section
  314. section = self.section_from_number(section_number)
  315. elif isinstance(section, str):
  316. section_number = self._section_enum.from_text(section)
  317. section = self.section_from_number(section_number)
  318. else:
  319. section_number = self.section_number(section)
  320. if isinstance(name, str):
  321. name = dns.name.from_text(name, idna_codec=idna_codec)
  322. rdtype = dns.rdatatype.RdataType.make(rdtype)
  323. rdclass = dns.rdataclass.RdataClass.make(rdclass)
  324. covers = dns.rdatatype.RdataType.make(covers)
  325. if deleting is not None:
  326. deleting = dns.rdataclass.RdataClass.make(deleting)
  327. key = (section_number, name, rdclass, rdtype, covers, deleting)
  328. if not force_unique:
  329. if self.index is not None:
  330. rrset = self.index.get(key)
  331. if rrset is not None:
  332. return rrset
  333. else:
  334. for rrset in section:
  335. if rrset.full_match(name, rdclass, rdtype, covers, deleting):
  336. return rrset
  337. if not create:
  338. raise KeyError
  339. rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting)
  340. section.append(rrset)
  341. if self.index is not None:
  342. self.index[key] = rrset
  343. return rrset
  344. def get_rrset(
  345. self,
  346. section: SectionType,
  347. name: dns.name.Name,
  348. rdclass: dns.rdataclass.RdataClass,
  349. rdtype: dns.rdatatype.RdataType,
  350. covers: dns.rdatatype.RdataType = dns.rdatatype.NONE,
  351. deleting: dns.rdataclass.RdataClass | None = None,
  352. create: bool = False,
  353. force_unique: bool = False,
  354. idna_codec: dns.name.IDNACodec | None = None,
  355. ) -> dns.rrset.RRset | None:
  356. """Get the RRset with the given attributes in the specified section.
  357. If the RRset is not found, None is returned.
  358. *section*, an ``int`` section number, a ``str`` section name, or one of
  359. the section attributes of this message. This specifies the
  360. the section of the message to search. For example::
  361. my_message.get_rrset(my_message.answer, name, rdclass, rdtype)
  362. my_message.get_rrset(dns.message.ANSWER, name, rdclass, rdtype)
  363. my_message.get_rrset("ANSWER", name, rdclass, rdtype)
  364. *name*, a ``dns.name.Name`` or ``str``, the name of the RRset.
  365. *rdclass*, an ``int`` or ``str``, the class of the RRset.
  366. *rdtype*, an ``int`` or ``str``, the type of the RRset.
  367. *covers*, an ``int`` or ``str``, the covers value of the RRset.
  368. The default is ``dns.rdatatype.NONE``.
  369. *deleting*, an ``int``, ``str``, or ``None``, the deleting value of the
  370. RRset. The default is ``None``.
  371. *create*, a ``bool``. If ``True``, create the RRset if it is not found.
  372. The created RRset is appended to *section*.
  373. *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``,
  374. create a new RRset regardless of whether a matching RRset exists
  375. already. The default is ``False``. This is useful when creating
  376. DDNS Update messages, as order matters for them.
  377. *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
  378. encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder
  379. is used.
  380. Returns a ``dns.rrset.RRset object`` or ``None``.
  381. """
  382. try:
  383. rrset = self.find_rrset(
  384. section,
  385. name,
  386. rdclass,
  387. rdtype,
  388. covers,
  389. deleting,
  390. create,
  391. force_unique,
  392. idna_codec,
  393. )
  394. except KeyError:
  395. rrset = None
  396. return rrset
  397. def section_count(self, section: SectionType) -> int:
  398. """Returns the number of records in the specified section.
  399. *section*, an ``int`` section number, a ``str`` section name, or one of
  400. the section attributes of this message. This specifies the
  401. the section of the message to count. For example::
  402. my_message.section_count(my_message.answer)
  403. my_message.section_count(dns.message.ANSWER)
  404. my_message.section_count("ANSWER")
  405. """
  406. if isinstance(section, int):
  407. section_number = section
  408. section = self.section_from_number(section_number)
  409. elif isinstance(section, str):
  410. section_number = self._section_enum.from_text(section)
  411. section = self.section_from_number(section_number)
  412. else:
  413. section_number = self.section_number(section)
  414. count = sum(max(1, len(rrs)) for rrs in section)
  415. if section_number == MessageSection.ADDITIONAL:
  416. if self.opt is not None:
  417. count += 1
  418. if self.tsig is not None:
  419. count += 1
  420. return count
  421. def _compute_opt_reserve(self) -> int:
  422. """Compute the size required for the OPT RR, padding excluded"""
  423. if not self.opt:
  424. return 0
  425. # 1 byte for the root name, 10 for the standard RR fields
  426. size = 11
  427. # This would be more efficient if options had a size() method, but we won't
  428. # worry about that for now. We also don't worry if there is an existing padding
  429. # option, as it is unlikely and probably harmless, as the worst case is that we
  430. # may add another, and this seems to be legal.
  431. opt_rdata = cast(dns.rdtypes.ANY.OPT.OPT, self.opt[0])
  432. for option in opt_rdata.options:
  433. wire = option.to_wire()
  434. # We add 4 here to account for the option type and length
  435. size += len(wire) + 4
  436. if self.pad:
  437. # Padding will be added, so again add the option type and length.
  438. size += 4
  439. return size
  440. def _compute_tsig_reserve(self) -> int:
  441. """Compute the size required for the TSIG RR"""
  442. # This would be more efficient if TSIGs had a size method, but we won't
  443. # worry about for now. Also, we can't really cope with the potential
  444. # compressibility of the TSIG owner name, so we estimate with the uncompressed
  445. # size. We will disable compression when TSIG and padding are both is active
  446. # so that the padding comes out right.
  447. if not self.tsig:
  448. return 0
  449. f = io.BytesIO()
  450. self.tsig.to_wire(f)
  451. return len(f.getvalue())
  452. def to_wire(
  453. self,
  454. origin: dns.name.Name | None = None,
  455. max_size: int = 0,
  456. multi: bool = False,
  457. tsig_ctx: Any | None = None,
  458. prepend_length: bool = False,
  459. prefer_truncation: bool = False,
  460. **kw: Dict[str, Any],
  461. ) -> bytes:
  462. """Return a string containing the message in DNS compressed wire
  463. format.
  464. Additional keyword arguments are passed to the RRset ``to_wire()``
  465. method.
  466. *origin*, a ``dns.name.Name`` or ``None``, the origin to be appended
  467. to any relative names. If ``None``, and the message has an origin
  468. attribute that is not ``None``, then it will be used.
  469. *max_size*, an ``int``, the maximum size of the wire format
  470. output; default is 0, which means "the message's request
  471. payload, if nonzero, or 65535".
  472. *multi*, a ``bool``, should be set to ``True`` if this message is
  473. part of a multiple message sequence.
  474. *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the
  475. ongoing TSIG context, used when signing zone transfers.
  476. *prepend_length*, a ``bool``, should be set to ``True`` if the caller
  477. wants the message length prepended to the message itself. This is
  478. useful for messages sent over TCP, TLS (DoT), or QUIC (DoQ).
  479. *prefer_truncation*, a ``bool``, should be set to ``True`` if the caller
  480. wants the message to be truncated if it would otherwise exceed the
  481. maximum length. If the truncation occurs before the additional section,
  482. the TC bit will be set.
  483. Raises ``dns.exception.TooBig`` if *max_size* was exceeded.
  484. Returns a ``bytes``.
  485. """
  486. if origin is None and self.origin is not None:
  487. origin = self.origin
  488. if max_size == 0:
  489. if self.request_payload != 0:
  490. max_size = self.request_payload
  491. else:
  492. max_size = 65535
  493. if max_size < 512:
  494. max_size = 512
  495. elif max_size > 65535:
  496. max_size = 65535
  497. r = dns.renderer.Renderer(self.id, self.flags, max_size, origin)
  498. opt_reserve = self._compute_opt_reserve()
  499. r.reserve(opt_reserve)
  500. tsig_reserve = self._compute_tsig_reserve()
  501. r.reserve(tsig_reserve)
  502. try:
  503. for rrset in self.question:
  504. r.add_question(rrset.name, rrset.rdtype, rrset.rdclass)
  505. for rrset in self.answer:
  506. r.add_rrset(dns.renderer.ANSWER, rrset, **kw)
  507. for rrset in self.authority:
  508. r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw)
  509. for rrset in self.additional:
  510. r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw)
  511. except dns.exception.TooBig:
  512. if prefer_truncation:
  513. if r.section < dns.renderer.ADDITIONAL:
  514. r.flags |= dns.flags.TC
  515. else:
  516. raise
  517. r.release_reserved()
  518. if self.opt is not None:
  519. r.add_opt(self.opt, self.pad, opt_reserve, tsig_reserve)
  520. r.write_header()
  521. if self.tsig is not None:
  522. if self.want_tsig_sign:
  523. (new_tsig, ctx) = dns.tsig.sign(
  524. r.get_wire(),
  525. self.keyring,
  526. self.tsig[0],
  527. int(time.time()),
  528. self.request_mac,
  529. tsig_ctx,
  530. multi,
  531. )
  532. self.tsig.clear()
  533. self.tsig.add(new_tsig)
  534. if multi:
  535. self.tsig_ctx = ctx
  536. r.add_rrset(dns.renderer.ADDITIONAL, self.tsig)
  537. r.write_header()
  538. wire = r.get_wire()
  539. self.wire = wire
  540. if prepend_length:
  541. wire = len(wire).to_bytes(2, "big") + wire
  542. return wire
  543. @staticmethod
  544. def _make_tsig(
  545. keyname, algorithm, time_signed, fudge, mac, original_id, error, other
  546. ):
  547. tsig = dns.rdtypes.ANY.TSIG.TSIG(
  548. dns.rdataclass.ANY,
  549. dns.rdatatype.TSIG,
  550. algorithm,
  551. time_signed,
  552. fudge,
  553. mac,
  554. original_id,
  555. error,
  556. other,
  557. )
  558. return dns.rrset.from_rdata(keyname, 0, tsig)
  559. def use_tsig(
  560. self,
  561. keyring: Any,
  562. keyname: dns.name.Name | str | None = None,
  563. fudge: int = 300,
  564. original_id: int | None = None,
  565. tsig_error: int = 0,
  566. other_data: bytes = b"",
  567. algorithm: dns.name.Name | str = dns.tsig.default_algorithm,
  568. ) -> None:
  569. """When sending, a TSIG signature using the specified key
  570. should be added.
  571. *keyring*, a ``dict``, ``callable`` or ``dns.tsig.Key``, is either
  572. the TSIG keyring or key to use.
  573. The format of a keyring dict is a mapping from TSIG key name, as
  574. ``dns.name.Name`` to ``dns.tsig.Key`` or a TSIG secret, a ``bytes``.
  575. If a ``dict`` *keyring* is specified but a *keyname* is not, the key
  576. used will be the first key in the *keyring*. Note that the order of
  577. keys in a dictionary is not defined, so applications should supply a
  578. keyname when a ``dict`` keyring is used, unless they know the keyring
  579. contains only one key. If a ``callable`` keyring is specified, the
  580. callable will be called with the message and the keyname, and is
  581. expected to return a key.
  582. *keyname*, a ``dns.name.Name``, ``str`` or ``None``, the name of
  583. this TSIG key to use; defaults to ``None``. If *keyring* is a
  584. ``dict``, the key must be defined in it. If *keyring* is a
  585. ``dns.tsig.Key``, this is ignored.
  586. *fudge*, an ``int``, the TSIG time fudge.
  587. *original_id*, an ``int``, the TSIG original id. If ``None``,
  588. the message's id is used.
  589. *tsig_error*, an ``int``, the TSIG error code.
  590. *other_data*, a ``bytes``, the TSIG other data.
  591. *algorithm*, a ``dns.name.Name`` or ``str``, the TSIG algorithm to use. This is
  592. only used if *keyring* is a ``dict``, and the key entry is a ``bytes``.
  593. """
  594. if isinstance(keyring, dns.tsig.Key):
  595. key = keyring
  596. keyname = key.name
  597. elif callable(keyring):
  598. key = keyring(self, keyname)
  599. else:
  600. if isinstance(keyname, str):
  601. keyname = dns.name.from_text(keyname)
  602. if keyname is None:
  603. keyname = next(iter(keyring))
  604. key = keyring[keyname]
  605. if isinstance(key, bytes):
  606. key = dns.tsig.Key(keyname, key, algorithm)
  607. self.keyring = key
  608. if original_id is None:
  609. original_id = self.id
  610. self.tsig = self._make_tsig(
  611. keyname,
  612. self.keyring.algorithm,
  613. 0,
  614. fudge,
  615. b"\x00" * dns.tsig.mac_sizes[self.keyring.algorithm],
  616. original_id,
  617. tsig_error,
  618. other_data,
  619. )
  620. self.want_tsig_sign = True
  621. @property
  622. def keyname(self) -> dns.name.Name | None:
  623. if self.tsig:
  624. return self.tsig.name
  625. else:
  626. return None
  627. @property
  628. def keyalgorithm(self) -> dns.name.Name | None:
  629. if self.tsig:
  630. rdata = cast(dns.rdtypes.ANY.TSIG.TSIG, self.tsig[0])
  631. return rdata.algorithm
  632. else:
  633. return None
  634. @property
  635. def mac(self) -> bytes | None:
  636. if self.tsig:
  637. rdata = cast(dns.rdtypes.ANY.TSIG.TSIG, self.tsig[0])
  638. return rdata.mac
  639. else:
  640. return None
  641. @property
  642. def tsig_error(self) -> int | None:
  643. if self.tsig:
  644. rdata = cast(dns.rdtypes.ANY.TSIG.TSIG, self.tsig[0])
  645. return rdata.error
  646. else:
  647. return None
  648. @property
  649. def had_tsig(self) -> bool:
  650. return bool(self.tsig)
  651. @staticmethod
  652. def _make_opt(flags=0, payload=DEFAULT_EDNS_PAYLOAD, options=None):
  653. opt = dns.rdtypes.ANY.OPT.OPT(payload, dns.rdatatype.OPT, options or ())
  654. return dns.rrset.from_rdata(dns.name.root, int(flags), opt)
  655. def use_edns(
  656. self,
  657. edns: int | bool | None = 0,
  658. ednsflags: int = 0,
  659. payload: int = DEFAULT_EDNS_PAYLOAD,
  660. request_payload: int | None = None,
  661. options: List[dns.edns.Option] | None = None,
  662. pad: int = 0,
  663. ) -> None:
  664. """Configure EDNS behavior.
  665. *edns*, an ``int``, is the EDNS level to use. Specifying ``None``, ``False``,
  666. or ``-1`` means "do not use EDNS", and in this case the other parameters are
  667. ignored. Specifying ``True`` is equivalent to specifying 0, i.e. "use EDNS0".
  668. *ednsflags*, an ``int``, the EDNS flag values.
  669. *payload*, an ``int``, is the EDNS sender's payload field, which is the maximum
  670. size of UDP datagram the sender can handle. I.e. how big a response to this
  671. message can be.
  672. *request_payload*, an ``int``, is the EDNS payload size to use when sending this
  673. message. If not specified, defaults to the value of *payload*.
  674. *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS options.
  675. *pad*, a non-negative ``int``. If 0, the default, do not pad; otherwise add
  676. padding bytes to make the message size a multiple of *pad*. Note that if
  677. padding is non-zero, an EDNS PADDING option will always be added to the
  678. message.
  679. """
  680. if edns is None or edns is False:
  681. edns = -1
  682. elif edns is True:
  683. edns = 0
  684. if edns < 0:
  685. self.opt = None
  686. self.request_payload = 0
  687. else:
  688. # make sure the EDNS version in ednsflags agrees with edns
  689. ednsflags &= 0xFF00FFFF
  690. ednsflags |= edns << 16
  691. if options is None:
  692. options = []
  693. self.opt = self._make_opt(ednsflags, payload, options)
  694. if request_payload is None:
  695. request_payload = payload
  696. self.request_payload = request_payload
  697. if pad < 0:
  698. raise ValueError("pad must be non-negative")
  699. self.pad = pad
  700. @property
  701. def edns(self) -> int:
  702. if self.opt:
  703. return (self.ednsflags & 0xFF0000) >> 16
  704. else:
  705. return -1
  706. @property
  707. def ednsflags(self) -> int:
  708. if self.opt:
  709. return self.opt.ttl
  710. else:
  711. return 0
  712. @ednsflags.setter
  713. def ednsflags(self, v):
  714. if self.opt:
  715. self.opt.ttl = v
  716. elif v:
  717. self.opt = self._make_opt(v)
  718. @property
  719. def payload(self) -> int:
  720. if self.opt:
  721. rdata = cast(dns.rdtypes.ANY.OPT.OPT, self.opt[0])
  722. return rdata.payload
  723. else:
  724. return 0
  725. @property
  726. def options(self) -> Tuple:
  727. if self.opt:
  728. rdata = cast(dns.rdtypes.ANY.OPT.OPT, self.opt[0])
  729. return rdata.options
  730. else:
  731. return ()
  732. def want_dnssec(self, wanted: bool = True) -> None:
  733. """Enable or disable 'DNSSEC desired' flag in requests.
  734. *wanted*, a ``bool``. If ``True``, then DNSSEC data is
  735. desired in the response, EDNS is enabled if required, and then
  736. the DO bit is set. If ``False``, the DO bit is cleared if
  737. EDNS is enabled.
  738. """
  739. if wanted:
  740. self.ednsflags |= dns.flags.DO
  741. elif self.opt:
  742. self.ednsflags &= ~int(dns.flags.DO)
  743. def rcode(self) -> dns.rcode.Rcode:
  744. """Return the rcode.
  745. Returns a ``dns.rcode.Rcode``.
  746. """
  747. return dns.rcode.from_flags(int(self.flags), int(self.ednsflags))
  748. def set_rcode(self, rcode: dns.rcode.Rcode) -> None:
  749. """Set the rcode.
  750. *rcode*, a ``dns.rcode.Rcode``, is the rcode to set.
  751. """
  752. (value, evalue) = dns.rcode.to_flags(rcode)
  753. self.flags &= 0xFFF0
  754. self.flags |= value
  755. self.ednsflags &= 0x00FFFFFF
  756. self.ednsflags |= evalue
  757. def opcode(self) -> dns.opcode.Opcode:
  758. """Return the opcode.
  759. Returns a ``dns.opcode.Opcode``.
  760. """
  761. return dns.opcode.from_flags(int(self.flags))
  762. def set_opcode(self, opcode: dns.opcode.Opcode) -> None:
  763. """Set the opcode.
  764. *opcode*, a ``dns.opcode.Opcode``, is the opcode to set.
  765. """
  766. self.flags &= 0x87FF
  767. self.flags |= dns.opcode.to_flags(opcode)
  768. def get_options(self, otype: dns.edns.OptionType) -> List[dns.edns.Option]:
  769. """Return the list of options of the specified type."""
  770. return [option for option in self.options if option.otype == otype]
  771. def extended_errors(self) -> List[dns.edns.EDEOption]:
  772. """Return the list of Extended DNS Error (EDE) options in the message"""
  773. return cast(List[dns.edns.EDEOption], self.get_options(dns.edns.OptionType.EDE))
  774. def _get_one_rr_per_rrset(self, value):
  775. # What the caller picked is fine.
  776. return value
  777. # pylint: disable=unused-argument
  778. def _parse_rr_header(self, section, name, rdclass, rdtype):
  779. return (rdclass, rdtype, None, False)
  780. # pylint: enable=unused-argument
  781. def _parse_special_rr_header(self, section, count, position, name, rdclass, rdtype):
  782. if rdtype == dns.rdatatype.OPT:
  783. if (
  784. section != MessageSection.ADDITIONAL
  785. or self.opt
  786. or name != dns.name.root
  787. ):
  788. raise BadEDNS
  789. elif rdtype == dns.rdatatype.TSIG:
  790. if (
  791. section != MessageSection.ADDITIONAL
  792. or rdclass != dns.rdatatype.ANY
  793. or position != count - 1
  794. ):
  795. raise BadTSIG
  796. return (rdclass, rdtype, None, False)
  797. class ChainingResult:
  798. """The result of a call to dns.message.QueryMessage.resolve_chaining().
  799. The ``answer`` attribute is the answer RRSet, or ``None`` if it doesn't
  800. exist.
  801. The ``canonical_name`` attribute is the canonical name after all
  802. chaining has been applied (this is the same name as ``rrset.name`` in cases
  803. where rrset is not ``None``).
  804. The ``minimum_ttl`` attribute is the minimum TTL, i.e. the TTL to
  805. use if caching the data. It is the smallest of all the CNAME TTLs
  806. and either the answer TTL if it exists or the SOA TTL and SOA
  807. minimum values for negative answers.
  808. The ``cnames`` attribute is a list of all the CNAME RRSets followed to
  809. get to the canonical name.
  810. """
  811. def __init__(
  812. self,
  813. canonical_name: dns.name.Name,
  814. answer: dns.rrset.RRset | None,
  815. minimum_ttl: int,
  816. cnames: List[dns.rrset.RRset],
  817. ):
  818. self.canonical_name = canonical_name
  819. self.answer = answer
  820. self.minimum_ttl = minimum_ttl
  821. self.cnames = cnames
  822. class QueryMessage(Message):
  823. def resolve_chaining(self) -> ChainingResult:
  824. """Follow the CNAME chain in the response to determine the answer
  825. RRset.
  826. Raises ``dns.message.NotQueryResponse`` if the message is not
  827. a response.
  828. Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long.
  829. Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN
  830. but an answer was found.
  831. Raises ``dns.exception.FormError`` if the question count is not 1.
  832. Returns a ChainingResult object.
  833. """
  834. if self.flags & dns.flags.QR == 0:
  835. raise NotQueryResponse
  836. if len(self.question) != 1:
  837. raise dns.exception.FormError
  838. question = self.question[0]
  839. qname = question.name
  840. min_ttl = dns.ttl.MAX_TTL
  841. answer = None
  842. count = 0
  843. cnames = []
  844. while count < MAX_CHAIN:
  845. try:
  846. answer = self.find_rrset(
  847. self.answer, qname, question.rdclass, question.rdtype
  848. )
  849. min_ttl = min(min_ttl, answer.ttl)
  850. break
  851. except KeyError:
  852. if question.rdtype != dns.rdatatype.CNAME:
  853. try:
  854. crrset = self.find_rrset(
  855. self.answer, qname, question.rdclass, dns.rdatatype.CNAME
  856. )
  857. cnames.append(crrset)
  858. min_ttl = min(min_ttl, crrset.ttl)
  859. for rd in crrset:
  860. qname = rd.target
  861. break
  862. count += 1
  863. continue
  864. except KeyError:
  865. # Exit the chaining loop
  866. break
  867. else:
  868. # Exit the chaining loop
  869. break
  870. if count >= MAX_CHAIN:
  871. raise ChainTooLong
  872. if self.rcode() == dns.rcode.NXDOMAIN and answer is not None:
  873. raise AnswerForNXDOMAIN
  874. if answer is None:
  875. # Further minimize the TTL with NCACHE.
  876. auname = qname
  877. while True:
  878. # Look for an SOA RR whose owner name is a superdomain
  879. # of qname.
  880. try:
  881. srrset = self.find_rrset(
  882. self.authority, auname, question.rdclass, dns.rdatatype.SOA
  883. )
  884. srdata = cast(dns.rdtypes.ANY.SOA.SOA, srrset[0])
  885. min_ttl = min(min_ttl, srrset.ttl, srdata.minimum)
  886. break
  887. except KeyError:
  888. try:
  889. auname = auname.parent()
  890. except dns.name.NoParent:
  891. break
  892. return ChainingResult(qname, answer, min_ttl, cnames)
  893. def canonical_name(self) -> dns.name.Name:
  894. """Return the canonical name of the first name in the question
  895. section.
  896. Raises ``dns.message.NotQueryResponse`` if the message is not
  897. a response.
  898. Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long.
  899. Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN
  900. but an answer was found.
  901. Raises ``dns.exception.FormError`` if the question count is not 1.
  902. """
  903. return self.resolve_chaining().canonical_name
  904. def _maybe_import_update():
  905. # We avoid circular imports by doing this here. We do it in another
  906. # function as doing it in _message_factory_from_opcode() makes "dns"
  907. # a local symbol, and the first line fails :)
  908. # pylint: disable=redefined-outer-name,import-outside-toplevel,unused-import
  909. import dns.update # noqa: F401
  910. def _message_factory_from_opcode(opcode):
  911. if opcode == dns.opcode.QUERY:
  912. return QueryMessage
  913. elif opcode == dns.opcode.UPDATE:
  914. _maybe_import_update()
  915. return dns.update.UpdateMessage # pyright: ignore
  916. else:
  917. return Message
  918. class _WireReader:
  919. """Wire format reader.
  920. parser: the binary parser
  921. message: The message object being built
  922. initialize_message: Callback to set message parsing options
  923. question_only: Are we only reading the question?
  924. one_rr_per_rrset: Put each RR into its own RRset?
  925. keyring: TSIG keyring
  926. ignore_trailing: Ignore trailing junk at end of request?
  927. multi: Is this message part of a multi-message sequence?
  928. DNS dynamic updates.
  929. continue_on_error: try to extract as much information as possible from
  930. the message, accumulating MessageErrors in the *errors* attribute instead of
  931. raising them.
  932. """
  933. def __init__(
  934. self,
  935. wire,
  936. initialize_message,
  937. question_only=False,
  938. one_rr_per_rrset=False,
  939. ignore_trailing=False,
  940. keyring=None,
  941. multi=False,
  942. continue_on_error=False,
  943. ):
  944. self.parser = dns.wire.Parser(wire)
  945. self.message = None
  946. self.initialize_message = initialize_message
  947. self.question_only = question_only
  948. self.one_rr_per_rrset = one_rr_per_rrset
  949. self.ignore_trailing = ignore_trailing
  950. self.keyring = keyring
  951. self.multi = multi
  952. self.continue_on_error = continue_on_error
  953. self.errors = []
  954. def _get_question(self, section_number, qcount):
  955. """Read the next *qcount* records from the wire data and add them to
  956. the question section.
  957. """
  958. assert self.message is not None
  959. section = self.message.sections[section_number]
  960. for _ in range(qcount):
  961. qname = self.parser.get_name(self.message.origin)
  962. (rdtype, rdclass) = self.parser.get_struct("!HH")
  963. (rdclass, rdtype, _, _) = self.message._parse_rr_header(
  964. section_number, qname, rdclass, rdtype
  965. )
  966. self.message.find_rrset(
  967. section, qname, rdclass, rdtype, create=True, force_unique=True
  968. )
  969. def _add_error(self, e):
  970. self.errors.append(MessageError(e, self.parser.current))
  971. def _get_section(self, section_number, count):
  972. """Read the next I{count} records from the wire data and add them to
  973. the specified section.
  974. section_number: the section of the message to which to add records
  975. count: the number of records to read
  976. """
  977. assert self.message is not None
  978. section = self.message.sections[section_number]
  979. force_unique = self.one_rr_per_rrset
  980. for i in range(count):
  981. rr_start = self.parser.current
  982. absolute_name = self.parser.get_name()
  983. if self.message.origin is not None:
  984. name = absolute_name.relativize(self.message.origin)
  985. else:
  986. name = absolute_name
  987. (rdtype, rdclass, ttl, rdlen) = self.parser.get_struct("!HHIH")
  988. if rdtype in (dns.rdatatype.OPT, dns.rdatatype.TSIG):
  989. (
  990. rdclass,
  991. rdtype,
  992. deleting,
  993. empty,
  994. ) = self.message._parse_special_rr_header(
  995. section_number, count, i, name, rdclass, rdtype
  996. )
  997. else:
  998. (rdclass, rdtype, deleting, empty) = self.message._parse_rr_header(
  999. section_number, name, rdclass, rdtype
  1000. )
  1001. rdata_start = self.parser.current
  1002. try:
  1003. if empty:
  1004. if rdlen > 0:
  1005. raise dns.exception.FormError
  1006. rd = None
  1007. covers = dns.rdatatype.NONE
  1008. else:
  1009. with self.parser.restrict_to(rdlen):
  1010. rd = dns.rdata.from_wire_parser(
  1011. rdclass, # pyright: ignore
  1012. rdtype,
  1013. self.parser,
  1014. self.message.origin,
  1015. )
  1016. covers = rd.covers()
  1017. if self.message.xfr and rdtype == dns.rdatatype.SOA:
  1018. force_unique = True
  1019. if rdtype == dns.rdatatype.OPT:
  1020. self.message.opt = dns.rrset.from_rdata(name, ttl, rd)
  1021. elif rdtype == dns.rdatatype.TSIG:
  1022. trd = cast(dns.rdtypes.ANY.TSIG.TSIG, rd)
  1023. if self.keyring is None or self.keyring is True:
  1024. raise UnknownTSIGKey("got signed message without keyring")
  1025. elif isinstance(self.keyring, dict):
  1026. key = self.keyring.get(absolute_name)
  1027. if isinstance(key, bytes):
  1028. key = dns.tsig.Key(absolute_name, key, trd.algorithm)
  1029. elif callable(self.keyring):
  1030. key = self.keyring(self.message, absolute_name)
  1031. else:
  1032. key = self.keyring
  1033. if key is None:
  1034. raise UnknownTSIGKey(f"key '{name}' unknown")
  1035. if key:
  1036. self.message.keyring = key
  1037. self.message.tsig_ctx = dns.tsig.validate(
  1038. self.parser.wire,
  1039. key,
  1040. absolute_name,
  1041. rd,
  1042. int(time.time()),
  1043. self.message.request_mac,
  1044. rr_start,
  1045. self.message.tsig_ctx,
  1046. self.multi,
  1047. )
  1048. self.message.tsig = dns.rrset.from_rdata(absolute_name, 0, rd)
  1049. else:
  1050. rrset = self.message.find_rrset(
  1051. section,
  1052. name,
  1053. rdclass, # pyright: ignore
  1054. rdtype,
  1055. covers,
  1056. deleting,
  1057. True,
  1058. force_unique,
  1059. )
  1060. if rd is not None:
  1061. if ttl > 0x7FFFFFFF:
  1062. ttl = 0
  1063. rrset.add(rd, ttl)
  1064. except Exception as e:
  1065. if self.continue_on_error:
  1066. self._add_error(e)
  1067. self.parser.seek(rdata_start + rdlen)
  1068. else:
  1069. raise
  1070. def read(self):
  1071. """Read a wire format DNS message and build a dns.message.Message
  1072. object."""
  1073. if self.parser.remaining() < 12:
  1074. raise ShortHeader
  1075. (id, flags, qcount, ancount, aucount, adcount) = self.parser.get_struct(
  1076. "!HHHHHH"
  1077. )
  1078. factory = _message_factory_from_opcode(dns.opcode.from_flags(flags))
  1079. self.message = factory(id=id)
  1080. self.message.flags = dns.flags.Flag(flags)
  1081. self.message.wire = self.parser.wire
  1082. self.initialize_message(self.message)
  1083. self.one_rr_per_rrset = self.message._get_one_rr_per_rrset(
  1084. self.one_rr_per_rrset
  1085. )
  1086. try:
  1087. self._get_question(MessageSection.QUESTION, qcount)
  1088. if self.question_only:
  1089. return self.message
  1090. self._get_section(MessageSection.ANSWER, ancount)
  1091. self._get_section(MessageSection.AUTHORITY, aucount)
  1092. self._get_section(MessageSection.ADDITIONAL, adcount)
  1093. if not self.ignore_trailing and self.parser.remaining() != 0:
  1094. raise TrailingJunk
  1095. if self.multi and self.message.tsig_ctx and not self.message.had_tsig:
  1096. self.message.tsig_ctx.update(self.parser.wire)
  1097. except Exception as e:
  1098. if self.continue_on_error:
  1099. self._add_error(e)
  1100. else:
  1101. raise
  1102. return self.message
  1103. def from_wire(
  1104. wire: bytes,
  1105. keyring: Any | None = None,
  1106. request_mac: bytes | None = b"",
  1107. xfr: bool = False,
  1108. origin: dns.name.Name | None = None,
  1109. tsig_ctx: dns.tsig.HMACTSig | dns.tsig.GSSTSig | None = None,
  1110. multi: bool = False,
  1111. question_only: bool = False,
  1112. one_rr_per_rrset: bool = False,
  1113. ignore_trailing: bool = False,
  1114. raise_on_truncation: bool = False,
  1115. continue_on_error: bool = False,
  1116. ) -> Message:
  1117. """Convert a DNS wire format message into a message object.
  1118. *keyring*, a ``dns.tsig.Key``, ``dict``, ``bool``, or ``None``, the key or keyring
  1119. to use if the message is signed. If ``None`` or ``True``, then trying to decode
  1120. a message with a TSIG will fail as it cannot be validated. If ``False``, then
  1121. TSIG validation is disabled.
  1122. *request_mac*, a ``bytes`` or ``None``. If the message is a response to a
  1123. TSIG-signed request, *request_mac* should be set to the MAC of that request.
  1124. *xfr*, a ``bool``, should be set to ``True`` if this message is part of a zone
  1125. transfer.
  1126. *origin*, a ``dns.name.Name`` or ``None``. If the message is part of a zone
  1127. transfer, *origin* should be the origin name of the zone. If not ``None``, names
  1128. will be relativized to the origin.
  1129. *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the ongoing TSIG
  1130. context, used when validating zone transfers.
  1131. *multi*, a ``bool``, should be set to ``True`` if this message is part of a multiple
  1132. message sequence.
  1133. *question_only*, a ``bool``. If ``True``, read only up to the end of the question
  1134. section.
  1135. *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own RRset.
  1136. *ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of the
  1137. message.
  1138. *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if the TC bit is
  1139. set.
  1140. *continue_on_error*, a ``bool``. If ``True``, try to continue parsing even if
  1141. errors occur. Erroneous rdata will be ignored. Errors will be accumulated as a
  1142. list of MessageError objects in the message's ``errors`` attribute. This option is
  1143. recommended only for DNS analysis tools, or for use in a server as part of an error
  1144. handling path. The default is ``False``.
  1145. Raises ``dns.message.ShortHeader`` if the message is less than 12 octets long.
  1146. Raises ``dns.message.TrailingJunk`` if there were octets in the message past the end
  1147. of the proper DNS message, and *ignore_trailing* is ``False``.
  1148. Raises ``dns.message.BadEDNS`` if an OPT record was in the wrong section, or
  1149. occurred more than once.
  1150. Raises ``dns.message.BadTSIG`` if a TSIG record was not the last record of the
  1151. additional data section.
  1152. Raises ``dns.message.Truncated`` if the TC flag is set and *raise_on_truncation* is
  1153. ``True``.
  1154. Returns a ``dns.message.Message``.
  1155. """
  1156. # We permit None for request_mac solely for backwards compatibility
  1157. if request_mac is None:
  1158. request_mac = b""
  1159. def initialize_message(message):
  1160. message.request_mac = request_mac
  1161. message.xfr = xfr
  1162. message.origin = origin
  1163. message.tsig_ctx = tsig_ctx
  1164. reader = _WireReader(
  1165. wire,
  1166. initialize_message,
  1167. question_only,
  1168. one_rr_per_rrset,
  1169. ignore_trailing,
  1170. keyring,
  1171. multi,
  1172. continue_on_error,
  1173. )
  1174. try:
  1175. m = reader.read()
  1176. except dns.exception.FormError:
  1177. if (
  1178. reader.message
  1179. and (reader.message.flags & dns.flags.TC)
  1180. and raise_on_truncation
  1181. ):
  1182. raise Truncated(message=reader.message)
  1183. else:
  1184. raise
  1185. # Reading a truncated message might not have any errors, so we
  1186. # have to do this check here too.
  1187. if m.flags & dns.flags.TC and raise_on_truncation:
  1188. raise Truncated(message=m)
  1189. if continue_on_error:
  1190. m.errors = reader.errors
  1191. return m
  1192. class _TextReader:
  1193. """Text format reader.
  1194. tok: the tokenizer.
  1195. message: The message object being built.
  1196. DNS dynamic updates.
  1197. last_name: The most recently read name when building a message object.
  1198. one_rr_per_rrset: Put each RR into its own RRset?
  1199. origin: The origin for relative names
  1200. relativize: relativize names?
  1201. relativize_to: the origin to relativize to.
  1202. """
  1203. def __init__(
  1204. self,
  1205. text: str,
  1206. idna_codec: dns.name.IDNACodec | None,
  1207. one_rr_per_rrset: bool = False,
  1208. origin: dns.name.Name | None = None,
  1209. relativize: bool = True,
  1210. relativize_to: dns.name.Name | None = None,
  1211. ):
  1212. self.message: Message | None = None # mypy: ignore
  1213. self.tok = dns.tokenizer.Tokenizer(text, idna_codec=idna_codec)
  1214. self.last_name = None
  1215. self.one_rr_per_rrset = one_rr_per_rrset
  1216. self.origin = origin
  1217. self.relativize = relativize
  1218. self.relativize_to = relativize_to
  1219. self.id = None
  1220. self.edns = -1
  1221. self.ednsflags = 0
  1222. self.payload = DEFAULT_EDNS_PAYLOAD
  1223. self.rcode = None
  1224. self.opcode = dns.opcode.QUERY
  1225. self.flags = 0
  1226. def _header_line(self, _):
  1227. """Process one line from the text format header section."""
  1228. token = self.tok.get()
  1229. what = token.value
  1230. if what == "id":
  1231. self.id = self.tok.get_int()
  1232. elif what == "flags":
  1233. while True:
  1234. token = self.tok.get()
  1235. if not token.is_identifier():
  1236. self.tok.unget(token)
  1237. break
  1238. self.flags = self.flags | dns.flags.from_text(token.value)
  1239. elif what == "edns":
  1240. self.edns = self.tok.get_int()
  1241. self.ednsflags = self.ednsflags | (self.edns << 16)
  1242. elif what == "eflags":
  1243. if self.edns < 0:
  1244. self.edns = 0
  1245. while True:
  1246. token = self.tok.get()
  1247. if not token.is_identifier():
  1248. self.tok.unget(token)
  1249. break
  1250. self.ednsflags = self.ednsflags | dns.flags.edns_from_text(token.value)
  1251. elif what == "payload":
  1252. self.payload = self.tok.get_int()
  1253. if self.edns < 0:
  1254. self.edns = 0
  1255. elif what == "opcode":
  1256. text = self.tok.get_string()
  1257. self.opcode = dns.opcode.from_text(text)
  1258. self.flags = self.flags | dns.opcode.to_flags(self.opcode)
  1259. elif what == "rcode":
  1260. text = self.tok.get_string()
  1261. self.rcode = dns.rcode.from_text(text)
  1262. else:
  1263. raise UnknownHeaderField
  1264. self.tok.get_eol()
  1265. def _question_line(self, section_number):
  1266. """Process one line from the text format question section."""
  1267. assert self.message is not None
  1268. section = self.message.sections[section_number]
  1269. token = self.tok.get(want_leading=True)
  1270. if not token.is_whitespace():
  1271. self.last_name = self.tok.as_name(
  1272. token, self.message.origin, self.relativize, self.relativize_to
  1273. )
  1274. name = self.last_name
  1275. if name is None:
  1276. raise NoPreviousName
  1277. token = self.tok.get()
  1278. if not token.is_identifier():
  1279. raise dns.exception.SyntaxError
  1280. # Class
  1281. try:
  1282. rdclass = dns.rdataclass.from_text(token.value)
  1283. token = self.tok.get()
  1284. if not token.is_identifier():
  1285. raise dns.exception.SyntaxError
  1286. except dns.exception.SyntaxError:
  1287. raise dns.exception.SyntaxError
  1288. except Exception:
  1289. rdclass = dns.rdataclass.IN
  1290. # Type
  1291. rdtype = dns.rdatatype.from_text(token.value)
  1292. (rdclass, rdtype, _, _) = self.message._parse_rr_header(
  1293. section_number, name, rdclass, rdtype
  1294. )
  1295. self.message.find_rrset(
  1296. section, name, rdclass, rdtype, create=True, force_unique=True
  1297. )
  1298. self.tok.get_eol()
  1299. def _rr_line(self, section_number):
  1300. """Process one line from the text format answer, authority, or
  1301. additional data sections.
  1302. """
  1303. assert self.message is not None
  1304. section = self.message.sections[section_number]
  1305. # Name
  1306. token = self.tok.get(want_leading=True)
  1307. if not token.is_whitespace():
  1308. self.last_name = self.tok.as_name(
  1309. token, self.message.origin, self.relativize, self.relativize_to
  1310. )
  1311. name = self.last_name
  1312. if name is None:
  1313. raise NoPreviousName
  1314. token = self.tok.get()
  1315. if not token.is_identifier():
  1316. raise dns.exception.SyntaxError
  1317. # TTL
  1318. try:
  1319. ttl = int(token.value, 0)
  1320. token = self.tok.get()
  1321. if not token.is_identifier():
  1322. raise dns.exception.SyntaxError
  1323. except dns.exception.SyntaxError:
  1324. raise dns.exception.SyntaxError
  1325. except Exception:
  1326. ttl = 0
  1327. # Class
  1328. try:
  1329. rdclass = dns.rdataclass.from_text(token.value)
  1330. token = self.tok.get()
  1331. if not token.is_identifier():
  1332. raise dns.exception.SyntaxError
  1333. except dns.exception.SyntaxError:
  1334. raise dns.exception.SyntaxError
  1335. except Exception:
  1336. rdclass = dns.rdataclass.IN
  1337. # Type
  1338. rdtype = dns.rdatatype.from_text(token.value)
  1339. (rdclass, rdtype, deleting, empty) = self.message._parse_rr_header(
  1340. section_number, name, rdclass, rdtype
  1341. )
  1342. token = self.tok.get()
  1343. if empty and not token.is_eol_or_eof():
  1344. raise dns.exception.SyntaxError
  1345. if not empty and token.is_eol_or_eof():
  1346. raise dns.exception.UnexpectedEnd
  1347. if not token.is_eol_or_eof():
  1348. self.tok.unget(token)
  1349. rd = dns.rdata.from_text(
  1350. rdclass,
  1351. rdtype,
  1352. self.tok,
  1353. self.message.origin,
  1354. self.relativize,
  1355. self.relativize_to,
  1356. )
  1357. covers = rd.covers()
  1358. else:
  1359. rd = None
  1360. covers = dns.rdatatype.NONE
  1361. rrset = self.message.find_rrset(
  1362. section,
  1363. name,
  1364. rdclass,
  1365. rdtype,
  1366. covers,
  1367. deleting,
  1368. True,
  1369. self.one_rr_per_rrset,
  1370. )
  1371. if rd is not None:
  1372. rrset.add(rd, ttl)
  1373. def _make_message(self):
  1374. factory = _message_factory_from_opcode(self.opcode)
  1375. message = factory(id=self.id)
  1376. message.flags = self.flags
  1377. if self.edns >= 0:
  1378. message.use_edns(self.edns, self.ednsflags, self.payload)
  1379. if self.rcode:
  1380. message.set_rcode(self.rcode)
  1381. if self.origin:
  1382. message.origin = self.origin
  1383. return message
  1384. def read(self):
  1385. """Read a text format DNS message and build a dns.message.Message
  1386. object."""
  1387. line_method = self._header_line
  1388. section_number = None
  1389. while 1:
  1390. token = self.tok.get(True, True)
  1391. if token.is_eol_or_eof():
  1392. break
  1393. if token.is_comment():
  1394. u = token.value.upper()
  1395. if u == "HEADER":
  1396. line_method = self._header_line
  1397. if self.message:
  1398. message = self.message
  1399. else:
  1400. # If we don't have a message, create one with the current
  1401. # opcode, so that we know which section names to parse.
  1402. message = self._make_message()
  1403. try:
  1404. section_number = message._section_enum.from_text(u)
  1405. # We found a section name. If we don't have a message,
  1406. # use the one we just created.
  1407. if not self.message:
  1408. self.message = message
  1409. self.one_rr_per_rrset = message._get_one_rr_per_rrset(
  1410. self.one_rr_per_rrset
  1411. )
  1412. if section_number == MessageSection.QUESTION:
  1413. line_method = self._question_line
  1414. else:
  1415. line_method = self._rr_line
  1416. except Exception:
  1417. # It's just a comment.
  1418. pass
  1419. self.tok.get_eol()
  1420. continue
  1421. self.tok.unget(token)
  1422. line_method(section_number)
  1423. if not self.message:
  1424. self.message = self._make_message()
  1425. return self.message
  1426. def from_text(
  1427. text: str,
  1428. idna_codec: dns.name.IDNACodec | None = None,
  1429. one_rr_per_rrset: bool = False,
  1430. origin: dns.name.Name | None = None,
  1431. relativize: bool = True,
  1432. relativize_to: dns.name.Name | None = None,
  1433. ) -> Message:
  1434. """Convert the text format message into a message object.
  1435. The reader stops after reading the first blank line in the input to
  1436. facilitate reading multiple messages from a single file with
  1437. ``dns.message.from_file()``.
  1438. *text*, a ``str``, the text format message.
  1439. *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
  1440. encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder
  1441. is used.
  1442. *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put
  1443. into its own rrset. The default is ``False``.
  1444. *origin*, a ``dns.name.Name`` (or ``None``), the
  1445. origin to use for relative names.
  1446. *relativize*, a ``bool``. If true, name will be relativized.
  1447. *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use
  1448. when relativizing names. If not set, the *origin* value will be used.
  1449. Raises ``dns.message.UnknownHeaderField`` if a header is unknown.
  1450. Raises ``dns.exception.SyntaxError`` if the text is badly formed.
  1451. Returns a ``dns.message.Message object``
  1452. """
  1453. # 'text' can also be a file, but we don't publish that fact
  1454. # since it's an implementation detail. The official file
  1455. # interface is from_file().
  1456. reader = _TextReader(
  1457. text, idna_codec, one_rr_per_rrset, origin, relativize, relativize_to
  1458. )
  1459. return reader.read()
  1460. def from_file(
  1461. f: Any,
  1462. idna_codec: dns.name.IDNACodec | None = None,
  1463. one_rr_per_rrset: bool = False,
  1464. ) -> Message:
  1465. """Read the next text format message from the specified file.
  1466. Message blocks are separated by a single blank line.
  1467. *f*, a ``file`` or ``str``. If *f* is text, it is treated as the
  1468. pathname of a file to open.
  1469. *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
  1470. encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder
  1471. is used.
  1472. *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put
  1473. into its own rrset. The default is ``False``.
  1474. Raises ``dns.message.UnknownHeaderField`` if a header is unknown.
  1475. Raises ``dns.exception.SyntaxError`` if the text is badly formed.
  1476. Returns a ``dns.message.Message object``
  1477. """
  1478. if isinstance(f, str):
  1479. cm: contextlib.AbstractContextManager = open(f, encoding="utf-8")
  1480. else:
  1481. cm = contextlib.nullcontext(f)
  1482. with cm as f:
  1483. return from_text(f, idna_codec, one_rr_per_rrset)
  1484. assert False # for mypy lgtm[py/unreachable-statement]
  1485. def make_query(
  1486. qname: dns.name.Name | str,
  1487. rdtype: dns.rdatatype.RdataType | str,
  1488. rdclass: dns.rdataclass.RdataClass | str = dns.rdataclass.IN,
  1489. use_edns: int | bool | None = None,
  1490. want_dnssec: bool = False,
  1491. ednsflags: int | None = None,
  1492. payload: int | None = None,
  1493. request_payload: int | None = None,
  1494. options: List[dns.edns.Option] | None = None,
  1495. idna_codec: dns.name.IDNACodec | None = None,
  1496. id: int | None = None,
  1497. flags: int = dns.flags.RD,
  1498. pad: int = 0,
  1499. ) -> QueryMessage:
  1500. """Make a query message.
  1501. The query name, type, and class may all be specified either
  1502. as objects of the appropriate type, or as strings.
  1503. The query will have a randomly chosen query id, and its DNS flags
  1504. will be set to dns.flags.RD.
  1505. qname, a ``dns.name.Name`` or ``str``, the query name.
  1506. *rdtype*, an ``int`` or ``str``, the desired rdata type.
  1507. *rdclass*, an ``int`` or ``str``, the desired rdata class; the default
  1508. is class IN.
  1509. *use_edns*, an ``int``, ``bool`` or ``None``. The EDNS level to use; the
  1510. default is ``None``. If ``None``, EDNS will be enabled only if other
  1511. parameters (*ednsflags*, *payload*, *request_payload*, or *options*) are
  1512. set.
  1513. See the description of dns.message.Message.use_edns() for the possible
  1514. values for use_edns and their meanings.
  1515. *want_dnssec*, a ``bool``. If ``True``, DNSSEC data is desired.
  1516. *ednsflags*, an ``int``, the EDNS flag values.
  1517. *payload*, an ``int``, is the EDNS sender's payload field, which is the
  1518. maximum size of UDP datagram the sender can handle. I.e. how big
  1519. a response to this message can be.
  1520. *request_payload*, an ``int``, is the EDNS payload size to use when
  1521. sending this message. If not specified, defaults to the value of
  1522. *payload*.
  1523. *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS
  1524. options.
  1525. *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA
  1526. encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder
  1527. is used.
  1528. *id*, an ``int`` or ``None``, the desired query id. The default is
  1529. ``None``, which generates a random query id.
  1530. *flags*, an ``int``, the desired query flags. The default is
  1531. ``dns.flags.RD``.
  1532. *pad*, a non-negative ``int``. If 0, the default, do not pad; otherwise add
  1533. padding bytes to make the message size a multiple of *pad*. Note that if
  1534. padding is non-zero, an EDNS PADDING option will always be added to the
  1535. message.
  1536. Returns a ``dns.message.QueryMessage``
  1537. """
  1538. if isinstance(qname, str):
  1539. qname = dns.name.from_text(qname, idna_codec=idna_codec)
  1540. rdtype = dns.rdatatype.RdataType.make(rdtype)
  1541. rdclass = dns.rdataclass.RdataClass.make(rdclass)
  1542. m = QueryMessage(id=id)
  1543. m.flags = dns.flags.Flag(flags)
  1544. m.find_rrset(m.question, qname, rdclass, rdtype, create=True, force_unique=True)
  1545. # only pass keywords on to use_edns if they have been set to a
  1546. # non-None value. Setting a field will turn EDNS on if it hasn't
  1547. # been configured.
  1548. kwargs: Dict[str, Any] = {}
  1549. if ednsflags is not None:
  1550. kwargs["ednsflags"] = ednsflags
  1551. if payload is not None:
  1552. kwargs["payload"] = payload
  1553. if request_payload is not None:
  1554. kwargs["request_payload"] = request_payload
  1555. if options is not None:
  1556. kwargs["options"] = options
  1557. if kwargs and use_edns is None:
  1558. use_edns = 0
  1559. kwargs["edns"] = use_edns
  1560. kwargs["pad"] = pad
  1561. m.use_edns(**kwargs)
  1562. if want_dnssec:
  1563. m.want_dnssec(want_dnssec)
  1564. return m
  1565. class CopyMode(enum.Enum):
  1566. """
  1567. How should sections be copied when making an update response?
  1568. """
  1569. NOTHING = 0
  1570. QUESTION = 1
  1571. EVERYTHING = 2
  1572. def make_response(
  1573. query: Message,
  1574. recursion_available: bool = False,
  1575. our_payload: int = 8192,
  1576. fudge: int = 300,
  1577. tsig_error: int = 0,
  1578. pad: int | None = None,
  1579. copy_mode: CopyMode | None = None,
  1580. ) -> Message:
  1581. """Make a message which is a response for the specified query.
  1582. The message returned is really a response skeleton; it has all of the infrastructure
  1583. required of a response, but none of the content.
  1584. Response section(s) which are copied are shallow copies of the matching section(s)
  1585. in the query, so the query's RRsets should not be changed.
  1586. *query*, a ``dns.message.Message``, the query to respond to.
  1587. *recursion_available*, a ``bool``, should RA be set in the response?
  1588. *our_payload*, an ``int``, the payload size to advertise in EDNS responses.
  1589. *fudge*, an ``int``, the TSIG time fudge.
  1590. *tsig_error*, an ``int``, the TSIG error.
  1591. *pad*, a non-negative ``int`` or ``None``. If 0, the default, do not pad; otherwise
  1592. if not ``None`` add padding bytes to make the message size a multiple of *pad*. Note
  1593. that if padding is non-zero, an EDNS PADDING option will always be added to the
  1594. message. If ``None``, add padding following RFC 8467, namely if the request is
  1595. padded, pad the response to 468 otherwise do not pad.
  1596. *copy_mode*, a ``dns.message.CopyMode`` or ``None``, determines how sections are
  1597. copied. The default, ``None`` copies sections according to the default for the
  1598. message's opcode, which is currently ``dns.message.CopyMode.QUESTION`` for all
  1599. opcodes. ``dns.message.CopyMode.QUESTION`` copies only the question section.
  1600. ``dns.message.CopyMode.EVERYTHING`` copies all sections other than OPT or TSIG
  1601. records, which are created appropriately if needed. ``dns.message.CopyMode.NOTHING``
  1602. copies no sections; note that this mode is for server testing purposes and is
  1603. otherwise not recommended for use. In particular, ``dns.message.is_response()``
  1604. will be ``False`` if you create a response this way and the rcode is not
  1605. ``FORMERR``, ``SERVFAIL``, ``NOTIMP``, or ``REFUSED``.
  1606. Returns a ``dns.message.Message`` object whose specific class is appropriate for the
  1607. query. For example, if query is a ``dns.update.UpdateMessage``, the response will
  1608. be one too.
  1609. """
  1610. if query.flags & dns.flags.QR:
  1611. raise dns.exception.FormError("specified query message is not a query")
  1612. opcode = query.opcode()
  1613. factory = _message_factory_from_opcode(opcode)
  1614. response = factory(id=query.id)
  1615. response.flags = dns.flags.QR | (query.flags & dns.flags.RD)
  1616. if recursion_available:
  1617. response.flags |= dns.flags.RA
  1618. response.set_opcode(opcode)
  1619. if copy_mode is None:
  1620. copy_mode = CopyMode.QUESTION
  1621. if copy_mode != CopyMode.NOTHING:
  1622. response.question = list(query.question)
  1623. if copy_mode == CopyMode.EVERYTHING:
  1624. response.answer = list(query.answer)
  1625. response.authority = list(query.authority)
  1626. response.additional = list(query.additional)
  1627. if query.edns >= 0:
  1628. if pad is None:
  1629. # Set response padding per RFC 8467
  1630. pad = 0
  1631. for option in query.options:
  1632. if option.otype == dns.edns.OptionType.PADDING:
  1633. pad = 468
  1634. response.use_edns(0, 0, our_payload, query.payload, pad=pad)
  1635. if query.had_tsig and query.keyring:
  1636. assert query.mac is not None
  1637. assert query.keyalgorithm is not None
  1638. response.use_tsig(
  1639. query.keyring,
  1640. query.keyname,
  1641. fudge,
  1642. None,
  1643. tsig_error,
  1644. b"",
  1645. query.keyalgorithm,
  1646. )
  1647. response.request_mac = query.mac
  1648. return response
  1649. ### BEGIN generated MessageSection constants
  1650. QUESTION = MessageSection.QUESTION
  1651. ANSWER = MessageSection.ANSWER
  1652. AUTHORITY = MessageSection.AUTHORITY
  1653. ADDITIONAL = MessageSection.ADDITIONAL
  1654. ### END generated MessageSection constants