pax_global_header00006660000000000000000000000064145444677570014541gustar00rootroot0000000000000052 comment=5b585015f2772b8e258bbb6441b8bf5a4b2861af dq-20240101/000077500000000000000000000000001454446775700124005ustar00rootroot00000000000000dq-20240101/.gitignore000066400000000000000000000000071454446775700143650ustar00rootroot00000000000000/build dq-20240101/LICENCE000066400000000000000000000156101454446775700133700ustar00rootroot00000000000000Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. dq-20240101/Makefile000066400000000000000000000362771454446775700140570ustar00rootroot00000000000000CC?=cc CFLAGS+=-O3 -fno-strict-overflow -fwrapv -Wno-parentheses -Wundef -Wunused-value -Wmissing-prototypes -Wmissing-declarations -Wwrite-strings -Wdeclaration-after-statement -Wshadow -Wno-unused-function -Wno-overlength-strings -Wno-long-long -Wall -pedantic LDFLAGS?= DESTDIR?= BINARIES=dq BINARIES+=dqcache BINARIES+=dqcache-makekey BINARIES+=dqcache-start all: $(BINARIES) alloc.o: alloc.c e.h uint64_pack.h crypto_uint64.h uint64_unpack.h byte.h \ purge.h alloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c alloc.c base32decode.o: base32decode.c base32decode.h $(CC) $(CFLAGS) $(CPPFLAGS) -c base32decode.c blocking.o: blocking.c blocking.h $(CC) $(CFLAGS) $(CPPFLAGS) -c blocking.c buffer_2.o: buffer_2.c buffer.h $(CC) $(CFLAGS) $(CPPFLAGS) -c buffer_2.c buffer.o: buffer.c buffer.h $(CC) $(CFLAGS) $(CPPFLAGS) -c buffer.c buffer_put.o: buffer_put.c e.h str.h byte.h buffer.h $(CC) $(CFLAGS) $(CPPFLAGS) -c buffer_put.c buffer_write.o: buffer_write.c writeall.h buffer.h $(CC) $(CFLAGS) $(CPPFLAGS) -c buffer_write.c byte.o: byte.c byte.h $(CC) $(CFLAGS) $(CPPFLAGS) -c byte.c cache.o: cache.c alloc.h byte.h uint64_pack.h crypto_uint64.h \ uint64_unpack.h uint32_pack.h crypto_uint32.h uint32_unpack.h seconds.h \ die.h randombytes.h buffer.h open.h dns.h stralloc.h \ crypto_auth_siphash24.h e.h cache.h $(CC) $(CFLAGS) $(CPPFLAGS) -c cache.c case.o: case.c case.h $(CC) $(CFLAGS) $(CPPFLAGS) -c case.c cleanup.o: cleanup.c cleanup.h $(CC) $(CFLAGS) $(CPPFLAGS) -c cleanup.c crypto_auth_siphash24.o: crypto_auth_siphash24.c siphash.h \ crypto_verify_8.h crypto_auth_siphash24.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_auth_siphash24.c crypto_box_curve25519xsalsa20poly1305.o: \ crypto_box_curve25519xsalsa20poly1305.c crypto_core_hsalsa20.h \ crypto_scalarmult_curve25519.h crypto_secretbox_xsalsa20poly1305.h \ randombytes.h crypto_box_curve25519xsalsa20poly1305.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_box_curve25519xsalsa20poly1305.c crypto_core_hsalsa20.o: crypto_core_hsalsa20.c salsa.h crypto_uint32.h \ uint32_unpack.h cleanup.h crypto_core_hsalsa20.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_core_hsalsa20.c crypto_onetimeauth_poly1305.o: crypto_onetimeauth_poly1305.c \ crypto_onetimeauth_poly1305.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_onetimeauth_poly1305.c crypto_scalarmult_curve25519.o: crypto_scalarmult_curve25519.c \ crypto_scalarmult_curve25519.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_scalarmult_curve25519.c crypto_secretbox_xsalsa20poly1305.o: crypto_secretbox_xsalsa20poly1305.c \ crypto_onetimeauth_poly1305.h crypto_stream_xsalsa20.h cleanup.h \ crypto_secretbox_xsalsa20poly1305.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_secretbox_xsalsa20poly1305.c crypto_stream_salsa20.o: crypto_stream_salsa20.c salsa.h crypto_uint32.h \ crypto_stream_salsa20.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_stream_salsa20.c crypto_stream_xsalsa20.o: crypto_stream_xsalsa20.c crypto_core_hsalsa20.h \ crypto_stream_salsa20.h cleanup.h crypto_stream_xsalsa20.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_stream_xsalsa20.c crypto_verify_16.o: crypto_verify_16.c verify.h crypto_verify_16.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_verify_16.c crypto_verify_32.o: crypto_verify_32.c verify.h crypto_verify_32.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_verify_32.c crypto_verify_8.o: crypto_verify_8.c verify.h crypto_verify_8.h $(CC) $(CFLAGS) $(CPPFLAGS) -c crypto_verify_8.c die.o: die.c alloc.h writeall.h die.h $(CC) $(CFLAGS) $(CPPFLAGS) -c die.c dns_base32.o: dns_base32.c byte.h dns.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_base32.c dns_data.o: dns_data.c stralloc.h alloc.h byte.h dns.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_data.c dns_domain.o: dns_domain.c alloc.h byte.h case.h e.h dns.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_domain.c dns_dtda.o: dns_dtda.c stralloc.h dns.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_dtda.c dns_ip.o: dns_ip.c alloc.h byte.h crypto_uint16.h uint16_unpack_big.h \ base32decode.h hexdecode.h case.h str.h stralloc.h strtoip.h \ milliseconds.h dns.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_ip.c dns_ipq.o: dns_ipq.c stralloc.h case.h byte.h str.h dns.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_ipq.c dns_iptoname.o: dns_iptoname.c byte.h numtostr.h dns.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_iptoname.c dns_keys.o: dns_keys.c crypto_stream_salsa20.h dns.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_keys.c dns_nonce.o: dns_nonce.c nanoseconds.h randombytes.h uint32_pack.h \ crypto_uint32.h uint32_unpack.h crypto_uint64.h byte.h purge.h dns.h \ stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_nonce.c dns_packet.o: dns_packet.c e.h byte.h dns.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_packet.c dns_rcip.o: dns_rcip.c milliseconds.h openreadclose.h stralloc.h byte.h \ env.h strtoip.h strtomultiip.h hasipv6.h xsocket.h dns.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_rcip.c dns_rcrw.o: dns_rcrw.c milliseconds.h env.h byte.h str.h openreadclose.h \ stralloc.h dns.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_rcrw.c dns_resolve.o: dns_resolve.c milliseconds.h byte.h e.h dns.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_resolve.c dns_sortip.o: dns_sortip.c randommod.h byte.h dns.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_sortip.c dns_transmit.o: dns_transmit.c alloc.h milliseconds.h xsocket.h hasipv6.h \ e.h byte.h uint16_pack_big.h crypto_uint16.h uint16_unpack_big.h \ randombytes.h randommod.h case.h str.h dns.h stralloc.h \ crypto_box_curve25519xsalsa20poly1305.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_transmit.c dns_verbosity.o: dns_verbosity.c stralloc.h writeall.h iptostr.h \ porttostr.h numtostr.h e.h uint16_unpack_big.h crypto_uint16.h byte.h \ dns.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dns_verbosity.c dq.o: dq.c dns.h stralloc.h strtonum.h case.h die.h e.h randombytes.h \ byte.h printpacket.h writeall.h milliseconds.h str.h uint16_pack_big.h \ crypto_uint16.h uint16_unpack_big.h portparse.h base32decode.h \ hexdecode.h strtoip.h keyparse.h typeparse.h purge.h \ crypto_box_curve25519xsalsa20poly1305.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dq.c dqcache.o: dqcache.c env.h byte.h xsocket.h hasipv6.h strtoip.h \ randombytes.h crypto_uint64.h query.h dns.h stralloc.h crypto_uint32.h \ die.h warn.h e.h numtostr.h strtonum.h cache.h response.h log.h roots.h \ hexparse.h alloc.h milliseconds.h blocking.h uint16_pack_big.h \ crypto_uint16.h uint16_unpack_big.h portparse.h droproot.h okclient.h \ purge.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dqcache.c dqcache-makekey.o: dqcache-makekey.c randombytes.h writeall.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dqcache-makekey.c dqcache-start.o: dqcache-start.c numtostr.h strtonum.h e.h die.h $(CC) $(CFLAGS) $(CPPFLAGS) -c dqcache-start.c droproot.o: droproot.c env.h die.h strtonum.h e.h droproot.h $(CC) $(CFLAGS) $(CPPFLAGS) -c droproot.c e.o: e.c e.h $(CC) $(CFLAGS) $(CPPFLAGS) -c e.c env.o: env.c str.h env.h $(CC) $(CFLAGS) $(CPPFLAGS) -c env.c hexdecode.o: hexdecode.c hexdecode.h $(CC) $(CFLAGS) $(CPPFLAGS) -c hexdecode.c hexparse.o: hexparse.c hexparse.h $(CC) $(CFLAGS) $(CPPFLAGS) -c hexparse.c iptostr.o: iptostr.c byte.h iptostr.h $(CC) $(CFLAGS) $(CPPFLAGS) -c iptostr.c keyparse.o: keyparse.c hexdecode.h base32decode.h byte.h str.h keyparse.h $(CC) $(CFLAGS) $(CPPFLAGS) -c keyparse.c log.o: log.c buffer.h uint32_unpack_big.h crypto_uint32.h \ uint16_unpack_big.h crypto_uint16.h e.h byte.h iptostr.h numtostr.h \ log.h crypto_uint64.h $(CC) $(CFLAGS) $(CPPFLAGS) -c log.c milliseconds.o: milliseconds.c milliseconds.h $(CC) $(CFLAGS) $(CPPFLAGS) -c milliseconds.c nanoseconds.o: nanoseconds.c nanoseconds.h $(CC) $(CFLAGS) $(CPPFLAGS) -c nanoseconds.c numtostr.o: numtostr.c numtostr.h $(CC) $(CFLAGS) $(CPPFLAGS) -c numtostr.c okclient.o: okclient.c str.h byte.h iptostr.h okclient.h $(CC) $(CFLAGS) $(CPPFLAGS) -c okclient.c open_read.o: open_read.c open.h $(CC) $(CFLAGS) $(CPPFLAGS) -c open_read.c openreadclose.o: openreadclose.c open.h e.h byte.h openreadclose.h \ stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c openreadclose.c open_trunc.o: open_trunc.c open.h $(CC) $(CFLAGS) $(CPPFLAGS) -c open_trunc.c portparse.o: portparse.c portparse.h $(CC) $(CFLAGS) $(CPPFLAGS) -c portparse.c porttostr.o: porttostr.c crypto_uint16.h porttostr.h $(CC) $(CFLAGS) $(CPPFLAGS) -c porttostr.c printpacket.o: printpacket.c uint16_unpack_big.h crypto_uint16.h e.h \ byte.h dns.h stralloc.h printrecord.h printpacket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c printpacket.c printrecord.o: printrecord.c uint16_unpack_big.h crypto_uint16.h \ uint32_unpack_big.h crypto_uint32.h e.h byte.h dns.h stralloc.h \ printrecord.h iptostr.h $(CC) $(CFLAGS) $(CPPFLAGS) -c printrecord.c query.o: query.c e.h roots.h log.h crypto_uint64.h case.h cache.h byte.h \ dns.h stralloc.h uint32_unpack_big.h crypto_uint32.h uint16_unpack_big.h \ crypto_uint16.h alloc.h response.h query.h strtoip.h iptostr.h xsocket.h \ hasipv6.h crypto_scalarmult_curve25519.h \ crypto_box_curve25519xsalsa20poly1305.h purge.h $(CC) $(CFLAGS) $(CPPFLAGS) -c query.c randombytes.o: randombytes.c randombytes.h $(CC) $(CFLAGS) $(CPPFLAGS) -c randombytes.c randommod.o: randommod.c randombytes.h randommod.h $(CC) $(CFLAGS) $(CPPFLAGS) -c randommod.c response.o: response.c dns.h stralloc.h byte.h uint16_pack_big.h \ crypto_uint16.h uint32_pack_big.h crypto_uint32.h response.h $(CC) $(CFLAGS) $(CPPFLAGS) -c response.c roots.o: roots.c open.h e.h str.h byte.h direntry.h strtoip.h dns.h \ stralloc.h openreadclose.h roots.h keyparse.h $(CC) $(CFLAGS) $(CPPFLAGS) -c roots.c salsa.o: salsa.c crypto_uint64.h crypto_uint32.h uint32_pack.h \ uint32_unpack.h cleanup.h salsa.h $(CC) $(CFLAGS) $(CPPFLAGS) -c salsa.c seconds.o: seconds.c seconds.h $(CC) $(CFLAGS) $(CPPFLAGS) -c seconds.c siphash.o: siphash.c uint64_pack.h crypto_uint64.h uint64_unpack.h \ siphash.h $(CC) $(CFLAGS) $(CPPFLAGS) -c siphash.c stralloc.o: stralloc.c alloc.h e.h stralloc.h $(CC) $(CFLAGS) $(CPPFLAGS) -c stralloc.c str.o: str.c str.h $(CC) $(CFLAGS) $(CPPFLAGS) -c str.c strtoip.o: strtoip.c byte.h strtoip.h $(CC) $(CFLAGS) $(CPPFLAGS) -c strtoip.c strtomultiip.o: strtomultiip.c byte.h str.h strtoip.h strtomultiip.h $(CC) $(CFLAGS) $(CPPFLAGS) -c strtomultiip.c strtonum.o: strtonum.c e.h strtonum.h $(CC) $(CFLAGS) $(CPPFLAGS) -c strtonum.c typeparse.o: typeparse.c strtonum.h uint16_pack_big.h crypto_uint16.h \ case.h dns.h stralloc.h byte.h typeparse.h $(CC) $(CFLAGS) $(CPPFLAGS) -c typeparse.c uint16_pack_big.o: uint16_pack_big.c uint16_pack_big.h crypto_uint16.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint16_pack_big.c uint16_unpack_big.o: uint16_unpack_big.c uint16_unpack_big.h \ crypto_uint16.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint16_unpack_big.c uint32_pack_big.o: uint32_pack_big.c uint32_pack_big.h crypto_uint32.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint32_pack_big.c uint32_pack.o: uint32_pack.c uint32_pack.h crypto_uint32.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint32_pack.c uint32_unpack_big.o: uint32_unpack_big.c uint32_unpack_big.h \ crypto_uint32.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint32_unpack_big.c uint32_unpack.o: uint32_unpack.c uint32_unpack.h crypto_uint32.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint32_unpack.c uint64_pack.o: uint64_pack.c uint64_pack.h crypto_uint64.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint64_pack.c uint64_unpack.o: uint64_unpack.c uint64_unpack.h crypto_uint64.h $(CC) $(CFLAGS) $(CPPFLAGS) -c uint64_unpack.c verify.o: verify.c verify.h $(CC) $(CFLAGS) $(CPPFLAGS) -c verify.c warn.o: warn.c writeall.h warn.h $(CC) $(CFLAGS) $(CPPFLAGS) -c warn.c writeall.o: writeall.c e.h writeall.h $(CC) $(CFLAGS) $(CPPFLAGS) -c writeall.c xsocket_accept.o: xsocket_accept.c e.h byte.h hasipv6.h xsocket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_accept.c xsocket_bind.o: xsocket_bind.c e.h byte.h hasipv6.h xsocket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_bind.c xsocket_conn.o: xsocket_conn.c e.h byte.h hasipv6.h xsocket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_conn.c xsocket_listen.o: xsocket_listen.c e.h xsocket.h hasipv6.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_listen.c xsocket_recv.o: xsocket_recv.c e.h byte.h hasipv6.h xsocket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_recv.c xsocket_send.o: xsocket_send.c e.h byte.h hasipv6.h xsocket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_send.c xsocket_tcp.o: xsocket_tcp.c hasipv6.h blocking.h e.h xsocket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_tcp.c xsocket_type.o: xsocket_type.c byte.h xsocket.h hasipv6.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_type.c xsocket_udp.o: xsocket_udp.c hasipv6.h blocking.h e.h xsocket.h $(CC) $(CFLAGS) $(CPPFLAGS) -c xsocket_udp.c OBJECTS=alloc.o OBJECTS+=base32decode.o OBJECTS+=blocking.o OBJECTS+=buffer_2.o OBJECTS+=buffer.o OBJECTS+=buffer_put.o OBJECTS+=buffer_write.o OBJECTS+=byte.o OBJECTS+=cache.o OBJECTS+=case.o OBJECTS+=cleanup.o OBJECTS+=crypto_auth_siphash24.o OBJECTS+=crypto_box_curve25519xsalsa20poly1305.o OBJECTS+=crypto_core_hsalsa20.o OBJECTS+=crypto_onetimeauth_poly1305.o OBJECTS+=crypto_scalarmult_curve25519.o OBJECTS+=crypto_secretbox_xsalsa20poly1305.o OBJECTS+=crypto_stream_salsa20.o OBJECTS+=crypto_stream_xsalsa20.o OBJECTS+=crypto_verify_16.o OBJECTS+=crypto_verify_32.o OBJECTS+=crypto_verify_8.o OBJECTS+=die.o OBJECTS+=dns_base32.o OBJECTS+=dns_data.o OBJECTS+=dns_domain.o OBJECTS+=dns_dtda.o OBJECTS+=dns_ip.o OBJECTS+=dns_ipq.o OBJECTS+=dns_iptoname.o OBJECTS+=dns_keys.o OBJECTS+=dns_nonce.o OBJECTS+=dns_packet.o OBJECTS+=dns_rcip.o OBJECTS+=dns_rcrw.o OBJECTS+=dns_resolve.o OBJECTS+=dns_sortip.o OBJECTS+=dns_transmit.o OBJECTS+=dns_verbosity.o OBJECTS+=droproot.o OBJECTS+=e.o OBJECTS+=env.o OBJECTS+=hexdecode.o OBJECTS+=hexparse.o OBJECTS+=iptostr.o OBJECTS+=keyparse.o OBJECTS+=log.o OBJECTS+=milliseconds.o OBJECTS+=nanoseconds.o OBJECTS+=numtostr.o OBJECTS+=okclient.o OBJECTS+=open_read.o OBJECTS+=openreadclose.o OBJECTS+=open_trunc.o OBJECTS+=portparse.o OBJECTS+=porttostr.o OBJECTS+=printpacket.o OBJECTS+=printrecord.o OBJECTS+=query.o OBJECTS+=randombytes.o OBJECTS+=randommod.o OBJECTS+=response.o OBJECTS+=roots.o OBJECTS+=salsa.o OBJECTS+=seconds.o OBJECTS+=siphash.o OBJECTS+=stralloc.o OBJECTS+=str.o OBJECTS+=strtoip.o OBJECTS+=strtomultiip.o OBJECTS+=strtonum.o OBJECTS+=typeparse.o OBJECTS+=uint16_pack_big.o OBJECTS+=uint16_unpack_big.o OBJECTS+=uint32_pack_big.o OBJECTS+=uint32_pack.o OBJECTS+=uint32_unpack_big.o OBJECTS+=uint32_unpack.o OBJECTS+=uint64_pack.o OBJECTS+=uint64_unpack.o OBJECTS+=verify.o OBJECTS+=warn.o OBJECTS+=writeall.o OBJECTS+=xsocket_accept.o OBJECTS+=xsocket_bind.o OBJECTS+=xsocket_conn.o OBJECTS+=xsocket_listen.o OBJECTS+=xsocket_recv.o OBJECTS+=xsocket_send.o OBJECTS+=xsocket_tcp.o OBJECTS+=xsocket_type.o OBJECTS+=xsocket_udp.o dq: dq.o $(OBJECTS) $(CC) $(CFLAGS) $(CPPFLAGS) -o dq dq.o $(OBJECTS) $(LDFLAGS) dqcache: dqcache.o $(OBJECTS) $(CC) $(CFLAGS) $(CPPFLAGS) -o dqcache dqcache.o $(OBJECTS) $(LDFLAGS) dqcache-makekey: dqcache-makekey.o $(OBJECTS) $(CC) $(CFLAGS) $(CPPFLAGS) -o dqcache-makekey dqcache-makekey.o $(OBJECTS) $(LDFLAGS) dqcache-start: dqcache-start.o $(OBJECTS) $(CC) $(CFLAGS) $(CPPFLAGS) -o dqcache-start dqcache-start.o $(OBJECTS) $(LDFLAGS) install: dq dqcache dqcache-makekey dqcache-start install -D -m 0755 dq $(DESTDIR)/usr/bin/dq install -D -m 0755 dqcache $(DESTDIR)/usr/sbin/dqcache install -D -m 0755 dqcache-makekey $(DESTDIR)/usr/sbin/dqcache-makekey install -D -m 0755 dqcache-start $(DESTDIR)/usr/sbin/dqcache-start clean: rm -f *.o *.out $(BINARIES) dq-20240101/README.md000066400000000000000000000017351454446775700136650ustar00rootroot00000000000000#### dq tool #### * based on dnsq and dnsqr from djbdns * added IPv6 support * added DNSCurve support (Streamlined/TXT) #### dqcache recursive server #### * based on dnscache from djbdns * added support for streamlined DNSCurve * added support for TXT DNSCurve * added support for combined DNSCurve (streamlined and TXT) * added support for DNS anchors with DNSCurve keys * added full IPv6 support * added support for IPv6 DNS anchors * added support for cache dumping/loading * used siphash24 instead of hash5381 in cache library * added SOA record caching * added authority record to DNS response * improved logs - IPs not printed in hex format * fixed CVE-2012-1191 * fixed CVE-2008-4392 #### examples #### - [examples page](examples.md) #### installation #### - [installation](install.md) #### licence #### * Dq is derived from public-domain djbdns-1.05 - see: https://cr.yp.to/distributors.html * Dq is released under CC0 licence http://creativecommons.org/publicdomain/zero/1.0/ dq-20240101/alloc.c000066400000000000000000000056771454446775700136550ustar00rootroot00000000000000/* 20130503 Jan Mojzis Public domain. */ #include #include #include #include "e.h" #include "uint64_pack.h" #include "uint64_unpack.h" #include "byte.h" #include "purge.h" #include "alloc.h" #define ALLOC_ALIGNMENT 16 #define ALLOC_SPACE 8192 #define ALLOC_LIMIT 4000000000LL typedef union { unsigned char irrelevant[ALLOC_ALIGNMENT]; double d; } aligned; static aligned realspace[ALLOC_SPACE / ALLOC_ALIGNMENT]; #define space ((unsigned char *) realspace) static long long avail = ALLOC_SPACE; static long long allocated = 0; static long long limit = -1; static long long getlimit(void) { struct rlimit r; if (limit >= 0) return limit; #ifdef RLIMIT_DATA if (getrlimit(RLIMIT_DATA, &r) == 0) { if (r.rlim_cur > r.rlim_max) r.rlim_cur = r.rlim_max; limit = (long long)r.rlim_cur; } #endif if (limit < 0 || limit > ALLOC_LIMIT) limit = ALLOC_LIMIT; return limit; } #ifdef TEST void alloc_setlimit(long long l) { limit = l; } long long alloc_getallocated(void) { return allocated; } long long alloc_getspace(void) { return ALLOC_SPACE; } #endif static void **ptr = 0; static long long ptrlen = 0; static long long ptralloc = 0; static int ptr_add(void *x) { void **newptr; if (ptrlen + 1 > ptralloc) { while (ptrlen + 1 > ptralloc) ptralloc = 2 * ptralloc + 1; newptr = (void **)malloc(ptralloc * sizeof(void *)); if (!newptr) return 0; if (ptr) { byte_copy(newptr, ptrlen * sizeof(void *), ptr); free(ptr); } ptr = newptr; } if (!x) return 1; ptr[ptrlen++] = x; return 1; } static int ptr_remove(void *x) { long long i; for (i = 0; i < ptrlen; ++i) { if (ptr[i] == x) goto ok; } return 0; ok: --ptrlen; ptr[i] = ptr[ptrlen]; return 1; } void *alloc(long long nn) { unsigned char *x; crypto_uint64 n; if (nn < 0 || nn > ALLOC_LIMIT) goto nomem; if (nn == 0) nn = 1; n = nn; n = ALLOC_ALIGNMENT + n - (n & (ALLOC_ALIGNMENT - 1)); if (n <= avail) { avail -= n; return (void *)(space + avail); } n += ALLOC_ALIGNMENT; if (allocated + n > getlimit()) goto nomem; x = (unsigned char *)malloc(n); if (!x) goto nomem; allocated += n; byte_zero(x, n); uint64_pack(x, n); x += ALLOC_ALIGNMENT; if (!ptr_add(x)) goto nomem; return (void *)x; nomem: errno = ENOMEM; return (void *)0; } void alloc_free(void *xv) { crypto_uint64 n; unsigned char *x = xv; if (x >= space) if (x < space + ALLOC_SPACE) return; if (!ptr_remove(x)) return; x -= ALLOC_ALIGNMENT; n = uint64_unpack(x); allocated -= n; purge(x, n); free(x); } void alloc_freeall(void) { while (ptrlen > 0) { alloc_free(ptr[0]); } if (ptr) { free(ptr); ptr = 0; ptrlen = 0; ptralloc = 0; } purge(space, ALLOC_SPACE); } dq-20240101/alloc.h000066400000000000000000000005271454446775700136470ustar00rootroot00000000000000#ifndef _ALLOC_H____ #define _ALLOC_H____ #ifdef TEST extern void alloc_setlimit(long long); extern long long alloc_getallocated(void); extern long long alloc_getspace(void); #endif extern void *alloc(long long); extern void alloc_free(void *x); extern int alloc_re(void **x, long long, long long); extern void alloc_freeall(void); #endif dq-20240101/base32decode.c000066400000000000000000000030011454446775700147610ustar00rootroot00000000000000#include "base32decode.h" static const unsigned char base32values[128] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0xff, 0x0d, 0x0e, 0x0f, 0xff, 0x10, 0x11, 0x12, 0x13, 0x14, 0xff, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0xff, 0x0d, 0x0e, 0x0f, 0xff, 0x10, 0x11, 0x12, 0x13, 0x14, 0xff, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff }; int base32decode(unsigned char *out, long long outlen, const unsigned char *in, long long inlen) { long long i, j = 0; unsigned char u; unsigned long long v = 0, vbits = 0; for (i = 0; i < inlen; ++i) { if (in[j] & 0x80) return 0; u = base32values[in[i]]; if (u > 0x1f) return 0; v |= u << vbits; vbits += 5; if (vbits >= 8) { if (j >= outlen) return 0; out[j++] = v; vbits -= 8; v >>= 8; } } if (vbits) { if (j >= outlen) return 0; out[j++] = v; } return 1; } dq-20240101/base32decode.h000066400000000000000000000002301454446775700147670ustar00rootroot00000000000000#ifndef _BASE32DECODE_H____ #define _BASE32DECODE_H____ extern int base32decode(unsigned char *, long long, const unsigned char *, long long); #endif dq-20240101/blocking.c000066400000000000000000000004431454446775700143350ustar00rootroot00000000000000/* taken from nacl-20110221, from curvecp/blocking.c (public domain) */ #include #include "blocking.h" void blocking_enable(int fd) { fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); } void blocking_disable(int fd) { fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); } dq-20240101/blocking.h000066400000000000000000000001641454446775700143420ustar00rootroot00000000000000#ifndef BLOCKING_H #define BLOCKING_H extern void blocking_enable(int); extern void blocking_disable(int); #endif dq-20240101/buffer.c000066400000000000000000000003101454446775700140070ustar00rootroot00000000000000#include "buffer.h" void buffer_init(buffer *s, long long (*op)(), int fd, char *buf, long long len) { s->x = buf; s->fd = fd; s->op = op; s->p = 0; s->n = len; return; } dq-20240101/buffer.h000066400000000000000000000034331454446775700140250ustar00rootroot00000000000000#ifndef _BUFFER_H____ #define _BUFFER_H____ typedef struct buffer { char *x; long long p; long long n; int fd; long long (*op)(); } buffer; #define BUFFER_INIT(op, fd, buf, len) { (buf), 0, (len), (fd), (op) } #define BUFFER_INSIZE 8192 #define BUFFER_OUTSIZE 8192 #define BUFFER_ERRSIZE 256 extern void buffer_init(buffer *, long long (*op)(), int, char *, long long); extern int buffer_flush(buffer *); extern int buffer_putalign(buffer *, const char *, long long); extern int buffer_put(buffer *, const char *, long long); extern int buffer_putflush(buffer *, const char *, long long); extern int buffer_putsalign(buffer *, const char *); extern int buffer_puts(buffer *, const char *); extern int buffer_putsflush(buffer *, const char *); #define buffer_PUTC(s,c) \ ( ((s)->n != (s)->p) \ ? ( (s)->x[(s)->p++] = (c), 0 ) \ : buffer_put((s),&(c),1) \ ) extern long long buffer_get(buffer *, char *, long long); extern long long buffer_bget(buffer *, char *, long long); extern long long buffer_feed(buffer *); extern char *buffer_peek(buffer *); extern void buffer_seek(buffer *, long long); #define buffer_PEEK(s) ( (s)->x + (s)->n ) #define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) #define buffer_GETC(s,c) \ ( ((s)->p > 0) \ ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \ : buffer_get((s),(c),1) \ ) extern int buffer_copy(buffer *,buffer *); extern long long buffer_unixread(int, char *, long long); extern long long buffer_unixwrite(int, const char *, long long); #define buffer_PEEK(s) ( (s)->x + (s)->n ) #define buffer_SEEK(s, len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) extern buffer *buffer_0; extern buffer *buffer_0small; extern buffer *buffer_1; extern buffer *buffer_1small; extern buffer *buffer_2; #endif dq-20240101/buffer_2.c000066400000000000000000000002561454446775700142410ustar00rootroot00000000000000#include "buffer.h" char buffer_2_space[BUFFER_ERRSIZE]; static buffer it = BUFFER_INIT(buffer_unixwrite, 2, buffer_2_space, sizeof buffer_2_space); buffer *buffer_2 = ⁢ dq-20240101/buffer_put.c000066400000000000000000000042321454446775700147060ustar00rootroot00000000000000#include "e.h" #include "str.h" #include "byte.h" #include "buffer.h" static int allwrite(long long (*op)(int, const char *, long long), int fd, const char *buf, long long len) { long long w; if (!buf || len < 0) { errno = EINVAL; return -1; } while (len > 0) { w = op(fd, buf, len); if (w == -1) { if (errno == EINTR) continue; if (errno == EAGAIN) continue; if (errno == EWOULDBLOCK) continue; return -1; } buf += w; len -= w; } return 0; } int buffer_flush(buffer *s) { long long p; p = s->p; if (!p) return 0; s->p = 0; return allwrite(s->op, s->fd, s->x, p); } int buffer_putalign(buffer *s, const char *buf, long long len) { long long n; if (!buf || len < 0) { errno = EINVAL; return -1; } while (len > (n = s->n - s->p)) { byte_copy(s->x + s->p, n, buf); s->p += n; buf += n; len -= n; s->p += n; buf += n; len -= n; if (buffer_flush(s) == -1) return -1; } /* now len <= s->n - s->p */ byte_copy(s->x + s->p, len, buf); s->p += len; return 0; } int buffer_put(buffer *s, const char *buf, long long len) { long long n; if (!buf || len < 0) { errno = EINVAL; return -1; } n = s->n; if (len > n - s->p) { if (buffer_flush(s) == -1) return -1; /* now s->p == 0 */ if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE; while (len > s->n) { if (n > len) n = len; if (allwrite(s->op, s->fd, buf, n) == -1) return -1; buf += n; len -= n; } } /* now len <= s->n - s->p */ byte_copy(s->x + s->p, len, buf); s->p += len; return 0; } int buffer_putflush(buffer *s, const char *buf, long long len) { if (buffer_flush(s) == -1) return -1; return allwrite(s->op, s->fd, buf, len); } int buffer_putsalign(buffer *s, const char *buf) { return buffer_putalign(s, buf, str_len(buf)); } int buffer_puts(buffer *s, const char *buf) { return buffer_put(s, buf, str_len(buf)); } int buffer_putsflush(buffer *s, const char *buf) { return buffer_putflush(s, buf, str_len(buf)); } dq-20240101/buffer_write.c000066400000000000000000000002641454446775700152310ustar00rootroot00000000000000#include "writeall.h" #include "buffer.h" long long buffer_unixwrite(int fd, const char *x, long long xlen) { if (writeall(fd, x, xlen) == -1) return -1; return xlen; } dq-20240101/byte.c000066400000000000000000000031401454446775700135050ustar00rootroot00000000000000/* 20130505 Jan Mojzis Public domain. */ #include "byte.h" void byte_copy(void *yv, long long ylen, const void *xv) { long long i; const char *x = xv; char *y = yv; for (i = 0; i < ylen; ++i) y[i] = x[i]; } void byte_copyr(void *yv, long long ylen, const void *xv) { long long i; const char *x = xv; char *y = yv; for (i = ylen - 1; i >= 0; --i) y[i] = x[i]; } long long byte_chr(const void *yv, long long ylen, int c) { long long i; const char *y = yv; char ch = c; if (ylen <= 0) return ylen; for (i = 0; i < ylen; ++i) if (y[i] == ch) break; return i; } long long byte_rchr(const void *yv, long long ylen, int c) { long long i, u = -1; const char *y = yv; char ch = c; if (ylen <= 0) return ylen; for (i = ylen - 1; i >= 0; --i) if (y[i] == ch) { u = i; break; } if (u == -1) return ylen; return u; } void byte_zero(void *yv, long long ylen) { long long i; char *y = yv; for (i = 0; i < ylen; ++i) y[i] = 0; } int byte_isequal(const void *yv, long long ylen, const void *xv) { long long i; const unsigned char *y = yv; const unsigned char *x = xv; unsigned char diff = 0; for (i = 0; i < ylen; ++i) diff |= x[i] ^ y[i]; return (256 - (unsigned int) diff) >> 8; } int byte_diff(const void *yv, long long ylen, const void *xv) { long long i; const unsigned char *y = yv; const unsigned char *x = xv; for (i = 0; i < ylen; ++i) { if (x[i] == y[i]) continue; return ((int)(unsigned int)y[i]) - ((int)(unsigned int)x[i]); } return 0; } dq-20240101/byte.h000066400000000000000000000006131454446775700135140ustar00rootroot00000000000000#ifndef _BYTE_H____ #define _BYTE_H____ void byte_copy(void *, long long, const void *); void byte_copyr(void *, long long, const void *); long long byte_chr(const void *, long long, int); long long byte_rchr(const void *, long long, int); void byte_zero(void *, long long); int byte_isequal(const void *, long long, const void *); int byte_diff(const void *, long long, const void *); #endif dq-20240101/cache.c000066400000000000000000000206061454446775700136130ustar00rootroot00000000000000#include #include #include #include #include "alloc.h" #include "byte.h" #include "uint64_pack.h" #include "uint64_unpack.h" #include "uint32_pack.h" #include "uint32_unpack.h" #include "seconds.h" #include "die.h" #include "randombytes.h" #include "buffer.h" #include "open.h" #include "dns.h" #include "crypto_auth_siphash24.h" #include "e.h" #include "cache.h" crypto_uint64 cache_motion = 0; crypto_uint64 cache_hit = 0; crypto_uint64 cache_miss = 0; static unsigned char *x = 0; static crypto_uint32 size; static crypto_uint32 hsize; static crypto_uint32 writer; static crypto_uint32 oldest; static crypto_uint32 unused; static unsigned char hashkey[crypto_auth_siphash24_KEYBYTES]; /* 100 <= size <= 3000000000. 4 <= hsize <= size/16. hsize is a power of 2. hsize <= writer <= oldest <= unused <= size. If oldest == unused then unused == size. x is a hash table with the following structure: x[0...hsize-1]: hsize/4 head links. x[hsize...writer-1]: consecutive entries, newest entry on the right. x[writer...oldest-1]: free space for new entries. x[oldest...unused-1]: consecutive entries, oldest entry on the left. x[unused...size-1]: unused. Each hash bucket is a linked list containing the following items: the head link, the newest entry, the second-newest entry, etc. Each link is a 4-byte number giving the xor of the positions of the adjacent items in the list. Entries are always inserted immediately after the head and removed at the tail. Each entry contains the following information: 4-byte link; 4-byte keylen; 4-byte datalen; 8-byte expire time; key; data. */ #define MAXKEYLEN 1000 #define MAXDATALEN 1000000 static void cache_impossible(void) { die_0(111); } static void set4(crypto_uint32 pos, crypto_uint32 u) { if (pos > size - 4) cache_impossible(); uint32_pack(x + pos, u); } static crypto_uint32 get4(crypto_uint32 pos) { crypto_uint32 result; if (pos > size - 4) cache_impossible(); result = uint32_unpack(x + pos); return result; } #if 0 static crypto_uint32 hash(const unsigned char *key, crypto_uint32 keylen) { unsigned int result = 5381; while (keylen) { result = (result << 5) + result; result ^= (unsigned char) *key; ++key; --keylen; } result <<= 2; result &= hsize - 4; return result; } #else static crypto_uint32 hash(const unsigned char *key, crypto_uint32 keylen) { unsigned char a[crypto_auth_siphash24_BYTES]; crypto_auth_siphash24(a, key, keylen, hashkey); return (uint32_unpack(a) & (hsize - 4)); } #endif unsigned char *cache_get(const unsigned char *key, long long keylen, long long *datalen, long long *ttl, unsigned char *flags) { crypto_uint32 pos; crypto_uint32 prevpos; crypto_uint32 nextpos; crypto_uint32 u; long long loop; long long xttl; unsigned char dummy; unsigned char expirestr[8]; if (!flags) flags = &dummy; if (!x) return 0; if (keylen > MAXKEYLEN) return 0; prevpos = hash(key, keylen); pos = get4(prevpos); loop = 0; *ttl = 0; while (pos) { if (get4(pos + 4) == keylen) { if (pos + 20 + keylen > size) cache_impossible(); if (byte_isequal(key, keylen, x + pos + 20)) { byte_copy(expirestr, 8, x + pos + 12); *flags = expirestr[7]; expirestr[7] = 0; xttl = uint64_unpack(expirestr) - seconds(); if (xttl <= 0) return 0; if (xttl > 604800) xttl = 604800; *ttl = xttl; u = get4(pos + 8); if (u > size - pos - 20 - keylen) cache_impossible(); *datalen = u; ++cache_hit; return x + pos + 20 + keylen; } } nextpos = prevpos ^ get4(pos); prevpos = pos; pos = nextpos; if (++loop > 100) { ++cache_miss; return 0; } /* to protect against hash flooding */ } ++cache_miss; return 0; } void cache_set(const unsigned char *key, long long keylen, const unsigned char *data, long long datalen, long long ttl, unsigned char flags) { crypto_uint32 entrylen; crypto_uint32 keyhash; crypto_uint32 pos; if (!x) return; if (keylen > MAXKEYLEN || keylen < 0) return; if (datalen > MAXDATALEN || datalen < 0) return; if (ttl <= 0) return; if (ttl > 604800) ttl = 604800; entrylen = keylen + datalen + 20; while (writer + entrylen > oldest) { if (oldest == unused) { if (writer <= hsize) return; unused = writer; oldest = hsize; writer = hsize; } pos = get4(oldest); set4(pos,get4(pos) ^ oldest); oldest += get4(oldest + 4) + get4(oldest + 8) + 20; if (oldest > unused) cache_impossible(); if (oldest == unused) { unused = size; oldest = size; } } keyhash = hash(key, keylen); pos = get4(keyhash); if (pos) set4(pos,get4(pos) ^ keyhash ^ writer); set4(writer,pos ^ keyhash); set4(writer + 4, keylen); set4(writer + 8, datalen); uint64_pack(x + writer + 12, seconds() + ttl); x[writer + 12 + 7] = flags; byte_copy(x + writer + 20, keylen, key); byte_copy(x + writer + 20 + keylen, datalen, data); set4(keyhash, writer); writer += entrylen; cache_motion += entrylen; } int cache_init(long long cachesize) { randombytes(hashkey, sizeof hashkey); if (x) { alloc_free(x); x = 0; } if (cachesize > 3000000000LL) cachesize = 3000000000LL; if (cachesize < 100) cachesize = 100; size = cachesize; hsize = 4; while (hsize <= (size >> 5)) hsize <<= 1; x = alloc(size); if (!x) return 0; byte_zero(x, size); writer = hsize; oldest = size; unused = size; return 1; } static const char fn[]="dump/dnsdata"; static const char fntmp[]="dump/dnsdata.tmp"; char bspace[8096]; buffer b; void cache_clean(void) { unlink(fn); die_0(0); } int cache_dump(void) { crypto_uint32 pos; long long len; int r; int fd; fd = open_trunc(fntmp); if (fd == -1) return -1; buffer_init(&b, buffer_unixwrite, fd, bspace, sizeof bspace); pos = oldest; while (pos < unused) { len = get4(pos + 4) + get4(pos + 8) + 16; if (byte_diff(x + pos + 20, 2, DNS_T_AXFR)){ if (byte_diff(x + pos + 20, 2, DNS_T_ANY)){ r = buffer_put(&b, (char *)x + pos + 4, len); if (r == -1) { close(fd); return -1; } } } pos += 4 + len; } pos = hsize; while (pos < writer) { len = get4(pos + 4) + get4(pos + 8) + 16; if (byte_diff(x + pos + 20, 2, DNS_T_AXFR)){ if (byte_diff(x + pos + 20, 2, DNS_T_ANY)){ r = buffer_put(&b, (char *)x + pos + 4, len); if (r == -1) { close(fd); return -1; } } } pos += 4 + len; } if (buffer_flush(&b) == -1) { close(fd); return -1; } if (fsync(fd) == -1) { close(fd); return -1; } if (close(fd) == -1) return -1; if (chmod(fntmp, 0600) == -1) return -1; if (rename(fntmp,fn) == -1) return -1; return 0; } int cache_load(void) { unsigned char *p, *xx; crypto_uint32 pos; long long len; crypto_uint32 keylen; crypto_uint32 datalen; int nb; struct stat st; int fd; int flags = 0; long long now, expire; unsigned char expirestr[8]; fd = open_read(fn); if (fd == -1) { if (errno == ENOENT) return 0; return -1; } if (fstat(fd,&st) == -1) { close(fd); return -1; } if (st.st_size == 0) { close(fd); return 0; } xx = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (xx == MAP_FAILED) {close(fd); return -1;} len = st.st_size; p = xx; now = seconds(); pos = 0; nb = 0; while (pos + 16 <= len) { keylen = uint32_unpack(p + pos); datalen = uint32_unpack(p + pos + 4); byte_copy(expirestr, 8, p + pos + 8); flags = expirestr[7]; expirestr[7] = 0; expire = uint64_unpack(expirestr) - now; pos += 16; if (pos + keylen + datalen > len) break; /* missing data */ if (expire > 0) { cache_set(p + pos, keylen, p + pos + keylen, datalen, expire, flags); } pos += keylen + datalen; nb++; } munmap(xx, st.st_size); close(fd); return 0; } dq-20240101/cache.h000066400000000000000000000006221454446775700136140ustar00rootroot00000000000000#ifndef _CACHE_H____ #define _CACHE_H____ extern int cache_init(long long); extern void cache_set(const unsigned char *, long long, const unsigned char *, long long, long long, unsigned char); extern unsigned char *cache_get(const unsigned char *, long long, long long *, long long *, unsigned char *); extern void cache_clean(void); extern int cache_dump(void); extern int cache_load(void); #endif dq-20240101/case.c000066400000000000000000000021021454446775700134520ustar00rootroot00000000000000#include "case.h" int case_diffb(const void *yv, long long ylen, const void *xv) { unsigned char a, b; const unsigned char *y = yv; const unsigned char *x = xv; while (ylen > 0) { a = *x++ - 'A'; b = *y++ - 'A'; --ylen; if (a <= 'Z' - 'A') a += 'a'; else a += 'A'; if (b <= 'Z' - 'A') b += 'a'; else b += 'A'; if (a != b) return ((int)(unsigned int)b) - ((int)(unsigned int)a); } return 0; } int case_diffs(const void *yv, const void *xv) { unsigned char a, b; const unsigned char *y = yv; const unsigned char *x = xv; for (;;) { a = *x++ - 'A'; b = *y++ - 'A'; if (a <= 'Z' - 'A') a += 'a'; else a += 'A'; if (b <= 'Z' - 'A') b += 'a'; else b += 'A'; if (a != b) break; if (!a) break; } return ((int)(unsigned int)b) - ((int)(unsigned int)a); } void case_lowerb(void *xv, long long len) { unsigned char *x = xv; unsigned char y; while (len > 0) { --len; y = *x - 'A'; if (y <= 'Z' - 'A') *x = y + 'a'; ++x; } } dq-20240101/case.h000066400000000000000000000004001454446775700134560ustar00rootroot00000000000000#ifndef _CASE_H____ #define _CASE_H____ extern int case_diffb(const void *, long long, const void *); extern int case_diffs(const void *, const void *); extern void case_lowerb(void *, long long); #define case_equals(s,t) (!case_diffs((s),(t))) #endif dq-20240101/cleanup.c000066400000000000000000000003171454446775700141740ustar00rootroot00000000000000#include "cleanup.h" void cleanup_(void *yv, long long ylen) { volatile char *y = (volatile char *)yv; while (ylen > 0) { *y++ = 0; --ylen; } __asm__ __volatile__("" : : "r"(yv) : "memory"); } dq-20240101/cleanup.h000066400000000000000000000002141454446775700141750ustar00rootroot00000000000000#ifndef _CLEANUP_H____ #define _CLEANUP_H____ extern void cleanup_(void *, long long); #define cleanup(x) cleanup_((x), sizeof(x)) #endif dq-20240101/crypto_auth_siphash24.c000066400000000000000000000010011454446775700167620ustar00rootroot00000000000000#include "siphash.h" #include "crypto_verify_8.h" #include "crypto_auth_siphash24.h" int crypto_auth_siphash24_tinynacl(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *k) { return siphash(out, in, inlen, k, 2, 4); } int crypto_auth_siphash24_tinynacl_verify(const unsigned char *h, const unsigned char *m, unsigned long long n, const unsigned char *k) { unsigned char x[8]; crypto_auth_siphash24_tinynacl(x, m, n, k); return crypto_verify_8(h, x); } dq-20240101/crypto_auth_siphash24.h000066400000000000000000000014611454446775700170010ustar00rootroot00000000000000#ifndef crypto_auth_siphash24_H #define crypto_auth_siphash24_H #define crypto_auth_siphash24_tinynacl_BYTES 8 #define crypto_auth_siphash24_tinynacl_KEYBYTES 16 extern int crypto_auth_siphash24_tinynacl(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); extern int crypto_auth_siphash24_tinynacl_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); #define crypto_auth_siphash24 crypto_auth_siphash24_tinynacl #define crypto_auth_siphash24_verify crypto_auth_siphash24_tinynacl_verify #define crypto_auth_siphash24_BYTES crypto_auth_siphash24_tinynacl_BYTES #define crypto_auth_siphash24_KEYBYTES crypto_auth_siphash24_tinynacl_KEYBYTES #define crypto_auth_siphash24_IMPLEMENTATION "tinynacl" #define crypto_auth_siphash24_VERSION "-" #endif dq-20240101/crypto_box_curve25519xsalsa20poly1305.c000066400000000000000000000037261454446775700213510ustar00rootroot00000000000000#include "crypto_core_hsalsa20.h" #include "crypto_scalarmult_curve25519.h" #include "crypto_secretbox_xsalsa20poly1305.h" #include "randombytes.h" #include "crypto_box_curve25519xsalsa20poly1305.h" static const unsigned char zero[16] = {0}; static const unsigned char sigma[16] = "expand 32-byte k"; int crypto_box_curve25519xsalsa20poly1305_tinynacl_beforenm( unsigned char *k, const unsigned char *pk, const unsigned char *sk ) { unsigned char s[32]; crypto_scalarmult_curve25519(s,sk,pk); return crypto_core_hsalsa20(k, zero, s, sigma); } int crypto_box_curve25519xsalsa20poly1305_tinynacl_afternm( unsigned char *c, const unsigned char *m,unsigned long long mlen, const unsigned char *n, const unsigned char *k ) { return crypto_secretbox_xsalsa20poly1305(c,m,mlen,n,k); } int crypto_box_curve25519xsalsa20poly1305_tinynacl_open_afternm( unsigned char *m, const unsigned char *c,unsigned long long clen, const unsigned char *n, const unsigned char *k ) { return crypto_secretbox_xsalsa20poly1305_open(m,c,clen,n,k); } int crypto_box_curve25519xsalsa20poly1305_tinynacl( unsigned char *c, const unsigned char *m,unsigned long long mlen, const unsigned char *n, const unsigned char *pk, const unsigned char *sk ) { unsigned char k[32]; crypto_box_curve25519xsalsa20poly1305_tinynacl_beforenm(k,pk,sk); return crypto_box_curve25519xsalsa20poly1305_tinynacl_afternm(c,m,mlen,n,k); } int crypto_box_curve25519xsalsa20poly1305_tinynacl_open( unsigned char *m, const unsigned char *c,unsigned long long clen, const unsigned char *n, const unsigned char *pk, const unsigned char *sk ) { unsigned char k[32]; crypto_box_curve25519xsalsa20poly1305_tinynacl_beforenm(k,pk,sk); return crypto_box_curve25519xsalsa20poly1305_tinynacl_open_afternm(m,c,clen,n,k); } int crypto_box_curve25519xsalsa20poly1305_tinynacl_keypair( unsigned char *pk, unsigned char *sk ) { randombytes(sk,32); return crypto_scalarmult_curve25519_base(pk,sk); } dq-20240101/crypto_box_curve25519xsalsa20poly1305.h000066400000000000000000000056231454446775700213540ustar00rootroot00000000000000#ifndef crypto_box_curve25519xsalsa20poly1305_H #define crypto_box_curve25519xsalsa20poly1305_H #define crypto_box_curve25519xsalsa20poly1305_tinynacl_PUBLICKEYBYTES 32 #define crypto_box_curve25519xsalsa20poly1305_tinynacl_SECRETKEYBYTES 32 #define crypto_box_curve25519xsalsa20poly1305_tinynacl_BEFORENMBYTES 32 #define crypto_box_curve25519xsalsa20poly1305_tinynacl_NONCEBYTES 24 #define crypto_box_curve25519xsalsa20poly1305_tinynacl_ZEROBYTES 32 #define crypto_box_curve25519xsalsa20poly1305_tinynacl_BOXZEROBYTES 16 extern int crypto_box_curve25519xsalsa20poly1305_tinynacl(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tinynacl_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tinynacl_keypair(unsigned char *,unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tinynacl_beforenm(unsigned char *,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tinynacl_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); extern int crypto_box_curve25519xsalsa20poly1305_tinynacl_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); #define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tinynacl #define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tinynacl_open #define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tinynacl_keypair #define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tinynacl_beforenm #define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tinynacl_afternm #define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tinynacl_open_afternm #define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tinynacl_PUBLICKEYBYTES #define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tinynacl_SECRETKEYBYTES #define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tinynacl_BEFORENMBYTES #define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tinynacl_NONCEBYTES #define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tinynacl_ZEROBYTES #define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tinynacl_BOXZEROBYTES #define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "tinynacl" #define crypto_box_curve25519xsalsa20poly1305_VERSION "-" #endif dq-20240101/crypto_core_hsalsa20.c000066400000000000000000000010641454446775700165720ustar00rootroot00000000000000#include "salsa.h" #include "uint32_unpack.h" #include "cleanup.h" #include "crypto_core_hsalsa20.h" int crypto_core_hsalsa20_tinynacl(unsigned char *o, const unsigned char *nn, const unsigned char *kk, const unsigned char *cc) { crypto_uint32 k[8], n[4], c[4]; long long i; for (i = 0; i < 8; ++i) k[i] = uint32_unpack(kk + 4 * i); for (i = 0; i < 4; ++i) n[i] = uint32_unpack(nn + 4 * i); for (i = 0; i < 4; ++i) c[i] = uint32_unpack(cc + 4 * i); salsa_core(o, n, k, c, 1, 20); cleanup(k); cleanup(n); cleanup(c); return 0; } dq-20240101/crypto_core_hsalsa20.h000066400000000000000000000015611454446775700166010ustar00rootroot00000000000000#ifndef crypto_core_hsalsa20_H #define crypto_core_hsalsa20_H #define crypto_core_hsalsa20_tinynacl_OUTPUTBYTES 32 #define crypto_core_hsalsa20_tinynacl_INPUTBYTES 16 #define crypto_core_hsalsa20_tinynacl_KEYBYTES 32 #define crypto_core_hsalsa20_tinynacl_CONSTBYTES 16 extern int crypto_core_hsalsa20_tinynacl(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); #define crypto_core_hsalsa20 crypto_core_hsalsa20_tinynacl #define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tinynacl_OUTPUTBYTES #define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tinynacl_INPUTBYTES #define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tinynacl_KEYBYTES #define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tinynacl_CONSTBYTES #define crypto_core_hsalsa20_IMPLEMENTATION "tinynacl" #define crypto_core_hsalsa20_VERSION "-" #endif dq-20240101/crypto_onetimeauth_poly1305.c000066400000000000000000000131341454446775700200440ustar00rootroot00000000000000/* 20200202 */ /* Based on poly1305-donna (https://github.com/floodyberry/poly1305-opt/blob/master/extensions/poly1305_ref-32.c) - modified for NaCl API */ #include "crypto_onetimeauth_poly1305.h" /* clang-format off */ static inline unsigned long unpack32(const unsigned char *x) { return (unsigned long) (x[0]) \ | (((unsigned long) (x[1])) << 8) \ | (((unsigned long) (x[2])) << 16) \ | (((unsigned long) (x[3])) << 24); } static inline void pack32(unsigned char *x, unsigned long u) { x[0] = u; u >>= 8; x[1] = u; u >>= 8; x[2] = u; u >>= 8; x[3] = u; } int crypto_onetimeauth_poly1305_tinynacl(unsigned char *o, const unsigned char *m, unsigned long long n, const unsigned char *k) { unsigned long h0, h1, h2, h3, h4; unsigned long r0, r1, r2, r3, r4; unsigned long s1, s2, s3, s4; unsigned long long d0, d1, d2, d3, d4; unsigned long c, mask; unsigned long long f; long long i; /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ r0 = (unpack32(k + 0) ) & 0x3ffffff; r1 = (unpack32(k + 3) >> 2) & 0x3ffff03; r2 = (unpack32(k + 6) >> 4) & 0x3ffc0ff; r3 = (unpack32(k + 9) >> 6) & 0x3f03fff; r4 = (unpack32(k + 12) >> 8) & 0x00fffff; s1 = r1 * 5; s2 = r2 * 5; s3 = r3 * 5; s4 = r4 * 5; /* h = 0 */ h0 = h1 = h2 = h3 = h4 = 0; while (n > 0) { /* h += m[i] */ if (n >= 16) { h0 += (unpack32(m ) ) & 0x3ffffff; h1 += (unpack32(m + 3) >> 2) & 0x3ffffff; h2 += (unpack32(m + 6) >> 4) & 0x3ffffff; h3 += (unpack32(m + 9) >> 6) & 0x3ffffff; h4 += (unpack32(m + 12) >> 8) | 16777216; m += 16; n -= 16; } else { unsigned char mm[16]; for (i = 0; i < 16; ++i) mm[i] = 0; for (i = 0; i < n; ++i) mm[i] = m[i]; mm[i] = 1; h0 += (unpack32(mm ) ) & 0x3ffffff; h1 += (unpack32(mm + 3) >> 2) & 0x3ffffff; h2 += (unpack32(mm + 6) >> 4) & 0x3ffffff; h3 += (unpack32(mm + 9) >> 6) & 0x3ffffff; h4 += (unpack32(mm + 12) >> 8); n = 0; } /* h *= r */ d0 = ((unsigned long long)h0 * r0) + ((unsigned long long)h1 * s4) + ((unsigned long long)h2 * s3) + ((unsigned long long)h3 * s2) + ((unsigned long long)h4 * s1); d1 = ((unsigned long long)h0 * r1) + ((unsigned long long)h1 * r0) + ((unsigned long long)h2 * s4) + ((unsigned long long)h3 * s3) + ((unsigned long long)h4 * s2); d2 = ((unsigned long long)h0 * r2) + ((unsigned long long)h1 * r1) + ((unsigned long long)h2 * r0) + ((unsigned long long)h3 * s4) + ((unsigned long long)h4 * s3); d3 = ((unsigned long long)h0 * r3) + ((unsigned long long)h1 * r2) + ((unsigned long long)h2 * r1) + ((unsigned long long)h3 * r0) + ((unsigned long long)h4 * s4); d4 = ((unsigned long long)h0 * r4) + ((unsigned long long)h1 * r3) + ((unsigned long long)h2 * r2) + ((unsigned long long)h3 * r1) + ((unsigned long long)h4 * r0); /* (partial) h %= p */ c = (unsigned long)(d0 >> 26); h0 = (unsigned long)d0 & 0x3ffffff; d1 += c; c = (unsigned long)(d1 >> 26); h1 = (unsigned long)d1 & 0x3ffffff; d2 += c; c = (unsigned long)(d2 >> 26); h2 = (unsigned long)d2 & 0x3ffffff; d3 += c; c = (unsigned long)(d3 >> 26); h3 = (unsigned long)d3 & 0x3ffffff; d4 += c; c = (unsigned long)(d4 >> 26); h4 = (unsigned long)d4 & 0x3ffffff; h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; h1 += c; } /* fully carry h */ c = h1 >> 26; h1 = h1 & 0x3ffffff; h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += c; /* compute h + -p */ r0 = h0 + 5; c = r0 >> 26; r0 &= 0x3ffffff; r1 = h1 + c; c = r1 >> 26; r1 &= 0x3ffffff; r2 = h2 + c; c = r2 >> 26; r2 &= 0x3ffffff; r3 = h3 + c; c = r3 >> 26; r3 &= 0x3ffffff; r4 = h4 + c - (1 << 26); /* select h if h < p, or h + -p if h >= p */ mask = (r4 >> ((sizeof(unsigned long) * 8) - 1)) - 1; r0 &= mask; r1 &= mask; r2 &= mask; r3 &= mask; r4 &= mask; mask = ~mask; h0 = (h0 & mask) | r0; h1 = (h1 & mask) | r1; h2 = (h2 & mask) | r2; h3 = (h3 & mask) | r3; h4 = (h4 & mask) | r4; /* h = h % (2^128) */ h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; /* mac = (h + pad) % (2^128) */ f = (unsigned long long)h0 + unpack32(k + 16) ; h0 = (unsigned long)f; f = (unsigned long long)h1 + unpack32(k + 20) + (f >> 32); h1 = (unsigned long)f; f = (unsigned long long)h2 + unpack32(k + 24) + (f >> 32); h2 = (unsigned long)f; f = (unsigned long long)h3 + unpack32(k + 28) + (f >> 32); h3 = (unsigned long)f; pack32(o + 0, h0); pack32(o + 4, h1); pack32(o + 8, h2); pack32(o + 12, h3); return 0; } int crypto_onetimeauth_poly1305_tinynacl_verify(const unsigned char *h, const unsigned char *in, unsigned long long l, const unsigned char *k) { unsigned char correct[16]; unsigned int d = 0; long long i; crypto_onetimeauth_poly1305(correct, in, l, k); for (i = 0; i < 16; ++i) d |= correct[i] ^ h[i]; return (1 & ((d - 1) >> 8)) - 1; } /* clang-format on */ dq-20240101/crypto_onetimeauth_poly1305.h000066400000000000000000000016221454446775700200500ustar00rootroot00000000000000#ifndef crypto_onetimeauth_poly1305_H #define crypto_onetimeauth_poly1305_H #define crypto_onetimeauth_poly1305_tinynacl_BYTES 16 #define crypto_onetimeauth_poly1305_tinynacl_KEYBYTES 32 extern int crypto_onetimeauth_poly1305_tinynacl(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); extern int crypto_onetimeauth_poly1305_tinynacl_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *); #define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tinynacl #define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tinynacl_verify #define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tinynacl_BYTES #define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tinynacl_KEYBYTES #define crypto_onetimeauth_poly1305_IMPLEMENTATION "tinynacl" #define crypto_onetimeauth_poly1305_VERSION "-" #endif dq-20240101/crypto_scalarmult_curve25519.c000066400000000000000000000217271454446775700201360ustar00rootroot00000000000000/* 20180104 Jan Mojzis Public domain. */ #include "crypto_scalarmult_curve25519.h" typedef unsigned long fe[8]; /* o = x */ static void fe_copy(fe o, const fe x) { long long i; for (i = 0; i < 8; ++i) o[i] = x[i]; } /* o = 0 */ static void fe_0(fe o) { long long i; for (i = 0; i < 8; ++i) o[i] = 0; } /* o = 1 */ static void fe_1(fe o) { fe_0(o); o[0] = 1; } /* if (b) swap(f, g) */ static void fe_cswap(fe f, fe g, unsigned long b) { long long i; fe t; b = -b; for (i = 0; i < 8; ++i) t[i] = b & (f[i] ^ g[i]); for (i = 0; i < 8; ++i) f[i] ^= t[i]; for (i = 0; i < 8; ++i) g[i] ^= t[i]; } static unsigned long uint32_unpack(const unsigned char *x) { unsigned long y = 0; long long i; for (i = 3; i >= 0; --i) y = (y << 8) | x[i]; return y; } static void fe_frombytes(fe out, const unsigned char *in) { long long i; /* unpack from little-endian format */ for (i = 0; i < 8; ++i) out[i] = uint32_unpack(in + 4 * i); out[7] &= 0x7fffffff; } static void uint32_pack(unsigned char *y, unsigned long x) { long long i; for (i = 0; i < 4; ++i) { y[i] = x; x >>= 8; } } /* select r if r < p, or r + -p if r >= p */ static void fe_squeeze(fe r) { unsigned long long pb = 0, b; long long i; fe t; const unsigned long long p[8] = { 0xffffffedULL, 0xffffffffULL, 0xffffffffULL, 0xffffffffULL, 0xffffffffULL, 0xffffffffULL, 0xffffffffULL, 0x7fffffffULL, }; for (i = 0; i < 8; ++i) { pb += p[i]; b = (unsigned long long)r[i] - pb; b >>= (sizeof(unsigned long long) * 8) - 1; t[i] = (unsigned long long)r[i] - pb + (b << 32); pb = b; } b = - pb; b >>= (sizeof(unsigned long long) * 8) - 1; b -= 1; for (i = 0; i < 8; ++i) r[i] ^= b & (r[i] ^ t[i]); } static void fe_tobytes(unsigned char *out, const fe in) { fe r; long long i; fe_copy(r, in); fe_squeeze(r); for (i = 0; i < 8; ++i) uint32_pack(out + 4 * i, r[i]); } /* o = (x * c) % p */ static void fe_mulc(fe o, const fe x, const unsigned long long c) { unsigned long long u = 0; long long i; for (i = 0; i < 7; ++i) { u += (unsigned long long)x[i] * c; o[i] = u & 0xffffffff; u >>= 32; } u += (unsigned long long)x[i] * c; o[i] = u & 0x7fffffff; u >>= 31; u *= 19ULL; for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; } } /* o = (a * b) % p */ static void fe_mul(fe o, const fe a, const fe b) { unsigned long long u, t[16]; long long i; for (i = 0; i < 16; ++i) t[i] = 0; /* Unrolled version of: for (i = 0; i < 8; ++i) for (j = 0; j < 8; ++j) { u = (unsigned long long)a[i] * (unsigned long long)b[j]; t[i + j ] += u & 0xffffffff; t[i + j + 1] += u >> 32; } */ #define M(i, j) u = (unsigned long long)a[i] * (unsigned long long)b[j]; \ t[i + j ] += u & 0xffffffff; \ t[i + j + 1] += u >> 32; M(0, 0); M(0, 1); M(0, 2); M(0, 3); M(0, 4); M(0, 5); M(0, 6); M(0, 7); M(1, 0); M(1, 1); M(1, 2); M(1, 3); M(1, 4); M(1, 5); M(1, 6); M(1, 7); M(2, 0); M(2, 1); M(2, 2); M(2, 3); M(2, 4); M(2, 5); M(2, 6); M(2, 7); M(3, 0); M(3, 1); M(3, 2); M(3, 3); M(3, 4); M(3, 5); M(3, 6); M(3, 7); M(4, 0); M(4, 1); M(4, 2); M(4, 3); M(4, 4); M(4, 5); M(4, 6); M(4, 7); M(5, 0); M(5, 1); M(5, 2); M(5, 3); M(5, 4); M(5, 5); M(5, 6); M(5, 7); M(6, 0); M(6, 1); M(6, 2); M(6, 3); M(6, 4); M(6, 5); M(6, 6); M(6, 7); M(7, 0); M(7, 1); M(7, 2); M(7, 3); M(7, 4); M(7, 5); M(7, 6); M(7, 7); #undef M u = 0; for (i = 0; i < 7; ++i) { u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0xffffffff; u >>= 32; } u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0x7fffffff; u >>= 31; u *= 19ULL; for (i = 0; i < 8; ++i) { u += t[i]; o[i] = u & 0xffffffff; u >>= 32; } } /* o = (x ^ 2) % p */ static void fe_sq(fe o, const fe a) { unsigned long long u, t[16]; long long i; for (i = 0; i < 16; ++i) t[i] = 0; /* Unrolled version of: for (i = 0; i < 8; ++i) for (j = i + 1; j < 8; ++j) { u = (unsigned long long)a[i] * (unsigned long long)a[j]; t[i + j ] += 2 * (u & 0xffffffff); t[i + j + 1] += 2 * (u >> 32); } for (i = 0; i < 8; ++i) { u = (unsigned long long)a[i] * (unsigned long long)a[i]; t[2 * i ] += u & 0xffffffff; t[2 * i + 1] += u >> 32; } */ #define M(i, j) u = (unsigned long long)a[i] * (unsigned long long)a[j]; \ t[i + j ] += (u & 0x00000000ffffffff) << 1; \ t[i + j + 1] += (u & 0xffffffff00000000) >> 31; M(0, 1); M(0, 2); M(0, 3); M(0, 4); M(0, 5); M(0, 6); M(0, 7); M(1, 2); M(1, 3); M(1, 4); M(1, 5); M(1, 6); M(1, 7); M(2, 3); M(2, 4); M(2, 5); M(2, 6); M(2, 7); M(3, 4); M(3, 5); M(3, 6); M(3, 7); M(4, 5); M(4, 6); M(4, 7); M(5, 6); M(5, 7); M(6, 7); #undef M #define S(i) u = (unsigned long long)a[i] * (unsigned long long)a[i]; \ t[2 * i ] += (u & 0xffffffff); \ t[2 * i + 1] += (u >> 32) S(0); S(1); S(2); S(3); S(4); S(5); S(6); S(7); #undef S u = 0; for (i = 0; i < 7; ++i) { u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0xffffffff; u >>= 32; } u += t[i] + 38ULL * t[i + 8]; t[i] = u & 0x7fffffff; u >>= 31; u *= 19ULL; for (i = 0; i < 8; ++i) { u += t[i]; o[i] = u & 0xffffffff; u >>= 32; } } /* o = (x + y) % p */ static void fe_add(fe o, const fe x, const fe y) { unsigned long long u = 0; long long i; for (i = 0; i < 7; ++i) { u += (unsigned long long)x[i] + (unsigned long long)y[i]; o[i] = u & 0xffffffff; u >>= 32; } u += (unsigned long long)x[i] + (unsigned long long)y[i]; o[i] = u & 0x7fffffff; u >>= 31; u *= 19ULL; for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; } } /* o = (x - y) % p */ static void fe_sub(fe o, const fe x, const fe y) { long long i; unsigned long long u = 0; const unsigned long long p4[8] = { 0x3ffffffb4ULL, 0x3fffffffcULL, 0x3fffffffcULL, 0x3fffffffcULL, 0x3fffffffcULL, 0x3fffffffcULL, 0x3fffffffcULL, 0x1fffffffcULL, }; for (i = 0; i < 7; ++i) { u += p4[i] - (unsigned long long)y[i] + (unsigned long long)x[i]; o[i] = u & 0xffffffff; u >>= 32; } u += p4[i] - (unsigned long long)y[i] + (unsigned long long)x[i]; o[i] = u & 0x7fffffff; u >>= 31; u *= 19ULL; for (i = 0; i < 8; ++i) { u += o[i]; o[i] = u & 0xffffffff; u >>= 32; } } /* o = (1 / z) % p */ static void fe_inv(fe o, const fe z) { fe t0, t1, t2, t3; long long i; fe_sq(t0, z); for (i = 1; i < 1; ++i) fe_sq(t0, t0); fe_sq(t1,t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, z, t1); fe_mul(t0, t0, t1); fe_sq(t2, t0); for (i = 1; i < 1; ++i) fe_sq(t2, t2); fe_mul(t1, t1, t2); fe_sq(t2, t1); for (i = 1; i < 5; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); fe_sq(t2, t1); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); fe_sq(t3, t2); for (i = 1; i < 20; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); fe_sq(t2, t2); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); fe_sq(t2, t1); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); fe_sq(t3, t2); for (i = 1; i < 100; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); fe_sq(t2, t2); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); fe_sq(t1, t1); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul(o, t1, t0); } int crypto_scalarmult_curve25519_tinynacl(unsigned char *q, const unsigned char *n, const unsigned char *p) { unsigned char e[32]; fe x1, x2, z2, x3, z3, tmp0, tmp1; long long i, pos; unsigned int d = 0; unsigned long swap, b; for (i = 0; i < 32; ++i) e[i] = n[i]; e[0] &= 248; e[31] &= 127; e[31] |= 64; fe_frombytes(x1, p); fe_1(x2); fe_0(z2); fe_copy(x3, x1); fe_1(z3); swap = 0; for (pos = 254; pos >= 0; --pos) { b = e[pos / 8] >> (pos & 7); b &= 1; swap ^= b; fe_cswap(x2, x3, swap); fe_cswap(z2, z3, swap); swap = b; fe_sub(tmp0, x3, z3); fe_sub(tmp1, x2, z2); fe_add(x2, x2, z2); fe_add(z2, x3, z3); fe_mul(z3, tmp0, x2); fe_mul(z2, z2, tmp1); fe_sq(tmp0, tmp1); fe_sq(tmp1, x2); fe_add(x3, z3, z2); fe_sub(z2, z3, z2); fe_mul(x2, tmp1, tmp0); fe_sub(tmp1, tmp1, tmp0); fe_sq(z2, z2); fe_mulc(z3, tmp1, 121666); fe_sq(x3, x3); fe_add(tmp0, tmp0, z3); fe_mul(z3, x1, z2); fe_mul(z2, tmp1, tmp0); } fe_cswap(x2, x3, swap); fe_cswap(z2, z3, swap); fe_inv(z2, z2); fe_mul(x2, x2, z2); fe_tobytes(q, x2); for (i = 0; i < 32; ++i) d |= q[i]; return -(1 & ((d - 1) >> 8)); } static const unsigned char basepoint[32] = {9}; int crypto_scalarmult_curve25519_tinynacl_base(unsigned char *q, const unsigned char *n) { return crypto_scalarmult_curve25519_tinynacl(q, n, basepoint); } dq-20240101/crypto_scalarmult_curve25519.h000066400000000000000000000015431454446775700201350ustar00rootroot00000000000000#ifndef crypto_scalarmult_curve25519_H #define crypto_scalarmult_curve25519_H #define crypto_scalarmult_curve25519_tinynacl_BYTES 32 #define crypto_scalarmult_curve25519_tinynacl_SCALARBYTES 32 extern int crypto_scalarmult_curve25519_tinynacl(unsigned char *,const unsigned char *,const unsigned char *); extern int crypto_scalarmult_curve25519_tinynacl_base(unsigned char *,const unsigned char *); #define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tinynacl #define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tinynacl_base #define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tinynacl_BYTES #define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tinynacl_SCALARBYTES #define crypto_scalarmult_curve25519_IMPLEMENTATION "tinynacl" #define crypto_scalarmult_curve25519_VERSION "-" #endif dq-20240101/crypto_secretbox_xsalsa20poly1305.c000066400000000000000000000020211454446775700210670ustar00rootroot00000000000000#include "crypto_onetimeauth_poly1305.h" #include "crypto_stream_xsalsa20.h" #include "cleanup.h" #include "crypto_secretbox_xsalsa20poly1305.h" int crypto_secretbox_xsalsa20poly1305_tinynacl(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k) { long long i; if (mlen < 32) return -1; crypto_stream_xsalsa20_xor(c, m, mlen, n, k); crypto_onetimeauth_poly1305(c + 16, c + 32, mlen - 32, c); for (i = 0; i < 16; ++i) c[i] = 0; return 0; } int crypto_secretbox_xsalsa20poly1305_tinynacl_open(unsigned char *m, const unsigned char *c, unsigned long long clen, const unsigned char *n, const unsigned char *k) { long long i; unsigned char subkey[32]; if (clen < 32) return -1; crypto_stream_xsalsa20(subkey, 32, n, k); if (crypto_onetimeauth_poly1305_verify(c + 16, c + 32, clen - 32, subkey) != 0) return -1; crypto_stream_xsalsa20_xor(m, c, clen, n, k); for (i = 0; i < 32; ++i) m[i] = 0; cleanup(subkey); return 0; } dq-20240101/crypto_secretbox_xsalsa20poly1305.h000066400000000000000000000026041454446775700211030ustar00rootroot00000000000000#ifndef crypto_secretbox_xsalsa20poly1305_H #define crypto_secretbox_xsalsa20poly1305_H #define crypto_secretbox_xsalsa20poly1305_tinynacl_KEYBYTES 32 #define crypto_secretbox_xsalsa20poly1305_tinynacl_NONCEBYTES 24 #define crypto_secretbox_xsalsa20poly1305_tinynacl_ZEROBYTES 32 #define crypto_secretbox_xsalsa20poly1305_tinynacl_BOXZEROBYTES 16 extern int crypto_secretbox_xsalsa20poly1305_tinynacl(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *); extern int crypto_secretbox_xsalsa20poly1305_tinynacl_open(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *); #define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tinynacl #define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tinynacl_open #define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tinynacl_KEYBYTES #define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tinynacl_NONCEBYTES #define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tinynacl_ZEROBYTES #define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tinynacl_BOXZEROBYTES #define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "tinynacl" #define crypto_secretbox_xsalsa20poly1305_VERSION "-" #endif dq-20240101/crypto_stream_salsa20.c000066400000000000000000000007341454446775700167700ustar00rootroot00000000000000/* 20140727 Jan Mojzis Public domain. */ #include "salsa.h" #include "crypto_stream_salsa20.h" int crypto_stream_salsa20_tinynacl_xor(unsigned char *c, const unsigned char *m, unsigned long long l, const unsigned char *n, const unsigned char *k) { return salsa_stream_xor(c, m, l, n, k, 20); } int crypto_stream_salsa20_tinynacl(unsigned char *c, unsigned long long l, const unsigned char *n, const unsigned char *k) { return salsa_stream_xor(c, 0, l, n, k, 20); } dq-20240101/crypto_stream_salsa20.h000066400000000000000000000015071454446775700167740ustar00rootroot00000000000000#ifndef crypto_stream_salsa20_H #define crypto_stream_salsa20_H #define crypto_stream_salsa20_tinynacl_KEYBYTES 32 #define crypto_stream_salsa20_tinynacl_NONCEBYTES 8 extern int crypto_stream_salsa20_tinynacl(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); extern int crypto_stream_salsa20_tinynacl_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); #define crypto_stream_salsa20 crypto_stream_salsa20_tinynacl #define crypto_stream_salsa20_xor crypto_stream_salsa20_tinynacl_xor #define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tinynacl_KEYBYTES #define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tinynacl_NONCEBYTES #define crypto_stream_salsa20_IMPLEMENTATION "tinynacl" #define crypto_stream_salsa20_VERSION "-" #endif dq-20240101/crypto_stream_xsalsa20.c000066400000000000000000000013541454446775700171570ustar00rootroot00000000000000/* 20140727 Jan Mojzis Public domain. */ #include "crypto_core_hsalsa20.h" #include "crypto_stream_salsa20.h" #include "cleanup.h" #include "crypto_stream_xsalsa20.h" static const unsigned char sigma[16] = "expand 32-byte k"; int crypto_stream_xsalsa20_tinynacl_xor(unsigned char *c, const unsigned char *m, unsigned long long l, const unsigned char *n, const unsigned char *k) { unsigned char subkey[32]; crypto_core_hsalsa20(subkey, n, k, sigma); crypto_stream_salsa20_xor(c, m, l, n + 16, subkey); cleanup(subkey); return 0; } int crypto_stream_xsalsa20_tinynacl(unsigned char *c, unsigned long long l, const unsigned char *n, const unsigned char *k) { return crypto_stream_xsalsa20_tinynacl_xor(c, 0, l, n, k); } dq-20240101/crypto_stream_xsalsa20.h000066400000000000000000000015301454446775700171600ustar00rootroot00000000000000#ifndef crypto_stream_xsalsa20_H #define crypto_stream_xsalsa20_H #define crypto_stream_xsalsa20_tinynacl_KEYBYTES 32 #define crypto_stream_xsalsa20_tinynacl_NONCEBYTES 24 extern int crypto_stream_xsalsa20_tinynacl(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); extern int crypto_stream_xsalsa20_tinynacl_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *); #define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tinynacl #define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tinynacl_xor #define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tinynacl_KEYBYTES #define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tinynacl_NONCEBYTES #define crypto_stream_xsalsa20_IMPLEMENTATION "tinynacl" #define crypto_stream_xsalsa20_VERSION "-" #endif dq-20240101/crypto_uint16.h000066400000000000000000000001561454446775700153010ustar00rootroot00000000000000#ifndef crypto_uint16_h #define crypto_uint16_h #include typedef uint16_t crypto_uint16; #endif dq-20240101/crypto_uint32.h000066400000000000000000000001561454446775700152770ustar00rootroot00000000000000#ifndef crypto_uint32_h #define crypto_uint32_h #include typedef uint32_t crypto_uint32; #endif dq-20240101/crypto_uint64.h000066400000000000000000000001561454446775700153040ustar00rootroot00000000000000#ifndef crypto_uint64_h #define crypto_uint64_h #include typedef uint64_t crypto_uint64; #endif dq-20240101/crypto_uint8.h000066400000000000000000000001521454446775700152160ustar00rootroot00000000000000#ifndef crypto_uint8_h #define crypto_uint8_h #include typedef uint8_t crypto_uint8; #endif dq-20240101/crypto_verify_16.c000066400000000000000000000002421454446775700157540ustar00rootroot00000000000000#include "verify.h" #include "crypto_verify_16.h" int crypto_verify_16_tinynacl(const unsigned char *x, const unsigned char *y) { return verify(x, y, 16); } dq-20240101/crypto_verify_16.h000066400000000000000000000006111454446775700157610ustar00rootroot00000000000000#ifndef crypto_verify_16_H #define crypto_verify_16_H #define crypto_verify_16_tinynacl_BYTES 16 extern int crypto_verify_16_tinynacl(const unsigned char *, const unsigned char *); #define crypto_verify_16 crypto_verify_16_tinynacl #define crypto_verify_16_BYTES crypto_verify_16_tinynacl_BYTES #define crypto_verify_16_IMPLEMENTATION "tinynacl" #define crypto_verify_16_VERSION "-" #endif dq-20240101/crypto_verify_32.c000066400000000000000000000002421454446775700157520ustar00rootroot00000000000000#include "verify.h" #include "crypto_verify_32.h" int crypto_verify_32_tinynacl(const unsigned char *x, const unsigned char *y) { return verify(x, y, 32); } dq-20240101/crypto_verify_32.h000066400000000000000000000006111454446775700157570ustar00rootroot00000000000000#ifndef crypto_verify_32_H #define crypto_verify_32_H #define crypto_verify_32_tinynacl_BYTES 32 extern int crypto_verify_32_tinynacl(const unsigned char *, const unsigned char *); #define crypto_verify_32 crypto_verify_32_tinynacl #define crypto_verify_32_BYTES crypto_verify_32_tinynacl_BYTES #define crypto_verify_32_IMPLEMENTATION "tinynacl" #define crypto_verify_32_VERSION "-" #endif dq-20240101/crypto_verify_8.c000066400000000000000000000002371454446775700157010ustar00rootroot00000000000000#include "verify.h" #include "crypto_verify_8.h" int crypto_verify_8_tinynacl(const unsigned char *x, const unsigned char *y) { return verify(x, y, 8); } dq-20240101/crypto_verify_8.h000066400000000000000000000005761454446775700157140ustar00rootroot00000000000000#ifndef crypto_verify_8_H #define crypto_verify_8_H #define crypto_verify_8_tinynacl_BYTES 8 extern int crypto_verify_8_tinynacl(const unsigned char *, const unsigned char *); #define crypto_verify_8 crypto_verify_8_tinynacl #define crypto_verify_8_BYTES crypto_verify_8_tinynacl_BYTES #define crypto_verify_8_IMPLEMENTATION "tinynacl" #define crypto_verify_8_VERSION "-" #endif dq-20240101/die.c000066400000000000000000000013211454446775700133020ustar00rootroot00000000000000#include #include "alloc.h" #include "writeall.h" #include "die.h" void die_9(int e ,const char *s0 ,const char *s1 ,const char *s2 ,const char *s3 ,const char *s4 ,const char *s5 ,const char *s6 ,const char *s7 ,const char *s8 ) { const char *s[9]; const char *x; char buf[256]; long long buflen = 0; long long i; s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7; s[8] = s8; for (i = 0;i < 9;++i) { x = s[i]; if (!x) continue; while (*x) { if (buflen == sizeof buf) { writeall(2,buf,buflen); buflen = 0; } buf[buflen++] = *x++; } } writeall(2,buf,buflen); alloc_freeall(); _exit(e); } dq-20240101/die.h000066400000000000000000000010771454446775700133170ustar00rootroot00000000000000#ifndef DIE_H #define DIE_H extern void die_9(int,const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *); #define die_8(x,a,b,c,d,e,f,g,h) die_9(x,a,b,c,d,e,f,g,h,0) #define die_7(x,a,b,c,d,e,f,g) die_8(x,a,b,c,d,e,f,g,0) #define die_6(x,a,b,c,d,e,f) die_7(x,a,b,c,d,e,f,0) #define die_5(x,a,b,c,d,e) die_6(x,a,b,c,d,e,0) #define die_4(x,a,b,c,d) die_5(x,a,b,c,d,0) #define die_3(x,a,b,c) die_4(x,a,b,c,0) #define die_2(x,a,b) die_3(x,a,b,0) #define die_1(x,a) die_2(x,a,0) #define die_0(x) die_1(x,0) #endif dq-20240101/direntry.h000066400000000000000000000002601454446775700144070ustar00rootroot00000000000000/* Public domain. */ #ifndef _DIRENTRY_H____ #define _DIRENTRY_H____ #include #include #define direntry struct dirent #endif /* _DIRENTRY_H____ */ dq-20240101/dns.h000066400000000000000000000136671454446775700133520ustar00rootroot00000000000000#ifndef _DNS_H____ #define _DNS_H____ #include #include "stralloc.h" #define DNS_C_IN (unsigned char *)"\0\1" #define DNS_C_ANY (unsigned char *)"\0\377" #define DNS_T_A (unsigned char *)"\0\1" #define DNS_T_NS (unsigned char *)"\0\2" #define DNS_T_CNAME (unsigned char *)"\0\5" #define DNS_T_SOA (unsigned char *)"\0\6" #define DNS_T_PTR (unsigned char *)"\0\14" #define DNS_T_MX (unsigned char *)"\0\17" #define DNS_T_TXT (unsigned char *)"\0\20" #define DNS_T_AAAA (unsigned char *)"\0\34" #define DNS_T_SRV (unsigned char *)"\0\41" #define DNS_T_AXFR (unsigned char *)"\0\374" #define DNS_T_ANY (unsigned char *)"\0\377" #define DNS_MAGICQ (unsigned char *)"Q6fnvWj8" #define DNS_MAGICR (unsigned char *)"R6fnvWJ8" struct dns_transmit { unsigned char *query; /* 0, or dynamically allocated */ long long querylen; unsigned char *packet; /* 0, or dynamically allocated */ long long packetlen; int s1; /* 0, or 1 + an open file descriptor */ int s1type; long long tcpstate; long long udploop; long long curserver; long long deadline; long long pos; const unsigned char *servers; unsigned char localip[32]; unsigned char qtype[2]; unsigned char port[2]; long long scope_id; long long paddinglen; unsigned char id[2]; unsigned char nonce[12]; const unsigned char *keys; const unsigned char *pk; const unsigned char *suffix; const unsigned char *name; int flagrecursive; int flagipv4only; }; #define DNS_HASKEY(d) (d->keys && *(d->keys + 33 * d->curserver)) #define DNS_ISTXT(d) (d->keys && (*(d->keys + 33 * d->curserver) == 2)) #define DNS_KEYPTR(d) d->keys + 33 * d->curserver + 1 /* dns_domain */ extern void dns_domain_free(unsigned char **); extern int dns_domain_copy(unsigned char **, const unsigned char *); extern long long dns_domain_length(const unsigned char *); extern int dns_domain_equal(const unsigned char *, const unsigned char *); extern int dns_domain_suffix(const unsigned char *, const unsigned char *); extern long long dns_domain_suffixpos(const unsigned char *, const unsigned char *); extern int dns_domain_fromdot(unsigned char **, const unsigned char *, long long); extern int dns_domain_fromdot_static(unsigned char *, const unsigned char *, long long); extern int dns_domain_todot_cat(stralloc *, const unsigned char *); /* dns_packet */ extern long long dns_packet_copy(const unsigned char *,long long,long long,unsigned char *,long long); extern long long dns_packet_getname(const unsigned char *,long long,long long,unsigned char **); extern long long dns_packet_skipname(const unsigned char *,long long,long long); extern long long dns_packet_getname_static(const unsigned char *,long long,long long,unsigned char *); /* dns_transmit */ extern int dns_transmit_start(struct dns_transmit *d, const unsigned char servers[256], int flagrecursive, const unsigned char *q, const unsigned char qtype[2], const unsigned char localip[32]); extern int dns_transmit_startext(struct dns_transmit *d, const unsigned char servers[256], int flagrecursive, int flagtcp, int flagipv4only, const unsigned char *q, const unsigned char qtype[2], const unsigned char localip[32], const unsigned char port[2], const unsigned char keys[528], const unsigned char pk[32], const unsigned char *suffix); extern void dns_transmit_free(struct dns_transmit *); extern void dns_transmit_io(struct dns_transmit *,struct pollfd *,long long *); extern int dns_transmit_get(struct dns_transmit *,const struct pollfd *,const long long); extern void dns_transmit_magic(const char *, const char *); /* dns_data */ struct dns_data { /* ---- OUTPUT */ /* name */ unsigned char *name; stralloc fqdn; /* result */ stralloc result; /* keys */ unsigned char *curvecpkey; unsigned char *dnscurvekey; /* ---- INPUT */ /* options */ char curvecpselector; }; extern void dns_data_free(struct dns_data *); extern int dns_resolvconfip(unsigned char *); extern int dns_resolve(const unsigned char *q, const unsigned char qtype[2]); extern struct dns_transmit dns_resolve_tx; extern int dns_ip(struct dns_data *, const char *); extern int dns_ip4(struct dns_data *, const char *); extern int dns_ip6(struct dns_data *, const char *); extern int dns_resolvconfrewrite(stralloc *); extern int dns_ip_qualify(struct dns_data *, const char *); extern int dns_ip4_qualify(struct dns_data *, const char *); extern int dns_ip6_qualify(struct dns_data *, const char *); #define DNS_IPTONAME_LEN 73 extern char *dns_iptoname(char *, const unsigned char *); /* utils */ extern void dns_sortip4(unsigned char *, long long); extern void dns_sortip(unsigned char *, long long); extern void dns_sortipkey(unsigned char *, unsigned char *, long long); /*base32 */ extern long long dns_base32_bytessize(long long); extern void dns_base32_encodebytes(unsigned char *, const unsigned char *, long long); extern void dns_base32_encodekey(unsigned char *, const unsigned char *); extern long long base32_decode(unsigned char *, const unsigned char *, long long, int); /* nonce */ extern void dns_nonce_purge(void); extern int dns_nonce_init(const char *, const unsigned char *); extern void dns_nonce(unsigned char *); /* verbose */ extern int dns_verbosity_flag; extern const char *dns_verbosity_message; extern void dns_verbosity_setflag(int); extern void dns_verbosity_setmessage(const char *); extern void dns_verbosity_writehex(const char *, const unsigned char *, long long); extern void dns_verbosity_writedomain(const char *, unsigned char *); extern void dns_verbosity_resolving(const char *); extern void dns_verbosity_resolved(struct dns_data *, const char *); extern void dns_verbosity_querysent(struct dns_transmit *, int); extern void dns_verbosity_queryfailed(struct dns_transmit *, int); extern void dns_verbosity_queryfailedtc(struct dns_transmit *); extern void dns_verbosity_queryok(struct dns_transmit *); /* keys */ extern void dns_keys_derive(unsigned char *, long long, unsigned char *); #endif dq-20240101/dns_base32.c000066400000000000000000000054071454446775700144750ustar00rootroot00000000000000#include "byte.h" #include "dns.h" static const char base32_digits[32] = "0123456789bcdfghjklmnpqrstuvwxyz"; long long dns_base32_bytessize(long long len) { if (len < 0) return 0; len = (8 * len + 4) / 5; return len + (len + 49) / 50; } void dns_base32_encodebytes(unsigned char *out, const unsigned char *in, long long len) { unsigned long long i, x, v, vbits; if (len < 0) return; x = v = vbits = 0; for (i = 0; i < len; ++i) { v |= ((unsigned long long)in[i]) << vbits; vbits += 8; do { out[++x] = base32_digits[v & 31]; v >>= 5; vbits -= 5; if (x == 50) { *out = x; out += 1 + x; x = 0; } } while (vbits >= 5); } if (vbits) out[++x] = base32_digits[v & 31]; if (x) *out = x; } void dns_base32_encodekey(unsigned char *out, const unsigned char *key) { unsigned long long i, v, vbits; byte_copy(out, 4, "\66x1a"); out += 4; v = vbits = 0; for (i = 0; i < 32; ++i) { v |= ((unsigned long long)key[i]) << vbits; vbits += 8; do { *out++ = base32_digits[v & 31]; v >>= 5; vbits -= 5; } while (vbits >= 5); } } static const unsigned char val[128] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0xff, 0x0d, 0x0e, 0x0f, 0xff, 0x10, 0x11, 0x12, 0x13, 0x14, 0xff, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0xff, 0x0d, 0x0e, 0x0f, 0xff, 0x10, 0x11, 0x12, 0x13, 0x14, 0xff, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff }; long long base32_decode(unsigned char *out, const unsigned char *in, long long len, int mode) { long long i; unsigned long long x, v, vbits; unsigned char *out0 = out; if (len < 0) return 0; v = vbits = 0; for (i = 0; i < len; ++i) { if (in[i] & 0x80) return 0; x = val[in[i]]; if (x > 0x1f) return 0; v |= x << vbits; vbits += 5; if (vbits >= 8) { *out++ = v; v >>= 8; vbits -= 8; } } if (mode) { if (vbits) *out++ = v; } else if (vbits >= 5 || v) return 0; return out - out0; } dq-20240101/dns_data.c000066400000000000000000000005621454446775700143240ustar00rootroot00000000000000#include "stralloc.h" #include "alloc.h" #include "byte.h" #include "dns.h" void dns_data_free(struct dns_data *r) { dns_domain_free(&r->name); stralloc_free(&r->result); stralloc_free(&r->fqdn); if (r->curvecpkey) alloc_free(r->curvecpkey); if (r->dnscurvekey) alloc_free(r->dnscurvekey); byte_zero(r, sizeof(struct dns_data)); return; } dq-20240101/dns_domain.c000066400000000000000000000103671454446775700146660ustar00rootroot00000000000000#include "alloc.h" #include "byte.h" #include "case.h" #include "e.h" #include "dns.h" long long dns_domain_length(const unsigned char *dn) { const unsigned char *x; unsigned char c; x = dn; while (c = *x++) { x += c; } return (x - dn); } void dns_domain_free(unsigned char **out) { if (*out) { alloc_free(*out); *out = 0; } } int dns_domain_copy(unsigned char **out, const unsigned char *in) { long long len; unsigned char *x; len = dns_domain_length(in); x = alloc(len); if (!x) return 0; byte_copy(x, len, in); if (*out) alloc_free(*out); *out = x; return 1; } int dns_domain_equal(const unsigned char *dn1, const unsigned char *dn2) { long long len; len = dns_domain_length(dn1); if (len != dns_domain_length(dn2)) return 0; return !case_diffb(dn1, len, dn2); } int dns_domain_suffix(const unsigned char *big, const unsigned char *little) { unsigned char c; for (;;) { if (dns_domain_equal(big, little)) return 1; c = *big++; if (!c) return 0; big += c; } } long long dns_domain_suffixpos(const unsigned char *big, const unsigned char *little) { const unsigned char *orig = big; unsigned char c; for (;;) { if (dns_domain_equal(big, little)) return (big - orig); c = *big++; if (!c) return 0; big += c; } } int dns_domain_fromdot(unsigned char **out,const unsigned char *buf,long long n) { unsigned char label[63]; long long labellen = 0; /* <= sizeof label */ unsigned char name[255]; long long namelen = 0; /* <= sizeof name */ unsigned char ch; unsigned char *x; errno = EPROTO; if (n < 0) return 0; for (;;) { if (!n) break; ch = *buf++; --n; if (ch == '.') { if (labellen > 0) { if (namelen + labellen + 1 > sizeof name) return 0; name[namelen++] = labellen; byte_copy(name + namelen,labellen,label); namelen += labellen; labellen = 0; } continue; } if (ch == '\\') { if (!n) break; ch = *buf++; --n; if ((ch >= '0') && (ch <= '7')) { ch -= '0'; if (n && (*buf >= '0') && (*buf <= '7')) { ch <<= 3; ch += *buf - '0'; ++buf; --n; if (n && (*buf >= '0') && (*buf <= '7')) { ch <<= 3; ch += *buf - '0'; ++buf; --n; } } } } if (labellen >= sizeof label) return 0; label[labellen++] = ch; } if (labellen > 0) { if (namelen + labellen + 1 > sizeof name) return 0; name[namelen++] = labellen; byte_copy(name + namelen,labellen,label); namelen += labellen; labellen = 0; } if (namelen + 1 > sizeof name) return 0; name[namelen++] = 0; x = alloc(namelen); if (!x) return 0; byte_copy(x,namelen,name); if (*out) alloc_free(*out); *out = x; return 1; } int dns_domain_fromdot_static(unsigned char *name,const unsigned char *buf,long long n) { unsigned char label[63]; long long labellen = 0; /* <= sizeof label */ long long namelen = 0; /* <= sizeof name */ unsigned char ch; errno = EPROTO; if (n < 0) return 0; byte_zero(name, 256); for (;;) { if (!n) break; ch = *buf++; --n; if (ch == '.') { if (labellen > 0) { if (namelen + labellen + 1 > 255) return 0; name[namelen++] = labellen; byte_copy(name + namelen,labellen,label); namelen += labellen; labellen = 0; } continue; } if (ch == '\\') { if (!n) break; ch = *buf++; --n; if ((ch >= '0') && (ch <= '7')) { ch -= '0'; if (n && (*buf >= '0') && (*buf <= '7')) { ch <<= 3; ch += *buf - '0'; ++buf; --n; if (n && (*buf >= '0') && (*buf <= '7')) { ch <<= 3; ch += *buf - '0'; ++buf; --n; } } } } if (labellen >= sizeof label) return 0; label[labellen++] = ch; } if (labellen > 0) { if (namelen + labellen + 1 > 255) return 0; name[namelen++] = labellen; byte_copy(name + namelen,labellen,label); namelen += labellen; labellen = 0; } if (namelen + 1 > 255) return 0; name[namelen++] = 0; return 1; } dq-20240101/dns_dtda.c000066400000000000000000000017201454446775700143240ustar00rootroot00000000000000#include "stralloc.h" #include "dns.h" int dns_domain_todot_cat(stralloc *out, const unsigned char *d) { char ch; char ch2; unsigned char ch3; unsigned char buf[4]; if (!*d) return stralloc_append(out, "."); for (;;) { ch = *d++; while (ch--) { ch2 = *d++; if ((ch2 >= 'A') && (ch2 <= 'Z')) ch2 += 32; if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_')) { if (!stralloc_append(out,&ch2)) return 0; } else { ch3 = ch2; buf[3] = '0' + (ch3 & 7); ch3 >>= 3; buf[2] = '0' + (ch3 & 7); ch3 >>= 3; buf[1] = '0' + (ch3 & 7); buf[0] = '\\'; if (!stralloc_catb(out, buf, 4)) return 0; } } if (!*d) return 1; if (!stralloc_append(out,".")) return 0; } } dq-20240101/dns_ip.c000066400000000000000000000217151454446775700140260ustar00rootroot00000000000000#include "alloc.h" #include "byte.h" #include "crypto_uint16.h" #include "uint16_unpack_big.h" #include "base32decode.h" #include "hexdecode.h" #include "case.h" #include "str.h" #include "stralloc.h" #include "strtoip.h" #include "milliseconds.h" #include "dns.h" static int dns_curvecpkey_parse(struct dns_data *r, const unsigned char *d) { long long pos = 0; long long i; unsigned char c; unsigned char key[32]; unsigned char ext[16]; if (r->curvecpkey) return 0; for (;;) { c = d[pos++]; if (!c) break; if (c == 54 && byte_isequal(d + pos, 3, "uz7") && base32decode(key, sizeof key, d + pos + 3, 51)) { pos += c; c = d[pos++]; if (!c) break; if (c >= 32 && hexdecode(ext, sizeof ext, d + pos, 32)) { if (c == 32 || r->curvecpselector == 0) { r->curvecpkey = alloc(48); if (!r->curvecpkey) return -1; byte_copy(r->curvecpkey, 32, key); byte_copy(r->curvecpkey + 32, 16, ext); return 0; } if (d[pos + 32] == '/') { for (i = 33; i < c; ++i) { if (!case_diffb(d + pos + i, 1, &r->curvecpselector)) { r->curvecpkey = alloc(48); if (!r->curvecpkey) return -1; byte_copy(r->curvecpkey, 32, key); byte_copy(r->curvecpkey + 32, 16, ext); return 0; } } } } } pos += c; } return 0; } static int dns_dnscurvekey_parse(struct dns_data *r, const unsigned char *d) { long long pos = 0; unsigned char c; unsigned char key[32]; if (r->dnscurvekey) return 0; for (;;) { c = d[pos++]; if (!c) break; if (c == 54 && byte_isequal(d + pos, 3, "uz5") && base32decode(key, sizeof key, d + pos + 3, 51)) { r->dnscurvekey = alloc(32); if (!r->dnscurvekey) return -1; byte_copy(r->dnscurvekey, 32, key); return 0; } pos += c; } return 0; } static int ip_packet(struct dns_data *r, unsigned char *buf, long long len) { crypto_uint16 numanswers; crypto_uint16 numauthority; crypto_uint16 datalen; long long pos, newpos; unsigned char data[16]; unsigned char d[256]; /* header */ pos = dns_packet_copy(buf, len, 0, data, 12); if (!pos) return -1; numanswers = uint16_unpack_big(data + 6); numauthority = uint16_unpack_big(data + 8); pos = dns_packet_getname_static(buf, len, pos, d); if (!pos) return -1; pos += 4; if (dns_dnscurvekey_parse(r, d) == -1) return -1; if (dns_curvecpkey_parse(r, d) == -1) return -1; while (numanswers--) { pos = dns_packet_skipname(buf, len, pos); if (!pos) return -1; pos = dns_packet_copy(buf, len, pos, data, 10); if (!pos) return -1; datalen = uint16_unpack_big(data + 8); newpos = pos + datalen; /* CNAME answers */ if (byte_isequal(data, 2, DNS_T_CNAME)) { if (byte_isequal(data + 2, 2, DNS_C_IN)) { if (!dns_packet_getname_static(buf, len, pos, d)) return -1; if (dns_curvecpkey_parse(r, d) == -1) return -1; } } /* A answers */ else if (byte_isequal(data, 2, DNS_T_A)) { if (byte_isequal(data + 2, 2, DNS_C_IN)) { if (datalen == 4) { if (!dns_packet_copy(buf, len, pos, data + 12, 4)) return -1; byte_copy(data, 12, "\0\0\0\0\0\0\0\0\0\0\377\377"); if (!stralloc_catb(&r->result, data, 16)) return -1; } } } /* AAAA answers */ else if (byte_isequal(data, 2, DNS_T_AAAA)) { if (byte_isequal(data + 2, 2, DNS_C_IN)) { if (datalen == 16) { if (!dns_packet_copy(buf, len, pos, data, 16)) return -1; if (!stralloc_catb(&r->result, data, 16)) return -1; } } } pos = newpos; } while (numauthority--) { pos = dns_packet_skipname(buf, len, pos); if (!pos) return -1; pos = dns_packet_copy(buf, len, pos, data, 10); if (!pos) return -1; datalen = uint16_unpack_big(data + 8); newpos = pos + datalen; /* NS authority */ if (byte_isequal(data, 2, DNS_T_NS)) { if (byte_isequal(data + 2, 2, DNS_C_IN)) { if (!dns_packet_getname_static(buf, len, pos, d)) return -1; if (dns_curvecpkey_parse(r, d) == -1) return -1; } } pos = newpos; } return 0; } struct dns_transmit dns_resolve_tx0 = {0}; struct dns_transmit dns_resolve_tx1 = {0}; static int resolve2(struct dns_data *d, const unsigned char *q, const unsigned char qtype0[2], const unsigned char qtype1[2]) { long long deadline, stamp, timeout, max; unsigned char servers[256]; struct pollfd x[2]; int r; if (dns_resolvconfip(servers) == -1) return -1; if (dns_transmit_start(&dns_resolve_tx0, servers, 1, q, qtype0, 0) == -1) return -1; if (dns_transmit_start(&dns_resolve_tx1, servers, 1, q, qtype1, 0) == -1) return -1; for (;;) { stamp = milliseconds(); deadline = 120000 + stamp; dns_transmit_io(&dns_resolve_tx0, &x[0], &deadline); dns_transmit_io(&dns_resolve_tx1, &x[1], &deadline); timeout = deadline - stamp; if (timeout <= 0) timeout = 20; poll(x, 2, timeout); r = dns_transmit_get(&dns_resolve_tx0, &x[0], stamp); if (r == -1) return -1; if (r == 1) { if (ip_packet(d, dns_resolve_tx0.packet, dns_resolve_tx0.packetlen) == -1) return -1; dns_transmit_free(&dns_resolve_tx0); byte_copy(&dns_resolve_tx0, sizeof (struct dns_transmit), &dns_resolve_tx1); byte_zero(&dns_resolve_tx1, sizeof (struct dns_transmit)); break; } r = dns_transmit_get(&dns_resolve_tx1, &x[1], stamp); if (r == -1) return -1; if (r == 1) { if (ip_packet(d, dns_resolve_tx1.packet, dns_resolve_tx1.packetlen) == -1) return -1; break; } } max = 3000 + milliseconds(); for (;;) { stamp = milliseconds(); if (stamp > max) return 0; deadline = max; dns_transmit_io(&dns_resolve_tx0, x, &deadline); timeout = deadline - stamp; if (timeout <= 0) timeout = 20; poll(x, 1, timeout); r = dns_transmit_get(&dns_resolve_tx0, x, stamp); if (r == -1) return -1; if (r == 1) { if (ip_packet(d, dns_resolve_tx0.packet, dns_resolve_tx0.packetlen) == -1) return -1; return 0; } } } int dns_ip(struct dns_data *r, const char *name) { unsigned char ip[16]; if (!dns_domain_fromdot(&r->name, (unsigned char *)name, str_len(name))) return -1; if (strtoip(ip, name)) { if (!stralloc_copyb(&r->result, ip, 16)) return -1; return 0; } if (!stralloc_copys(&r->result, "")) return -1; if (resolve2(r, r->name, DNS_T_AAAA, DNS_T_A) == -1) return -1; dns_transmit_free(&dns_resolve_tx0); dns_transmit_free(&dns_resolve_tx1); if (r->fqdn.len == 0) { if (!stralloc_copys(&r->fqdn, name)) return -1; if (!stralloc_0(&r->fqdn)) return -1; } dns_sortip(r->result.s, r->result.len); return 0; } int dns_ip4(struct dns_data *r, const char *name) { unsigned char ip[16]; if (!dns_domain_fromdot(&r->name, (unsigned char *)name, str_len(name))) return -1; if (strtoip4(ip, name)) { if (!stralloc_copyb(&r->result, ip, 16)) return -1; return 0; } if (!stralloc_copys(&r->result, "")) return -1; /* A */ if (dns_resolve(r->name, DNS_T_A) == -1) return -1; if (ip_packet(r, dns_resolve_tx.packet, dns_resolve_tx.packetlen) == -1) return -1; dns_transmit_free(&dns_resolve_tx); if (r->fqdn.len == 0) { if (!stralloc_copys(&r->fqdn, name)) return -1; if (!stralloc_0(&r->fqdn)) return -1; } dns_sortip(r->result.s, r->result.len); return 0; } int dns_ip6(struct dns_data *r, const char *name) { unsigned char ip[16]; if (!dns_domain_fromdot(&r->name, (unsigned char *)name, str_len(name))) return -1; if (strtoip6(ip, name)) { if (!stralloc_copyb(&r->result, ip, 16)) return -1; return 0; } if (!stralloc_copys(&r->result, "")) return -1; /* AAAA */ if (dns_resolve(r->name, DNS_T_AAAA) == -1) return -1; if (ip_packet(r, dns_resolve_tx.packet, dns_resolve_tx.packetlen) == -1) return -1; dns_transmit_free(&dns_resolve_tx); if (r->fqdn.len == 0) { if (!stralloc_copys(&r->fqdn, name)) return -1; if (!stralloc_0(&r->fqdn)) return -1; } dns_sortip(r->result.s, r->result.len); return 0; } dq-20240101/dns_ipq.c000066400000000000000000000054001454446775700142000ustar00rootroot00000000000000#include "stralloc.h" #include "case.h" #include "byte.h" #include "str.h" #include "dns.h" static int doit(stralloc *work,const unsigned char *rule) { unsigned char ch; long long colon; long long prefixlen; ch = *rule++; if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1; colon = str_chr((char *)rule,':'); if (!rule[colon]) return 1; if (work->len < colon) return 1; prefixlen = work->len - colon; if ((ch == '=') && prefixlen) return 1; if (case_diffb(rule,colon,work->s + prefixlen)) return 1; if (ch == '?') { if (byte_chr(work->s,prefixlen,':') < prefixlen) return 1; /* IPv6 */ if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1; if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1; if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1; } work->len = prefixlen; if (ch == '-') work->len = 0; return stralloc_cats(work,rule + colon + 1); } static int dns_ip_qualify_rules(struct dns_data *out,stralloc *fqdn,const char *in,const stralloc *rules, int (*op)(struct dns_data *, const char *)) { long long i; long long j; long long plus; long long fqdnlen; if (!stralloc_copys(fqdn,in)) return -1; for (j = i = 0;j < rules->len;++j) if (!rules->s[j]) { if (!doit(fqdn,rules->s + i)) return -1; i = j + 1; } fqdnlen = fqdn->len; plus = byte_chr(fqdn->s,fqdnlen,'+'); fqdn->s[fqdn->len] = 0; if (plus >= fqdnlen) return op(out,(char *)fqdn->s); i = plus + 1; for (;;) { j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); byte_copy(fqdn->s + plus,j,fqdn->s + i); fqdn->len = plus + j; fqdn->s[fqdn->len] = 0; if (op(out,(char *)fqdn->s) == -1) return -1; if (out->result.len) return 0; i += j; if (i >= fqdnlen) return 0; ++i; } } int dns_ip_qualify(struct dns_data *out, const char *in) { stralloc rules = {0}; int r; dns_verbosity_resolving(in); if (dns_resolvconfrewrite(&rules) == -1) return -1; r = dns_ip_qualify_rules(out, &out->fqdn, in, &rules, dns_ip); stralloc_free(&rules); dns_verbosity_resolved(out, in); return r; } int dns_ip4_qualify(struct dns_data *out, const char *in) { stralloc rules = {0}; int r; dns_verbosity_resolving(in); if (dns_resolvconfrewrite(&rules) == -1) return -1; r = dns_ip_qualify_rules(out, &out->fqdn, in, &rules, dns_ip4); stralloc_free(&rules); dns_verbosity_resolved(out, in); return r; } int dns_ip6_qualify(struct dns_data *out, const char *in) { stralloc rules = {0}; int r; dns_verbosity_resolving(in); if (dns_resolvconfrewrite(&rules) == -1) return -1; r = dns_ip_qualify_rules(out, &out->fqdn, in, &rules, dns_ip6); stralloc_free(&rules); dns_verbosity_resolved(out, in); return r; } dq-20240101/dns_iptoname.c000066400000000000000000000020551454446775700152260ustar00rootroot00000000000000#include "byte.h" #include "numtostr.h" #include "dns.h" static char *dns_iptoname4(char *name, const unsigned char *ip) { long long i,j; char strnum[NUMTOSTR_LEN], *x; j = 0; for (i = 3; i >= 0; --i) { x = numtostr(strnum, ip[i]); while (*x) name[j++] = *x++; name[j++] = '.'; } byte_copy(name + j, 13, "in-addr.arpa"); return name; } static char *dns_iptoname6(char *name, const unsigned char *ip) { long long i,j; j = 0; for (i = 15; i >= 0; --i) { name[j++] = "0123456789abcdef"[(ip[i] >> 0) & 15]; name[j++] = '.'; name[j++] = "0123456789abcdef"[(ip[i] >> 4) & 15]; name[j++] = '.'; } byte_copy(name + j, 9, "ip6.arpa"); return name; } char *dns_iptoname(char *namebuf, const unsigned char *ip) { static char staticbuf[DNS_IPTONAME_LEN]; if (!namebuf) namebuf = staticbuf; /* not thread-safe */ if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { return dns_iptoname4(namebuf, ip + 12); } return dns_iptoname6(namebuf, ip); } dq-20240101/dns_keys.c000066400000000000000000000003571454446775700143700ustar00rootroot00000000000000#include "crypto_stream_salsa20.h" #include "dns.h" static const unsigned char zero[8] = {0}; void dns_keys_derive(unsigned char *out, long long outlen, unsigned char *skseed) { crypto_stream_salsa20(out, outlen, zero, skseed); } dq-20240101/dns_nonce.c000066400000000000000000000045511454446775700145170ustar00rootroot00000000000000/* version 20130522 Jan Mojzis Public domain. */ #include "nanoseconds.h" #include "randombytes.h" #include "uint32_pack.h" #include "uint32_unpack.h" #include "crypto_uint64.h" #include "byte.h" #include "purge.h" #include "dns.h" #define NSS 1 /* nonce separation space, 1 - 3 bytes */ static unsigned char noncekey[16] = {0}; static crypto_uint64 noncecounter = 0; static unsigned char noncemask[NSS]; static unsigned char noncedata[NSS]; void dns_nonce_purge(void) { purge(noncekey, sizeof noncekey); } int dns_nonce_init(const char *ns, const unsigned char *nk) { long long i; noncecounter = nanoseconds(); for (i = 0; i < NSS; ++i) noncemask[i] = 0xff; for (i = 0; i < NSS; ++i) noncedata[i] = 0x00; if (!ns) ns = ""; i = 0; while (i < 8 * NSS) { if (ns[i] != '0' && ns[i] != '1') break; noncemask[i/8] = noncemask[i/8] * 2; noncedata[i/8] = noncedata[i/8] * 2 + ns[i] - '0'; ++i; } if (ns[i] == '0' || ns[i] == '1') return 0; while (i < 8 * NSS) { noncemask[i/8] = noncemask[i/8] * 2 + 1; noncedata[i/8] = noncedata[i/8] * 2; ++i; } if (nk) byte_copy(noncekey, sizeof noncekey, nk); else randombytes(noncekey, sizeof noncekey); return 1; } static void dns_nonce_encrypt(unsigned char *out, crypto_uint64 in, const unsigned char *k) { long long i; crypto_uint32 v0, v1, k0, k1, k2, k3; crypto_uint32 sum = 0; crypto_uint32 delta = 0x9e3779b9; v0 = in; in >>= 32; v1 = in; k0 = uint32_unpack(k + 0); k1 = uint32_unpack(k + 4); k2 = uint32_unpack(k + 8); k3 = uint32_unpack(k + 12); for (i = 0; i < 32; i++) { sum += delta; v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); } uint32_pack(out + 0, v0); uint32_pack(out + 4, v1); } /* n is 12-byte nonce with the following structure: n[0...NSS-1]: random or nonce-separation bits n[NSS...4]: random n[4...11]: TEA encrypted counter */ void dns_nonce(unsigned char *n) { long long x; if (!noncecounter) dns_nonce_init(0, 0); x = nanoseconds(); if (x > noncecounter) noncecounter = x; randombytes(n, 4); for(x = 0; x < NSS; ++x) { n[x] &= noncemask[x]; n[x] += noncedata[x]; } dns_nonce_encrypt((n + 4), ++noncecounter, noncekey); } dq-20240101/dns_packet.c000066400000000000000000000060411454446775700146600ustar00rootroot00000000000000#include "e.h" #include "byte.h" #include "dns.h" long long dns_packet_copy(const unsigned char *buf, long long len, long long pos, unsigned char *out, long long outlen) { while (outlen > 0) { if (pos >= len) { errno = EPROTO; return 0; } *out = buf[pos++]; ++out; --outlen; } return pos; } long long dns_packet_skipname(const unsigned char *buf, long long len, long long pos) { unsigned char ch; for (;;) { if (pos >= len) break; ch = buf[pos++]; if (ch >= 192) return pos + 1; if (ch >= 64) break; if (!ch) return pos; pos += ch; } errno = EPROTO; return 0; } long long dns_packet_getname(const unsigned char *buf, long long len, long long pos, unsigned char **d) { long long loop = 0; long long state = 0; long long firstcompress = 0; long long where; unsigned char ch; unsigned char name[255]; long long namelen = 0; for (;;) { if (pos >= len) goto PROTO; ch = buf[pos++]; if (++loop >= 1000) goto PROTO; if (state > 0) { if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch; --state; } else { while (ch >= 192) { where = ch; where -= 192; where <<= 8; if (pos >= len) goto PROTO; ch = buf[pos++]; if (!firstcompress) firstcompress = pos; pos = where + ch; if (pos >= len) goto PROTO; ch = buf[pos++]; if (++loop >= 1000) goto PROTO; } if (ch >= 64) goto PROTO; if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch; if (!ch) break; state = ch; } } if (!dns_domain_copy(d, name)) return 0; if (firstcompress) return firstcompress; return pos; PROTO: errno = EPROTO; return 0; } long long dns_packet_getname_static(const unsigned char *buf, long long len, long long pos, unsigned char *name) { long long loop = 0; long long state = 0; long long firstcompress = 0; long long where; unsigned char ch; long long namelen = 0; byte_zero(name, 256); for (;;) { if (pos >= len) goto PROTO; ch = buf[pos++]; if (++loop >= 1000) goto PROTO; if (state > 0) { if (namelen + 1 > 255) goto PROTO; name[namelen++] = ch; --state; } else { while (ch >= 192) { where = ch; where -= 192; where <<= 8; if (pos >= len) goto PROTO; ch = buf[pos++]; if (!firstcompress) firstcompress = pos; pos = where + ch; if (pos >= len) goto PROTO; ch = buf[pos++]; if (++loop >= 1000) goto PROTO; } if (ch >= 64) goto PROTO; if (namelen + 1 > 255) goto PROTO; name[namelen++] = ch; if (!ch) break; state = ch; } } if (firstcompress) return firstcompress; return pos; PROTO: errno = EPROTO; return 0; } dq-20240101/dns_rcip.c000066400000000000000000000052071454446775700143510ustar00rootroot00000000000000#include "milliseconds.h" #include "openreadclose.h" #include "byte.h" #include "env.h" #include "stralloc.h" #include "strtoip.h" #include "strtomultiip.h" #include "hasipv6.h" #include "xsocket.h" #include "dns.h" static stralloc data = {0}; static int init(unsigned char ip[256]) { long long i, j, iplen = 0; long long k = 0; byte_zero(ip, 256); iplen = strtomultiip(ip, 256, env_get("DNSCACHEIP")); if (!iplen) { i = openreadclose("/etc/resolv.conf", &data, 64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data, "\n")) return -1; i = 0; for (j = 0; j < data.len; ++j) { if (data.s[j] == '\n') { k = j; while (k >= 0 && ((data.s[k] == ' ') || (data.s[k] == '\t') || (data.s[k] == '\n'))) { data.s[k--] = 0; } if (byte_isequal("nameserver ", 11, data.s + i) || byte_isequal("nameserver\t", 11, data.s + i)) { i += 10; while ((data.s[i] == ' ') || (data.s[i] == '\t')) ++i; if (iplen + 16 <= 256) { if (strtoip(ip + iplen, (char *)data.s + i)) { if (byte_isequal(ip + iplen, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { byte_copy(ip + iplen, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"); } if (byte_isequal(ip + iplen, 16, "\0\0\0\0\0\0\0\0\0\0\377\377\0\0\0\0")) { byte_copy(ip + iplen, 16, "\0\0\0\0\0\0\0\0\0\0\377\377\177\0\0\1"); } iplen += 16; } } } i = j + 1; } } } } if (!iplen) { #ifdef HASIPV6 byte_copy(ip + iplen, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"); iplen += 16; #endif byte_copy(ip + iplen, 16, "\0\0\0\0\0\0\0\0\0\0\377\377\177\0\0\1"); iplen += 16; } return 0; } static int ok = 0; static long long uses = 0; static long long deadline = 0; static unsigned char ip[256]; /* defined if ok */ int dns_resolvconfip(unsigned char *s) { long long now; now = milliseconds(); if (deadline < now) ok = 0; if (uses <= 0) ok = 0; if (!ok) { if (init(ip) == -1) return -1; deadline = 600000 + now; uses = 10000; ok = 1; } --uses; byte_copy(s, sizeof ip, ip); return 0; } dq-20240101/dns_rcrw.c000066400000000000000000000066461454446775700144010ustar00rootroot00000000000000#include #include "milliseconds.h" #include "env.h" #include "byte.h" #include "str.h" #include "openreadclose.h" #include "dns.h" static stralloc data = {0}; static int init(stralloc *rules) { char host[256]; const char *x; int i; int j; int k; int flagds = 0; if (!stralloc_copys(rules,"")) return -1; x = env_get("DNSREWRITEFILE"); if (!x) x = "/etc/dnsrewrite"; i = openreadclose(x,&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,"\n")) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == '\n') { if (!stralloc_catb(rules,data.s + i,j - i)) return -1; while (rules->len) { if (rules->s[rules->len - 1] != ' ') if (rules->s[rules->len - 1] != '\t') if (rules->s[rules->len - 1] != '\r') break; --rules->len; } if (!stralloc_0(rules)) return -1; i = j + 1; } return 0; } x = env_get("LOCALDOMAIN"); if (x) { if (!stralloc_copys(&data,x)) return -1; if (!stralloc_append(&data," ")) return -1; if (!stralloc_copys(rules,"?:")) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == ' ') { if (!stralloc_cats(rules,"+.")) return -1; if (!stralloc_catb(rules,data.s + i,j - i)) return -1; i = j + 1; } if (!stralloc_0(rules)) return -1; if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; } i = openreadclose("/etc/resolv.conf",&data,64); if (i == -1) return -1; if (i) { if (!stralloc_append(&data,"\n")) return -1; i = 0; for (j = 0;j < data.len;++j) if (data.s[j] == '\n') { if (byte_isequal("domain ",7,data.s + i) || byte_isequal("domain\t",7,data.s + i)) { flagds = 1; } if (byte_isequal("search ",7,data.s + i) || byte_isequal("search\t",7,data.s + i)) { flagds = 2; } if (flagds) { if (!stralloc_copys(rules,"?:")) return -1; i += 7; while (i < j) { k = byte_chr(data.s + i,j - i,' '); k = byte_chr(data.s + i,k,'\t'); if (!k) { ++i; continue; } if (!stralloc_cats(rules,"+.")) return -1; if (!stralloc_catb(rules,data.s + i,k)) return -1; i += k; } if (!stralloc_0(rules)) return -1; if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; if (flagds > 1) return 0; } i = j + 1; } if (flagds > 0) return 0; } host[0] = 0; if (gethostname(host,sizeof host) == -1) return -1; host[(sizeof host) - 1] = 0; i = str_chr(host,'.'); if (host[i]) { if (!stralloc_copys(rules,"?:")) return -1; if (!stralloc_cats(rules,host + i)) return -1; if (!stralloc_0(rules)) return -1; } if (!stralloc_cats(rules,"*.:")) return -1; if (!stralloc_0(rules)) return -1; return 0; } static int ok = 0; static long long uses; static long long deadline; static stralloc rules = {0}; /* defined if ok */ int dns_resolvconfrewrite(stralloc *out) { long long now; now = milliseconds(); if (deadline < now) ok = 0; if (uses <= 0) ok = 0; if (!ok) { if (init(&rules) == -1) return -1; deadline = 600000 + now; uses = 10000; ok = 1; } --uses; if (!stralloc_copy(out, &rules)) return -1; return 0; } dq-20240101/dns_resolve.c000066400000000000000000000014761454446775700150770ustar00rootroot00000000000000#include #include "milliseconds.h" #include "byte.h" #include "e.h" #include "dns.h" struct dns_transmit dns_resolve_tx = {0}; int dns_resolve(const unsigned char *q, const unsigned char qtype[2]) { long long deadline, stamp, timeout; unsigned char servers[256]; struct pollfd x[1]; int r; if (dns_resolvconfip(servers) == -1) return -1; if (dns_transmit_start(&dns_resolve_tx, servers, 1, q, qtype, 0) == -1) return -1; for (;;) { stamp = milliseconds(); deadline = 120000 + stamp;; dns_transmit_io(&dns_resolve_tx, x, &deadline); timeout = deadline - stamp; if (timeout <= 0) timeout = 20; poll(x, 1, timeout); r = dns_transmit_get(&dns_resolve_tx, x, stamp); if (r == -1) return -1; if (r == 1) return 0; } } dq-20240101/dns_sortip.c000066400000000000000000000054011454446775700147300ustar00rootroot00000000000000#include "randommod.h" #include "byte.h" #include "dns.h" static void swap(unsigned char *x, long long len, unsigned char *y) { unsigned char t[33]; byte_copy(t, len, x); byte_copy(x, len, y); byte_copy(y, len, t); } void dns_sortip4(unsigned char *s, long long n) { long long i; if (n < 0) return; n >>= 2; while (n > 1) { i = randommod(n); --n; swap(s + (i << 2), 4, s + (n << 2)); } } void dns_sortip(unsigned char *s, long long nn) { long long i; long long n = nn; if (nn < 0) return; n >>= 4; while (n > 1) { i = randommod(n); --n; swap(s + (i << 4), 16, s + (n << 4)); } for (i = 0; i + 16 <= nn; i += 16) { if (!byte_isequal(s + i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + i, 16, s); break; } } } void dns_sortipkey(unsigned char *s, unsigned char *t, long long nn) { long long i, j, k; long long n; unsigned char *key; nn >>=4; n = nn; while (n > 1) { i = randommod(n); --n; swap(s + 16 * i, 16, s + 16 * n); swap(t + 33 * i, 33, t + 33 * n); } n = nn; j = 0; k = 0; for (i = k; i < n; ++i) { key = t + 33 * i; if (key[0] == 1) { swap(s + 16 * i, 16, s + 16 * j); swap(t + 33 * i, 33, t + 33 * j); ++j; } } for (i = k; i < j; ++i) { key = t + 33 * i; if (key[0] != 1) continue; if (!byte_isequal(s + 16 * i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + 16 * i, 16, s + 16 * k); swap(t + 33 * i, 33, t + 33 * k); break; } } k = j; for (i = k; i < n; ++i) { key = t + 33 * i; if (key[0] == 2) { swap(s + 16 * i, 16, s + 16 * j); swap(t + 33 * i, 33, t + 33 * j); ++j; } } for (i = k; i < j; ++i) { key = t + 33 * i; if (key[0] != 2) continue; if (!byte_isequal(s + 16 * i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + 16 * i, 16, s + 16 * k); swap(t + 33 * i, 33, t + 33 * k); break; } } k = j; for (i = k; i < n; ++i) { key = t + 33 * i; if (!byte_isequal(s + 16 * i, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { swap(s + 16 * i, 16, s + 16 * j); swap(t + 33 * i, 33, t + 33 * j); ++j; } } for (i = k; i < j; ++i) { key = t + 33 * i; if (key[0] != 0) continue; if (!byte_isequal(s + 16 * i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + 16 * i, 16, s + 16 * k); swap(t + 33 * i, 33, t + 33 * k); break; } } } dq-20240101/dns_transmit.c000066400000000000000000000421661454446775700152620ustar00rootroot00000000000000#include #include "alloc.h" #include "milliseconds.h" #include "xsocket.h" #include "e.h" #include "byte.h" #include "uint16_pack_big.h" #include "uint16_unpack_big.h" #include "randombytes.h" #include "randommod.h" #include "case.h" #include "str.h" #include "dns.h" #include "crypto_box_curve25519xsalsa20poly1305.h" unsigned char *magicq = DNS_MAGICQ; unsigned char *magicr = DNS_MAGICR; void dns_transmit_magic(const char *mq, const char *mr) { if (mq && str_len(mq) == 8) magicq = (unsigned char *)mq; if (mr && str_len(mr) == 8) magicr = (unsigned char *)mr; } static void basequery(struct dns_transmit *d, unsigned char *query) { long long len; len = dns_domain_length(d->name); byte_copy(query, 2, d->id); byte_copy(query + 2, 10, d->flagrecursive ? "\1\0\0\1\0\0\0\0\0\0" : "\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround"); byte_copy(query + 12, len, d->name); byte_copy(query + 12 + len, 2, d->qtype); byte_copy(query + 14 + len, 2, DNS_C_IN); if (d->paddinglen > 0) { byte_zero(query + 16 + len, d->paddinglen); query[16 + len + d->paddinglen - 1] = 0x80; } } static void regularquery(struct dns_transmit *d) { long long len; d->paddinglen = 0; len = dns_domain_length(d->name) + d->paddinglen; d->querylen = len + 18; uint16_pack_big(d->query, d->querylen - 2); randombytes(d->id, 2); basequery(d, d->query + 2); d->name = d->query + 14; } static void streamlinedquery(struct dns_transmit *d) { long long len; unsigned char nonce[24]; d->paddinglen = (2 + randommod(2)) * 64 - (dns_domain_length(d->name) + 16) % 64; len = dns_domain_length(d->name) + d->paddinglen; d->querylen = len + 86; dns_nonce(d->nonce); byte_copy(nonce, 12, d->nonce); byte_zero(nonce + 12, 12); dns_verbosity_writehex("DNSCurve pk: ", d->pk, 32); dns_verbosity_writehex("DNSCurve nonce: ", nonce, 24); byte_zero(d->query + 38, 32); randombytes(d->id, 2); basequery(d, d->query + 38 + 32); crypto_box_curve25519xsalsa20poly1305_afternm(d->query + 38, d->query + 38, len + 48, nonce, DNS_KEYPTR(d)); uint16_pack_big(d->query, d->querylen - 2); byte_copy(d->query + 2, 8, magicq); byte_copy(d->query + 10, 32, d->pk); byte_copy(d->query + 42, 12, nonce); } static void txtquery(struct dns_transmit *d) { long long len, suffixlen, m; unsigned char nonce[24]; d->paddinglen = 0; len = dns_domain_length(d->name) + d->paddinglen; suffixlen = dns_domain_length(d->suffix); m = dns_base32_bytessize(len + 44); d->querylen = m + suffixlen + 73; dns_nonce(d->nonce); byte_copy(nonce, 12, d->nonce); byte_zero(nonce + 12, 12); dns_verbosity_writehex("DNSCurve pk: ", d->pk, 32); dns_verbosity_writehex("DNSCurve nonce: ", nonce, 24); byte_zero(d->query, 32); randombytes(d->id, 2); basequery(d, d->query + 32); crypto_box_curve25519xsalsa20poly1305_afternm(d->query, d->query, len + 48, nonce, DNS_KEYPTR(d)); byte_copyr(d->query + d->querylen - len - 32, len + 32, d->query + 16); byte_copy(d->query + d->querylen - len - 44, 12, nonce); uint16_pack_big(d->query, d->querylen - 2); randombytes(d->query + 2, 2); byte_copy(d->query + 4, 10, "\0\0\0\1\0\0\0\0\0\0"); dns_base32_encodebytes(d->query + 14,d->query + d->querylen - len - 44, len + 44); dns_base32_encodekey(d->query + 14 + m, d->pk); byte_copy(d->query + 69 + m, suffixlen, d->suffix); dns_verbosity_writedomain("DNSCurve txt: ", d->query + 14); byte_copy(d->query + 69 + m + suffixlen, 2, DNS_T_TXT); byte_copy(d->query + 69 + m + suffixlen + 2, 2, DNS_C_IN); } static void makequery(struct dns_transmit *d) { if (!DNS_HASKEY(d)) { regularquery(d); return; } if (!DNS_ISTXT(d)) { streamlinedquery(d); return; } txtquery(d); } static int getquery(const struct dns_transmit *d, unsigned char *buf, long long *lenp) { long long len; unsigned char nonce[24]; long long pos; unsigned char out[16]; long long namelen; long long txtlen; long long i, j; unsigned char ch; crypto_uint16 datalen; if (!DNS_HASKEY(d)) return 0; len = *lenp; if (!DNS_ISTXT(d)) { if (len < 48) return 1; if (!byte_isequal(buf, 8, magicr)) return 1; if (!byte_isequal(buf + 8, 12, d->nonce)) return 1; byte_copy(nonce, 24, buf + 8); dns_verbosity_writehex("DNSCurve nonce: ", nonce, 24); byte_zero(buf + 16, 16); if (crypto_box_curve25519xsalsa20poly1305_open_afternm(buf + 16, buf + 16, len - 16, nonce, DNS_KEYPTR(d))) return 1; byte_copy(buf, len - 48, buf + 48); *lenp = len - 48; return 0; } pos = dns_packet_copy(buf, len, 0, out, 12); if (!pos) return 1; if (!byte_isequal(out, 2, d->query + 2)) return 1; if (!byte_isequal(out + 2, 10, "\204\0\0\1\0\1\0\0\0\0")) return 1; /* query name might be >255 bytes, so can't use dns_packet_getname */ namelen = dns_domain_length(d->query + 14); if (namelen > len - pos) return 1; if (case_diffb(buf + pos, namelen, d->query + 14)) return 1; pos += namelen; pos = dns_packet_copy(buf, len, pos, out, 16); if (!pos) return 1; if (!byte_isequal(out, 14, "\0\20\0\1\300\14\0\20\0\1\0\0\0\0")) return 1; datalen = uint16_unpack_big(out + 14); if (datalen > len - pos) return 1; j = 4; txtlen = 0; for (i = 0; i < datalen; ++i) { ch = buf[pos + i]; if (!txtlen) txtlen = ch; else { --txtlen; buf[j++] = ch; } } if (txtlen) return 1; if (j < 32) return 1; byte_copy(nonce, 12, d->nonce); byte_copy(nonce + 12, 12, buf + 4); dns_verbosity_writehex("DNSCurve nonce: ", nonce, 24); byte_zero(buf, 16); if (crypto_box_curve25519xsalsa20poly1305_open_afternm(buf, buf, j, nonce, DNS_KEYPTR(d))) return 1; byte_copy(buf, j - 32, buf + 32); *lenp = j - 32; return 0; } static int serverwantstcp(const unsigned char *buf, long long len) { unsigned char out[12]; if (!dns_packet_copy(buf, len, 0, out, 12)) return 1; if (out[2] & 2) return 1; return 0; } static int serverfailed(const unsigned char *buf, long long len) { unsigned char out[12]; unsigned long long rcode; if (!dns_packet_copy(buf, len, 0, out, 12)) return 1; rcode = out[3]; rcode &= 15; if (rcode && (rcode != 3)) { errno = EAGAIN; return 1; } return 0; } static int irrelevant(const struct dns_transmit *d, const unsigned char *buf, long long len) { unsigned char out[12]; unsigned char *dn; long long pos; pos = dns_packet_copy(buf, len, 0, out, 12); if (!pos) return 1; if (!byte_isequal(out, 2, d->id)) return 1; if (out[4] != 0) return 1; if (out[5] != 1) return 1; dn = 0; pos = dns_packet_getname(buf, len, pos, &dn); if (!pos) return 1; if (!dns_domain_equal(dn, d->name)) { alloc_free(dn); return 1; } alloc_free(dn); pos = dns_packet_copy(buf, len, pos, out, 4); if (!pos) return 1; if (!byte_isequal(out, 2, d->qtype)) return 1; if (!byte_isequal(out + 2, 2, DNS_C_IN)) return 1; return 0; } static void packetfree(struct dns_transmit *d) { if (!d->packet) return; alloc_free(d->packet); d->packet = 0; } static void queryfree(struct dns_transmit *d) { if (!d->query) return; alloc_free(d->query); d->query = 0; } static void socketfree(struct dns_transmit *d) { if (!d->s1) return; close(d->s1 - 1); d->s1 = 0; d->s1type = 0; } void dns_transmit_free(struct dns_transmit *d) { queryfree(d); socketfree(d); packetfree(d); } static int randombind(struct dns_transmit *d) { long long j; unsigned char port[2]; long long pos = 0; if (d->s1type == XSOCKET_V4) pos = 0; if (d->s1type == XSOCKET_V6) pos = 16; for (j = 0;j < 10;++j) { uint16_pack_big(port, randommod(64510) + 1025); if (xsocket_bind(d->s1 - 1, d->s1type, d->localip + pos, port, d->scope_id) == 0) return 0; } byte_zero(port, 2); if (xsocket_bind(d->s1 - 1, d->s1type, d->localip + pos, port, d->scope_id) == 0) return 0; return -1; } static const long long timeouts[4] = { 1000, 3000, 11000, 45000 }; static int thisudp(struct dns_transmit *d) { const unsigned char *ip; socketfree(d); while (d->udploop < 4) { for (;d->curserver < 16; ++d->curserver) { ip = d->servers + 16 * d->curserver; if (!byte_isequal(ip, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { makequery(d); d->s1type = XSOCKET_V6; if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { d->s1type = XSOCKET_V4; } if (d->s1type == XSOCKET_V6 && d->flagipv4only) continue; d->s1 = 1 + xsocket_udp(d->s1type); if (!d->s1) { if (errno == EPROTONOSUPPORT) { dns_verbosity_queryfailed(d, 0); continue; } dns_transmit_free(d); return -1; } if (randombind(d) == -1) { if (errno == EPROTONOSUPPORT) { dns_verbosity_queryfailed(d, 0); continue; } dns_transmit_free(d); return -1; } if (xsocket_send(d->s1 - 1, d->s1type, d->query + 2, d->querylen - 2, ip, d->port, d->scope_id) == d->querylen - 2) { dns_verbosity_querysent(d, 0); d->deadline = milliseconds() + timeouts[d->udploop]; d->tcpstate = 0; return 0; } dns_verbosity_queryfailed(d, 0); socketfree(d); } } ++d->udploop; d->curserver = 0; } dns_transmit_free(d); return -1; } static int firstudp(struct dns_transmit *d) { d->curserver = 0; return thisudp(d); } static int nextudp(struct dns_transmit *d) { dns_verbosity_queryfailed(d, 0); ++d->curserver; return thisudp(d); } static int thistcp(struct dns_transmit *d) { const unsigned char *ip; socketfree(d); packetfree(d); for (;d->curserver < 16; ++d->curserver) { ip = d->servers + 16 * d->curserver; if (!byte_isequal(ip, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { makequery(d); d->s1type = XSOCKET_V6; if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { d->s1type = XSOCKET_V4; } if (d->s1type == XSOCKET_V6 && d->flagipv4only) continue; d->s1 = 1 + xsocket_tcp(d->s1type); if (!d->s1) { if (errno == EPROTONOSUPPORT) { dns_verbosity_queryfailed(d, 1); continue; } dns_transmit_free(d); return -1; } if (randombind(d) == -1) { if (errno == EPROTONOSUPPORT) { dns_verbosity_queryfailed(d, 1); continue; } dns_transmit_free(d); return -1; } d->deadline = milliseconds() + 10000; if (xsocket_connect(d->s1 - 1, d->s1type, ip, d->port, d->scope_id) == 0) { d->pos = 0; d->tcpstate = 2; dns_verbosity_querysent(d, 1); return 0; } if ((errno == EINPROGRESS) || (errno == EWOULDBLOCK)) { d->tcpstate = 1; dns_verbosity_querysent(d, 1); return 0; } dns_verbosity_queryfailed(d, 1); socketfree(d); } } dns_transmit_free(d); return -1; } static int firsttcp(struct dns_transmit *d) { d->curserver = 0; return thistcp(d); } static int nexttcp(struct dns_transmit *d) { dns_verbosity_queryfailed(d, 1); ++d->curserver; return thistcp(d); } int dns_transmit_startext(struct dns_transmit *d, const unsigned char servers[256], int flagrecursive, int flagtcp, int flagipv4only, const unsigned char *q, const unsigned char qtype[2], const unsigned char localip[32], const unsigned char port[2], const unsigned char keys[512], const unsigned char pk[32], const unsigned char *suffix) { long long len, suffixlen = 0; dns_transmit_free(d); errno = EIO; /* suffix length */ if (!suffix) suffix = (unsigned char *)""; suffixlen = dns_domain_length(suffix); /* length */ len = dns_domain_length(q); /* allocate enough space */ if (!keys) { d->paddinglen = 0; d->query = alloc(len + 18 + d->paddinglen); } else { d->paddinglen = 3 * 64 - (len + 16) % 64; /* padding MAX */ d->query = alloc(dns_base32_bytessize(len + d->paddinglen + 44) + suffixlen + 73); } if (!d->query) return -1; /* init structure */ byte_copy(d->qtype, 2, qtype); d->servers = servers; if (!localip) { byte_copy(d->localip, 16, xsocket_ANYIP4); byte_copy(d->localip + 16, 16, xsocket_ANYIP6); } else { byte_copy(d->localip, 32, localip); } d->udploop = flagrecursive ? 1 : 0; d->flagrecursive = flagrecursive; d->flagipv4only = flagipv4only; d->name = q; d->keys = keys; d->pk = pk; d->suffix = suffix; if (!port) { uint16_pack_big(d->port, 53); } else { byte_copy(d->port, 2, port); } if (len + 16 > 512 || flagtcp) return firsttcp(d); return firstudp(d); } int dns_transmit_start(struct dns_transmit *d, const unsigned char servers[256], int flagrecursive, const unsigned char *q, const unsigned char qtype[2], const unsigned char localip[32]) { return dns_transmit_startext(d, servers, flagrecursive, 0, 0, q, qtype, localip, 0, 0, 0, 0); } void dns_transmit_io(struct dns_transmit *d, struct pollfd *x, long long *deadline) { x->fd = d->s1 - 1; switch(d->tcpstate) { case 0: case 3: case 4: case 5: x->events = POLLIN; break; case 1: case 2: x->events = POLLOUT; break; } if (d->deadline < *deadline) *deadline = d->deadline; } int dns_transmit_get(struct dns_transmit *d, const struct pollfd *x, const long long when) { unsigned char udpbuf[4097]; unsigned char ch; long long r; int fd; unsigned char ip[16]; unsigned char port[2]; errno = EIO; fd = d->s1 - 1; if (!x->revents) { if (when < d->deadline) return 0; errno = ETIMEDOUT; if (d->tcpstate == 0) return nextudp(d); return nexttcp(d); } if (d->tcpstate == 0) { /* have attempted to send UDP query to each server udploop times have sent query to curserver on UDP socket s */ r = xsocket_recv(fd,d->s1type,udpbuf,sizeof udpbuf,ip,port,0); if (r <= 0) { /* if (errno == ECONNREFUSED) if (d->udploop == 2) return 0; */ return nextudp(d); } if (r + 1 > sizeof udpbuf) return 0; if (getquery(d, udpbuf, &r)) return 0; if (irrelevant(d,udpbuf,r)) return 0; if (serverwantstcp(udpbuf,r)) { dns_verbosity_queryfailedtc(d); return firsttcp(d); } if (serverfailed(udpbuf,r)) { /* if (d->udploop == 2) return 0; */ return nextudp(d); } socketfree(d); d->packetlen = r; d->packet = alloc(d->packetlen); if (!d->packet) { dns_transmit_free(d); return -1; } byte_copy(d->packet,d->packetlen,udpbuf); queryfree(d); dns_verbosity_queryok(d); return 1; } if (d->tcpstate == 1) { /* have sent connection attempt to curserver on TCP socket s pos not defined */ if (!xsocket_connected(fd)) return nexttcp(d); d->pos = 0; d->tcpstate = 2; return 0; } if (d->tcpstate == 2) { /* have connection to curserver on TCP socket s have sent pos bytes of query */ r = write(fd,d->query + d->pos,d->querylen - d->pos); if (r <= 0) return nexttcp(d); d->pos += r; if (d->pos == d->querylen) { d->deadline = milliseconds() + 10000; d->tcpstate = 3; } return 0; } if (d->tcpstate == 3) { /* have sent entire query to curserver on TCP socket s pos not defined */ r = read(fd,&ch,1); if (r <= 0) return nexttcp(d); d->packetlen = ch; d->tcpstate = 4; return 0; } if (d->tcpstate == 4) { /* have sent entire query to curserver on TCP socket s pos not defined have received one byte of packet length into packetlen */ r = read(fd,&ch,1); if (r <= 0) return nexttcp(d); d->packetlen <<= 8; d->packetlen += ch; d->tcpstate = 5; d->pos = 0; d->packet = alloc(d->packetlen); if (!d->packet) { dns_transmit_free(d); return -1; } return 0; } if (d->tcpstate == 5) { /* have sent entire query to curserver on TCP socket s have received entire packet length into packetlen packet is allocated have received pos bytes of packet */ r = read(fd,d->packet + d->pos,d->packetlen - d->pos); if (r <= 0) return nexttcp(d); d->pos += r; if (d->pos < d->packetlen) return 0; socketfree(d); if (getquery(d,d->packet,&d->packetlen)) return nexttcp(d); if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d); if (serverwantstcp(d->packet,d->packetlen)) { dns_verbosity_queryfailedtc(d); return nexttcp(d); } if (serverfailed(d->packet,d->packetlen)) return nexttcp(d); queryfree(d); dns_verbosity_queryok(d); return 1; } return 0; } dq-20240101/dns_verbosity.c000066400000000000000000000161401454446775700154400ustar00rootroot00000000000000#include "stralloc.h" #include "writeall.h" #include "iptostr.h" #include "porttostr.h" #include "numtostr.h" #include "e.h" #include "uint16_unpack_big.h" #include "byte.h" #include "dns.h" int dns_verbosity_flag = 1; const char *dns_verbosity_message = "dns: info: "; void dns_verbosity_setflag(int x) { dns_verbosity_flag = x; } void dns_verbosity_setmessage(const char *x) { dns_verbosity_message = x; } static stralloc out = {0}; void dns_verbosity_writehex(const char *message, const unsigned char *x, long long xlen) { if (dns_verbosity_flag < 3) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (!stralloc_cats(&out, message)) return; while (xlen > 0) { if (!stralloc_catb(&out, "0123456789abcdef" + ((*x >> 4) & 15), 1)) return; if (!stralloc_catb(&out, "0123456789abcdef" + (*x & 15), 1)) return; ++x; --xlen; } if (!stralloc_cats(&out, "\n")) return; writeall(2, out.s, out.len); } void dns_verbosity_writedomain(const char *message, unsigned char *x) { if (dns_verbosity_flag < 3) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (!stralloc_cats(&out, message)) return; if (!dns_domain_todot_cat(&out, x)) return; if (!stralloc_cats(&out, "\n")) return; writeall(2, out.s, out.len); } static const unsigned char *qtypetostr(const unsigned char *qtype) { crypto_uint16 u16; if (byte_isequal(qtype, 2, DNS_T_A)) return (unsigned char *)"A"; if (byte_isequal(qtype, 2, DNS_T_NS)) return (unsigned char *)"NS"; if (byte_isequal(qtype, 2, DNS_T_MX)) return (unsigned char *)"MX"; if (byte_isequal(qtype, 2, DNS_T_ANY)) return (unsigned char *)"ANY"; if (byte_isequal(qtype, 2, DNS_T_PTR)) return (unsigned char *)"PTR"; if (byte_isequal(qtype, 2, DNS_T_TXT)) return (unsigned char *)"TXT"; if (byte_isequal(qtype, 2, DNS_T_SOA)) return (unsigned char *)"SOA"; if (byte_isequal(qtype, 2, DNS_T_SRV)) return (unsigned char *)"SRV"; if (byte_isequal(qtype, 2, DNS_T_AAAA)) return (unsigned char *)"AAAA"; if (byte_isequal(qtype, 2, DNS_T_PTR)) return (unsigned char *)"PTR"; if (byte_isequal(qtype, 2, DNS_T_CNAME)) return (unsigned char *)"CNAME"; u16 = uint16_unpack_big(qtype); return (const unsigned char *)numtostr(0, u16); } void dns_verbosity_resolving(const char *x) { if (dns_verbosity_flag < 3) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (!stralloc_cats(&out, "resolving: ")) return; if (!stralloc_cats(&out, x)) return; if (!stralloc_cats(&out, "\n")) return; writeall(2, out.s, out.len); } void dns_verbosity_resolved(struct dns_data *r, const char *x) { long long j; if (dns_verbosity_flag < 3) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (!stralloc_cats(&out, "resolved: ")) return; if (!stralloc_cats(&out, x)) return; if (!stralloc_cats(&out, ": ")) return; if (!stralloc_cat(&out, &r->fqdn)) return; if (!stralloc_cats(&out, " ")) return; for (j = 0; j + 16 <= r->result.len; j += 16) { if (!stralloc_cats(&out, iptostr(0, r->result.s + j))) return; if (!stralloc_cats(&out, ",")) return; } out.len -= 1; if (!stralloc_cats(&out, "\n")) return; writeall(2, out.s, out.len); } void dns_verbosity_querysent(struct dns_transmit *d, int flagtcp) { if (dns_verbosity_flag < 3) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (DNS_HASKEY(d)) { if (!stralloc_cats(&out, "DNSCurve query: ")) return; } else { if (!stralloc_cats(&out, "DNS query: ")) return; } if (!dns_domain_todot_cat(&out, d->name)) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, qtypetostr(d->qtype))) return; if (!stralloc_cats(&out, " ")) return; if (flagtcp) { if (!stralloc_cats(&out, "TCP ")) return; } else { if (!stralloc_cats(&out, "UDP ")) return; } if (!stralloc_cats(&out, iptostr(0, d->servers + 16 * d->curserver))) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, porttostr(0, d->port))) return; if (!stralloc_cats(&out, ": sent\n")) return; writeall(2, out.s, out.len); } void dns_verbosity_queryfailed(struct dns_transmit *d, int flagtcp) { if (dns_verbosity_flag < 2) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (DNS_HASKEY(d)) { if (!stralloc_cats(&out, "DNSCurve query: ")) return; } else { if (!stralloc_cats(&out, "DNS query: ")) return; } if (!dns_domain_todot_cat(&out, d->name)) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, qtypetostr(d->qtype))) return; if (!stralloc_cats(&out, " ")) return; if (flagtcp) { if (!stralloc_cats(&out, "TCP ")) return; } else { if (!stralloc_cats(&out, "UDP ")) return; } if (!stralloc_cats(&out, iptostr(0, d->servers + 16 * d->curserver))) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, porttostr(0, d->port))) return; if (!stralloc_cats(&out, ": failed: ")) return; if (!stralloc_cats(&out, e_str(errno))) return; if (!stralloc_cats(&out, "\n")) return; writeall(2, out.s, out.len); } void dns_verbosity_queryfailedtc(struct dns_transmit *d) { if (dns_verbosity_flag < 2) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (DNS_HASKEY(d)) { if (!stralloc_cats(&out, "DNSCurve query: ")) return; } else { if (!stralloc_cats(&out, "DNS query: ")) return; } if (!dns_domain_todot_cat(&out, d->name)) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, qtypetostr(d->qtype))) return; if (!stralloc_cats(&out, " ")) return; if (d->tcpstate > 0) { if (!stralloc_cats(&out, "TCP ")) return; } else { if (!stralloc_cats(&out, "UDP ")) return; } if (!stralloc_cats(&out, iptostr(0, d->servers + 16 * d->curserver))) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, porttostr(0, d->port))) return; if (!stralloc_cats(&out, ": failed: truncated\n")) return; writeall(2, out.s, out.len); } void dns_verbosity_queryok(struct dns_transmit *d) { if (dns_verbosity_flag < 3) return; if (!stralloc_copys(&out, dns_verbosity_message)) return; if (DNS_HASKEY(d)) { if (!stralloc_cats(&out, "DNSCurve query: ")) return; } else { if (!stralloc_cats(&out, "DNS query: ")) return; } if (!dns_domain_todot_cat(&out, d->name)) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, qtypetostr(d->qtype))) return; if (!stralloc_cats(&out, " ")) return; if (d->tcpstate > 0) { if (!stralloc_cats(&out, "TCP ")) return; } else { if (!stralloc_cats(&out, "UDP ")) return; } if (!stralloc_cats(&out, iptostr(0, d->servers + 16 * d->curserver))) return; if (!stralloc_cats(&out, " ")) return; if (!stralloc_cats(&out, porttostr(0, d->port))) return; if (!stralloc_cats(&out, ": received\n")) return; writeall(2, out.s, out.len); } dq-20240101/dq.c000066400000000000000000000226611454446775700131570ustar00rootroot00000000000000/* * 20130521 * Jan Mojzis * Public domain. */ #include #include "dns.h" #include "strtonum.h" #include "case.h" #include "die.h" #include "e.h" #include "randombytes.h" #include "byte.h" #include "stralloc.h" #include "printpacket.h" #include "writeall.h" #include "milliseconds.h" #include "str.h" #include "uint16_pack_big.h" #include "uint16_unpack_big.h" #include "portparse.h" #include "base32decode.h" #include "hexdecode.h" #include "strtoip.h" #include "keyparse.h" #include "typeparse.h" #include "purge.h" #include "crypto_box_curve25519xsalsa20poly1305.h" #define USAGE "\ \n\ dq: usage:\n\ \n\ name:\n\ dq - DNS/DNSCurve query tool\n\ \n\ synopsis:\n\ dq [options] type fqdn [host]\n\ dq -a [options] type fqdn host\n\ \n\ options:\n\ -v (optional): print extra information\n\ -r (optional): send recursive query (default)\n\ -a (optional): send authoritative query\n\ -u (optional): use UDP (default)\n\ -t (optional): use TCP\n\ -s (optional): send DNSCurve query in streamlined format (default), ignored for regular DNS queries\n\ -S suffix (optional): send DNSCurve query in TXT format using suffix suffix, ignored for regular DNS queries\n\ -T timeout (optional): give up on the DNS/DNSCurve query attempt after timeout seconds <1-60> (default 60)\n\ -p port (optional): send query to port port (default 53)\n\ -k key (optional): send DNSCurve query and use servers public-key key\n\ type: DNS query type (A, NS, MX, ANY, PTR, TXT, SOA, SRV, AAAA, AXFR, CNAME or numeric type)\n\ fqdn: fully qualified domain name\n\ host: DNS server, hostname or IP address\n\ \n\ environment:\n\ DNSCACHEIP: use IP address $DNSCACHEIP instead of 'nameserver' lines from /etc/resolv.conf\n\ LOCALDOMAIN: use space separated names from $LOCALDOMAIN instead of 'search' line from /etc/resolv.conf\n\ DNSREWRITEFILE: use $DNSREWRITEFILE file instead of /etc/dnsrewrite\n\ \n\ notes:\n\ dq rewrites IP address to *.in-addr.arpa or *.ip6.arpa for PTR queries e.g.:\n\ 127.0.0.1 -> 1.0.0.127.in-addr.arpa\n\ ::1 -> 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\n\ \n\ recursive examples:\n\ dq any dnscurve.cz\n\ dq any dnscurve.cz 8.8.8.8\n\ env DNSCACHEIP=8.8.8.8 dq any dnscurve.cz\n\ dq ptr 1.0.0.127.in-addr.arpa\n\ dq ptr 127.0.0.1\n\ dq ptr ::1\n\ dq ptr 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\n\ \n\ authoritative examples:\n\ dq -a any dnscurve.cz uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq.ns.dnscurve.cz\n\ dq -a -S cz any dnscurve.cz uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq.ns.dnscurve.cz\n\ dq -a -k uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq any dnscurve.cz 2a02:2b88:2:1::127d:1\n\ \n\ " #define FATAL "dq: fatal: " #define DEBUG "dq: debug: " static int flagverbose = 1; static int flagrecursive = 1; static int flagtcp = 0; #define NUMIP 16 static struct global { int x; unsigned char servers[16 * NUMIP]; unsigned char keys[33 * NUMIP]; unsigned char pk[32]; unsigned char sk[32]; stralloc out; unsigned char qtype[2]; unsigned char q[256]; struct dns_transmit tx; struct dns_data r; } g = {0}; static unsigned char *suffix = 0; static const char *transport = "regular DNS"; static const char *portstr = "53"; static unsigned char port[2]; static char *keystr = 0; static const char *timeoutstr = "60"; static long long maxtimeout; static void die_usage(const char *s) { if (s) die_4(100, USAGE, FATAL, s, "\n"); die_1(100, USAGE); } static void die_fatal(const char *trouble, const char *fn) { purge(&g, sizeof g); if (errno) { if (fn) die_7(111, FATAL, trouble, " ", fn, ": ", e_str(errno), "\n"); die_5(111, FATAL, trouble, ": ", e_str(errno), "\n"); } if (fn) die_5(111, FATAL, trouble, " ", fn, "\n"); die_3(111, FATAL, trouble, "\n"); } static int resolve(void) { long long deadline, stamp, timeout, max; struct pollfd x[1]; int r; if (dns_transmit_startext(&g.tx, g.servers, flagrecursive, flagtcp, 0, g.q, g.qtype, 0, port, g.keys, g.pk, suffix) == -1) return -1; max = maxtimeout * 1000 + milliseconds(); for (;;) { stamp = milliseconds(); if (stamp > max) { errno = ETIMEDOUT; dns_verbosity_queryfailed(&g.tx, flagtcp); return -1; } deadline = max; dns_transmit_io(&g.tx, x, &deadline); timeout = deadline - stamp; if (timeout <= 0) timeout = 20; poll(x, 1, timeout); r = dns_transmit_get(&g.tx, x, stamp); if (r == -1) return -1; if (r == 1) break; } return 0; } static int nameparse(unsigned char *s, const char *x) { unsigned char ip[16]; if (!x) return 0; if (byte_isequal(g.qtype, 2, DNS_T_PTR)) { if (strtoip(ip, x)) x = dns_iptoname(0, ip); } return dns_domain_fromdot_static(s, (unsigned char *)x, str_len(x)); } static int ipget(const char *host) { if (host) { if (dns_ip_qualify(&g.r, host) == -1) return 0; if (g.r.result.len == 0) return 0; if (g.r.result.len > sizeof g.servers) g.r.result.len = sizeof g.servers; byte_copy(g.servers, g.r.result.len, g.r.result.s); if (g.r.dnscurvekey && !g.keys[0]) { byte_copy(g.keys + 1, 32, g.r.dnscurvekey); g.keys[0] = 1; } } else { if (!flagrecursive) return 0; if (dns_resolvconfip(g.servers) == -1) return 0; } return 1; } static void oops(void) { die_fatal("unable to parse", 0); } int main(int argc, char **argv) { crypto_uint16 u16; char *x; long long i; if (!argv[0]) die_usage(0); for (;;) { if (!argv[1]) break; if (argv[1][0] != '-') break; x = *++argv; if (x[0] == '-' && x[1] == 0) break; if (x[0] == '-' && x[1] == '-' && x[2] == 0) break; while (*++x) { if (*x == 'q') { flagverbose = 0; continue; } if (*x == 'Q') { flagverbose = 1; continue; } if (*x == 'v') { if (flagverbose >= 2) flagverbose = 3; else flagverbose = 2; continue; } if (*x == 'a') { flagrecursive = 0; continue; } if (*x == 'r') { flagrecursive = 1; continue; } if (*x == 't') { flagtcp = 1; continue; } if (*x == 'u') { flagtcp = 0; continue; } if (*x == 's') { dns_domain_free(&suffix); continue; } if (*x == 'S') { if (x[1]) { dns_domain_fromdot(&suffix, (unsigned char *)x + 1, str_len(x + 1)); break; } if (argv[1]) { ++argv; dns_domain_fromdot(&suffix, (unsigned char *)*argv, str_len(*argv)); break; } } if (*x == 'p') { if (x[1]) { portstr = x + 1; break; } if (argv[1]) { portstr = *++argv; break; } } if (*x == 'k') { if (x[1]) { keystr = x + 1; ; break; } if (argv[1]) { keystr = *++argv; break; } } if (*x == 'T') { if (x[1]) { timeoutstr = x + 1; break; } if (argv[1]) { timeoutstr = *++argv; break; } } die_usage(0); } } if (!strtonum(&maxtimeout, timeoutstr) || maxtimeout < 1 || maxtimeout > 60) die_usage("unable to parse timeout, timeout must be an integer between 1 and 60"); dns_verbosity_setflag(flagverbose); dns_verbosity_setmessage(DEBUG); if (!portparse(port, portstr)) die_usage("unable to parse port"); if (keystr) { if (!keyparse(g.keys + 1, 32, keystr)) die_usage("unable to parse key"); g.keys[0] = 1; } if (!typeparse(g.qtype, *++argv)) die_usage("unable to parse type"); if (!nameparse(g.q, *++argv)) die_usage("unable to parse fqdn/IP"); if (!*++argv) { if (!flagrecursive) die_usage("missing host"); byte_zero(g.keys, sizeof g.keys); } if (!ipget(*argv)) die_usage("unable to figure out IP from host"); if (g.keys[0] > 0) { crypto_box_curve25519xsalsa20poly1305_keypair(g.pk, g.sk); crypto_box_curve25519xsalsa20poly1305_beforenm(g.keys + 1, g.keys + 1, g.sk); for (i = 0; i + 33 < sizeof g.keys; ++i) g.keys[i + 33] = g.keys[i]; if (suffix) { for (i = 0; i < NUMIP; ++i) g.keys[33 * i] = 2; transport = "txt DNSCurve"; } else { transport = "streamlined DNSCurve"; } } if (!stralloc_copys(&g.out, "")) oops(); u16 = uint16_unpack_big(g.qtype); if (!stralloc_catnum(&g.out, u16)) oops(); if (!stralloc_cats(&g.out, " ")) oops(); if (!dns_domain_todot_cat(&g.out, g.q)) oops(); if (!stralloc_cats(&g.out, " - ")) oops(); if (!stralloc_cats(&g.out, transport)) oops(); if (!stralloc_cats(&g.out, ":\n")) oops(); if (byte_isequal(g.qtype, 2, DNS_T_AXFR)) { if (!stralloc_cats(&g.out, "axfr not supported, use axfr-get\n")) oops(); } else if (resolve() == -1) { if (!stralloc_cats(&g.out, e_str(errno))) oops(); if (!stralloc_cats(&g.out, "\n")) oops(); } else { if (g.tx.packetlen < 4) oops(); if (flagrecursive) { g.tx.packet[2] &= ~1; g.tx.packet[3] &= ~128; } if (!printpacket_cat(&g.out, g.tx.packet, g.tx.packetlen)) oops(); } if (writeall(1, g.out.s, g.out.len) == -1) die_fatal("unable to write output", 0); purge(&g, sizeof g); die_0(0); return 111; } dq-20240101/dqcache-makekey.c000066400000000000000000000010361454446775700155600ustar00rootroot00000000000000/* 20160325 Jan Mojzis Public domain. */ #include #include "randombytes.h" #include "writeall.h" static unsigned char sk[32]; static unsigned char out[65]; int main(int argc, char **argv) { long long i; randombytes(sk, sizeof sk); for (i = 0; i < 32; ++i) { out[2 * i + 0] = "0123456789abcdef"[15 & (int) (sk[i] >> 4)]; out[2 * i + 1] = "0123456789abcdef"[15 & (int) (sk[i] >> 0)]; } out[2 * i] = '\n'; if (writeall(1, out, sizeof out) == -1) _exit(111); fsync(1); _exit(0); } dq-20240101/dqcache-start.c000066400000000000000000000031351454446775700152710ustar00rootroot00000000000000#include #include #include /* workaround for *BSD #include */ extern int setenv(const char *, const char *, int); #include "numtostr.h" #include "strtonum.h" #include "e.h" #include "die.h" static const char *account; static const char *root; static struct passwd *pw; static long long uid, gid; #define USAGE "dqcache-start: usage: dqcache-start root-directory account child\n" #define FATAL "dqcache-start: fatal: " int main(int argc, char **argv) { root = *++argv; if (!root) die_1(100, USAGE); account = *++argv; if (!account || !*++argv) die_1(100, USAGE); pw = getpwnam(account); if (pw) { uid = pw->pw_uid; gid = pw->pw_gid; } else { if (!strtonum(&uid, account) || uid < 0) die_4(111, FATAL, "unknown account ", account, "\n"); gid = uid; } if (chdir(root) == -1) die_6(111, FATAL, "unable to change directory to ", root, ": ", e_str(errno), "\n"); if (chown("dump", uid, gid) == -1) die_6(111, FATAL, "unable to change owner on ", root, "/dump: ", e_str(errno), "\n"); if (setenv("ROOT", root, 1) == -1) die_4(111, FATAL, "unable to set env. variable ROOT: ", e_str(errno), "\n"); if (setenv("GID", numtostr(0, gid), 1) == -1) die_4(111, FATAL, "unable to set env. variable GID: ", e_str(errno), "\n"); if (setenv("UID", numtostr(0, uid), 1) == -1) die_4(111, FATAL, "unable to set env. variable UID: ", e_str(errno), "\n"); execvp(*argv, argv); die_6(111, FATAL, "unable to run ", *argv, ": ", e_str(errno), "\n"); return 111; } dq-20240101/dqcache.c000066400000000000000000000344451454446775700141460ustar00rootroot00000000000000#include #include #include #include "env.h" #include "byte.h" #include "xsocket.h" #include "strtoip.h" #include "randombytes.h" #include "crypto_uint64.h" #include "query.h" #include "die.h" #include "warn.h" #include "e.h" #include "numtostr.h" #include "strtonum.h" #include "cache.h" #include "response.h" #include "log.h" #include "roots.h" #include "hexparse.h" #include "alloc.h" #include "milliseconds.h" #include "blocking.h" #include "uint16_pack_big.h" #include "uint16_unpack_big.h" #include "portparse.h" #include "droproot.h" #include "okclient.h" #include "purge.h" static int flagokclient = 0; static int packetquery(unsigned char *buf, long long len, unsigned char **q, unsigned char qtype[2], unsigned char qclass[2], unsigned char id[2]) { long long pos; unsigned char header[12]; errno = EPROTO; pos = dns_packet_copy(buf, len, 0, header, 12); if (!pos) return 0; if (header[2] & 128) return 0; /* must not respond to responses */ if (!(header[2] & 1)) return 0; /* do not respond to non-recursive queries */ if (header[2] & 120) return 0; if (header[2] & 2) return 0; if (!byte_isequal(header + 4, 2, "\0\1")) return 0; pos = dns_packet_getname(buf, len, pos, q); if (!pos) return 0; pos = dns_packet_copy(buf, len, pos, qtype, 2); if (!pos) return 0; pos = dns_packet_copy(buf, len, pos, qclass, 2); if (!pos) return 0; if (!byte_isequal(qclass, 2, DNS_C_IN) && !byte_isequal(qclass, 2, DNS_C_ANY)) return 0; byte_copy(id, 2, header); return 1; } static unsigned char myport[2] = {0, 53}; static unsigned char myipoutgoing[32]; static unsigned char myipincoming[16]; static int mytypeincoming = XSOCKET_V6; static unsigned char buf[1024]; static int udp53; #define MAXUDPDUPLICATED 10 #define MAXUDP 200 static struct udpclient { struct query q; long long start; crypto_uint64 active; /* query number, if active; otherwise 0 */ struct pollfd *io; unsigned char ip[16]; unsigned char port[2]; long long scope_id; unsigned char id[2]; } u[MAXUDP]; static void u_drop(long long j) { if (!u[j].active) return; log_querydrop(&u[j].active); u[j].active = 0; --log_uactive; } static void u_respond(long long j) { if (!u[j].active) return; response_id(u[j].id); if (response_len > 512) response_tc(); xsocket_send(udp53, mytypeincoming, response, response_len, u[j].ip, u[j].port, u[j].scope_id); log_querydone(&u[j].active, response_len); u[j].active = 0; --log_uactive; } static long long u_duplicatequerycount(unsigned char *q, unsigned char *qtype) { long long j, c = 0; struct query *z; for (j = 0; j < MAXUDP; ++j) { if (!u[j].active) continue; z = &u[j].q; if (!byte_isequal(z->type, 2, qtype)) continue; if (!dns_domain_equal(z->name[0], q)) continue; ++c; } return c; } static void u_new(void) { long long j; long long i; struct udpclient *x; long long len; static unsigned char *q = 0; unsigned char qtype[2]; unsigned char qclass[2]; crypto_uint16 port; for (j = 0; j < MAXUDP; ++j) if (!u[j].active) break; if (j >= MAXUDP) { j = 0; for (i = 1;i < MAXUDP;++i) if (u[i].start < u[j].start) j = i; errno = ETIMEDOUT; u_drop(j); } x = u + j; x->start = milliseconds(); len = xsocket_recv(udp53, mytypeincoming, buf, sizeof buf, x->ip, x->port, &x->scope_id); if (len == -1) return; if (len >= sizeof buf) return; port = uint16_unpack_big(x->port); if (port < 1024) if (port != 53) return; if (!flagokclient && !okclient(x->ip)) { log_queryreject(x->ip, x->port, 0, 0, 0, "IP address not allowed"); return; } if (!packetquery(buf, len, &q, qtype, qclass, x->id)) { log_queryreject(x->ip, x->port, x->id, q, qtype, "bad query"); return; } if (u_duplicatequerycount(q, qtype) >= MAXUDPDUPLICATED) { log_queryreject(x->ip, x->port, x->id, q, qtype, "too many duplicate queries"); return; } x->active = ++log_numqueries; ++log_uactive; log_query(&x->active, x->ip, x->port, x->id, q, qtype); switch(query_start(&x->q, q, qtype, qclass, myipoutgoing)) { case -1: u_drop(j); return; case 1: u_respond(j); } } static int tcp53; #define MAXTCP 20 struct tcpclient { struct query q; long long start; long long timeout; crypto_uint64 active; /* query number or 1, if active; otherwise 0 */ struct pollfd *io; unsigned char ip[16]; /* send response to this address */ unsigned char port[2]; /* send response to this port */ long long scope_id; int type; unsigned char id[2]; int tcp; /* open TCP socket, if active */ int state; unsigned char *buf; /* 0, or dynamically allocated of length len */ long long len; long long pos; } t[MAXTCP]; /* state 1: buf 0; normal state at beginning of TCP connection state 2: buf 0; have read 1 byte of query packet length into len state 3: buf allocated; have read pos bytes of buf state 0: buf 0; handling query in q state -1: buf allocated; have written pos bytes */ static void t_free(long long j) { if (!t[j].buf) return; alloc_free(t[j].buf); t[j].buf = 0; } static void t_timeout(long long j) { if (!t[j].active) return; t[j].timeout = milliseconds() + 10000; } static void t_close(long long j) { if (!t[j].active) return; t_free(j); log_tcpclose(t[j].ip, t[j].port); close(t[j].tcp); t[j].active = 0; --log_tactive; } static void t_drop(long long j) { log_querydrop(&t[j].active); errno = EPIPE; t_close(j); } static void t_respond(long long j) { if (!t[j].active) return; log_querydone(&t[j].active, response_len); response_id(t[j].id); t[j].len = response_len + 2; t_free(j); t[j].buf = alloc(response_len + 2); if (!t[j].buf) { t_close(j); return; } uint16_pack_big(t[j].buf, response_len); byte_copy(t[j].buf + 2, response_len, response); t[j].pos = 0; t[j].state = -1; } static void t_rw(long long j) { struct tcpclient *x; unsigned char ch; static unsigned char *q = 0; unsigned char qtype[2]; unsigned char qclass[2]; long long r; x = t + j; if (x->state == -1) { r = write(x->tcp, x->buf + x->pos, x->len - x->pos); if (r <= 0) { t_close(j); return; } x->pos += r; if (x->pos == x->len) { t_free(j); x->state = 1; /* could drop connection immediately */ } return; } if (x->state == 1) { r = read(x->tcp, &ch, 1); if (r == 0) { errno = EPIPE; t_close(j); return; } if (r < 0) { t_close(j); return; } x->len = (unsigned char) ch; x->len <<= 8; x->state = 2; return; } if (x->state == 2) { r = read(x->tcp, &ch, 1); if (r == 0) { errno = EPIPE; t_close(j); return; } if (r < 0) { t_close(j); return; } x->len += (unsigned char) ch; if (!x->len) { errno = EPROTO; t_close(j); return; } x->buf = alloc(x->len); if (!x->buf) { t_close(j); return; } x->pos = 0; x->state = 3; return; } if (x->state != 3) return; /* impossible */ r = read(x->tcp, x->buf + x->pos, x->len - x->pos); if (r == 0) { errno = EPIPE; t_close(j); return; } if (r < 0) { t_close(j); return; } x->pos += r; if (x->pos < x->len) return; if (!packetquery(x->buf, x->len, &q, qtype, qclass, x->id)) { log_queryreject(x->ip, x->port, x->id, q, qtype, "bad query"); t_close(j); return; } x->active = ++log_numqueries; log_query(&x->active, x->ip, x->port, x->id, q, qtype); switch(query_start(&x->q,q,qtype,qclass,myipoutgoing)) { case -1: t_drop(j); return; case 1: t_respond(j); return; } t_free(j); x->state = 0; } static void t_new(void) { long long i; long long j; struct tcpclient *x; crypto_uint16 port; for (j = 0;j < MAXTCP;++j) if (!t[j].active) break; if (j >= MAXTCP) { j = 0; for (i = 1;i < MAXTCP;++i) if (t[i].start < t[j].start) j = i; errno = ETIMEDOUT; if (t[j].state == 0) t_drop(j); else t_close(j); } x = t + j; x->start = milliseconds(); x->tcp = xsocket_accept(tcp53, mytypeincoming, x->ip, x->port, &x->scope_id); if (x->tcp == -1) return; port = uint16_unpack_big(x->port); if (port < 1024) if (port != 53) { close(x->tcp); return; } if (!flagokclient && !okclient(x->ip)) { log_queryreject(x->ip, x->port, 0, 0, 0, "IP address not allowed"); close(x->tcp); return; } blocking_disable(x->tcp); x->active = 1; ++log_tactive; x->state = 1; t_timeout(j); log_tcpopen(x->ip,x->port); } static struct pollfd io[3 + MAXUDP + MAXTCP]; static struct pollfd *udp53io; static struct pollfd *tcp53io; static void doit(void) { long long j; long long deadline; long long stamp; long long timeout; long long iolen; int r; for (;;) { stamp = milliseconds(); deadline = stamp + 120000; iolen = 0; udp53io = io + iolen++; udp53io->fd = udp53; udp53io->events = POLLIN; tcp53io = io + iolen++; tcp53io->fd = tcp53; tcp53io->events = POLLIN; for (j = 0;j < MAXUDP;++j) if (u[j].active) { u[j].io = io + iolen++; query_io(&u[j].q,u[j].io,&deadline); } for (j = 0;j < MAXTCP;++j) if (t[j].active) { t[j].io = io + iolen++; if (t[j].state == 0) query_io(&t[j].q,t[j].io,&deadline); else { if (t[j].timeout < deadline) deadline = t[j].timeout; t[j].io->fd = t[j].tcp; t[j].io->events = (t[j].state > 0) ? POLLIN : POLLOUT; } } timeout = deadline - stamp; if (timeout < 0) timeout = 10; poll(io, iolen, timeout); for (j = 0;j < MAXUDP;++j) if (u[j].active) { r = query_get(&u[j].q,u[j].io,stamp); if (r == -1) u_drop(j); if (r == 1) u_respond(j); } for (j = 0;j < MAXTCP;++j) if (t[j].active) { if (t[j].io->revents) t_timeout(j); if (t[j].state == 0) { r = query_get(&t[j].q,t[j].io,stamp); if (r == -1) t_drop(j); if (r == 1) t_respond(j); } else if (t[j].io->revents || (t[j].timeout < stamp)) t_rw(j); } if (udp53io) if (udp53io->revents) u_new(); if (tcp53io) if (tcp53io->revents) t_new(); } } static unsigned char skseed[32]; static unsigned char sk[32 + 16]; #define FATAL "dqcache: fatal: " #define WARNING "dqcache: warning: " static void removesecrets(void) { query_purge(); dns_nonce_purge(); purge(skseed, sizeof skseed); purge(sk, sizeof sk); } static void die_fatal(const char *trouble, const char *fn) { removesecrets(); if (errno) { if (fn) die_7(111, FATAL, trouble, " ", fn, ": ", e_str(errno), "\n"); die_5(111, FATAL, trouble, ": ", e_str(errno), "\n"); } if (fn) die_5(111, FATAL, trouble, " ", fn, "\n"); die_3(111, FATAL, trouble, "\n"); } static char *dnscurvetype = 0; static void reload(int sig) { if (!roots_init(dnscurvetype)) die_fatal("unable to read servers", 0); } static void dump(int sig){ if (cache_dump() == -1) warn_4(WARNING, "unable to dump cache: ", e_str(errno), "\n"); } static void exitasap(int sig){ removesecrets(); dump(0); die_0(0); } static void clean(int sig){ cache_clean(); } int main(int argc, char **argv) { long long cachesize, ll; unsigned char port[2]; char *x; signal(SIGPIPE, SIG_IGN); signal(SIGHUP, reload); signal(SIGALRM, dump); signal(SIGINT, clean); signal(SIGTERM, exitasap); if (!strtoip(myipincoming, env_get("IP"))) { byte_copy(myipincoming, 16, xsocket_ANYIP); } mytypeincoming = xsocket_type(myipincoming); udp53 = xsocket_udp(mytypeincoming); if (udp53 == -1) die_fatal("unable to create UDP socket", 0); if (xsocket_bind_reuse(udp53, mytypeincoming, myipincoming, myport, 0) == -1) die_fatal("unable to bind UDP socket", 0); tcp53 = xsocket_tcp(mytypeincoming); if (tcp53 == -1) die_fatal("unable to create TCP socket", 0); if (xsocket_bind_reuse(tcp53, mytypeincoming, myipincoming, myport, 0) == -1) die_fatal("unable to bind TCP socket", 0); randombytes(skseed, sizeof skseed); x = env_get("SECRETKEY"); if (x) { if (!hexparse(skseed, sizeof skseed, x)) { warn_2(WARNING, "unable to parse $SECRETKEY\n"); randombytes(skseed, sizeof skseed); } while (*x) { *x = 0; ++x; } } droproot(FATAL); dns_keys_derive(sk, sizeof sk, skseed); query_init(sk); x = env_get("NONCESTART"); if (!dns_nonce_init(x, sk + 32)) die_fatal("too long $NONCESTART", x); purge(skseed, sizeof skseed); purge(sk, sizeof sk); dns_transmit_magic(env_get("QUERYMAGIC"), env_get("RESPONSEMAGIC")); xsocket_tryreservein(udp53, 131072); if (!strtoip(myipoutgoing, env_get("IPSEND4"))) { byte_copy(myipoutgoing, 16, xsocket_ANYIP4); } if (!strtoip(myipoutgoing + 16, env_get("IPSEND6"))) { byte_copy(myipoutgoing + 16, 16, xsocket_ANYIP6); } if (portparse(port, env_get("REMOTEPORT"))) { query_remoteport(port); } if (!strtonum(&cachesize, env_get("CACHESIZE"))) { cachesize = 10000000; } if (!cache_init(cachesize)) die_fatal("not enough memory for cache of size", numtostr(0, cachesize)); if (env_get("HIDETTL")) response_hidettl(); if (env_get("FORWARDONLY")) query_forwardonly(); if (env_get("TCPONLY")) query_tcponly(); if (env_get("DISABLEIPV6")) query_ipv4only(); if (strtonum(&ll, env_get("MINTTL"))) query_minttl(ll); if (env_get("OKCLIENT")) flagokclient = 1; dnscurvetype = env_get("DNSCURVETYPE"); query_dnscurvetype(dnscurvetype); if (!roots_init(dnscurvetype)) die_fatal("unable to read servers", 0); if (xsocket_listen(tcp53, 20) == -1) die_fatal("unable to listen on TCP socket", 0); if (cache_load() == -1) warn_4(WARNING, "unable to load cache: ", e_str(errno), "\n"); log_startup(); doit(); return 111; } dq-20240101/droproot.c000066400000000000000000000030771454446775700144230ustar00rootroot00000000000000#include #include #include #include "env.h" #include "die.h" #include "strtonum.h" #include "e.h" #include "droproot.h" static void die_fatal(const char *fatal, const char *trouble, const char *fn) { if (errno) { if (fn) die_7(111, fatal, trouble, " ", fn, ": ", e_str(errno), "\n"); die_5(111, fatal, trouble, ": ", e_str(errno), "\n"); } if (fn) die_5(111, fatal, trouble, " ", fn, "\n"); die_3(111, fatal, trouble, "\n"); } void droproot(const char *fatal) { char *x; long long id; gid_t gid; uid_t uid; x = env_get("ROOT"); if (!x) die_fatal(fatal, "$ROOT not set", 0); if (chdir(x) == -1) die_fatal(fatal, "unable to chdir to", x); if (chroot(".") == -1) die_fatal(fatal, "unable to chroot to", x); x = env_get("GID"); if (!x) die_fatal(fatal, "$GID not set", 0); if (!strtonum(&id, x)) die_fatal(fatal, "unable to parse $GID", 0); gid = id; if (id != (long long)gid) die_fatal(fatal, "bad $GID", 0); if (setgroups(1, &gid) == -1) die_fatal(fatal, "unable to setgid", 0); if (setgid(gid) == -1) die_fatal(fatal, "unable to setgid", 0); if (getgid() != gid) die_fatal(fatal, "unable to setgid", 0); x = env_get("UID"); if (!x) die_fatal(fatal, "$UID not set", 0); if (!strtonum(&id, x)) die_fatal(fatal, "unable to parse $UID", 0); uid = id; if (id != (long long)uid) die_fatal(fatal, "bad $UID", 0); if (setuid(uid) == -1) die_fatal(fatal, "unable to setuid", 0); if (getuid() != uid) die_fatal(fatal, "unable to setuid", 0); } dq-20240101/droproot.h000066400000000000000000000001351454446775700144200ustar00rootroot00000000000000#ifndef _DROPROOT_H____ #define _DROPROOT_H____ extern void droproot(const char *); #endif dq-20240101/e.c000066400000000000000000000070341454446775700127740ustar00rootroot00000000000000#include "e.h" #define X(e,s) if (i == e) return s; const char *e_str(int i) { X(0,"no error"); X(EINTR,"interrupted system call") X(ENOMEM,"out of memory") X(ENOENT,"file does not exist") X(ETXTBSY,"text busy") X(EIO,"input/output error") X(EEXIST,"file already exists") X(ETIMEDOUT,"timed out") X(EINPROGRESS,"operation in progress") X(EAGAIN,"temporary failure") X(EWOULDBLOCK,"input/output would block") X(EPIPE,"broken pipe") X(EPERM,"permission denied") X(EACCES,"access denied") X(ENODEV,"device not configured") X(EPROTO,"protocol error") X(EISDIR,"is a directory") X(ESRCH,"no such process") X(E2BIG,"argument list too long") X(ENOEXEC,"exec format error") X(EBADF,"file descriptor not open") X(ECHILD,"no child processes") X(EDEADLK,"operation would cause deadlock") X(EFAULT,"bad address") X(ENOTBLK,"not a block device") X(EBUSY,"device busy") X(EXDEV,"cross-device link") X(ENODEV,"device does not support operation") X(ENOTDIR,"not a directory") X(EINVAL,"invalid argument") X(ENFILE,"system cannot open more files") X(EMFILE,"process cannot open more files") X(ENOTTY,"not a tty") X(EFBIG,"file too big") X(ENOSPC,"out of disk space") X(ESPIPE,"unseekable descriptor") X(EROFS,"read-only file system") X(EMLINK,"too many links") X(EDOM,"input out of range") X(ERANGE,"output out of range") X(EALREADY,"operation already in progress") X(ENOTSOCK,"not a socket") X(EDESTADDRREQ,"destination address required") X(EMSGSIZE,"message too long") X(EPROTOTYPE,"incorrect protocol type") X(ENOPROTOOPT,"protocol not available") X(EPROTONOSUPPORT,"protocol not supported") X(ESOCKTNOSUPPORT,"socket type not supported") X(EOPNOTSUPP,"operation not supported") X(EPFNOSUPPORT,"protocol family not supported") X(EAFNOSUPPORT,"address family not supported") X(EADDRINUSE,"address already used") X(EADDRNOTAVAIL,"address not available") X(ENETDOWN,"network down") X(ENETUNREACH,"network unreachable") X(ENETRESET,"network reset") X(ECONNABORTED,"connection aborted") X(ECONNRESET,"connection reset") X(ENOBUFS,"out of buffer space") X(EISCONN,"already connected") X(ENOTCONN,"not connected") X(ESHUTDOWN,"socket shut down") X(ETOOMANYREFS,"too many references") X(ECONNREFUSED,"connection refused") X(ELOOP,"symbolic link loop") X(ENAMETOOLONG,"file name too long") X(EHOSTDOWN,"host down") X(EHOSTUNREACH,"host unreachable") X(ENOTEMPTY,"directory not empty") X(EPROCLIM,"too many processes") X(EUSERS,"too many users") X(EDQUOT,"disk quota exceeded") X(ESTALE,"stale NFS file handle") X(EREMOTE,"too many levels of remote in path") X(EBADRPC,"RPC structure is bad") X(ERPCMISMATCH,"RPC version mismatch") X(EPROGUNAVAIL,"RPC program unavailable") X(EPROGMISMATCH,"program version mismatch") X(EPROCUNAVAIL,"bad procedure for program") X(ENOLCK,"no locks available") X(ENOSYS,"system call not available") X(EFTYPE,"bad file type") X(EAUTH,"authentication error") X(ENEEDAUTH,"not authenticated") X(ENOSTR,"not a stream device") X(ETIME,"timer expired") X(ENOSR,"out of stream resources") X(ENOMSG,"no message of desired type") X(EBADMSG,"bad message type") X(EIDRM,"identifier removed") X(ENONET,"machine not on network") X(EREMOTE,"object not local") X(ENOLINK,"link severed") X(EADV,"advertise error") X(ESRMNT,"srmount error") X(ECOMM,"communication error") X(EMULTIHOP,"multihop attempted") X(EREMCHG,"remote address changed") /* XXX */ X(DNSNOENT,"dns record doesn't exist") return "unknown error"; } dq-20240101/e.h000066400000000000000000000156021454446775700130010ustar00rootroot00000000000000#ifndef E_H #define E_H #include extern const char *e_str(int); #ifndef EPERM #define EPERM (-5001) #endif #ifndef ENOENT #define ENOENT (-5002) #endif #ifndef ESRCH #define ESRCH (-5003) #endif #ifndef EINTR #define EINTR (-5004) #endif #ifndef EIO #define EIO (-5005) #endif #ifndef ENXIO #define ENXIO (-5006) #endif #ifndef E2BIG #define E2BIG (-5007) #endif #ifndef ENOEXEC #define ENOEXEC (-5008) #endif #ifndef EBADF #define EBADF (-5009) #endif #ifndef ECHILD #define ECHILD (-5010) #endif #ifndef EAGAIN #define EAGAIN (-5011) #endif #ifndef EWOULDBLOCK #define EWOULDBLOCK (-7011) #endif #ifndef ENOMEM #define ENOMEM (-5012) #endif #ifndef EACCES #define EACCES (-5013) #endif #ifndef EFAULT #define EFAULT (-5014) #endif #ifndef ENOTBLK #define ENOTBLK (-5015) #endif #ifndef EBUSY #define EBUSY (-5016) #endif #ifndef EEXIST #define EEXIST (-5017) #endif #ifndef EXDEV #define EXDEV (-5018) #endif #ifndef ENODEV #define ENODEV (-5019) #endif #ifndef ENOTDIR #define ENOTDIR (-5020) #endif #ifndef EISDIR #define EISDIR (-5021) #endif #ifndef EINVAL #define EINVAL (-5022) #endif #ifndef ENFILE #define ENFILE (-5023) #endif #ifndef EMFILE #define EMFILE (-5024) #endif #ifndef ENOTTY #define ENOTTY (-5025) #endif #ifndef ETXTBSY #define ETXTBSY (-5026) #endif #ifndef EFBIG #define EFBIG (-5027) #endif #ifndef ENOSPC #define ENOSPC (-5028) #endif #ifndef ESPIPE #define ESPIPE (-5029) #endif #ifndef EROFS #define EROFS (-5030) #endif #ifndef EMLINK #define EMLINK (-5031) #endif #ifndef EPIPE #define EPIPE (-5032) #endif #ifndef EDOM #define EDOM (-5033) #endif #ifndef ERANGE #define ERANGE (-5034) #endif #ifndef EDEADLK #define EDEADLK (-5035) #endif #ifndef EDEADLOCK #define EDEADLOCK (-7035) #endif #ifndef ENAMETOOLONG #define ENAMETOOLONG (-5036) #endif #ifndef ENOLCK #define ENOLCK (-5037) #endif #ifndef ENOSYS #define ENOSYS (-5038) #endif #ifndef ENOTEMPTY #define ENOTEMPTY (-5039) #endif #ifndef ELOOP #define ELOOP (-5040) #endif #ifndef ENOMSG #define ENOMSG (-5042) #endif #ifndef EIDRM #define EIDRM (-5043) #endif #ifndef ECHRNG #define ECHRNG (-5044) #endif #ifndef EL2NSYNC #define EL2NSYNC (-5045) #endif #ifndef EL3HLT #define EL3HLT (-5046) #endif #ifndef EL3RST #define EL3RST (-5047) #endif #ifndef ELNRNG #define ELNRNG (-5048) #endif #ifndef EUNATCH #define EUNATCH (-5049) #endif #ifndef ENOCSI #define ENOCSI (-5050) #endif #ifndef EL2HLT #define EL2HLT (-5051) #endif #ifndef EBADE #define EBADE (-5052) #endif #ifndef EBADR #define EBADR (-5053) #endif #ifndef EXFULL #define EXFULL (-5054) #endif #ifndef ENOANO #define ENOANO (-5055) #endif #ifndef EBADRQC #define EBADRQC (-5056) #endif #ifndef EBADSLT #define EBADSLT (-5057) #endif #ifndef EBFONT #define EBFONT (-5059) #endif #ifndef ENOSTR #define ENOSTR (-5060) #endif #ifndef ENODATA #define ENODATA (-5061) #endif #ifndef ETIME #define ETIME (-5062) #endif #ifndef ENOSR #define ENOSR (-5063) #endif #ifndef ENONET #define ENONET (-5064) #endif #ifndef ENOPKG #define ENOPKG (-5065) #endif #ifndef EREMOTE #define EREMOTE (-5066) #endif #ifndef ENOLINK #define ENOLINK (-5067) #endif #ifndef EADV #define EADV (-5068) #endif #ifndef ESRMNT #define ESRMNT (-5069) #endif #ifndef ECOMM #define ECOMM (-5070) #endif #ifndef EPROTO #define EPROTO (-5071) #endif #ifndef EMULTIHOP #define EMULTIHOP (-5072) #endif #ifndef EDOTDOT #define EDOTDOT (-5073) #endif #ifndef EBADMSG #define EBADMSG (-5074) #endif #ifndef EOVERFLOW #define EOVERFLOW (-5075) #endif #ifndef ENOTUNIQ #define ENOTUNIQ (-5076) #endif #ifndef EBADFD #define EBADFD (-5077) #endif #ifndef EREMCHG #define EREMCHG (-5078) #endif #ifndef ELIBACC #define ELIBACC (-5079) #endif #ifndef ELIBBAD #define ELIBBAD (-5080) #endif #ifndef ELIBSCN #define ELIBSCN (-5081) #endif #ifndef ELIBMAX #define ELIBMAX (-5082) #endif #ifndef ELIBEXEC #define ELIBEXEC (-5083) #endif #ifndef EILSEQ #define EILSEQ (-5084) #endif #ifndef ERESTART #define ERESTART (-5085) #endif #ifndef ESTRPIPE #define ESTRPIPE (-5086) #endif #ifndef EUSERS #define EUSERS (-5087) #endif #ifndef ENOTSOCK #define ENOTSOCK (-5088) #endif #ifndef EDESTADDRREQ #define EDESTADDRREQ (-5089) #endif #ifndef EMSGSIZE #define EMSGSIZE (-5090) #endif #ifndef EPROTOTYPE #define EPROTOTYPE (-5091) #endif #ifndef ENOPROTOOPT #define ENOPROTOOPT (-5092) #endif #ifndef EPROTONOSUPPORT #define EPROTONOSUPPORT (-5093) #endif #ifndef ESOCKTNOSUPPORT #define ESOCKTNOSUPPORT (-5094) #endif #ifndef EOPNOTSUPP #define EOPNOTSUPP (-5095) #endif #ifndef EPFNOSUPPORT #define EPFNOSUPPORT (-5096) #endif #ifndef EAFNOSUPPORT #define EAFNOSUPPORT (-5097) #endif #ifndef EADDRINUSE #define EADDRINUSE (-5098) #endif #ifndef EADDRNOTAVAIL #define EADDRNOTAVAIL (-5099) #endif #ifndef ENETDOWN #define ENETDOWN (-5100) #endif #ifndef ENETUNREACH #define ENETUNREACH (-5101) #endif #ifndef ENETRESET #define ENETRESET (-5102) #endif #ifndef ECONNABORTED #define ECONNABORTED (-5103) #endif #ifndef ECONNRESET #define ECONNRESET (-5104) #endif #ifndef ENOBUFS #define ENOBUFS (-5105) #endif #ifndef EISCONN #define EISCONN (-5106) #endif #ifndef ENOTCONN #define ENOTCONN (-5107) #endif #ifndef ESHUTDOWN #define ESHUTDOWN (-5108) #endif #ifndef ETOOMANYREFS #define ETOOMANYREFS (-5109) #endif #ifndef ETIMEDOUT #define ETIMEDOUT (-5110) #endif #ifndef ECONNREFUSED #define ECONNREFUSED (-5111) #endif #ifndef EHOSTDOWN #define EHOSTDOWN (-5112) #endif #ifndef EHOSTUNREACH #define EHOSTUNREACH (-5113) #endif #ifndef EALREADY #define EALREADY (-5114) #endif #ifndef EINPROGRESS #define EINPROGRESS (-5115) #endif #ifndef ESTALE #define ESTALE (-5116) #endif #ifndef EUCLEAN #define EUCLEAN (-5117) #endif #ifndef ENOTNAM #define ENOTNAM (-5118) #endif #ifndef ENAVAIL #define ENAVAIL (-5119) #endif #ifndef EISNAM #define EISNAM (-5120) #endif #ifndef EREMOTEIO #define EREMOTEIO (-5121) #endif #ifndef EDQUOT #define EDQUOT (-5122) #endif #ifndef ENOMEDIUM #define ENOMEDIUM (-5123) #endif #ifndef EMEDIUMTYPE #define EMEDIUMTYPE (-5124) #endif #ifndef ECANCELED #define ECANCELED (-5125) #endif #ifndef ENOKEY #define ENOKEY (-5126) #endif #ifndef EKEYEXPIRED #define EKEYEXPIRED (-5127) #endif #ifndef EKEYREVOKED #define EKEYREVOKED (-5128) #endif #ifndef EKEYREJECTED #define EKEYREJECTED (-5129) #endif #ifndef EOWNERDEAD #define EOWNERDEAD (-5130) #endif #ifndef ENOTRECOVERABLE #define ENOTRECOVERABLE (-5131) #endif #ifndef ERFKILL #define ERFKILL (-5132) #endif #ifndef EPROCLIM #define EPROCLIM (-6067) #endif #ifndef EBADRPC #define EBADRPC (-6072) #endif #ifndef ERPCMISMATCH #define ERPCMISMATCH (-6073) #endif #ifndef EPROGUNAVAIL #define EPROGUNAVAIL (-6074) #endif #ifndef EPROGMISMATCH #define EPROGMISMATCH (-6075) #endif #ifndef EPROCUNAVAIL #define EPROCUNAVAIL (-6076) #endif #ifndef EFTYPE #define EFTYPE (-6079) #endif #ifndef EAUTH #define EAUTH (-6080) #endif #ifndef ENEEDAUTH #define ENEEDAUTH (-6081) #endif #ifndef ENOATTR #define ENOATTR (-6087) #endif #ifndef ENOTCAPABLE #define ENOTCAPABLE (-6093) #endif /* XXX */ #ifndef DNSNOENT #define DNSNOENT (-7000) #endif #endif dq-20240101/env.c000066400000000000000000000006761454446775700133450ustar00rootroot00000000000000#include "str.h" #include "env.h" /* The 'env_get(name)' function returns the value of the first environment variable whose name is 'name', or 0 if there is no such variable. */ char *env_get(const char *name) { long long len, i; if (!name) return 0; len = str_len(name); for (i = 0; environ[i]; ++i) if (str_start(environ[i], name) && (environ[i][len] == '=')) return environ[i] + len + 1; return 0; } dq-20240101/env.h000066400000000000000000000004201454446775700133350ustar00rootroot00000000000000#ifndef _ENV_H____ #define _ENV_H____ /* The environment 'environ', is a 0-terminated array of 0-terminated strings, called environment variables. Each environment variable is of the form name=value. */ extern char **environ; extern char *env_get(const char *); #endif dq-20240101/examples.md000066400000000000000000000210171454446775700145410ustar00rootroot00000000000000### Authoritative example - streamlined DNSCurve query (executed 23.11.2013): ### ~~~ $ dq -a a dnscurve.org uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org 1 dnscurve.org - streamlined DNSCurve: 320 bytes, 1+2+3+3 records, response, authoritative, noerror query: 1 dnscurve.org answer: dnscurve.org 600 A 131.193.32.142 answer: dnscurve.org 600 A 131.193.32.147 authority: dnscurve.org 259200 NS uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5uu2c7j228ujjccp3ustnfmr4pgcg5ylvt16kmd0qzw7bbjgd5xq.ns.dnscurve.org additional: uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.dnscurve.org 259200 A 131.193.32.142 additional: uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org 259200 A 131.155.71.143 additional: uz5uu2c7j228ujjccp3ustnfmr4pgcg5ylvt16kmd0qzw7bbjgd5xq.ns.dnscurve.org 259200 A 80.101.159.118 ~~~ ### Authoritative example - TXT DNSCurve query, using suffix 'dnscurve.org' (executed 23.11.2013): ### ~~~ $ dq -S 'dnscurve.org' -a a dnscurve.org uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org 1 dnscurve.org - txt DNSCurve: 320 bytes, 1+2+3+3 records, response, authoritative, noerror query: 1 dnscurve.org answer: dnscurve.org 600 A 131.193.32.142 answer: dnscurve.org 600 A 131.193.32.147 authority: dnscurve.org 259200 NS uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5uu2c7j228ujjccp3ustnfmr4pgcg5ylvt16kmd0qzw7bbjgd5xq.ns.dnscurve.org additional: uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.dnscurve.org 259200 A 131.193.32.142 additional: uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org 259200 A 131.155.71.143 additional: uz5uu2c7j228ujjccp3ustnfmr4pgcg5ylvt16kmd0qzw7bbjgd5xq.ns.dnscurve.org 259200 A 80.101.159.118 ~~~ ### Authoritative example - streamlined DNSCurve query, using IPv4 and key (executed 23.11.2013): ### ~~~ dq -k uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090 -a a dnscurve.org 131.155.71.143 1 dnscurve.org - streamlined DNSCurve: 320 bytes, 1+2+3+3 records, response, authoritative, noerror query: 1 dnscurve.org answer: dnscurve.org 600 A 131.193.32.147 answer: dnscurve.org 600 A 131.193.32.142 authority: dnscurve.org 259200 NS uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5uu2c7j228ujjccp3ustnfmr4pgcg5ylvt16kmd0qzw7bbjgd5xq.ns.dnscurve.org additional: uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.dnscurve.org 259200 A 131.193.32.142 additional: uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org 259200 A 131.155.71.143 additional: uz5uu2c7j228ujjccp3ustnfmr4pgcg5ylvt16kmd0qzw7bbjgd5xq.ns.dnscurve.org 259200 A 80.101.159.118 ~~~ ### Authoritative example - streamlined DNSCurve query, using IPv6 and key (executed 23.11.2013): ### ~~~ $ dq -a -k uz52zufj724bjt11s3pgk2dtcpw8ww1dr8g3ssm3hs3jkmwr8l090p a blinkenlights.ch 2a01:4f8:120:43c1::a 1 blinkenlights.ch - streamlined DNSCurve: 341 bytes, 1+1+3+3 records, response, authoritative, noerror query: 1 blinkenlights.ch answer: blinkenlights.ch 86400 A 78.46.72.150 authority: blinkenlights.ch 259200 NS uz5crn6x92t4vb4k3z68du7rmwmnnvkbdd29t79yzg9fr2s2rx5pk0.nsde1.eqmx.net authority: blinkenlights.ch 259200 NS uz5mnv8n4dzrp95zl50jryb4wgf45my27q6pvx8f540l9sspkcwvtm.nszh1.eqmx.net authority: blinkenlights.ch 259200 NS uz52zufj724bjt11s3pgk2dtcpw8ww1dr8g3ssm3hs3jkmwr8l090p.dns1.workaround.ch additional: uz5crn6x92t4vb4k3z68du7rmwmnnvkbdd29t79yzg9fr2s2rx5pk0.nsde1.eqmx.net 86400 A 178.209.50.169 additional: uz5mnv8n4dzrp95zl50jryb4wgf45my27q6pvx8f540l9sspkcwvtm.nszh1.eqmx.net 86400 A 46.246.93.162 additional: uz52zufj724bjt11s3pgk2dtcpw8ww1dr8g3ssm3hs3jkmwr8l090p.dns1.workaround.ch 86400 A 78.46.72.150 ~~~ ### Recursive example (executed 23.11.2013): ### ~~~ $ dq a dnscurve.org 1 dnscurve.org - regular DNS: 272 bytes, 1+2+3+0 records, response, noerror query: 1 dnscurve.org answer: dnscurve.org 600 A 131.193.32.147 answer: dnscurve.org 600 A 131.193.32.142 authority: dnscurve.org 259200 NS uz5hjgptn63q5qlch6xlrw63tf6vhvvu6mjwn0s31buw1lhmlk14kd.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5dz39x8xk8wyq3dzn7vpt670qmvzx0zd9zg4ldwldkv6kx9ft090.ns.dnscurve.org authority: dnscurve.org 259200 NS uz5uu2c7j228ujjccp3ustnfmr4pgcg5ylvt16kmd0qzw7bbjgd5xq.ns.dnscurve.org ~~~ ### Recursive example, using OpenDNS resolver - IPv6 (executed 23.11.2013): ### ~~~ $ dq a dnscurve.org 2620:0:ccc::2 1 dnscurve.org - regular DNS: 62 bytes, 1+2+0+0 records, response, noerror query: 1 dnscurve.org answer: dnscurve.org 600 A 131.193.32.147 answer: dnscurve.org 600 A 131.193.32.142 ~~~ ### Recursive example, using OpenDNS resolver - IPv4 (executed 23.11.2013): ### ~~~ $ dq a dnscurve.org 208.67.222.222 1 dnscurve.org - regular DNS: 62 bytes, 1+2+0+0 records, response, noerror query: 1 dnscurve.org answer: dnscurve.org 600 A 131.193.32.142 answer: dnscurve.org 600 A 131.193.32.147 ~~~ ### Recursive example, using OpenDNS resolver - IPv4, dnsqr backward compatibility (executed 23.11.2013): ### ~~~ env DNSCACHEIP=208.67.222.222 dq a dnscurve.org 1 dnscurve.org - regular DNS: 62 bytes, 1+2+0+0 records, response, noerror query: 1 dnscurve.org answer: dnscurve.org 600 A 131.193.32.142 answer: dnscurve.org 600 A 131.193.32.147 ~~~ ### Recursive example, PTR query (executed 23.11.2013): ### ~~~ $ dq ptr 1.0.0.127.in-addr.arpa 12 1.0.0.127.in-addr.arpa - regular DNS: 63 bytes, 1+1+0+0 records, response, noerror query: 12 1.0.0.127.in-addr.arpa answer: 1.0.0.127.in-addr.arpa 655360 PTR localhost ~~~ ### Recursive example, PTR query, auto-rewrite to *.in-addr.arpa (executed 23.11.2013): ### ~~~ $ dq ptr 127.0.0.1 12 1.0.0.127.in-addr.arpa - regular DNS: 63 bytes, 1+1+0+0 records, response, noerror query: 12 1.0.0.127.in-addr.arpa answer: 1.0.0.127.in-addr.arpa 655360 PTR localhost ~~~ ### Recursive example, PTR query, auto-rewrite to *.ip6.arpa (executed 23.11.2013): ### ~~~ $ dq ptr 2a01:4f8:120:43c1::aa 12 a.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.c.3.4.0.2.1.0.8.f.4.0.1.0.a.2.ip6.arpa - regular DNS: 90 bytes, 1+0+0+0 records, response, authoritative, nxdomain query: 12 a.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.c.3.4.0.2.1.0.8.f.4.0.1.0.a.2.ip6.arpa ~~~ ### Authoritative example, verbose mode, truncated answer (executed 23.11.2013): ### ~~~ $ dq -a -vv any google.com ns4.google.com dq: debug: resolving: ns4.google.com dq: debug: DNS query: ns4.google.com AAAA UDP 127.10.10.10 53: sent dq: debug: DNS query: ns4.google.com A UDP 127.10.10.10 53: sent dq: debug: DNS query: ns4.google.com A UDP 127.10.10.10 53: received dq: debug: DNS query: ns4.google.com AAAA UDP 127.10.10.10 53: received dq: debug: resolved: ns4.google.com: ns4.google.com 216.239.38.10 dq: debug: DNS query: google.com ANY UDP 216.239.38.10 53: sent dq: debug: DNS query: google.com ANY UDP 216.239.38.10 53: failed: truncated dq: debug: DNS query: google.com ANY TCP 216.239.38.10 53: sent dq: debug: DNS query: google.com ANY TCP 216.239.38.10 53: received 255 google.com - regular DNS: 577 bytes, 1+24+0+0 records, response, authoritative, noerror query: 255 google.com answer: google.com 300 A 173.194.112.97 answer: google.com 300 A 173.194.112.96 answer: google.com 300 A 173.194.112.104 answer: google.com 300 A 173.194.112.98 answer: google.com 300 A 173.194.112.99 answer: google.com 300 A 173.194.112.103 answer: google.com 300 A 173.194.112.110 answer: google.com 300 A 173.194.112.100 answer: google.com 300 A 173.194.112.102 answer: google.com 300 A 173.194.112.105 answer: google.com 300 A 173.194.112.101 answer: google.com 300 AAAA 2a00:1450:4001:803::1006 answer: google.com 86400 SOA ns1.google.com dns-admin.google.com 2013100300 7200 1800 1209600 300 answer: google.com 600 MX 10 aspmx.l.google.com answer: google.com 86400 257 \000\005issuesymantec.com answer: google.com 345600 NS ns3.google.com answer: google.com 345600 NS ns2.google.com answer: google.com 345600 NS ns1.google.com answer: google.com 600 MX 20 alt1.aspmx.l.google.com answer: google.com 600 MX 30 alt2.aspmx.l.google.com answer: google.com 345600 NS ns4.google.com answer: google.com 600 MX 50 alt4.aspmx.l.google.com answer: google.com 600 MX 40 alt3.aspmx.l.google.com answer: google.com 3600 TXT v=spf1 include:_spf.google.com ip4:216.73.93.70/31 ip4:216.73.93.72/31 ~all ~~~ dq-20240101/hasipv6.h000066400000000000000000000000501454446775700141240ustar00rootroot00000000000000/* Public domain. */ #define HASIPV6 1 dq-20240101/hexdecode.c000066400000000000000000000012301454446775700144700ustar00rootroot00000000000000#include "hexdecode.h" static int hexdigit(char x) { if (x >= '0' && x <= '9') return x - '0'; if (x >= 'a' && x <= 'f') return 10 + (x - 'a'); if (x >= 'A' && x <= 'F') return 10 + (x - 'A'); return -1; } int hexdecode(unsigned char *y, long long len, const unsigned char *x, long long xlen) { int digit0; int digit1; if (!x) return 0; while (len > 0 && xlen >= 2) { digit0 = hexdigit(x[0]); if (digit0 == -1) return 0; digit1 = hexdigit(x[1]); if (digit1 == -1) return 0; *y++ = digit1 + 16 * digit0; --len; x += 2; xlen -= 2; } if (xlen != 0) return 0; return 1; } dq-20240101/hexdecode.h000066400000000000000000000002171454446775700145010ustar00rootroot00000000000000#ifndef _HEXDECODE_H____ #define _HEXDECODE_H____ extern int hexdecode(unsigned char *, long long, const unsigned char *, long long); #endif dq-20240101/hexparse.c000066400000000000000000000010561454446775700143650ustar00rootroot00000000000000#include "hexparse.h" static int hexdigit(char x) { if (x >= '0' && x <= '9') return x - '0'; if (x >= 'a' && x <= 'f') return 10 + (x - 'a'); if (x >= 'A' && x <= 'F') return 10 + (x - 'A'); return -1; } int hexparse(unsigned char *y,long long len,const char *x) { if (!x) return 0; while (len > 0) { int digit0; int digit1; digit0 = hexdigit(x[0]); if (digit0 == -1) return 0; digit1 = hexdigit(x[1]); if (digit1 == -1) return 0; *y++ = digit1 + 16 * digit0; --len; x += 2; } if (x[0]) return 0; return 1; } dq-20240101/hexparse.h000066400000000000000000000001541454446775700143700ustar00rootroot00000000000000#ifndef HEXPARSE_H #define HEXPARSE_H extern int hexparse(unsigned char *,long long,const char *); #endif dq-20240101/install.md000066400000000000000000000027211454446775700143720ustar00rootroot00000000000000### Debian installation ### ~~~ apt-get install dq apt-get install dqcache ~~~ ###Unix installation ### #### download #### ~~~ wget https://github.com/janmojzis/dq/releases/download/20240101/20240101.tar.gz.asc wget https://github.com/janmojzis/dq/archive/20240101.tar.gz gpg --verify 20240101.tar.gz.asc 20240101.tar.gz gunzip < 20240101.tar.gz | tar -xf - cd dq-20240101 ~~~ #### compile and install binaries #### ~~~ make sudo make install ~~~ #### run dqcache #### ~~~ #under root - create dqcache root directory sudo mkdir -p /etc/dqcache/root/servers /etc/dqcache/env sudo echo 10000000 > /etc/dqcache/env/CACHESIZE sudo echo 127.0.0.1 > /etc/dqcache/env/IP sudo echo "/etc/dqcache/root" > /etc/dqcache/env/ROOT ~~~ ~~~ #under root - setup dqcache root servers sudo sh -c '( echo "198.41.0.4" echo "2001:503:ba3e::2:30" echo "192.228.79.201" echo "2001:500:84::b" echo "192.33.4.12" echo "2001:500:2::c" echo "199.7.91.13" echo "2001:500:2d::d" echo "192.203.230.10" echo "192.5.5.241" echo "2001:500:2f::f" echo "192.112.36.4" echo "198.97.190.53" echo "2001:500:1::53" echo "192.36.148.17" echo "2001:7fe::53" echo "192.58.128.30" echo "2001:503:c27::2:30" echo "193.0.14.129" echo "2001:7fd::1" echo "199.7.83.42" echo "2001:500:9f::42" echo "202.12.27.33" echo "2001:dc3::35" ) > /etc/dqcache/root/servers/@' ~~~ ~~~ #under root - create dqcache user sudo useradd dqcache ~~~ ~~~ #under root - run dqcache server sudo envuidgid dqcache envdir /etc/dqcache/env dqcache ~~~ dq-20240101/iptostr.c000066400000000000000000000076101454446775700142540ustar00rootroot00000000000000/* 20130604 Jan Mojzis Public domain. */ #include "byte.h" #include "iptostr.h" static char *iptostr4(char *, const unsigned char *); static char *iptostr6(char *, const unsigned char *); static char *iptostr6x(char *, const unsigned char *); /* The 'iptostr(strbuf,ip)' function converts IP address 'ip' from network byte order into the 0-terminated string. The 'ip' length is always 16 bytes. The caller must allocate at least IPTOSTR_LEN bytes for 'strbuf'. */ char *iptostr(char *strbuf, const unsigned char *ip) { static char staticbuf[IPTOSTR_LEN]; if (!strbuf) strbuf = staticbuf; /* not thread-safe */ if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { return iptostr4(strbuf, ip + 12); } return iptostr6(strbuf, ip); } char *iptostrx(char *strbuf, const unsigned char *ip) { static char staticbuf[IPTOSTR_LEN]; if (!strbuf) strbuf = staticbuf; /* not thread-safe */ if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { return iptostr4(strbuf, ip + 12); } return iptostr6x(strbuf, ip); } /* convert IPv4 address */ static char *iptostr4(char *strbuf, const unsigned char *ip) { long long i, len = 0; unsigned long long num; for (i = 3; i >= 0; --i) { num = ip[i]; do { num /= 10; ++len; } while (num); if (i > 0) ++len; } strbuf += len; for (i = 3; i >= 0; --i) { num = ip[i]; do { *--strbuf = '0' + (num % 10); num /= 10; } while (num); if (i > 0) *--strbuf = '.'; } while (len < IPTOSTR_LEN) strbuf[len++] = 0; return strbuf; } /* The 'ip' is splited into 8 16-bit blocks and the 'countz' function counts successive zeros and searches for largest zero-block. 'first' ... first position of the zero-block 'last' ... last position of the zero-block */ static void countz(long long *first, long long *last, const unsigned long long *ip) { long long i, j, e; long long count[8]; for (i = 7; i >= 0; --i) count[i] = 0; e = 8; for (i = 7; i >= 0; --i) { if (!ip[i]) { for (j = i; j < e; ++j) ++count[j]; } else { e = i; } } e = 0; j = 0; for (i = 7; i >= 0; --i) { if (count[i]) { if (count[i] >= e) { e = count[i]; j = i; } } } *first = j - count[j] + 1; *last = j; } /* convert IPv6 address */ static char *iptostr6(char *strbuf, const unsigned char *ip) { long long first, last, i; unsigned long long ip2[8]; char *s = strbuf; for (i = 7; i >= 0; --i) { ip2[i] = ip[2 * i]; ip2[i] <<= 8; ip2[i] += ip[2 * i + 1]; } countz(&first, &last, ip2); strbuf += IPTOSTR_LEN - 1; *strbuf = 0; for (i = 7; i >= 0; --i) { if (i <= last && i >= first && first != last) { if (i == last) *--strbuf = ':'; if (i == 7) *--strbuf = ':'; continue; } do { *--strbuf = "0123456789abcdef"[ip2[i] & 15]; ip2[i] >>= 4; } while (ip2[i]); if (i > 0) *--strbuf = ':'; } i = strbuf - s; byte_copy(s, IPTOSTR_LEN - i, strbuf); byte_zero(s + IPTOSTR_LEN - i, i); return s; } /* convert IPv6 address without '::' compression */ static char *iptostr6x(char *strbuf, const unsigned char *ip) { long long i; unsigned long long ip2[8]; char *s = strbuf; for (i = 7; i >= 0; --i) { ip2[i] = ip[2 * i]; ip2[i] <<= 8; ip2[i] += ip[2 * i + 1]; } strbuf += IPTOSTR_LEN - 1; *strbuf = 0; for (i = 7; i >= 0; --i) { do { *--strbuf = "0123456789abcdef"[ip2[i] & 15]; ip2[i] >>= 4; } while (ip2[i]); if (i > 0) *--strbuf = ':'; } i = strbuf - s; byte_copy(s, IPTOSTR_LEN - i, strbuf); byte_zero(s + IPTOSTR_LEN - i, i); return s; } dq-20240101/iptostr.h000066400000000000000000000002721454446775700142560ustar00rootroot00000000000000#ifndef _IPTOSTR_H____ #define _IPTOSTR_H____ #define IPTOSTR_LEN 46 extern char *iptostr(char *, const unsigned char *); extern char *iptostrx(char *, const unsigned char *); #endif dq-20240101/keyparse.c000066400000000000000000000014451454446775700143730ustar00rootroot00000000000000/* * 20131204 * Jan Mojzis * Public domain. */ #include "hexdecode.h" #include "base32decode.h" #include "byte.h" #include "str.h" #include "keyparse.h" int keyparse(unsigned char *keys, long long keyslen, const char *xx) { long long len; const unsigned char *x = (const unsigned char *)xx; if (!xx) return 0; if (keyslen != 32) return 0; len = str_len(xx); switch (len) { case 54: if (!byte_isequal(x, 3, "uz5")) return 0; if (!base32decode(keys, 32, x + 3, 51)) return 0; break; case 51: if (!base32decode(keys, 32, x, 51)) return 0; break; case 64: if (!hexdecode(keys, 32, x, 64)) return 0; break; default: return 0; } return 1; } dq-20240101/keyparse.h000066400000000000000000000001701454446775700143720ustar00rootroot00000000000000#ifndef _KEYPARSE_H____ #define _KEYPARSE_H____ extern int keyparse(unsigned char *, long long, const char *); #endif dq-20240101/log.c000066400000000000000000000225541454446775700133350ustar00rootroot00000000000000#include "buffer.h" #include "uint32_unpack_big.h" #include "uint16_unpack_big.h" #include "e.h" #include "byte.h" #include "iptostr.h" #include "numtostr.h" #include "log.h" /* work around gcc 2.95.2 bug */ #define number(x) ( (u64 = (x)), u64_print() ) static crypto_uint64 u64; static void u64_print(void) { char buf[20]; long long pos; pos = sizeof buf; do { if (pos <= 0) break; buf[--pos] = '0' + (u64 % 10); u64 /= 10; } while(u64); buffer_put(buffer_2, buf + pos, sizeof buf - pos); } static void hex(unsigned char c) { buffer_put(buffer_2, "0123456789abcdef" + (c >> 4), 1); buffer_put(buffer_2, "0123456789abcdef" + (c & 15), 1); } static void string(const char *s) { buffer_puts(buffer_2, s); } static void line(void) { string("\n"); buffer_flush(buffer_2); } static void space(void) { string(" "); } static void ip(const unsigned char i[16]) { #if 1 string(iptostr(0, i)); #else hex(i[0]); hex(i[1]); hex(i[2]); hex(i[3]); hex(i[4]); hex(i[5]); hex(i[6]); hex(i[7]); hex(i[8]); hex(i[9]); hex(i[10]); hex(i[11]); hex(i[12]); hex(i[13]); hex(i[14]); hex(i[15]); #endif } static void dctype(unsigned char x) { switch(x) { case 1: string("S"); break; case 2: string("T"); break; default: string("R"); break; } } static void logid(const unsigned char id[2]) { #if 1 string(numtostr(0, uint16_unpack_big(id))); #else hex(id[0]); hex(id[1]); #endif } static void logtype(const unsigned char type[2]) { crypto_uint16 u; u = uint16_unpack_big(type); number(u); } static void name(const unsigned char *q) { unsigned char ch; int state; if (!*q) { string("."); return; } while(state = *q++) { while (state) { ch = *q++; --state; if ((ch <= 32) || (ch > 126)) ch = '?'; if ((ch >= 'A') && (ch <= 'Z')) ch += 32; buffer_put(buffer_2, (char *)&ch, 1); } string("."); } } void log_startup(void) { string("starting"); line(); } void log_dnscurvekey(const unsigned char *key) { long long i; string("dnscurve public-key "); for(i = 0; i < 32; ++i) { hex(key[i]); } line(); } void log_query(crypto_uint64 *qnum, const unsigned char client[16], unsigned char port[2], const unsigned char id[2], const unsigned char *q, const unsigned char qtype[2]) { string("query "); number(*qnum); space(); ip(client); string(":"); string(numtostr(0, uint16_unpack_big(port))); string(":"); logid(id); space(); logtype(qtype); space(); name(q); line(); } void log_queryreject(const unsigned char *client, unsigned char *port, const unsigned char *id, const unsigned char *q, const unsigned char *qtype, const char *x) { string("reject "); ip(client); string(":"); string(numtostr(0, uint16_unpack_big(port))); string(":"); if (id) { logid(id); } else { string("?"); } space(); if (qtype) { logtype(qtype); } else { string("?"); } space(); if (q) { name(q); } else { string("?"); } space(); string(x); line(); } void log_querydone(crypto_uint64 *qnum, long long len) { string("sent "); number(*qnum); space(); number(len); line(); } void log_querydrop(crypto_uint64 *qnum) { const char *x = e_str(errno); string("drop "); number(*qnum); space(); string(x); line(); } void log_tcpopen(const unsigned char client[16], unsigned char port[2]) { string("tcpopen "); ip(client); string(":"); hex(port[0]); hex(port[1]); line(); } void log_tcpclose(const unsigned char client[16],unsigned char port[2]) { const char *x = e_str(errno); string("tcpclose "); ip(client); string(":"); hex(port[0]); hex(port[1]); space(); string(x); line(); } /* XXX */ void log_tx(const unsigned char *q, const unsigned char qtype[2], const unsigned char *control, const unsigned char servers[256], const unsigned char keys[528], int flaghavekeys, unsigned int gluelessness) { long long i, j; const unsigned char *k; string("tx "); number(gluelessness); space(); logtype(qtype); space(); name(q); space(); name(control); string(flaghavekeys ? " +" : " -"); for (i = 0; i < 256; i += 16) { j = i >> 4; if (!byte_isequal(servers + i, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { k = keys + 33 * j; space(); dctype(k[0]); ip(servers + i); } } line(); } void log_cachedanswer(const unsigned char *q,const unsigned char type[2]) { string("cached "); logtype(type); space(); name(q); line(); } void log_cachedcname(const unsigned char *dn,const unsigned char *dn2) { string("cached cname "); name(dn); space(); name(dn2); line(); } void log_cachedns(const unsigned char *control,const unsigned char *ns) { string("cached ns "); name(control); space(); name(ns); line(); } void log_cachednxdomain(const unsigned char *dn) { string("cached nxdomain "); name(dn); line(); } void log_nxdomain(const unsigned char *server,const unsigned char *q,unsigned int ttl) { string("nxdomain "); ip(server); space(); number(ttl); space(); name(q); line(); } void log_nodata(const unsigned char *server,const unsigned char *q,const unsigned char qtype[2],unsigned int ttl) { string("nodata "); ip(server); space(); number(ttl); space(); logtype(qtype); space(); name(q); line(); } void log_lame(const unsigned char *server,const unsigned char *control,const unsigned char *referral) { string("lame "); ip(server); space(); name(control); space(); name(referral); line(); } void log_ignore_referral(const unsigned char *server, const unsigned char *control, const unsigned char *referral) { string("ignored referral "); ip(server); space(); name(control); space(); name(referral); line(); } void log_servfail(const unsigned char *dn) { const char *x = e_str(errno); string("servfail "); name(dn); space(); string(x); line(); } void log_cachedservfail(const unsigned char *dn, const unsigned char *dt) { string("cached servfail "); name(dn); space(); logtype(dt); line(); } void log_rr(const unsigned char *server,const unsigned char *q,const unsigned char type[2],const unsigned char *buf,unsigned int len,unsigned int ttl, unsigned char flagkey) { int i; string("rr "); dctype(flagkey); ip(server); space(); number(ttl); space(); logtype(type); space(); name(q); space(); for (i = 0;i < len;++i) { hex(buf[i]); if (i > 30) { string("..."); break; } } line(); } void log_rra(const unsigned char *server,const unsigned char *q,const unsigned char *data,unsigned int ttl, unsigned char flagkey) { unsigned char i[16]; byte_copy(i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377"); byte_copy(i + 12, 4, data); string("rr "); dctype(flagkey); ip(server); space(); number(ttl); string(" a "); name(q); space(); string(iptostr(0, i)); line(); } void log_rraaaa(const unsigned char *server,const unsigned char *q,const unsigned char *data,unsigned int ttl, unsigned char flagkey) { string("rr "); dctype(flagkey); ip(server); space(); number(ttl); string(" aaaa "); name(q); space(); string(iptostr(0, data)); line(); } void log_rrns(const unsigned char *server,const unsigned char *q,const unsigned char *data,unsigned int ttl, unsigned char flagkey) { string("rr "); dctype(flagkey); ip(server); space(); number(ttl); string(" ns "); name(q); space(); name(data); line(); } void log_rrcname(const unsigned char *server,const unsigned char *q,const unsigned char *data,unsigned int ttl, unsigned char flagkey) { string("rr "); dctype(flagkey); ip(server); space(); number(ttl); string(" cname "); name(q); space(); name(data); line(); } void log_rrptr(const unsigned char *server,const unsigned char *q,const unsigned char *data,unsigned int ttl, unsigned char flagkey) { string("rr "); dctype(flagkey); ip(server); space(); number(ttl); string(" ptr "); name(q); space(); name(data); line(); } void log_rrmx(const unsigned char *server,const unsigned char *q,const unsigned char *mx,const unsigned char pref[2],unsigned int ttl, unsigned char flagkey) { crypto_uint16 u; string("rr "); dctype(flagkey); ip(server); space(); number(ttl); string(" mx "); name(q); space(); u = uint16_unpack_big(pref); number(u); space(); name(mx); line(); } void log_rrsoa(const unsigned char *server,const unsigned char *q,const unsigned char *n1,const unsigned char *n2,const unsigned char misc[20],unsigned int ttl,unsigned char flagkey) { crypto_uint32 u; int i; string("rr "); dctype(flagkey); ip(server); space(); number(ttl); string(" soa "); name(q); space(); name(n1); space(); name(n2); for (i = 0;i < 20;i += 4) { u = uint32_unpack_big(misc + i); space(); number(u); } line(); } crypto_uint64 log_numqueries = 0; long long log_uactive = 0; long long log_tactive = 0; void log_stats(void) { extern crypto_uint64 cache_motion; extern crypto_uint64 cache_hit; extern crypto_uint64 cache_miss; extern crypto_uint64 tx4; extern crypto_uint64 tx6; string("stats "); number(log_numqueries); space(); number(cache_motion); space(); number(log_uactive); space(); number(log_tactive); space(); number(cache_hit); space(); number(cache_miss); space(); number(tx4); space(); number(tx6); line(); } dq-20240101/log.h000066400000000000000000000053201454446775700133320ustar00rootroot00000000000000#ifndef LOG_H #define LOG_H #include "crypto_uint64.h" extern void log_startup(void); extern void log_dnscurvekey(const unsigned char *key); extern void log_query(crypto_uint64 *,const unsigned char *,unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); extern void log_queryreject(const unsigned char *, unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *, const char *); extern void log_querydrop(crypto_uint64 *); extern void log_querydone(crypto_uint64 *,long long); extern void log_tcpopen(const unsigned char *,unsigned char *); extern void log_tcpclose(const unsigned char *,unsigned char *); extern void log_cachedanswer(const unsigned char *,const unsigned char *); extern void log_cachedcname(const unsigned char *,const unsigned char *); extern void log_cachednxdomain(const unsigned char *); extern void log_cachedns(const unsigned char *,const unsigned char *); extern void log_tx(const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,int,unsigned int); extern void log_nxdomain(const unsigned char *,const unsigned char *,unsigned int); extern void log_nodata(const unsigned char *,const unsigned char *,const unsigned char *,unsigned int); extern void log_servfail(const unsigned char *); extern void log_cachedservfail(const unsigned char *, const unsigned char *); extern void log_lame(const unsigned char *,const unsigned char *,const unsigned char *); extern void log_ignore_referral(const unsigned char *,const unsigned char *,const unsigned char *); extern void log_rr(const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned int,unsigned char); extern void log_rra(const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned char); extern void log_rraaaa(const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned char); extern void log_rrns(const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned char); extern void log_rrcname(const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned char); extern void log_rrptr(const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned char); extern void log_rrmx(const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned char); extern void log_rrsoa(const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,unsigned int,unsigned char); extern void log_stats(void); extern crypto_uint64 log_numqueries; extern long long log_uactive; extern long long log_tactive; #endif dq-20240101/makefilegen.sh000066400000000000000000000035531454446775700152110ustar00rootroot00000000000000#!/bin/sh ( ( echo "CC?=cc" echo "CFLAGS+=-O3 -fno-strict-overflow -fwrapv -Wno-parentheses -Wundef -Wunused-value -Wmissing-prototypes -Wmissing-declarations -Wwrite-strings -Wdeclaration-after-statement -Wshadow -Wno-unused-function -Wno-overlength-strings -Wno-long-long -Wall -pedantic" echo "LDFLAGS?=" echo "DESTDIR?=" echo i=0 for file in `ls *.c`; do if grep '^int main(' "${file}" >/dev/null; then x=`echo "${file}" | sed 's/\.c$//'` if [ $i -eq 0 ]; then echo "BINARIES=${x}" else echo "BINARIES+=${x}" fi i=`expr $i + 1` fi done echo echo "all: \$(BINARIES)" echo for file in `ls *.c`; do ( gcc -MM "${file}" echo " \$(CC) \$(CFLAGS) \$(CPPFLAGS) -c ${file}" echo ) done i=0 for file in `ls *.c`; do if ! grep '^int main(' "${file}" >/dev/null; then x=`echo "${file}" | sed 's/\.c$/.o/'` if [ $i -eq 0 ]; then echo "OBJECTS=${x}" else echo "OBJECTS+=${x}" fi i=`expr $i + 1` fi done echo for file in `ls *.c`; do if grep '^int main(' "${file}" >/dev/null; then x=`echo "${file}" | sed 's/\.c$//'` echo "${x}: ${x}.o \$(OBJECTS)" echo " \$(CC) \$(CFLAGS) \$(CPPFLAGS) -o ${x} ${x}.o \$(OBJECTS) \$(LDFLAGS)" echo fi done echo echo "install: dq dqcache dqcache-makekey dqcache-start" echo " install -D -m 0755 dq \$(DESTDIR)/usr/bin/dq" echo " install -D -m 0755 dqcache \$(DESTDIR)/usr/sbin/dqcache" echo " install -D -m 0755 dqcache-makekey \$(DESTDIR)/usr/sbin/dqcache-makekey" echo " install -D -m 0755 dqcache-start \$(DESTDIR)/usr/sbin/dqcache-start" echo echo "clean:" echo " rm -f *.o *.out \$(BINARIES)" echo ) > Makefile ) dq-20240101/man/000077500000000000000000000000001454446775700131535ustar00rootroot00000000000000dq-20240101/man/dq.1000066400000000000000000000050201454446775700136360ustar00rootroot00000000000000.TH dq 1 .SH NAME dq \- DNS/DNSCurve query tool .SH SYNOPSIS .B dq [ options ] .I type .I fqdn [ .I host ] .TP .B dq \-a [ options ] .I type .I fqdn .I host .SH DESCRIPTION .B dq is commandline tool derived from .B dnsq / .B dnsqr (https://cr.yp.to/djbdns/debugging.html) .sp .B dq asks for records of type .I type under the domain name .I fqdn .TP .B dq \-a sends a non\-recursive DNS/DNSCurve query to DNS/DNSCurve server .I host for records of type .I type under the domain name .I fqdn .SH OPTIONS .TP .B \-v print extra information .TP .B \-r send recursive query (default) .TP .B \-a send authoritative query .TP .B \-u use UDP (default) .TP .B \-t use TCP .TP .B \-s send DNSCurve query in streamlined format (default), ignored for regular DNS queries .TP .B \-S \fIsuffix send DNSCurve query in TXT format using suffix .IR suffix , ignored for regular DNS queries .TP .B \-T \fItimeout give up on the DNS/DNSCurve query attempt after .I timeout seconds <1\-60> (default 60) .TP .B \-p \fIport send query to port .I port (default 53) .TP .B \-k \fIkey send DNSCurve query and use servers public\-key .I key .TP .I type DNS query type (A, NS, MX, ANY, PTR, TXT, SOA, SRV, AAAA, AXFR, CNAME or numeric type) .TP .I fqdn fully qualified domain name .TP .I host DNS server (hostname or IP address) .SH ENVIRONMENT .TP .B DNSCACHEIP use IP address $DNSCACHEIP instead of 'nameserver' lines from /etc/resolv.conf .TP .B LOCALDOMAIN use space separated names from $LOCALDOMAIN instead of 'search' line from /etc/resolv.conf .TP .B DNSREWRITEFILE use $DNSREWRITEFILE file instead of /etc/dnsrewrite .SH NOTES .B dq rewrites IP address to *.in\-addr.arpa or *.ip6.arpa for PTR queries e.g.: .nf .RS 2 127.0.0.1 \-> 1.0.0.127.in\-addr.arpa ::1 \-> 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa .RE .SH RECURSIVE EXAMPLES .nf dq any dnscurve.cz dq any dnscurve.cz 8.8.8.8 env DNSCACHEIP=8.8.8.8 dq any dnscurve.cz dq ptr 1.0.0.127.in\-addr.arpa dq ptr 127.0.0.1 dq ptr ::1 dq ptr 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa .fi .SH AUTHORITATIVE EXAMPLES .nf dq \-a any dnscurve.cz uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq.ns.dnscurve.cz dq \-a \-S cz any dnscurve.cz uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq.ns.dnscurve.cz dq \-a \-k uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq any dnscurve.cz 2a02:2b88:2:1::127d:1 .fi .SH SEE ALSO .BR dnsq (1), .BR dnsqr (1), .BR dqcache (8) .sp .nf https://mojzis.com/software/dq https://dnscurve.org/ https://cr.yp.to/djbdns/debugging.html .fi dq-20240101/man/dqcache-makekey.8000066400000000000000000000006541454446775700162650ustar00rootroot00000000000000.TH dqcache\-makekey 8 .SH NAME dqcache\-makekey \- make DNSCurve secret\-key for dqcache .SH SYNOPSIS .B dqcache\-makekey .SH DESCRIPTION .B dqcache\-makekey creates secret\-key (in hex format) for dqcache .SH EXAMPLE .nf ( cd /etc/dqcache/env/ umask 077 dqcache\-makekey > SECRETKEY.tmp mv \-f SECRETKEY.tmp SECRETKEY ) .fi .SH SEE ALSO .BR dqcache (8) .sp .nf https://mojzis.com/software/dq https://dnscurve.org/ .fi dq-20240101/man/dqcache-start.8000066400000000000000000000010611454446775700157650ustar00rootroot00000000000000.TH dqcache\-start 8 .SH NAME dqcache\-start \- wrapper for dqcache daemon .SH SYNOPSIS .B dqcache\-start root\-directory account child .SH DESCRIPTION .B dqcache is designed to run under daemontools. .B dqcache\-start is a wrapper and allows running under e.g. systemd. .sp .B dqcache\-start sets $ROOT,$UID,$GID env. variables, sets appropriate permissions in $ROOT directory and runs .B dqcache .SH EXAMPLE .nf dqcache\-start /etc/dqcache/root dqcache dqcache .fi .SH SEE ALSO .BR dqcache (8) .sp .nf https://mojzis.com/software/dq https://dnscurve.org/ .fi dq-20240101/man/dqcache.8000066400000000000000000000110501454446775700146310ustar00rootroot00000000000000.TH dqcache 8 .SH NAME dqcache \- DNS cache with DNSCurve support .SH DESCRIPTION .B dqcache is recursive DNS server derived from .B dnscache (https://cr.yp.to/djbdns/dnscache.html) .SH CONFIGURATION .B dqcache runs chrooted in the directory specified by the $ROOT environment variable, under the uid and gid specified by the $UID and $GID environment variables. .sp .B dqcache listens for incoming UDP packets and TCP connections addressed to port 53 of $IP. Typically $IP is 127.0.0.1, but it can also be an externally accessible IP address. .sp .B dqcache accepts connections from localhost (127.0.0.0/8 or ::1/128). For external connections .B dqcache has file\-style accesslist. .RS 4 .nf e.g. for IPv4 address 1.2.3.4 dqcache allows connection when sees a file named: ip4/1.2.3.4 or ip4/1.2.3 or ip4/1.2 or ip4/1 e.g. for IPv6 address 2a02:598:7000:101:12dd:b1ff:fede:3476 dqcache allows connection when sees a file named: ip6/2a02:598:7000:101:12dd:b1ff:fede:3476 or ip6/2a02:598:7000:101:12dd:b1ff:fede or ip6/2a02:598:7000:101:12dd:b1ff or ip6/2a02:598:7000:101:12dd or ip6/2a02:598:7000:101 or ip6/2a02:598:7000 or ip6/2a02:598 or ip6/2a02 .fi .RE when environment variable $OKCLIENT is set, .B dqcache accepts all connections. .sp .B Warning , .B dqcache encrypts DNS packets and should run on client's machine. If You run .B dqcache on external IP (not on localhost), You're probably doing it wrong. .sp .B dqcache sends outgoing IPv4 packets from high ports of $IPSEND4. Typically $IPSEND4 is 0.0.0.0, meaning the machine's primary IPv4 address. .sp .B dqcache sends outgoing IPv6 packets from high ports of $IPSEND6. Typically $IPSEND6 is ::, meaning the machine's primary IPv6 address. .sp If $HIDETTL is set, .B dqcache always uses a TTL of 0 in its responses .sp .B dqcache reads a list of root servers as an anchor, one record per line, from servers/@. The record has format {IP} or {IP}|{DNSCURVEPUBLICKEY} e.g.: .RS 4 .nf servers/@: 198.41.0.4 2001:503:ba3e::2:30 192.228.79.201 2001:500:84::b etc. .fi .RE .sp .B dqcache also scans the servers directory for anchors for other domains, one record per line. The record has format {IP} or {IP}|{DNSCURVEPUBLICKEY} e.g.: .RS 4 .nf servers/dnscurve.cz: 185.66.36.55|uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq 37.157.196.86|uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq 2a02:2b88:2:1::127d:1|uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq 2a03:1e20:0:5::2|uz5mj60yr9tnudkkpcglw1y0w6dlh78j1l4gk4z7t8bsf1u4d48wlq .fi .RE .sp .B dqcache supports forward\-only mode. If $FORWARDONLY is set, dqcache treats servers/@ as a list of IP addresses for other caches, not root servers. It forwards queries to those caches the same way that a client does, rather than contacting a chain of servers according to NS records. .sp .B dqcache uses a fixed\-size cache, as controlled by the $CACHESIZE environment variable. Typically $CACHESIZE is 10000000 (10MB). .sp .B dqcache typically generates new secret key at start of program. If environment variable $SECRETKEY is set, then .B dqcache loads this secret key. $SECRETKEY must be safely generated using .BR dqcache\-makekey (8). .sp Note that .B dqcache uses internally two secret keys, one used as the discrete logarithm of the public key (256bit DNSCurve key) and one to encrypt the nonce (128bit TEA symmetric key). Both of these keys are actually derived from $SECRETKEY using crypto_stream_salsa20(). .sp .B dqcache also supports nonce\-separation via environment variable $NONCESTART. This means that several caches share a key but use separate nonces: .RS 2 .nf e.g.: NONCESTART=100 ... the first of four caches is configured to use top bits 100 NONCESTART=101 ... the second is configured to use top bits 101 NONCESTART=110 ... the third is configured to use top bits 110 NONCESTART=111 ... and the fourth is configured to use top bits 111. etc. .fi .RE .sp .B dqcache typically supports DNSCurve in 'combined mode' (meaning: if Streamlined query fails, .B dqcache tries also TXT query). Environment variable $DNSCURVETYPE selects specific DNSCurve type. .RS 2 .nf DNSCURVETYPE=1 ... Streamlined only DNSCurve DNSCURVETYPE=2 ... TXT only DNSCurve .fi .RE .sp .B dqcache caches records for at least $MINTTL seconds, when MINTTL is set. It's limited <0\-300> seconds. Use only if you really know what you're doing. .RE .sp .B dqcache sends only IPv4 queries, when DISABLEIPV6 is set. Use only if you really know what you're doing. .SH SEE ALSO .BR dqcache\-makekey (8), .BR dq (1), .BR dnscache (8) .sp .nf https://mojzis.com/software/dq https://dnscurve.org/ https://cr.yp.to/djbdns/dnscache.html .fi dq-20240101/milliseconds.c000066400000000000000000000004061454446775700152310ustar00rootroot00000000000000/* 20130505 Jan Mojzis Public domain. */ #include #include #include "milliseconds.h" long long milliseconds(void) { struct timeval t; gettimeofday(&t, (struct timezone *)0); return t.tv_sec * 1000LL + t.tv_usec / 1000LL; } dq-20240101/milliseconds.h000066400000000000000000000001461454446775700152370ustar00rootroot00000000000000#ifndef _MILLISECONDS_H____ #define _MILLISECONDS_H____ extern long long milliseconds(void); #endif dq-20240101/nanoseconds.c000066400000000000000000000010051454446775700150520ustar00rootroot00000000000000#include #include #include "nanoseconds.h" /* XXX: Y2036 problems; should upgrade to a 128-bit type for this */ /* XXX: nanosecond granularity limits users to 1 terabyte per second */ long long nanoseconds(void) { #ifdef CLOCK_REALTIME struct timespec t; if (clock_gettime(CLOCK_REALTIME,&t) != 0) return -1; return t.tv_sec * 1000000000LL + t.tv_nsec; #else struct timeval t; gettimeofday(&t,(struct timezone *) 0); return t.tv_sec * 1000000000LL + t.tv_usec * 1000LL; #endif } dq-20240101/nanoseconds.h000066400000000000000000000001311454446775700150560ustar00rootroot00000000000000#ifndef NANOSECONDS_H #define NANOSECONDS_H extern long long nanoseconds(void); #endif dq-20240101/numtostr.c000066400000000000000000000016321454446775700144410ustar00rootroot00000000000000/* 20130604 Jan Mojzis Public domain. */ #include "numtostr.h" /* The 'numtostr(strbuf,n)' converts number 'n' into the 0-terminated string. The caller must allocate at least NUMTOSTR_LEN bytes for 'strbuf'. The 'numtostr' function is ready for 128-bit integer. */ char *numtostr(char *strbuf, long long n) { long long len = 0; unsigned long long n1, n2; static char staticbuf[NUMTOSTR_LEN]; int flagsign = 0; if (!strbuf) strbuf = staticbuf; /* not thread-safe */ if (n < 0) { n1 = n2 = -(unsigned long long)n; flagsign = 1; } else { n1 = n2 = (unsigned long long)n; } do { n1 /= 10; ++len; } while (n1); if (flagsign) ++len; strbuf += len; do { *--strbuf = '0' + (n2 % 10); n2 /= 10; } while (n2); if (flagsign) *--strbuf = '-'; while (len < NUMTOSTR_LEN) strbuf[len++] = 0; return strbuf; } dq-20240101/numtostr.h000066400000000000000000000001741454446775700144460ustar00rootroot00000000000000#ifndef _NUMTOSTR_H____ #define _NUMTOSTR_H____ #define NUMTOSTR_LEN 41 extern char *numtostr(char *, long long); #endif dq-20240101/okclient.c000066400000000000000000000017721454446775700143630ustar00rootroot00000000000000#include #include #include "str.h" #include "byte.h" #include "iptostr.h" #include "okclient.h" static char fn[4 + IPTOSTR_LEN]; int okclient(unsigned char *ip) { struct stat st; long long i; char sep; /* allow ::1/128 */ if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 16, ip)) return 1; /* allow 127.0.0.0/8 */ if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377\177", 13, ip)) return 1; if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { fn[0] = 'i'; fn[1] = 'p'; fn[2] = '4'; fn[3] = '/'; iptostrx(fn + 4, ip); sep = '.'; } else { fn[0] = 'i'; fn[1] = 'p'; fn[2] = '6'; fn[3] = '/'; iptostrx(fn + 4, ip); sep = ':'; } for (;;) { if (stat(fn, &st) == 0) return 1; /* treat temporary error as rejection */ i = str_rchr(fn, sep); if (!fn[i]) return 0; fn[i] = 0; } return 0; } dq-20240101/okclient.h000066400000000000000000000001251454446775700143570ustar00rootroot00000000000000#ifndef OKCLIENT_H #define OKCLIENT_H extern int okclient(unsigned char *); #endif dq-20240101/open.h000066400000000000000000000003621454446775700135130ustar00rootroot00000000000000#ifndef OPEN_H #define OPEN_H extern int open_read(const char *); extern int open_write(const char *); extern int open_lock(const char *); extern int open_cwd(void); extern int open_pipe(int *); extern int open_trunc(const char *); #endif dq-20240101/open_read.c000066400000000000000000000005061454446775700145010ustar00rootroot00000000000000#include #include #include #include #include "open.h" int open_read(const char *fn) { #ifdef O_CLOEXEC return open(fn,O_RDONLY | O_NONBLOCK | O_CLOEXEC); #else int fd = open(fn,O_RDONLY | O_NONBLOCK); if (fd == -1) return -1; fcntl(fd,F_SETFD,1); return fd; #endif } dq-20240101/open_trunc.c000066400000000000000000000005711454446775700147230ustar00rootroot00000000000000#include #include #include #include #include "open.h" int open_trunc(const char *fn) { #ifdef O_CLOEXEC return open(fn,O_CREAT | O_WRONLY | O_NONBLOCK | O_TRUNC | O_CLOEXEC,0644); #else int fd = open(fn,O_CREAT | O_WRONLY | O_NONBLOCK | O_TRUNC,0644); if (fd == -1) return -1; fcntl(fd,F_SETFD,1); return fd; #endif } dq-20240101/openreadclose.c000066400000000000000000000020051454446775700153640ustar00rootroot00000000000000#include #include #include #include "open.h" #include "e.h" #include "byte.h" #include "openreadclose.h" int openreadclose(const char *fn, stralloc *sa, long long bufsize) { int fd; long long r; struct stat st; if (bufsize <= 1) bufsize = 32; fd = open_read(fn); if (fd == -1) { if (errno == ENOENT) return 0; return -1; } if (fstat(fd, &st) == -1) { close(fd); return -1; } if (!stralloc_readyplus(sa, st.st_size)) { close(fd); return -1; } if (!stralloc_copys(sa, "")) { close(fd); return -1; } for (;;) { if (!stralloc_readyplus(sa, bufsize)) { close(fd); return -1; } r = read(fd, sa->s + sa->len, bufsize); if (r == 0) break; if (r == -1) { if (errno == EINTR) continue; if (errno == EAGAIN) continue; if (errno == EWOULDBLOCK) continue; close(fd); return -1; } sa->len += r; } close(fd); return 1; } dq-20240101/openreadclose.h000066400000000000000000000002311454446775700153700ustar00rootroot00000000000000#ifndef _OPENREADCLOSE_H____ #define _OPENREADCLOSE_H____ #include "stralloc.h" extern int openreadclose(const char *, stralloc *, long long); #endif dq-20240101/portparse.c000066400000000000000000000005101454446775700145570ustar00rootroot00000000000000#include "portparse.h" int portparse(unsigned char *y,const char *x) { long long d = 0; long long j; if (!x) return 0; for (j = 0;j < 5 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0'); if (j == 0) return 0; if (x[j]) return 0; if (d > 65535) return 0; y[0] = d >> 8; y[1] = d; return 1; } dq-20240101/portparse.h000066400000000000000000000001451454446775700145700ustar00rootroot00000000000000#ifndef PORTPARSE_H #define PORTPARSE_H extern int portparse(unsigned char *,const char *); #endif dq-20240101/porttostr.c000066400000000000000000000015041454446775700146240ustar00rootroot00000000000000/* 20130604 Jan Mojzis Public domain. */ #include "crypto_uint16.h" #include "porttostr.h" /* The 'porttostr(strbuf,port)' converts 'port' from network byte order into the 0-terminated string. The 'port' length is always 2 bytes. The caller must allocate at least PORTTOSTR_LEN bytes for 'strbuf'. */ char *porttostr(char *strbuf, const unsigned char *port) { long long len = 0; crypto_uint16 num; static char staticbuf[PORTTOSTR_LEN]; if (!strbuf) strbuf = staticbuf; /* not thread-safe */ num = port[0]; num <<= 8; num |= port[1]; do { num /= 10; ++len; } while (num); strbuf += len; num = port[0]; num <<= 8; num |= port[1]; do { *--strbuf = '0' + (num % 10); num /= 10; } while (num); while (len < PORTTOSTR_LEN) strbuf[len++] = 0; return strbuf; } dq-20240101/porttostr.h000066400000000000000000000002131454446775700146250ustar00rootroot00000000000000#ifndef _PORTTOSTR_H____ #define _PORTTOSTR_H____ #define PORTTOSTR_LEN 6 extern char *porttostr(char *, const unsigned char *); #endif dq-20240101/printpacket.c000066400000000000000000000041301454446775700150660ustar00rootroot00000000000000#include "uint16_unpack_big.h" #include "e.h" #include "byte.h" #include "dns.h" #include "printrecord.h" #include "printpacket.h" static unsigned char *d = 0; #define X(s) if (!stralloc_cats(out,s)) return 0; #define NUM(u) if (!stralloc_catnum(out,u)) return 0; int printpacket_cat(stralloc *out, unsigned char *buf, long long len) { crypto_uint16 xnumqueries; crypto_uint16 numanswers; crypto_uint16 numauthority; crypto_uint16 numglue; long long pos; unsigned char data[12]; crypto_uint16 type; pos = dns_packet_copy(buf,len,0,data,12); if (!pos) return 0; xnumqueries = uint16_unpack_big(data + 4); numanswers = uint16_unpack_big(data + 6); numauthority = uint16_unpack_big(data + 8); numglue = uint16_unpack_big(data + 10); NUM(len) X(" bytes, ") NUM(xnumqueries) X("+") NUM(numanswers) X("+") NUM(numauthority) X("+") NUM(numglue) X(" records") if (data[2] & 128) X(", response") if (data[2] & 120) X(", weird op") if (data[2] & 4) X(", authoritative") if (data[2] & 2) X(", truncated") if (data[2] & 1) X(", weird rd") if (data[3] & 128) X(", weird ra") switch(data[3] & 15) { case 0: X(", noerror"); break; case 3: X(", nxdomain"); break; case 4: X(", notimp"); break; case 5: X(", refused"); break; default: X(", weird rcode"); } if (data[3] & 112) X(", weird z") X("\n") while (xnumqueries) { --xnumqueries; X("query: ") pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; pos = dns_packet_copy(buf,len,pos,data,4); if (!pos) return 0; if (!byte_isequal(data + 2,2,DNS_C_IN)) { X("weird class") } else { type = uint16_unpack_big(data); NUM(type) X(" ") if (!dns_domain_todot_cat(out,d)) return 0; } X("\n") } for (;;) { if (numanswers) { --numanswers; X("answer: ") } else if (numauthority) { --numauthority; X("authority: ") } else if (numglue) { --numglue; X("additional: ") } else break; pos = printrecord_cat(out,buf,len,pos,0,0); if (!pos) return 0; } if (pos != len) { errno = EPROTO; return 0; } return 1; } dq-20240101/printpacket.h000066400000000000000000000002321454446775700150720ustar00rootroot00000000000000#ifndef PRINTPACKET_H #define PRINTPACKET_H #include "stralloc.h" extern int printpacket_cat(stralloc *out, unsigned char *buf, long long len); #endif dq-20240101/printrecord.c000066400000000000000000000126031454446775700151010ustar00rootroot00000000000000#include "uint16_unpack_big.h" #include "uint32_unpack_big.h" #include "e.h" #include "byte.h" #include "dns.h" #include "printrecord.h" #include "iptostr.h" static unsigned char *d = 0; long long printrecord_cat(stralloc *out,const unsigned char *buf,long long len,long long pos,const unsigned char *q,const unsigned char qtype[2]) { const unsigned char *x; unsigned char misc[20]; crypto_uint16 datalen; crypto_uint16 u16; crypto_uint32 u32; long long newpos; long long i; unsigned char ch; long long txtlen; pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; pos = dns_packet_copy(buf,len,pos,misc,10); if (!pos) return 0; datalen = uint16_unpack_big(misc + 8); newpos = pos + datalen; if (q) { if (!dns_domain_equal(d,q)) return newpos; if (!byte_isequal(qtype,2,misc) && !byte_isequal(qtype,2,DNS_T_ANY)) return newpos; } if (!dns_domain_todot_cat(out,d)) return 0; if (!stralloc_cats(out," ")) return 0; u32 = uint32_unpack_big(misc + 4); if (!stralloc_catnum(out,u32)) return 0; if (!byte_isequal(misc + 2,2,DNS_C_IN)) { if (!stralloc_cats(out," weird class\n")) return 0; return newpos; } x = 0; if (byte_isequal(misc,2,DNS_T_NS)) x = (unsigned char *)" NS "; if (byte_isequal(misc,2,DNS_T_PTR)) x = (unsigned char *)" PTR "; if (byte_isequal(misc,2,DNS_T_CNAME)) x = (unsigned char *)" CNAME "; if (x) { pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; if (!stralloc_cats(out,x)) return 0; if (!dns_domain_todot_cat(out,d)) return 0; } else if (byte_isequal(misc,2,DNS_T_MX)) { if (!stralloc_cats(out," MX ")) return 0; pos = dns_packet_copy(buf,len,pos,misc,2); if (!pos) return 0; pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; u16 = uint16_unpack_big(misc); if (!stralloc_catnum(out,u16)) return 0; if (!stralloc_cats(out," ")) return 0; if (!dns_domain_todot_cat(out,d)) return 0; } else if (byte_isequal(misc,2,DNS_T_SOA)) { if (!stralloc_cats(out," SOA ")) return 0; pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; if (!dns_domain_todot_cat(out,d)) return 0; if (!stralloc_cats(out," ")) return 0; pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; if (!dns_domain_todot_cat(out,d)) return 0; pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) return 0; for (i = 0;i < 5;++i) { if (!stralloc_cats(out," ")) return 0; u32 = uint32_unpack_big(misc + 4 * i); if (!stralloc_catnum(out,u32)) return 0; } } else if (byte_isequal(misc,2,DNS_T_AAAA)) { if (datalen != 16) { errno = EPROTO; return 0; } if (!stralloc_cats(out," AAAA ")) return 0; pos = dns_packet_copy(buf,len,pos,misc,16); if (!pos) return 0; if (!stralloc_cats(out,iptostr(0, misc))) return 0; } else if (byte_isequal(misc,2,DNS_T_TXT)) { if (pos + datalen > len) return 0; if (!stralloc_cats(out," TXT ")) return 0; txtlen = 0; for (i = 0;i < datalen;++i) { ch = buf[pos + i]; if (!txtlen) txtlen = ch; else { --txtlen; if (ch < 32 || ch > 126) { misc[3] = '0' + (7 & ch); ch >>= 3; misc[2] = '0' + (7 & ch); ch >>= 3; misc[1] = '0' + (7 & ch); misc[0] = '\\'; if (!stralloc_catb(out,misc,4)) return 0; } else { if (!stralloc_append(out,&ch)) return 0; } } } pos += datalen; } else if (byte_isequal(misc,2,DNS_T_SRV)) { if (!stralloc_cats(out," SRV ")) return 0; pos = dns_packet_copy(buf,len,pos,misc,6); if (!pos) return 0; u16 = uint16_unpack_big(misc); if (!stralloc_catnum(out,u16)) return 0; if (!stralloc_cats(out," ")) return 0; u16 = uint16_unpack_big(misc + 2); if (!stralloc_catnum(out,u16)) return 0; if (!stralloc_cats(out," ")) return 0; u16 = uint16_unpack_big(misc + 4); if (!stralloc_catnum(out,u16)) return 0; if (!stralloc_cats(out," ")) return 0; pos = dns_packet_getname(buf,len,pos,&d); if (!pos) return 0; if (!dns_domain_todot_cat(out,d)) return 0; } else if (byte_isequal(misc,2,DNS_T_A)) { if (datalen != 4) { errno = EPROTO; return 0; } if (!stralloc_cats(out," A ")) return 0; pos = dns_packet_copy(buf,len,pos,misc,4); if (!pos) return 0; for (i = 0;i < 4;++i) { ch = misc[i]; if (i) if (!stralloc_cats(out,".")) return 0; if (!stralloc_catnum(out,ch)) return 0; } } else { if (!stralloc_cats(out," ")) return 0; u16 = uint16_unpack_big(misc); if (!stralloc_catnum(out,u16)) return 0; if (!stralloc_cats(out," ")) return 0; while (datalen--) { pos = dns_packet_copy(buf,len,pos,misc,1); if (!pos) return 0; if ((misc[0] >= 33) && (misc[0] <= 126) && (misc[0] != '\\')) { if (!stralloc_catb(out,misc,1)) return 0; } else { ch = misc[0]; misc[3] = '0' + (7 & ch); ch >>= 3; misc[2] = '0' + (7 & ch); ch >>= 3; misc[1] = '0' + (7 & ch); misc[0] = '\\'; if (!stralloc_catb(out,misc,4)) return 0; } } } if (!stralloc_cats(out,"\n")) return 0; if (pos != newpos) { errno = EPROTO; return 0; } return newpos; } long long printrecord(stralloc *out,const unsigned char *buf,long long len,long long pos,const unsigned char *q,const unsigned char qtype[2]) { if (!stralloc_copys(out,"")) return 0; return printrecord_cat(out,buf,len,pos,q,qtype); } dq-20240101/printrecord.h000066400000000000000000000005751454446775700151130ustar00rootroot00000000000000#ifndef PRINTRECORD_H #define PRINTRECORD_H #include "stralloc.h" extern long long printrecord_cat(stralloc *out,const unsigned char *buf,long long len,long long pos,const unsigned char *q,const unsigned char qtype[2]); extern long long printrecord(stralloc *out,const unsigned char *buf,long long len,long long pos,const unsigned char *q,const unsigned char qtype[2]); #endif dq-20240101/purge.h000066400000000000000000000001631454446775700136730ustar00rootroot00000000000000#ifndef _PURGE_H____ #define _PURGE_H____ extern void cleanup_(void *, long long); #define purge cleanup_ #endif dq-20240101/query.c000066400000000000000000001115101454446775700137100ustar00rootroot00000000000000#include "e.h" #include "roots.h" #include "log.h" #include "case.h" #include "cache.h" #include "byte.h" #include "dns.h" #include "uint32_unpack_big.h" #include "uint16_unpack_big.h" #include "alloc.h" #include "response.h" #include "query.h" #include "strtoip.h" #include "iptostr.h" #include "xsocket.h" #include "crypto_scalarmult_curve25519.h" #include "crypto_box_curve25519xsalsa20poly1305.h" #include "purge.h" static unsigned char secretkey[32]; static unsigned char publickey[32]; void query_init(const unsigned char *sk) { byte_copy(secretkey,32,sk); crypto_scalarmult_curve25519_base(publickey, secretkey); log_dnscurvekey(publickey); return; } void query_purge(void) { purge(secretkey, sizeof secretkey); purge(publickey, sizeof publickey); } static int flagforwardonly = 0; void query_forwardonly(void) { flagforwardonly = 1; } static int flagtcponly = 0; void query_tcponly(void) { flagtcponly = 1; } static int flagipv4only = 0; void query_ipv4only(void) { flagipv4only = 1; } static crypto_uint32 minttl = 0; void query_minttl(long long x) { if (x < 0) x = 0; if (x > 300) x = 300; minttl = x; } unsigned char remoteport[2] = { 0, 53 }; void query_remoteport(unsigned char *port) { byte_copy(remoteport, 2, port); } static int flagdnscurvetype1 = 1; static int flagdnscurvetype2 = 2; void query_dnscurvetype(char *x) { if (!x) return; if (*x == '1') { /* streamlined only */ flagdnscurvetype1 = 1; flagdnscurvetype2 = 0; } else if (*x == '2') { /* txt only */ flagdnscurvetype1 = 2; flagdnscurvetype2 = 0; } else { /* mixed */ flagdnscurvetype1 = 1; flagdnscurvetype2 = 2; } } static void cachegeneric(const unsigned char type[2],const unsigned char *d,const unsigned char *data,long long datalen,crypto_uint32 ttl, unsigned char flagns) { long long len; unsigned char key[257]; len = dns_domain_length(d); if (len > 255) return; byte_copy(key,2,type); byte_copy(key + 2,len,d); case_lowerb(key + 2,len); cache_set(key,len + 2,data,datalen,ttl,flagns); } static void cachegeneric2(const unsigned char type[2],const unsigned char dtype[2], const unsigned char *d,const unsigned char *data,long long datalen,crypto_uint32 ttl, unsigned char flagns) { long long len; unsigned char key[259]; len = dns_domain_length(d); if (len > 255) return; byte_copy(key,2,type); byte_copy(key + 2,len,d); byte_copy(key + 2 + len,2,dtype); case_lowerb(key + 2,len); cache_set(key,len + 4,data,datalen,ttl,flagns); } static unsigned char save_buf[8192]; static long long save_len; static long long save_ok; static void save_start(void) { save_len = 0; save_ok = 1; } static void save_data(const unsigned char *buf,long long len) { if (!save_ok) return; if (len > (sizeof save_buf) - save_len) { save_ok = 0; return; } byte_copy(save_buf + save_len,len,buf); save_len += len; } static void save_finish(const unsigned char type[2],const unsigned char *d,crypto_uint32 ttl,unsigned char flagns) { if (!save_ok) return; cachegeneric(type,d,save_buf,save_len,ttl,flagns); } static int typematch(const unsigned char rtype[2],const unsigned char qtype[2]) { return byte_isequal(qtype,2,rtype) || byte_isequal(qtype,2,DNS_T_ANY); } static long long ttlget(unsigned char buf[4]) { crypto_uint32 ttl; ttl=uint32_unpack_big(buf); if (ttl < minttl) ttl = minttl; if (ttl > 1000000000) return 0; if (ttl > 604800) return 604800; return ttl; } static void cleanup(struct query *z) { int j; int k; dns_transmit_free(&z->dt); for (j = 0;j < QUERY_MAXALIAS;++j) dns_domain_free(&z->alias[j]); for (j = 0;j < QUERY_MAXLEVEL;++j) { dns_domain_free(&z->name[j]); for (k = 0;k < QUERY_MAXNS;++k) dns_domain_free(&z->ns[j][k]); } } static int rqa(struct query *z) { int i; for (i = QUERY_MAXALIAS - 1;i >= 0;--i) if (z->alias[i]) { if (!response_query(z->alias[i],z->type,z->class)) return 0; while (i > 0) { if (!response_cname(z->alias[i],z->alias[i - 1],z->aliasttl[i])) return 0; --i; } if (!response_cname(z->alias[0],z->name[0],z->aliasttl[0])) return 0; return 1; } if (!response_query(z->name[0],z->type,z->class)) return 0; return 1; } static int dtis(char *out, long long outlen, const unsigned char *d) { long long pos = 0; char ch; char ch2; if (!*d) return 0; for (;;) { ch = *d++; while (ch--) { ch2 = *d++; if (((ch2 >= '0') && (ch2 <= '9')) || (ch2 == ':')) { if (pos >= outlen) return 0; out[pos++] = ch2; continue; } return 0; } if (!*d) { if (pos >= outlen) return 0; out[pos++] = 0; return 1; } if (pos >= outlen) return 0; out[pos++] = '.'; } return 0; } static int globalip(unsigned char *d,unsigned char ip[16]) { char xbuf[100]; if (dns_domain_equal(d,(unsigned char *)"\011localhost\0")) { byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\377\377\177\0\0\1"); return 1; } if (!dtis(xbuf, sizeof xbuf, d)) return 0; return strtoip4(ip, xbuf); } static int globalip6(unsigned char *d,unsigned char ip[16]) { char xbuf[100]; if (dns_domain_equal(d,(unsigned char *)"\011localhost\0")) { byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"); return 1; } if (!dtis(xbuf, sizeof xbuf, d)) return 0; return strtoip6(ip, xbuf); } static int findkey(const unsigned char *dn,unsigned char key[32]) { unsigned char c; while (c = *dn++) { if (c == 54) if (!case_diffb(dn,3,"uz5")) if (base32_decode(key,dn + 3,51,1) == 32) return 1; dn += (unsigned int) c; } return 0; } static unsigned char *t1 = 0; static unsigned char *t2 = 0; static unsigned char *t3 = 0; static unsigned char *cname = 0; static unsigned char *referral = 0; static long long *records = 0; static int smaller(unsigned char *buf,long long len,long long pos1,long long pos2) { unsigned char header1[12]; unsigned char header2[12]; int r; long long len1; long long len2; pos1 = dns_packet_getname(buf,len,pos1,&t1); dns_packet_copy(buf,len,pos1,header1,10); pos2 = dns_packet_getname(buf,len,pos2,&t2); dns_packet_copy(buf,len,pos2,header2,10); r = byte_diff(header1,4,header2); if (r < 0) return 1; if (r > 0) return 0; len1 = dns_domain_length(t1); len2 = dns_domain_length(t2); if (len1 < len2) return 1; if (len1 > len2) return 0; r = case_diffb(t1,len1,t2); if (r < 0) return 1; if (r > 0) return 0; if (pos1 < pos2) return 1; return 0; } static void addserver(struct query *z,const unsigned char *addr,const unsigned char *key) { int k; int i; unsigned char *kk; if (key) z->flaghavekeys[z->level - 1] = 1; for (k = 0;k < 256;k += 16) { i = k >> 4; if (byte_isequal(z->servers[z->level - 1] + k,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { byte_copy(z->servers[z->level - 1] + k,16,addr); kk = z->keys[z->level - 1] + 33 * i; if (key) { byte_copy(kk + 1,32,key); kk[0] = flagdnscurvetype1; } else { kk[0] = 0; } break; } } /* add txt */ if (!key || !flagdnscurvetype2) return; for (k = 0;k < 256;k += 16) { i = k >> 4; kk = z->keys[z->level - 1] + 33 * i; if (byte_isequal(z->servers[z->level - 1] + k,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { byte_copy(z->servers[z->level - 1] + k,16,addr); byte_copy(kk + 1,32,key); kk[0] = flagdnscurvetype2; break; } } } crypto_uint64 tx4 = 0; crypto_uint64 tx6 = 0; static int doit(struct query *z,int state) { unsigned char key[259]; unsigned char *cached; long long cachedlen; unsigned char *buf; long long len; unsigned char *whichserver; unsigned char *whichkey; unsigned char header[16]; unsigned char misc[20]; unsigned char pubkey[32]; int flaghaskey; long long rcode; long long posanswers; crypto_uint16 numanswers; long long posauthority; crypto_uint16 numauthority; /* long long posglue; */ crypto_uint16 numglue; long long pos; long long pos2; crypto_uint16 datalen; unsigned char *control; unsigned char *d; const unsigned char *dtype; long long dlen; int flagout; int flagcname; int flagreferral; unsigned char flagns; int flagsoa; long long ttl; long long soattl; long long cnamettl; long long cachedttl; unsigned char cachedflag; long long i; long long j; long long k; long long p; long long q; int flaghavekeys; errno = EIO; if (state == 1) goto HAVEPACKET; if (state == -1) { cachegeneric2(DNS_T_AXFR, z->type, z->name[z->level], (unsigned char *)"", 0, 10, 0); log_servfail(z->name[z->level]); goto SERVFAIL; } NEWNAME: if (++z->loop == QUERY_MAXLOOP) goto DIE; d = z->name[z->level]; /* dtype = z->level ? DNS_T_A : z->type; */ dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type; dlen = dns_domain_length(d); if (globalip(d,misc) && typematch(DNS_T_A,dtype)) { if (z->level) { addserver(z,misc,0); goto LOWERLEVEL; } if (!rqa(z)) goto DIE; if (typematch(DNS_T_A,dtype)) { if (!response_rstart(d,DNS_T_A,655360)) goto DIE; if (!response_addbytes(misc + 12,4)) goto DIE; response_rfinish(RESPONSE_ANSWER); } cleanup(z); return 1; } if (globalip6(d,misc) && typematch(DNS_T_AAAA,dtype)) { if (z->level) { addserver(z,misc,0); goto LOWERLEVEL; } if (!rqa(z)) goto DIE; if (typematch(DNS_T_AAAA,dtype)) { if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE; if (!response_addbytes(misc,16)) goto DIE; response_rfinish(RESPONSE_ANSWER); } cleanup(z); return 1; } if (dns_domain_equal(d,(unsigned char *)"\0011\0010\0010\003127\7in-addr\4arpa\0")) { if (z->level) goto LOWERLEVEL; if (!rqa(z)) goto DIE; if (typematch(DNS_T_PTR,dtype)) { if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE; if (!response_addname((unsigned char *)"\011localhost\0")) goto DIE; response_rfinish(RESPONSE_ANSWER); } cleanup(z); log_stats(); return 1; } if (dlen <= 255) { byte_copy(key,2,DNS_T_ANY); byte_copy(key + 2,dlen,d); case_lowerb(key + 2,dlen); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached) { log_cachednxdomain(d); goto NXDOMAIN; } byte_copy(key,2,DNS_T_AXFR); byte_copy(key + 2 + dlen,2,dtype); cached = cache_get(key,dlen + 4,&cachedlen,&ttl,0); if (cached && cachedlen == 0) { log_cachedservfail(d, dtype); goto SERVFAIL; } byte_copy(key,2,DNS_T_CNAME); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached) { if (typematch(DNS_T_CNAME,dtype)) { log_cachedanswer(d,DNS_T_CNAME); if (!rqa(z)) goto DIE; if (!response_cname(z->name[0],cached,ttl)) goto DIE; cleanup(z); return 1; } log_cachedcname(d,cached); if (!dns_domain_copy(&cname,cached)) goto DIE; goto CNAME; } if (typematch(DNS_T_NS,dtype)) { byte_copy(key,2,DNS_T_NS); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { log_cachedanswer(d,DNS_T_NS); if (!rqa(z)) goto DIE; pos = 0; while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) { if (!response_rstart(d,DNS_T_NS,ttl)) goto DIE; if (!response_addname(t2)) goto DIE; response_rfinish(RESPONSE_ANSWER); } cleanup(z); return 1; } } if (typematch(DNS_T_PTR,dtype)) { byte_copy(key,2,DNS_T_PTR); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { log_cachedanswer(d,DNS_T_PTR); if (!rqa(z)) goto DIE; pos = 0; while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) { if (!response_rstart(d,DNS_T_PTR,ttl)) goto DIE; if (!response_addname(t2)) goto DIE; response_rfinish(RESPONSE_ANSWER); } cleanup(z); return 1; } } if (typematch(DNS_T_MX,dtype)) { byte_copy(key,2,DNS_T_MX); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { log_cachedanswer(d,DNS_T_MX); if (!rqa(z)) goto DIE; pos = 0; while (pos = dns_packet_copy(cached,cachedlen,pos,misc,2)) { pos = dns_packet_getname(cached,cachedlen,pos,&t2); if (!pos) break; if (!response_rstart(d,DNS_T_MX,ttl)) goto DIE; if (!response_addbytes(misc,2)) goto DIE; if (!response_addname(t2)) goto DIE; response_rfinish(RESPONSE_ANSWER); } cleanup(z); return 1; } } if (typematch(DNS_T_SOA,dtype)) { byte_copy(key,2,DNS_T_SOA); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) { log_cachedanswer(d,DNS_T_SOA); if (!rqa(z)) goto DIE; pos = 0; while (pos = dns_packet_copy(cached,cachedlen,pos,misc,20)) { pos = dns_packet_getname(cached,cachedlen,pos,&t2); if (!pos) break; pos = dns_packet_getname(cached,cachedlen,pos,&t3); if (!pos) break; if (!response_rstart(d,DNS_T_SOA,ttl)) goto DIE; if (!response_addname(t2)) goto DIE; if (!response_addname(t3)) goto DIE; if (!response_addbytes(misc,20)) goto DIE; response_rfinish(RESPONSE_ANSWER); } cleanup(z); return 1; } } if (typematch(DNS_T_A,dtype)) { byte_copy(key,2,DNS_T_A); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns); if (cached && !cachedlen && z->level) { /* if we were looking the A record up to find an NS, try IPv6 too */ z->ipv6[z->level]=1; goto NEWNAME; } if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { if (z->level) { flaghaskey = findkey(d,pubkey); dns_sortip4(cached, cachedlen); log_cachedanswer(d,DNS_T_A); while (cachedlen >= 4) { byte_copy(misc, 12, "\0\0\0\0\0\0\0\0\0\0\377\377"); byte_copy(misc + 12, 4, cached); addserver(z,misc,flaghaskey ? pubkey : 0); cached += 4; cachedlen -= 4; } /* if we were looking the A record up to find an NS, try IPv6 too */ byte_copy(key,2,DNS_T_AAAA); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns); if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { flaghaskey = findkey(d,pubkey); dns_sortip(cached, cachedlen); log_cachedanswer(d,DNS_T_AAAA); while (cachedlen >= 16) { addserver(z,cached,flaghaskey ? pubkey : 0); cached += 16; cachedlen -= 16; } } goto LOWERLEVEL; } dns_sortip4(cached, cachedlen); log_cachedanswer(d,DNS_T_A); if (!rqa(z)) goto DIE; while (cachedlen >= 4) { if (!response_rstart(d,DNS_T_A,ttl)) goto DIE; if (!response_addbytes(cached,4)) goto DIE; response_rfinish(RESPONSE_ANSWER); cached += 4; cachedlen -= 4; } if (!flagns){ cleanup(z); return 1; } byte_copy(key,2,DNS_T_NS); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { pos = 0; while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) { if (!response_rstart(d,DNS_T_NS,ttl)) goto DIE; if (!response_addname(t2)) goto DIE; response_rfinish(RESPONSE_AUTHORITY); } cleanup(z); return 1; } } } if (typematch(DNS_T_AAAA,dtype)) { byte_copy(key,2,DNS_T_AAAA); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns); if (cached && !cachedlen && z->level) { /* if we were looking the AAAA record up to find an NS, go to LOWERLEVEL */ goto LOWERLEVEL; } if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { if (z->level) { flaghaskey = findkey(d,pubkey); dns_sortip(cached, cachedlen); log_cachedanswer(d,DNS_T_AAAA); while (cachedlen >= 16) { byte_copy(misc, 16, cached); addserver(z,misc,flaghaskey ? pubkey : 0); cached += 16; cachedlen -= 16; } goto LOWERLEVEL; } dns_sortip(cached, cachedlen); log_cachedanswer(d,DNS_T_AAAA); if (!rqa(z)) goto DIE; while (cachedlen >= 16) { if (!response_rstart(d,DNS_T_AAAA,ttl)) goto DIE; if (!response_addbytes(cached,16)) goto DIE; response_rfinish(RESPONSE_ANSWER); cached += 16; cachedlen -= 16; } if (!flagns){ cleanup(z); return 1; } byte_copy(key,2,DNS_T_NS); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { pos = 0; while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) { if (!response_rstart(d,DNS_T_NS,ttl)) goto DIE; if (!response_addname(t2)) goto DIE; response_rfinish(RESPONSE_AUTHORITY); } cleanup(z); return 1; } } } if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_AAAA,dtype) && !typematch(DNS_T_SOA,dtype)) { byte_copy(key,2,dtype); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns); if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) { log_cachedanswer(d,dtype); if (!rqa(z)) goto DIE; while (cachedlen >= 2) { datalen = uint16_unpack_big(cached); cached += 2; cachedlen -= 2; if (datalen > cachedlen) goto DIE; if (!response_rstart(d,dtype,ttl)) goto DIE; if (!response_addbytes(cached,datalen)) goto DIE; response_rfinish(RESPONSE_ANSWER); cached += datalen; cachedlen -= datalen; } cleanup(z); return 1; } } } for (;;) { if (roots(z->servers[z->level],z->keys[z->level],&flaghavekeys,d)) { z->flaghavekeys[z->level] = flaghavekeys; for (j = 0;j < QUERY_MAXNS;++j) dns_domain_free(&z->ns[z->level][j]); z->control[z->level] = d; break; } if (!flagforwardonly && (z->level < 2)) if (dlen < 255) { byte_copy(key,2,DNS_T_NS); byte_copy(key + 2,dlen,d); case_lowerb(key + 2,dlen); cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0); if (cached && cachedlen) { z->control[z->level] = d; byte_zero(z->servers[z->level],256); byte_zero(z->keys[z->level],528); z->flaghavekeys[z->level] = 0; for (j = 0;j < QUERY_MAXNS;++j) dns_domain_free(&z->ns[z->level][j]); pos = 0; j = 0; while (pos = dns_packet_getname(cached,cachedlen,pos,&t1)) { log_cachedns(d,t1); if (j < QUERY_MAXNS) if (!dns_domain_copy(&z->ns[z->level][j++],t1)) goto DIE; } break; } } if (!*d) goto DIE; j = 1 + (unsigned int) (unsigned char) *d; dlen -= j; d += j; } HAVENS: for (j = 0;j < QUERY_MAXNS;++j) if (z->ns[z->level][j]) { if (z->level + 1 < QUERY_MAXLEVEL) { if (!dns_domain_copy(&z->name[z->level + 1],z->ns[z->level][j])) goto DIE; dns_domain_free(&z->ns[z->level][j]); ++z->level; z->ipv6[z->level]=0; goto NEWNAME; } dns_domain_free(&z->ns[z->level][j]); } for (j = 0;j < 256;j += 16) if (!byte_isequal(z->servers[z->level] + j,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) break; if (j == 256) { log_servfail(z->name[z->level]); goto SERVFAIL; } byte_copy(key,2,DNS_T_AXFR); for (j = 0;j < 256;j += 16) { k = j >> 4; if (!byte_isequal(z->servers[z->level] + j,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { whichkey = z->keys[z->level] + 33 * k; if (whichkey[0]) { byte_copy(key + 2,32,whichkey + 1); cached = cache_get(key,34,&cachedlen,&ttl,0); if (cached && (cachedlen == 32)) { byte_copy(whichkey + 1,32,cached); continue; } crypto_box_curve25519xsalsa20poly1305_beforenm((unsigned char *) whichkey + 1,(const unsigned char *) whichkey + 1,(const unsigned char *) secretkey); cache_set(key,34,whichkey + 1,32,655360,0); } } } dns_sortipkey(z->servers[z->level],z->keys[z->level],256); /* dtype = z->level ? DNS_T_A : z->type; */ dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type; log_tx(z->name[z->level],dtype,z->control[z->level],z->servers[z->level],z->keys[z->level],z->flaghavekeys[z->level],z->level); if (dns_transmit_startext(&z->dt,z->servers[z->level],flagforwardonly,flagtcponly,flagipv4only,z->name[z->level],dtype,z->localip,remoteport,z->keys[z->level],publickey,z->control[z->level]) == -1) goto DIE; return 0; LOWERLEVEL: dns_domain_free(&z->name[z->level]); for (j = 0;j < QUERY_MAXNS;++j) dns_domain_free(&z->ns[z->level][j]); --z->level; goto HAVENS; HAVEPACKET: if (++z->loop == QUERY_MAXLOOP) goto DIE; buf = z->dt.packet; len = z->dt.packetlen; whichserver = (unsigned char *)z->dt.servers + 16 * z->dt.curserver; whichkey = (unsigned char *)z->dt.keys + 33 * z->dt.curserver; if (xsocket_type(whichserver) == XSOCKET_V4) ++tx4; if (xsocket_type(whichserver) == XSOCKET_V6) ++tx6; control = z->control[z->level]; d = z->name[z->level]; /* dtype = z->level ? DNS_T_A : z->type; */ dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type; pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto DIE; pos = dns_packet_skipname(buf,len,pos); if (!pos) goto DIE; pos += 4; posanswers = pos; numanswers = uint16_unpack_big(header + 6); numauthority = uint16_unpack_big(header + 8); numglue = uint16_unpack_big(header + 10); rcode = header[3] & 15; if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */ flagout = 0; flagcname = 0; flagreferral = 0; flagns = 0; flagsoa = 0; soattl = 0; cnamettl = 0; for (j = 0;j < numanswers;++j) { pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; if (dns_domain_equal(t1,d)) if (byte_isequal(header + 2,2,DNS_C_IN)) { /* should always be true */ if (byte_isequal(dtype,2,DNS_T_ANY)) if (byte_isequal(header,2,DNS_T_NS)) flagns = 1; if (typematch(header,dtype)) flagout = 1; else if (typematch(header,DNS_T_CNAME)) { if (!dns_packet_getname(buf,len,pos,&cname)) goto DIE; flagcname = 1; cnamettl = ttlget(header + 4); } } datalen=uint16_unpack_big(header + 8); pos += datalen; } posauthority = pos; for (j = 0;j < numauthority;++j) { pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; if (typematch(header,DNS_T_SOA)) { flagsoa = 1; soattl = ttlget(header + 4); if (soattl > 3600) soattl = 3600; } else if (typematch(header,DNS_T_NS)) { flagreferral = 1; if (dns_domain_equal(t1,d)) flagns = 1; if (!dns_domain_copy(&referral,t1)) goto DIE; } datalen=uint16_unpack_big(header + 8); pos += datalen; } /* posglue = pos; */ if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa) if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) { log_lame(whichserver,control,referral); byte_zero(whichserver,16); goto HAVENS; } if (records) { alloc_free(records); records = 0; } k = numanswers + numauthority + numglue; records = (long long *) alloc(k * sizeof(long long)); if (!records) goto DIE; pos = posanswers; for (j = 0;j < k;++j) { records[j] = pos; pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; datalen=uint16_unpack_big(header + 8); pos += datalen; } i = j = k; while (j > 1) { if (i > 1) { --i; pos = records[i - 1]; } else { pos = records[j - 1]; records[j - 1] = records[i - 1]; --j; } q = i; while ((p = q * 2) < j) { if (!smaller(buf,len,records[p],records[p - 1])) ++p; records[q - 1] = records[p - 1]; q = p; } if (p == j) { records[q - 1] = records[p - 1]; q = p; } while ((q > i) && smaller(buf,len,records[(p = q/2) - 1],pos)) { records[q - 1] = records[p - 1]; q = p; } records[q - 1] = pos; } i = 0; while (i < k) { unsigned char type[2]; pos = dns_packet_getname(buf,len,records[i],&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; ttl = ttlget(header + 4); byte_copy(type,2,header); if (!byte_isequal(header + 2,2,DNS_C_IN)) { ++i; continue; } for (j = i + 1;j < k;++j) { pos = dns_packet_getname(buf,len,records[j],&t2); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; if (!dns_domain_equal(t1,t2)) break; if (!byte_isequal(header,2,type)) break; if (!byte_isequal(header + 2,2,DNS_C_IN)) break; } if (!dns_domain_suffix(t1,control)) { i = j; continue; } if (!roots_same(t1,control)) { i = j; continue; } if (byte_isequal(type,2,DNS_T_ANY)) ; else if (byte_isequal(type,2,DNS_T_AXFR)) ; else if (byte_isequal(type,2,DNS_T_SOA)) { int non_authority = 0; save_start(); while (i < j) { pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE; pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE; if (records[i] < posauthority) { log_rrsoa(whichserver,t1,t2,t3,misc,ttl,whichkey[0]); save_data(misc,20); save_data(t2,dns_domain_length(t2)); save_data(t3,dns_domain_length(t3)); non_authority++; } ++i; } if (non_authority) save_finish(DNS_T_SOA,t1,ttl,0); } else if (byte_isequal(type,2,DNS_T_CNAME)) { pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE; pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE; log_rrcname(whichserver,t1,t2,ttl,whichkey[0]); cachegeneric(DNS_T_CNAME,t1,t2,dns_domain_length(t2),ttl,0); } else if (byte_isequal(type,2,DNS_T_PTR)) { save_start(); while (i < j) { pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE; log_rrptr(whichserver,t1,t2,ttl,whichkey[0]); save_data(t2,dns_domain_length(t2)); ++i; } save_finish(DNS_T_PTR,t1,ttl,0); } else if (byte_isequal(type,2,DNS_T_NS)) { cachedflag = 0; if (posauthority <= records[i]) { dlen = dns_domain_length(t1); byte_copy(key,2,DNS_T_NS); byte_copy(key + 2,dlen,t1); case_lowerb(key + 2,dlen); if (dns_domain_equal(t1,control)) { if (cache_get(key,dlen + 2,&cachedlen,&cachedttl,&cachedflag)) { if (cachedflag) if (cachedttl < ttl) ttl = cachedttl; } } } save_start(); while (i < j) { pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE; log_rrns(whichserver,t1,t2,ttl,whichkey[0]); save_data(t2,dns_domain_length(t2)); ++i; } save_finish(DNS_T_NS,t1,ttl,dns_domain_equal(t1,control)); } else if (byte_isequal(type,2,DNS_T_MX)) { save_start(); while (i < j) { pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos + 10,misc,2); if (!pos) goto DIE; pos = dns_packet_getname(buf,len,pos,&t2); if (!pos) goto DIE; log_rrmx(whichserver,t1,t2,misc,ttl,whichkey[0]); save_data(misc,2); save_data(t2,dns_domain_length(t2)); ++i; } save_finish(DNS_T_MX,t1,ttl,0); } else if (byte_isequal(type,2,DNS_T_A)) { save_start(); while (i < j) { pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; if (byte_isequal(header + 8,2,"\0\4")) { pos = dns_packet_copy(buf,len,pos,header,4); if (!pos) goto DIE; save_data(header,4); log_rra(whichserver,t1,header,ttl,whichkey[0]); } ++i; } save_finish(DNS_T_A,t1,ttl,flagns); } else if (byte_isequal(type,2,DNS_T_AAAA)) { save_start(); while (i < j) { pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; if (uint16_unpack_big(header + 8) == 16) { pos = dns_packet_copy(buf,len,pos,header,16); if (!pos) goto DIE; save_data(header,16); log_rraaaa(whichserver,t1,header,ttl,whichkey[0]); } ++i; } save_finish(DNS_T_AAAA,t1,ttl,flagns); } else { save_start(); while (i < j) { pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; datalen=uint16_unpack_big(header + 8); if (datalen > len - pos) goto DIE; save_data(header + 8,2); save_data(buf + pos,datalen); log_rr(whichserver,t1,type,buf + pos,datalen,ttl,whichkey[0]); ++i; } save_finish(type,t1,ttl,0); } i = j; } alloc_free(records); records = 0; if (flagcname) { ttl = cnamettl; CNAME: if (!z->level) { if (z->alias[QUERY_MAXALIAS - 1]) goto DIE; for (j = QUERY_MAXALIAS - 1;j > 0;--j) z->alias[j] = z->alias[j - 1]; for (j = QUERY_MAXALIAS - 1;j > 0;--j) z->aliasttl[j] = z->aliasttl[j - 1]; z->alias[0] = z->name[0]; z->aliasttl[0] = ttl; z->name[0] = 0; } if (!dns_domain_copy(&z->name[z->level],cname)) goto DIE; goto NEWNAME; } if (rcode == 3) { log_nxdomain(whichserver,d,soattl); cachegeneric(DNS_T_ANY,d,(unsigned char *)"",0,soattl,0); NXDOMAIN: if (z->level) goto LOWERLEVEL; if (!rqa(z)) goto DIE; response_nxdomain(); cleanup(z); return 1; } if (!flagout && flagsoa) if (!byte_isequal(DNS_T_ANY,2,dtype)) if (!byte_isequal(DNS_T_AXFR,2,dtype)) if (!byte_isequal(DNS_T_CNAME,2,dtype)) { save_start(); save_finish(dtype,d,soattl,0); log_nodata(whichserver,d,dtype,soattl); if (z->level && byte_isequal(DNS_T_A,2,dtype)) { d = z->name[z->level]; z->ipv6[z->level] = 1; goto NEWNAME; /* retry, will ask for AAAA next */ } } log_stats(); if (flagout || flagsoa || !flagreferral) { if (z->level) { flaghaskey = findkey(d,pubkey); pos = posanswers; for (j = 0;j < numanswers;++j) { pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; datalen=uint16_unpack_big(header + 8); if (dns_domain_equal(t1,d)) { if (typematch(header,DNS_T_A)) if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */ if (datalen == 4) { byte_copy(misc, 12, "\0\0\0\0\0\0\0\0\0\0\377\377"); if (!dns_packet_copy(buf,len,pos,misc+12,4)) goto DIE; addserver(z,misc,flaghaskey ? pubkey : 0); } if (typematch(header,DNS_T_AAAA)) if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */ if (datalen == 16) { if (!dns_packet_copy(buf,len,pos,misc,16)) goto DIE; addserver(z,misc,flaghaskey ? pubkey : 0); } } pos += datalen; } goto LOWERLEVEL; } if (!rqa(z)) goto DIE; pos = posanswers; for (j = 0;j < numanswers;++j) { pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; ttl = ttlget(header + 4); datalen=uint16_unpack_big(header + 8); if (dns_domain_equal(t1,d)) if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */ if (typematch(header,dtype)) { if (!response_rstart(t1,header,ttl)) goto DIE; if (typematch(header,DNS_T_NS) || typematch(header,DNS_T_CNAME) || typematch(header,DNS_T_PTR)) { if (!dns_packet_getname(buf,len,pos,&t2)) goto DIE; if (!response_addname(t2)) goto DIE; } else if (typematch(header,DNS_T_MX)) { pos2 = dns_packet_copy(buf,len,pos,misc,2); if (!pos2) goto DIE; if (!response_addbytes(misc,2)) goto DIE; if (!dns_packet_getname(buf,len,pos2,&t2)) goto DIE; if (!response_addname(t2)) goto DIE; } else if (typematch(header,DNS_T_SOA)) { pos2 = dns_packet_getname(buf,len,pos,&t2); if (!pos2) goto DIE; if (!response_addname(t2)) goto DIE; pos2 = dns_packet_getname(buf,len,pos2,&t3); if (!pos2) goto DIE; if (!response_addname(t3)) goto DIE; pos2 = dns_packet_copy(buf,len,pos2,misc,20); if (!pos2) goto DIE; if (!response_addbytes(misc,20)) goto DIE; } else { if (pos + datalen > len) goto DIE; if (!response_addbytes(buf + pos,datalen)) goto DIE; } response_rfinish(RESPONSE_ANSWER); } pos += datalen; } pos = posauthority; for (j = 0;j < numauthority;++j) { pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; ttl = ttlget(header + 4); datalen = uint16_unpack_big(header + 8); if (dns_domain_equal(t1,d)) if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */ if (typematch(header,DNS_T_NS)) { if (!response_rstart(t1,header,ttl)) goto DIE; if (!dns_packet_getname(buf,len,pos,&t2)) goto DIE; if (!response_addname(t2)) goto DIE; response_rfinish(RESPONSE_AUTHORITY); } pos += datalen; } cleanup(z); return 1; } if (!dns_domain_suffix(d,referral)) goto DIE; /* In strict "forwardonly" mode, we don't, as the manual states, ** contact a chain of servers according to "NS" resource records. ** We don't obey any referral responses, therefore. Instead, we ** eliminate the server from the list and try the next one. */ if (flagforwardonly) { log_ignore_referral(whichserver,control,referral); byte_zero(whichserver,16); goto HAVENS; } control = d + dns_domain_suffixpos(d,referral); z->control[z->level] = control; byte_zero(z->servers[z->level],256); z->flaghavekeys[z->level] = 0; for (j = 0;j < QUERY_MAXNS;++j) dns_domain_free(&z->ns[z->level][j]); k = 0; pos = posauthority; for (j = 0;j < numauthority;++j) { pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE; pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE; datalen = uint16_unpack_big(header + 8); if (dns_domain_equal(referral,t1)) /* should always be true */ if (typematch(header,DNS_T_NS)) /* should always be true */ if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */ if (k < QUERY_MAXNS) if (!dns_packet_getname(buf,len,pos,&z->ns[z->level][k++])) goto DIE; pos += datalen; } goto HAVENS; SERVFAIL: if (z->level) goto LOWERLEVEL; if (!rqa(z)) goto DIE; response_servfail(); cleanup(z); return 1; DIE: cleanup(z); if (records) { alloc_free(records); records = 0; } return -1; } int query_start(struct query *z,unsigned char *dn,unsigned char type[2],unsigned char class[2],unsigned char localip[32]) { if (byte_isequal(type,2,DNS_T_AXFR)) { errno = EPERM; return -1; } cleanup(z); z->level = 0; z->loop = 0; if (!dns_domain_copy(&z->name[0],dn)) return -1; byte_copy(z->type,2,type); byte_copy(z->class,2,class); byte_copy(z->localip,32,localip); z->ipv6[0]=0; return doit(z,0); } int query_get(struct query *z,struct pollfd *x,long long stamp) { switch(dns_transmit_get(&z->dt,x,stamp)) { case 1: return doit(z,1); case -1: return doit(z,-1); } return 0; } void query_io(struct query *z,struct pollfd *x,long long *deadline) { dns_transmit_io(&z->dt,x,deadline); } dq-20240101/query.h000066400000000000000000000024121454446775700137150ustar00rootroot00000000000000#ifndef QUERY_H #define QUERY_H #include "dns.h" #include "crypto_uint32.h" #define QUERY_MAXLEVEL 5 #define QUERY_MAXALIAS 16 #define QUERY_MAXNS 16 #define QUERY_MAXLOOP 500 struct query { unsigned int loop; unsigned int level; unsigned char *name[QUERY_MAXLEVEL]; unsigned char *control[QUERY_MAXLEVEL]; /* pointing inside name */ unsigned char *ns[QUERY_MAXLEVEL][QUERY_MAXNS]; unsigned char servers[QUERY_MAXLEVEL][256]; unsigned char keys[QUERY_MAXLEVEL][528]; int flaghavekeys[QUERY_MAXLEVEL]; int ipv6[QUERY_MAXLEVEL]; unsigned char *alias[QUERY_MAXALIAS]; crypto_uint32 aliasttl[QUERY_MAXALIAS]; unsigned char localip[32]; unsigned char type[2]; unsigned char class[2]; struct dns_transmit dt; } ; extern int query_start(struct query *,unsigned char *,unsigned char *,unsigned char *,unsigned char *); extern void query_io(struct query *,struct pollfd *,long long *); extern int query_get(struct query *,struct pollfd *,long long); extern void query_init(const unsigned char *); extern void query_purge(void); extern void query_forwardonly(void); extern void query_tcponly(void); extern void query_ipv4only(void); extern void query_minttl(long long); extern void query_remoteport(unsigned char *); extern void query_dnscurvetype(char *); #endif dq-20240101/randombytes.c000066400000000000000000000014041454446775700150720ustar00rootroot00000000000000/* taken from nacl-20110221, from randombytes/devurandom.c, added close-on-exec */ #include #include #include #include #include "randombytes.h" /* it's really stupid that there isn't a syscall for this */ static int fd = -1; void randombytes(unsigned char *x,unsigned long long xlen) { int i; if (fd == -1) { for (;;) { #ifdef O_CLOEXEC fd = open("/dev/urandom",O_RDONLY | O_CLOEXEC); #else fd = open("/dev/urandom",O_RDONLY); fcntl(fd,F_SETFD,1); #endif if (fd != -1) break; sleep(1); } } while (xlen > 0) { if (xlen < 1048576) i = xlen; else i = 1048576; i = read(fd,x,i); if (i < 1) { sleep(1); continue; } x += i; xlen -= i; } } dq-20240101/randombytes.h000066400000000000000000000003261454446775700151010ustar00rootroot00000000000000#ifndef _RANDOMBYTES_H____ #define _RANDOMBYTES_H____ extern void randombytes(unsigned char *, unsigned long long); #ifndef randombytes_implementation #define randombytes_implementation "tinynacl" #endif #endif dq-20240101/randommod.c000066400000000000000000000006451454446775700145310ustar00rootroot00000000000000/* taken from nacl-20110221, from curvecp/randommod.c (public-domain) */ #include "randombytes.h" #include "randommod.h" /* XXX: current implementation is limited to n<2^55 */ long long randommod(long long n) { long long result = 0; long long j; unsigned char r[32]; if (n <= 1) return 0; randombytes(r,32); for (j = 0;j < 32;++j) result = (result * 256 + (unsigned long long) r[j]) % n; return result; } dq-20240101/randommod.h000066400000000000000000000001421454446775700145260ustar00rootroot00000000000000#ifndef _RANDOMMOD_H____ #define _RANDOMMOD_H____ extern long long randommod(long long); #endif dq-20240101/response.c000066400000000000000000000057471454446775700144170ustar00rootroot00000000000000#include "dns.h" #include "byte.h" #include "uint16_pack_big.h" #include "uint32_pack_big.h" #include "response.h" unsigned char response[65535]; long long response_len = 0; /* <= 65535 */ static long long tctarget; #define NAMES 100 static unsigned char name[NAMES][255]; static long long name_ptr[NAMES]; /* each < 16384 */ static long long name_num; int response_addbytes(const unsigned char *buf, long long len) { if (len < 0) return 0; if (len > 65535 - response_len) return 0; byte_copy(response + response_len, len, buf); response_len += len; return 1; } int response_addname(const unsigned char *d) { long long dlen; long long i; unsigned char buf[2]; dlen = dns_domain_length(d); while (*d) { for (i = 0; i < name_num; ++i) if (dns_domain_equal(d, name[i])) { uint16_pack_big(buf, 49152 + name_ptr[i]); return response_addbytes(buf, 2); } if ((dlen <= 255) && (response_len < 16384)) if (name_num < NAMES) { byte_copy(name[name_num], dlen, d); name_ptr[name_num] = response_len; ++name_num; } i = *d; ++i; if (!response_addbytes(d, i)) return 0; d += i; dlen -= i; } return response_addbytes(d, 1); } int response_query(const unsigned char *q, const unsigned char qtype[2], const unsigned char qclass[2]) { response_len = 0; name_num = 0; if (!response_addbytes((unsigned char *)"\0\0\201\200\0\1\0\0\0\0\0\0", 12)) return 0; if (!response_addname(q)) return 0; if (!response_addbytes(qtype, 2)) return 0; if (!response_addbytes(qclass, 2)) return 0; tctarget = response_len; return 1; } static long long dpos; static int flaghidettl = 0; void response_hidettl(void) { flaghidettl = 1; } int response_rstart(const unsigned char *d, const unsigned char type[2], crypto_uint32 ttl) { unsigned char ttlstr[4]; if (!response_addname(d)) return 0; if (!response_addbytes(type, 2)) return 0; if (!response_addbytes(DNS_C_IN, 2)) return 0; if (flaghidettl) ttl = 0; uint32_pack_big(ttlstr, ttl); if (!response_addbytes(ttlstr, 4)) return 0; if (!response_addbytes((unsigned char *)"\0\0", 2)) return 0; dpos = response_len; return 1; } void response_rfinish(int x) { uint16_pack_big(response + dpos - 2, response_len - dpos); if (!++response[x + 1]) ++response[x]; } int response_cname(const unsigned char *c, const unsigned char *d, crypto_uint32 ttl) { if (!response_rstart(c, DNS_T_CNAME, ttl)) return 0; if (!response_addname(d)) return 0; response_rfinish(RESPONSE_ANSWER); return 1; } void response_nxdomain(void) { response[3] |= 3; response[2] |= 4; } void response_servfail(void) { response[3] |= 2; } void response_id(const unsigned char id[2]) { byte_copy(response, 2, id); } void response_tc(void) { response[2] |= 2; response_len = tctarget; byte_zero(response + 6, 6); } dq-20240101/response.h000066400000000000000000000015121454446775700144060ustar00rootroot00000000000000#ifndef RESPONSE_H #define RESPONSE_H #include "crypto_uint32.h" extern unsigned char response[]; extern long long response_len; extern int response_query(const unsigned char *, const unsigned char *, const unsigned char *); extern void response_nxdomain(void); extern void response_servfail(void); extern void response_id(const unsigned char *); extern void response_tc(void); extern int response_addbytes(const unsigned char *, long long); extern int response_addname(const unsigned char *); extern void response_hidettl(void); extern int response_rstart(const unsigned char *, const unsigned char *, crypto_uint32); extern void response_rfinish(int); #define RESPONSE_ANSWER 6 #define RESPONSE_AUTHORITY 8 #define RESPONSE_ADDITIONAL 10 extern int response_cname(const unsigned char *, const unsigned char *, crypto_uint32); #endif dq-20240101/roots.c000066400000000000000000000122251454446775700137140ustar00rootroot00000000000000#include #include "open.h" #include "e.h" #include "str.h" #include "byte.h" #include "direntry.h" #include "strtoip.h" #include "dns.h" #include "openreadclose.h" #include "roots.h" #include "keyparse.h" static int flagdnscurvetype1 = 1; static int flagdnscurvetype2 = 2; static stralloc data; static stralloc text; static long long roots_find(unsigned char *q) { long long i,j; i = 0; while (i < data.len) { j = dns_domain_length(data.s + i); if (dns_domain_equal(data.s + i, q)) return i + j; i += j; i += 256 + 528 + 1; } return -1; } static long long roots_search(unsigned char *q) { long long r; for (;;) { r = roots_find(q); if (r >= 0) return r; if (!*q) return -1; /* user misconfiguration */ q += *q; q += 1; } } int roots(unsigned char servers[256], unsigned char keys[528], int *flaghavekeys, unsigned char *q) { long long r; r = roots_find(q); if (r == -1) return 0; byte_copy(servers, 256, data.s + r); byte_copy(keys, 528, data.s + r + 256); *flaghavekeys = 0; if (data.s[r + 256 + 528]) *flaghavekeys = 1; return 1; } int roots_same(unsigned char *q, unsigned char *q2) { return roots_search(q) == roots_search(q2); } static int init2(DIR *dir) { direntry *d; const char *fqdn; static unsigned char *q; unsigned char servers[256]; unsigned char keys[528]; int flaghavekeys; long long serverslen; long long keyslen; long long i; long long j; long long k; unsigned char *kk; byte_zero(keys, 528); for (;;) { errno = 0; d = readdir(dir); if (!d) { if (errno) return 0; return 1; } if (d->d_name[0] != '.') { if (openreadclose(d->d_name, &text, 32) != 1) return 0; if (!stralloc_append(&text,"\n")) return 0; fqdn = d->d_name; if (str_equal(fqdn,"@")) fqdn = "."; if (!dns_domain_fromdot(&q,(unsigned char *)fqdn,str_len(fqdn))) return 0; serverslen = 0; keyslen = 0; j = 0; k = 0; flaghavekeys = 0; if (byte_chr(text.s, text.len, '|') != text.len) { flaghavekeys = 1; } for (i = 0;i < text.len;++i) { if (text.s[i] == '|') { k = i + 1; text.s[i] = 0; continue; } if (text.s[i] == '\n') { text.s[i] = 0; if (serverslen <= 240) { if (strtoip(servers + serverslen, (char *)text.s + j)) { kk = keys + keyslen; kk[0] = 0; if (k && keyparse(kk + 1, 32, (char *)text.s + k)) { kk[0] = flagdnscurvetype1; serverslen += 16; keyslen += 33; /* add txt */ if (flagdnscurvetype2 && serverslen <= 240) { byte_copy(servers + serverslen, 16, servers + serverslen - 16); byte_copy(keys + keyslen, 33, keys + keyslen - 33); kk = keys + keyslen; kk[0] = flagdnscurvetype2; serverslen += 16; keyslen += 33; } } else { serverslen += 16; keyslen += 33; } } } j = i + 1; k = 0; } } byte_zero(servers + serverslen,256 - serverslen); byte_zero(keys + keyslen,528 - keyslen); if (!stralloc_catb(&data,q,dns_domain_length(q))) return 0; if (!stralloc_catb(&data,servers,256)) return 0; if (!stralloc_catb(&data,keys,528)) return 0; if (flaghavekeys) { if (!stralloc_catb(&data,"1",1)) return 0; } else { if (!stralloc_0(&data)) return 0; } } } } static int init1(void) { DIR *dir; int r; if (chdir("servers") == -1) return 0; dir = opendir("."); if (!dir) return 0; r = init2(dir); closedir(dir); return r; } int roots_init(char *x) { int fddir; int r; if (x) { if (*x == '1') { /* streamlined only */ flagdnscurvetype1 = 1; flagdnscurvetype2 = 0; } else if (*x == '2') { /* txt only */ flagdnscurvetype1 = 2; flagdnscurvetype2 = 0; } else { /* mixed */ flagdnscurvetype1 = 1; flagdnscurvetype2 = 2; } } if (!stralloc_copys(&data, "")) return 0; fddir = open_read("."); if (fddir == -1) return 0; r = init1(); if (fchdir(fddir) == -1) r = 0; close(fddir); return r; } dq-20240101/roots.h000066400000000000000000000003151454446775700137160ustar00rootroot00000000000000#ifndef ROOTS_H #define ROOTS_H extern int roots(unsigned char *, unsigned char *, int *, unsigned char *); extern int roots_same(unsigned char *, unsigned char *); extern int roots_init(char *); #endif dq-20240101/salsa.c000066400000000000000000000051201454446775700136450ustar00rootroot00000000000000/* 20140727 Jan Mojzis Public domain. */ #include "crypto_uint64.h" #include "crypto_uint32.h" #include "uint32_pack.h" #include "uint32_unpack.h" #include "cleanup.h" #include "salsa.h" #define ROTATE(x, c) ((x) << (c)) | ((x) >> (32 - (c))) /* sigma: "expand 32-byte k" */ static const crypto_uint32 sigma[4] = { 0x61707865, 0x3320646E, 0x79622D32, 0x6B206574 }; void salsa_core(unsigned char *out, crypto_uint32 *n, const crypto_uint32 *k, const crypto_uint32 *c, int h, long long r) { long long i, j, m; crypto_uint32 x[16], y[16], t[4], w[16]; for (i = 0; i < 4; ++i) { x[i * 5] = c[i ]; x[i + 1] = k[i ]; x[i + 6] = n[i ]; x[i + 11] = k[i + 4]; } for (i = 0; i < 16; ++i) y[i] = x[i]; for (i = 0; i < r; ++i) { for (j = 0; j < 4; ++j) { for (m = 0; m < 4; ++m) t[m] = x[(5 * j + 4 * m) % 16]; t[1] ^= ROTATE(t[0] + t[3], 7); t[2] ^= ROTATE(t[1] + t[0], 9); t[3] ^= ROTATE(t[2] + t[1], 13); t[0] ^= ROTATE(t[3] + t[2], 18); for (m = 0; m < 4; ++m) w[4 * j + (j + m) % 4] = t[m]; } for (j = 0; j < 16; ++j) x[j] = w[j]; } if (h) { for (i = 0; i < 16; ++i) x[i] += y[i]; for (i = 0; i < 4; ++i) { x[5 * i] -= c[i]; x[6 + i] -= n[i]; } for (i = 0; i < 4; ++i) { uint32_pack(out + 4 * i, x[5 * i]); uint32_pack(out + 16 + 4 * i, x[6 + i]); } } else { for (i = 0; i < 16; ++i) uint32_pack(out + 4 * i, x[i] + y[i]); } cleanup(x); cleanup(y); cleanup(t); cleanup(w); } int salsa_stream_xor(unsigned char *c, const unsigned char *m, unsigned long long l, const unsigned char *nn, const unsigned char *kk, long long r) { unsigned char x[64]; crypto_uint32 k[8], n[4]; long long i; crypto_uint64 u; if (!l) return 0; for (i = 0; i < 8; ++i) k[i ] = uint32_unpack(kk + 4 * i); for (i = 0; i < 2; ++i) n[i + 2] = 0; for (i = 0; i < 2; ++i) n[i ] = uint32_unpack(nn + 4 * i); while (l >= 64) { salsa_core(m ? x : c, n, k, sigma, 0, r); if (m) for (i = 0; i < 64; ++i) c[i] = m[i] ^ x[i]; u = 1; for (i = 0; i < 2; ++i) { u += (crypto_uint64)n[i + 2]; n[i + 2] = u; u >>= 32; } l -= 64; c += 64; if (m) m += 64; } if (l) { salsa_core(x, n, k, sigma, 0, r); for (i = 0; i < l; ++i) c[i] = (m ? m[i] : 0) ^ x[i]; } cleanup(x); cleanup(k); cleanup(n); return 0; } dq-20240101/salsa.h000066400000000000000000000005311454446775700136530ustar00rootroot00000000000000#ifndef _SALSA_H____ #define _SALSA_H____ #include "crypto_uint32.h" extern void salsa_core(unsigned char *, crypto_uint32 *, const crypto_uint32 *, const crypto_uint32 *, int, long long); extern int salsa_stream_xor(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, const unsigned char *, long long); #endif dq-20240101/seconds.c000066400000000000000000000001431454446775700142000ustar00rootroot00000000000000#include "seconds.h" #include long long seconds(void) { return time((time_t *)0); } dq-20240101/seconds.h000066400000000000000000000001271454446775700142070ustar00rootroot00000000000000#ifndef _SECONDS_H____ #define _SECONDS_H____ extern long long seconds(void); #endif dq-20240101/siphash.c000066400000000000000000000026421454446775700142070ustar00rootroot00000000000000/* - based on crypto_auth/siphash24/little2 from supercop-20140622 */ #include "uint64_pack.h" #include "uint64_unpack.h" #include "siphash.h" #define ROTATE(x,b) x = (x << b) | (x >> (64 - b)) #define ROUND \ do { \ v0 += v1; v2 += v3; \ ROTATE(v1,13); ROTATE(v3,16); \ v1 ^= v0; v3 ^= v2; \ ROTATE(v0,32); \ v2 += v1; v0 += v3; \ ROTATE(v1,17); ROTATE(v3,21); \ v1 ^= v2; v3 ^= v0; \ ROTATE(v2,32); \ } while(0); int siphash(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *k, long long rounds, long long finalrounds) { crypto_uint64 v0, v1, v2, v3, lastblock = inlen; unsigned char block[8]; long long i; v0 = v2 = uint64_unpack(k + 0); v1 = v3 = uint64_unpack(k + 8); v0 ^= 0x736f6d6570736575; v1 ^= 0x646f72616e646f6d; v2 ^= 0x6c7967656e657261; v3 ^= 0x7465646279746573; while (inlen >= 8) { crypto_uint64 mi = uint64_unpack(in); in += 8; v3 ^= mi; for (i = 0; i < rounds; ++i) ROUND v0 ^= mi; inlen -= 8; } for (i = 0; i < 7; ++i) block[i] = 0; for (i = 0; i < inlen; ++i) block[i] = in[i]; block[7] = lastblock; lastblock = uint64_unpack(block); v3 ^= lastblock; for (i = 0; i < rounds; ++i) ROUND v0 ^= lastblock; v2 ^= 0xff; for (i = 0; i < finalrounds; ++i) ROUND uint64_pack(out, (v0 ^ v1) ^ (v2 ^ v3)); return 0; } dq-20240101/siphash.h000066400000000000000000000002661454446775700142140ustar00rootroot00000000000000#ifndef _SIPHASH_H_____ #define _SIPHASH_H_____ extern int siphash(unsigned char *, const unsigned char *, unsigned long long, const unsigned char *, long long, long long); #endif dq-20240101/str.c000066400000000000000000000023431454446775700133560ustar00rootroot00000000000000/* 20130505 Jan Mojzis Public domain. */ #include "str.h" long long str_len(const char *s) { long long i; for (i = 0; s[i]; ++i); return i; } long long str_chr(const char *s, int c) { long long i; char ch = c; for (i = 0; s[i]; ++i) if (s[i] == ch) break; return i; } long long str_rchr(const char *s, int c) { long long i, u = -1; char ch = c; for (i = 0; s[i]; ++i) if (s[i] == ch) u = i; if (u != -1) return u; return i; } int str_diff(const char *s, const char *t) { register char x; for (;;) { x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; } return ((int)(unsigned int)(unsigned char) x) - ((int)(unsigned int)(unsigned char) *t); } int str_start(const char *s, const char *t) { char x; for (;;) { x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; } } dq-20240101/str.h000066400000000000000000000005011454446775700133550ustar00rootroot00000000000000#ifndef _STR_H____ #define _STR_H____ extern long long str_len(const char *); extern long long str_chr(const char *, int); extern long long str_rchr(const char *, int); extern int str_diff(const char *, const char *); extern int str_start(const char *, const char *); #define str_equal(s,t) (!str_diff((s),(t))) #endif dq-20240101/stralloc.c000066400000000000000000000055161454446775700143760ustar00rootroot00000000000000/* 20130505 Jan Mojzis Public domain. */ #include "alloc.h" #include "e.h" #include "stralloc.h" int stralloc_readyplus(stralloc *r, long long len) { unsigned char *newdata; long long i; if (!r || len < 0) { errno = EINVAL; return 0; } if (len == 0) return 1; if (r->len + len + 1 > r->alloc) { while (r->len + len + 1 > r->alloc) r->alloc = 2 * r->alloc + 1; newdata = alloc(r->alloc); if (!newdata) return 0; if (r->s) { for (i = 0; i < r->len; ++i) newdata[i] = r->s[i]; alloc_free(r->s); } r->s = newdata; } return 1; } int stralloc_catb(stralloc *r, const void *xv, long long xlen) { const unsigned char *x = xv; long long i; if (!r || !xv || xlen < 0) { errno = EINVAL; return 0; } if (xlen == 0) return 1; if (!stralloc_readyplus(r, xlen)) return 0; for (i = 0; i < xlen; ++i) r->s[r->len + i] = x[i]; r->len += xlen; return 1; } int stralloc_cats(stralloc *r, const void *xv) { const unsigned char *x = xv; long long xlen; if (!r || !xv) { errno = EINVAL; return 0; } for (xlen = 0; x[xlen]; ++xlen); return stralloc_catb(r, x, xlen); } int stralloc_cat(stralloc *x, stralloc *y) { if (!y) { errno = EINVAL; return 0; } return stralloc_catb(x, y->s, y->len); } int stralloc_copyb(stralloc *r, const void *xv, long long xlen) { if (!r) { errno = EINVAL; return 0; } r->len = 0; return stralloc_catb(r, xv, xlen); } int stralloc_copys(stralloc *r, const void *xv) { if (!r) { errno = EINVAL; return 0; } r->len = 0; return stralloc_cats(r, xv); } int stralloc_copy(stralloc *x, stralloc *y) { if (!x || !y) { errno = EINVAL; return 0; } x->len = 0; return stralloc_cat(x, y); } int stralloc_append(stralloc *r, const void *xv) { return stralloc_catb(r, xv, 1); } int stralloc_0(stralloc *r) { return stralloc_append(r, ""); } static int stralloc_catunum0(stralloc *sa, unsigned long long u, long long n) { long long len; unsigned long long q; unsigned char *s; if (!sa) { errno = EINVAL; return 0; } len = 1; q = u; while (q > 9) { ++len; q /= 10; } if (len < n) len = n; if (!stralloc_readyplus(sa, len)) return 0; s = sa->s + sa->len; sa->len += len; while (len) { s[--len] = '0' + (u % 10); u /= 10; } return 1; } int stralloc_catnum0(stralloc *sa, long long l, long long n) { if (!sa) { errno = EINVAL; return 0; } if (l < 0) { if (!stralloc_append(sa,"-")) return 0; l = -l; } return stralloc_catunum0(sa, l, n); } int stralloc_catnum(stralloc *r, long long num) { return stralloc_catnum0(r, num, 0); } void stralloc_free(stralloc *r) { if (!r) return; if (r->s) alloc_free(r->s); r->s = 0; r->len = 0; r->alloc = 0; } dq-20240101/stralloc.h000066400000000000000000000014211454446775700143720ustar00rootroot00000000000000#ifndef _STRALLOC_H____ #define _STRALLOC_H____ typedef struct stralloc { unsigned char *s; long long len; long long alloc; } stralloc; extern int stralloc_readyplus(stralloc *, long long); extern int stralloc_catb(stralloc *, const void *, long long); extern int stralloc_cats(stralloc *, const void *); extern int stralloc_cat(stralloc *, stralloc *); extern int stralloc_copyb(stralloc *, const void *, long long); extern int stralloc_copys(stralloc *, const void *); extern int stralloc_copy(stralloc *, stralloc *); extern int stralloc_append(stralloc *, const void *); extern int stralloc_0(stralloc *); extern void stralloc_free(stralloc *); extern int stralloc_catnum(stralloc *, long long); extern int stralloc_catnum0(stralloc *, long long, long long); #endif dq-20240101/strtoip.c000066400000000000000000000021411454446775700142460ustar00rootroot00000000000000/* 20130604 Jan Mojzis Public domain. */ #include #include #include "byte.h" #include "strtoip.h" /* taken from nacl-20110221, from curvecp/curvecpserver.c (public-domain) */ int strtoip4(unsigned char *ip, const char *x) { unsigned char *y = ip + 12; long long j; long long k; long long d; if (!x) return 0; for (k = 0; k < 4; ++k) y[k] = 0; for (k = 0; k < 4; ++k) { d = 0; for (j = 0; j < 3 && x[j] >= '0' && x[j] <= '9'; ++j) d = d * 10 + (x[j] - '0'); if (j == 0) return 0; x += j; if (k >= 0 && k < 4) y[k] = d; if (k < 3) { if (*x != '.') return 0; ++x; } } if (*x) return 0; byte_copy(ip, 12, "\0\0\0\0\0\0\0\0\0\0\377\377"); return 1; } /* XXX TODO rewrite without inet_pton */ int strtoip6(unsigned char *ip, const char *x) { if (!x) return 0; if (inet_pton(AF_INET6, x, ip) != 1) return 0; return 1; } int strtoip(unsigned char *ip, const char *x) { if (strtoip4(ip, x)) return 1; if (strtoip6(ip, x)) return 1; return 0; } dq-20240101/strtoip.h000066400000000000000000000003221454446775700142520ustar00rootroot00000000000000#ifndef _STRTOIP_H____ #define _STRTOIP_H____ extern int strtoip4(unsigned char *, const char *); extern int strtoip6(unsigned char *, const char *); extern int strtoip(unsigned char *, const char *); #endif dq-20240101/strtomultiip.c000066400000000000000000000034731454446775700153320ustar00rootroot00000000000000/* 20130607 Jan Mojzis Public domain. */ #include "byte.h" #include "str.h" #include "strtoip.h" #include "strtomultiip.h" static char separators[] = { ',', ' ', '\t', '\n', 0 }; static long long _strtomultiip(unsigned char *ip, long long ipmax, const char *x, int (*op)(unsigned char *, const char *)) { unsigned char data[STRTOMULTIIP_BUFSIZE]; long long i, j, k; long long iplen = 0; long long len; if (!x) return 0; byte_zero(ip, ipmax); len = str_len(x); if (len > STRTOMULTIIP_BUFSIZE - 1) { len = STRTOMULTIIP_BUFSIZE - 1; for (j = 0; separators[j]; ++j) len = byte_rchr(x, len, separators[j]); } byte_copy(data, len, x); data[len++] = 0; /* separators ',' ' ' '\t' '\n' */ for (i = 0; i < len; ++i) { for (j = 0; separators[j]; ++j) if (data[i] == separators[j]) data[i] = 0; } /* separator '.' - IPv4 backward compatibility */ j = byte_chr(data, len, ':'); if (j == len) { k = 0; for (i = 0; i < len; ++i) { if (data[i] == 0) k = 0; if (data[i] == '.') if (++k % 4 == 0) data[i] = 0; } } /* parse ip */ i = 0; for (j = 0; j < len; ++j) { if (data[j] == 0) { if (iplen + 16 <= ipmax) { if (op(ip + iplen, (char *)data + i)) { iplen += 16; } } i = j + 1; } } return iplen; } long long strtomultiip4(unsigned char *ip, long long ipmax, const char *x) { return _strtomultiip(ip, ipmax, x, strtoip4); } long long strtomultiip6(unsigned char *ip, long long ipmax, const char *x) { return _strtomultiip(ip, ipmax, x, strtoip6); } long long strtomultiip(unsigned char *ip, long long ipmax, const char *x) { return _strtomultiip(ip, ipmax, x, strtoip); } dq-20240101/strtomultiip.h000066400000000000000000000005001454446775700153230ustar00rootroot00000000000000#ifndef _STRTOMULTIIP_H____ #define _STRTOMULTIIP_H____ #define STRTOMULTIIP_BUFSIZE 800 extern long long strtomultiip(unsigned char *, long long, const char *); extern long long strtomultiip4(unsigned char *, long long, const char *); extern long long strtomultiip6(unsigned char *, long long, const char *); #endif dq-20240101/strtonum.c000066400000000000000000000021061454446775700144360ustar00rootroot00000000000000/* 20130605 Jan Mojzis Public domain. */ #include "e.h" #include "strtonum.h" /* The 'strnum(r,buf)' converts 0-terminated string 'buf' into number 'r'. */ int strtonum(long long *r, const char *buf) { char *bufpos = (char *)buf; int flagsign = 0; long long i; unsigned long long c, ret = 0; if (!buf) goto failed; switch (buf[0]) { case 0: goto failed; break; case '+': ++bufpos; break; case '-': flagsign = 1; ++bufpos; break; default: break; } for(i = 0; bufpos[i]; ++i) { c = bufpos[i] - '0'; if (c > 9) break; c += 10 * (ret); if (ret > c) goto failed; /* overflow */ ret = c; } if (i == 0) goto failed; /* "+..." or "-..." */ if (flagsign) { *r = -ret; if (*r > 0) goto failed; /* overflow */ } else { *r = ret; if (*r < 0) goto failed; /* overflow */ } return 1; failed: *r = 0; errno = EINVAL; return 0; } dq-20240101/strtonum.h000066400000000000000000000001511454446775700144410ustar00rootroot00000000000000#ifndef _STRTONUM_H____ #define _STRTONUM_H____ extern int strtonum(long long *, const char *); #endif dq-20240101/typeparse.c000066400000000000000000000020741454446775700145630ustar00rootroot00000000000000#include "strtonum.h" #include "uint16_pack_big.h" #include "case.h" #include "dns.h" #include "byte.h" #include "typeparse.h" int typeparse(unsigned char *type, const char *s) { long long l; if (!s) return 0; if (strtonum(&l, s) && l > 0 && l <= 65535) { uint16_pack_big(type, l); } else if (case_equals(s, "a")) byte_copy(type, 2, DNS_T_A); else if (case_equals(s, "ns")) byte_copy(type, 2, DNS_T_NS); else if (case_equals(s, "mx")) byte_copy(type, 2, DNS_T_MX); else if (case_equals(s, "any")) byte_copy(type, 2, DNS_T_ANY); else if (case_equals(s, "ptr")) byte_copy(type, 2, DNS_T_PTR); else if (case_equals(s, "txt")) byte_copy(type, 2, DNS_T_TXT); else if (case_equals(s, "soa")) byte_copy(type, 2, DNS_T_SOA); else if (case_equals(s, "srv")) byte_copy(type, 2, DNS_T_SRV); else if (case_equals(s, "aaaa")) byte_copy(type, 2, DNS_T_AAAA); else if (case_equals(s, "axfr")) byte_copy(type, 2, DNS_T_AXFR); else if (case_equals(s, "cname")) byte_copy(type, 2, DNS_T_CNAME); else return 0; return 1; } dq-20240101/typeparse.h000066400000000000000000000001601454446775700145620ustar00rootroot00000000000000#ifndef _TYPEPARSE_H____ #define _TYPEPARSE_H____ extern int typeparse(unsigned char *, const char *); #endif dq-20240101/uint16_pack_big.c000066400000000000000000000002141454446775700155060ustar00rootroot00000000000000#include "uint16_pack_big.h" void uint16_pack_big(unsigned char *y, crypto_uint16 x) { y[1] = x & 255; x >>= 8; y[0] = x & 255; } dq-20240101/uint16_pack_big.h000066400000000000000000000002341454446775700155150ustar00rootroot00000000000000#ifndef _UINT16_PACK_BIG____ #define _UINT16_PACK_BIG____ #include "crypto_uint16.h" extern void uint16_pack_big(unsigned char *, crypto_uint16); #endif dq-20240101/uint16_unpack_big.c000066400000000000000000000002511454446775700160520ustar00rootroot00000000000000#include "uint16_unpack_big.h" crypto_uint16 uint16_unpack_big(const unsigned char *x) { crypto_uint16 y; y = x[0]; y <<= 8; y |= x[1]; return y; } dq-20240101/uint16_unpack_big.h000066400000000000000000000002421454446775700160570ustar00rootroot00000000000000#ifndef _UINT16_UNPACK_BIG____ #define _UINT16_UNPACK_BIG____ #include "crypto_uint16.h" extern crypto_uint16 uint16_unpack_big(const unsigned char *); #endif dq-20240101/uint32_pack.c000066400000000000000000000004051454446775700146650ustar00rootroot00000000000000#include "uint32_pack.h" /* The 'uint32_pack' function converts 32-bit unsigned integer into 4 bytes stored in little-endian format */ void uint32_pack(unsigned char *y, crypto_uint32 x) { long long i; for (i = 0; i < 4; ++i) { y[i] = x; x >>= 8; } } dq-20240101/uint32_pack.h000066400000000000000000000002241454446775700146710ustar00rootroot00000000000000#ifndef _UINT32_PACK_H____ #define _UINT32_PACK_H____ #include "crypto_uint32.h" extern void uint32_pack(unsigned char *, crypto_uint32); #endif dq-20240101/uint32_pack_big.c000066400000000000000000000004201454446775700155030ustar00rootroot00000000000000#include "uint32_pack_big.h" /* The 'uint32_pack_big' function converts 32-bit unsigned integer into 4 bytes stored in big-endian format */ void uint32_pack_big(unsigned char *y, crypto_uint32 x) { long long i; for (i = 3; i >= 0; --i) { y[i] = x; x >>= 8; } } dq-20240101/uint32_pack_big.h000066400000000000000000000002371454446775700155160ustar00rootroot00000000000000#ifndef _UINT32_PACK_BIG____ #define _UINT32_PACK_BIG____ #include "crypto_uint32.h" extern void uint32_pack_big(unsigned char *y, crypto_uint32 x); #endif dq-20240101/uint32_unpack.c000066400000000000000000000004511454446775700152310ustar00rootroot00000000000000#include "uint32_unpack.h" /* The 'uint32_unpack' function converts 4 bytes in little-endian format into 32-bit unsigned integer. */ crypto_uint32 uint32_unpack(const unsigned char *x) { crypto_uint32 y = 0; long long i; for (i = 3; i >= 0; --i) y = (y << 8) | x[i]; return y; } dq-20240101/uint32_unpack.h000066400000000000000000000002321454446775700152330ustar00rootroot00000000000000#ifndef _UINT32_UNPACK_H____ #define _UINT32_UNPACK_H____ #include "crypto_uint32.h" extern crypto_uint32 uint32_unpack(const unsigned char *); #endif dq-20240101/uint32_unpack_big.c000066400000000000000000000004621454446775700160540ustar00rootroot00000000000000#include "uint32_unpack_big.h" /* The 'uint32_unpack_big' function converts 4 bytes in big-endian format into 32-bit unsigned integer. */ crypto_uint32 uint32_unpack_big(const unsigned char *x) { crypto_uint32 y = 0; long long i; for (i = 0; i < 4; ++i) y = (y << 8) | x[i]; return y; } dq-20240101/uint32_unpack_big.h000066400000000000000000000002421454446775700160550ustar00rootroot00000000000000#ifndef _UINT32_UNPACK_BIG____ #define _UINT32_UNPACK_BIG____ #include "crypto_uint32.h" extern crypto_uint32 uint32_unpack_big(const unsigned char *); #endif dq-20240101/uint64_pack.c000066400000000000000000000004051454446775700146720ustar00rootroot00000000000000#include "uint64_pack.h" /* The 'uint64_pack' function converts 64-bit unsigned integer into 8 bytes stored in little-endian format */ void uint64_pack(unsigned char *y, crypto_uint64 x) { long long i; for (i = 0; i < 8; ++i) { y[i] = x; x >>= 8; } } dq-20240101/uint64_pack.h000066400000000000000000000002241454446775700146760ustar00rootroot00000000000000#ifndef _UINT64_PACK_H____ #define _UINT64_PACK_H____ #include "crypto_uint64.h" extern void uint64_pack(unsigned char *, crypto_uint64); #endif dq-20240101/uint64_unpack.c000066400000000000000000000004511454446775700152360ustar00rootroot00000000000000#include "uint64_unpack.h" /* The 'uint64_unpack' function converts 8 bytes in little-endian format into 64-bit unsigned integer. */ crypto_uint64 uint64_unpack(const unsigned char *x) { crypto_uint64 y = 0; long long i; for (i = 7; i >= 0; --i) y = (y << 8) | x[i]; return y; } dq-20240101/uint64_unpack.h000066400000000000000000000002321454446775700152400ustar00rootroot00000000000000#ifndef _UINT64_UNPACK_H____ #define _UINT64_UNPACK_H____ #include "crypto_uint64.h" extern crypto_uint64 uint64_unpack(const unsigned char *); #endif dq-20240101/verify.c000066400000000000000000000003371454446775700140530ustar00rootroot00000000000000#include "verify.h" int verify(const unsigned char *x, const unsigned char *y, long long n) { unsigned int d = 0; long long i; for (i = 0; i < n; ++i) d |= x[i] ^ y[i]; return (1 & ((d - 1) >> 8)) - 1; } dq-20240101/verify.h000066400000000000000000000002011454446775700140460ustar00rootroot00000000000000#ifndef _VERIFY_H____ #define _VERIFY_H____ extern int verify(const unsigned char *, const unsigned char *, long long); #endif dq-20240101/warn.c000066400000000000000000000012461454446775700135160ustar00rootroot00000000000000#include #include "writeall.h" #include "warn.h" void warn_9( const char *s0 ,const char *s1 ,const char *s2 ,const char *s3 ,const char *s4 ,const char *s5 ,const char *s6 ,const char *s7 ,const char *s8 ) { const char *s[9]; const char *x; char buf[256]; long long buflen = 0; long long i; s[0] = s0; s[1] = s1; s[2] = s2; s[3] = s3; s[4] = s4; s[5] = s5; s[6] = s6; s[7] = s7; s[8] = s8; for (i = 0;i < 9;++i) { x = s[i]; if (!x) continue; while (*x) { if (buflen == sizeof buf) { writeall(2,buf,buflen); buflen = 0; } buf[buflen++] = *x++; } } writeall(2,buf,buflen); return; } dq-20240101/warn.h000066400000000000000000000010341454446775700135160ustar00rootroot00000000000000#ifndef _WARN_H____ #define _WARN_H____ extern void warn_9(const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *); #define warn_8(a,b,c,d,e,f,g,h) warn_9(a,b,c,d,e,f,g,h,0) #define warn_7(a,b,c,d,e,f,g) warn_8(a,b,c,d,e,f,g,0) #define warn_6(a,b,c,d,e,f) warn_7(a,b,c,d,e,f,0) #define warn_5(a,b,c,d,e) warn_6(a,b,c,d,e,0) #define warn_4(a,b,c,d) warn_5(a,b,c,d,0) #define warn_3(a,b,c) warn_4(a,b,c,0) #define warn_2(a,b) warn_3(a,b,0) #define warn_1(a) warn_2(a,0) #endif dq-20240101/writeall.c000066400000000000000000000011531454446775700143670ustar00rootroot00000000000000/* taken from nacl-20110221, from curvecp/writeall.c (public domain) */ #include #include #include "e.h" #include "writeall.h" int writeall(int fd,const void *xv,long long xlen) { char *x = (char *)xv; long long w; while (xlen > 0) { w = xlen; if (w > 1048576) w = 1048576; w = write(fd,x,w); if (w < 0) { if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { struct pollfd p; p.fd = fd; p.events = POLLOUT | POLLERR; poll(&p,1,-1); continue; } return -1; } x += w; xlen -= w; } return 0; } dq-20240101/writeall.h000066400000000000000000000001401454446775700143670ustar00rootroot00000000000000#ifndef WRITEALL_H #define WRITEALL_H extern int writeall(int,const void *,long long); #endif dq-20240101/xsocket.h000066400000000000000000000027731454446775700142420ustar00rootroot00000000000000#ifndef _XSOCKET_H____ #define _XSOCKET_H____ #include "hasipv6.h" #define XSOCKET_V4 4 #define XSOCKET_V6 6 extern int xsocket_tcp(int); extern int xsocket_udp(int); extern long long xsocket_send(int, int, const unsigned char *, long long, const unsigned char *, const unsigned char *, long long); extern long long xsocket_recv(int, int, unsigned char *, long long, unsigned char *, unsigned char *, long long *); extern int xsocket_bind(int, int, const unsigned char *, const unsigned char *, long long); extern int xsocket_bind_reuse(int, int, const unsigned char *, const unsigned char *, long long); extern void xsocket_tryreservein(int, int); extern int xsocket_listen(int, long long); extern int xsocket_accept(int, int, unsigned char *, unsigned char *, long long *); extern int xsocket_local(int, int, unsigned char *, unsigned char *, long long *); extern int xsocket_connect(int, int, const unsigned char *, const unsigned char *, long long); extern int xsocket_connected(int); extern int xsocket_ipoptionskill(int); extern int xsocket_tcpnodelay(int); extern long long xsocket_getscopeid(const char *); extern int xsocket_type(const unsigned char *); #define xsocket_ANYIP6 (const unsigned char *)"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" #define xsocket_ANYIP4 (const unsigned char *)"\0\0\0\0\0\0\0\0\0\0\377\377\0\0\0\0" #define xsocket_PREFIX4 (const unsigned char *)"\0\0\0\0\0\0\0\0\0\0\377\377" #ifdef HASIPV6 #define xsocket_ANYIP xsocket_ANYIP6 #else #define xsocket_ANYIP xsocket_ANYIP4 #endif #endif dq-20240101/xsocket_accept.c000066400000000000000000000032611454446775700155450ustar00rootroot00000000000000/* 20131206 Jan Mojzis Public domain. */ #include #include #include #include #include #include "e.h" #include "byte.h" #include "hasipv6.h" #include "xsocket.h" static int xsocket_accept6(int s, unsigned char *ip, unsigned char *port, long long *id) { #ifdef HASIPV6 struct sockaddr_in6 sa; socklen_t salen = sizeof sa; int fd; byte_zero(&sa, sizeof sa); fd = accept(s, (struct sockaddr *)&sa, &salen); if (fd == -1) return -1; if (((struct sockaddr *)&sa)->sa_family != PF_INET6) { close(fd); errno = EPROTO; return -1; } if (ip) byte_copy(ip, 16, &sa.sin6_addr); if (port) byte_copy(port, 2, &sa.sin6_port); if (id) *id = sa.sin6_scope_id; return fd; #else errno = EPROTONOSUPPORT; return -1; #endif } static int xsocket_accept4(int s, unsigned char *ip, unsigned char *port, long long *id) { struct sockaddr_in sa; socklen_t salen = sizeof sa; int fd; byte_zero(&sa, sizeof sa); fd = accept(s, (struct sockaddr *)&sa, &salen); if (fd == -1) return -1; if (((struct sockaddr *)&sa)->sa_family != PF_INET) { close(fd); errno = EPROTO; return -1; } if (ip) byte_copy(ip, 12, "\0\0\0\0\0\0\0\0\0\0\377\377"); if (ip) byte_copy(ip + 12, 4, &sa.sin_addr); if (port) byte_copy(port, 2, &sa.sin_port); if (id) *id = 0; return fd; } int xsocket_accept(int fd, int type, unsigned char *ip, unsigned char *port, long long *id) { if (type == XSOCKET_V4) { return xsocket_accept4(fd, ip, port, id); } if (type == XSOCKET_V6) { return xsocket_accept6(fd, ip, port, id); } errno = EPROTO; return -1; } dq-20240101/xsocket_bind.c000066400000000000000000000035621454446775700152260ustar00rootroot00000000000000/* 20131117 Jan Mojzis Public domain. */ #include #include #include #include #include "e.h" #include "byte.h" #include "hasipv6.h" #include "xsocket.h" static int xsocket_bind6(int fd, const unsigned char *ip, const unsigned char *port, long long id) { #ifdef HASIPV6 struct sockaddr_in6 sa; if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin6_family = PF_INET6; byte_copy(&sa.sin6_addr, 16, ip); byte_copy(&sa.sin6_port, 2, port); sa.sin6_scope_id = id; return bind(fd, (struct sockaddr *)&sa, sizeof sa); #else errno = EPROTONOSUPPORT; return -1; #endif } static int xsocket_bind4(int fd, const unsigned char *ip, const unsigned char *port, long long id) { struct sockaddr_in sa; if (!byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin_family = PF_INET; byte_copy(&sa.sin_addr, 4, ip + 12); byte_copy(&sa.sin_port, 2, port); return bind(fd, (struct sockaddr *)&sa, sizeof sa); } int xsocket_bind(int fd, int type, const unsigned char *ip, const unsigned char *port, long long id) { if (type == XSOCKET_V4) { return xsocket_bind4(fd, ip, port, id); } if (type == XSOCKET_V6) { return xsocket_bind6(fd, ip, port, id); } errno = EPROTO; return -1; } int xsocket_bind_reuse(int fd, int type, const unsigned char *ip, const unsigned char *port, long long id) { int opt = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt); return xsocket_bind(fd, type, ip, port, id); } void xsocket_tryreservein(int fd, int size) { while (size >= 1024) { if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof size) == 0) return; size -= (size >> 5); } } dq-20240101/xsocket_conn.c000066400000000000000000000033331454446775700152430ustar00rootroot00000000000000/* 20130505 Jan Mojzis Public domain. */ #include #include #include #include #include #include "e.h" #include "byte.h" #include "hasipv6.h" #include "xsocket.h" static int xsocket_connect6(int s, const unsigned char *ip, const unsigned char *port, long long id) { #ifdef HASIPV6 struct sockaddr_in6 sa; if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin6_family = PF_INET6; byte_copy(&sa.sin6_addr, 16, ip); byte_copy(&sa.sin6_port, 2, port); sa.sin6_scope_id = id; return connect(s, (struct sockaddr *)&sa, sizeof sa); #else errno = EPROTONOSUPPORT; return -1; #endif } static int xsocket_connect4(int s, const unsigned char *ip, const unsigned char *port, long long id) { struct sockaddr_in sa; if (!byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin_family = PF_INET; byte_copy(&sa.sin_addr, 4, ip + 12); byte_copy(&sa.sin_port, 2, port); return connect(s, (struct sockaddr *)&sa, sizeof sa); } int xsocket_connect(int s, int type, const unsigned char *ip, const unsigned char *port, long long id) { if (type == XSOCKET_V4) { return xsocket_connect4(s, ip, port, id); } if (type == XSOCKET_V6) { return xsocket_connect6(s, ip, port, id); } errno = EPROTO; return -1; } int xsocket_connected(int s) { struct sockaddr sa; socklen_t dummy; char ch; dummy = sizeof sa; if (getpeername(s, &sa, &dummy) == -1) { if (read(s, &ch, 1) == -1) {}; /* sets errno */ return 0; } return 1; } dq-20240101/xsocket_listen.c000066400000000000000000000004361454446775700156050ustar00rootroot00000000000000#include #include #include #include #include "e.h" #include "xsocket.h" int xsocket_listen(int fd, long long backlog) { if (backlog < 0 || backlog > 1048576) { errno = EPROTO; return -1; } return listen(fd, backlog); } dq-20240101/xsocket_recv.c000066400000000000000000000036031454446775700152450ustar00rootroot00000000000000/* 20131117 Jan Mojzis Public domain. */ #include #include #include #include #include "e.h" #include "byte.h" #include "hasipv6.h" #include "xsocket.h" static long long xsocket_recv6(int fd, unsigned char *x, long long xlen, unsigned char *ip, unsigned char *port, long long *id) { #ifdef HASIPV6 struct sockaddr_in6 sa; socklen_t salen = sizeof sa; long long r; byte_zero(&sa, sizeof sa); r = recvfrom(fd, x, xlen, 0, (struct sockaddr *) &sa, &salen); if (r == -1) return -1; if (((struct sockaddr *)&sa)->sa_family != PF_INET6) { errno = EPROTO; return -1; } if (ip) byte_copy(ip, 16, &sa.sin6_addr); if (port) byte_copy(port, 2, &sa.sin6_port); if (id) *id = sa.sin6_scope_id; return r; #else errno = EPROTONOSUPPORT; return -1; #endif } static long long xsocket_recv4(int fd, unsigned char *x, long long xlen, unsigned char *ip, unsigned char *port, long long *id) { struct sockaddr_in sa; socklen_t salen = sizeof sa; long long r; byte_zero(&sa, sizeof sa); r = recvfrom(fd, x, xlen, 0, (struct sockaddr *) &sa, &salen); if (r == -1) return -1; if (((struct sockaddr *)&sa)->sa_family != PF_INET) { errno = EPROTO; return -1; } if (ip) byte_copy(ip, 12, "\0\0\0\0\0\0\0\0\0\0\377\377"); if (ip) byte_copy(ip + 12, 4, &sa.sin_addr); if (port) byte_copy(port, 2, &sa.sin_port); if (id) *id = 0; return r; } long long xsocket_recv(int fd, int type, unsigned char *x, long long xlen, unsigned char *ip, unsigned char *port, long long *id) { if (xlen < 0) { errno = EPROTO; return -1; } if (xlen > 1048576) xlen = 1048576; if (type == XSOCKET_V4) { return xsocket_recv4(fd, x, xlen, ip, port, id); } if (type == XSOCKET_V6) { return xsocket_recv6(fd, x, xlen, ip, port, id); } errno = EPROTO; return -1; } dq-20240101/xsocket_send.c000066400000000000000000000032701454446775700152370ustar00rootroot00000000000000/* 20131117 Jan Mojzis Public domain. */ #include #include #include #include #include "e.h" #include "byte.h" #include "hasipv6.h" #include "xsocket.h" static long long xsocket_send6(int fd, const unsigned char *x, long long xlen, const unsigned char *ip, const unsigned char *port, long long id) { #ifdef HASIPV6 struct sockaddr_in6 sa; if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin6_family = PF_INET6; byte_copy(&sa.sin6_addr, 16, ip); byte_copy(&sa.sin6_port, 2, port); sa.sin6_scope_id = id; return sendto(fd, x, xlen, 0, (struct sockaddr *)&sa, sizeof sa); #else errno = EPROTONOSUPPORT; return -1; #endif } static long long xsocket_send4(int fd, const unsigned char *x, long long xlen, const unsigned char *ip, const unsigned char *port, long long id) { struct sockaddr_in sa; if (!byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin_family = PF_INET; byte_copy(&sa.sin_addr, 4, ip + 12); byte_copy(&sa.sin_port, 2, port); return sendto(fd, x, xlen, 0, (struct sockaddr *)&sa, sizeof sa); } long long xsocket_send(int fd, int type, const unsigned char *x, long long xlen, const unsigned char *ip, const unsigned char *port, long long id) { if (xlen < 0 || xlen > 1048576) { errno = EPROTO; return -1; } if (type == XSOCKET_V4) { return xsocket_send4(fd, x, xlen, ip, port, id); } if (type == XSOCKET_V6) { return xsocket_send6(fd, x, xlen, ip, port, id); } errno = EPROTO; return -1; } dq-20240101/xsocket_tcp.c000066400000000000000000000017521454446775700150770ustar00rootroot00000000000000/* 20131117 Jan Mojzis Public domain. */ #include #include #include #include #include #include #include "hasipv6.h" #include "blocking.h" #include "e.h" #include "xsocket.h" int xsocket_tcp(int type) { int s; #ifdef HASIPV6 int opt = 1; #endif if (type == XSOCKET_V6) { #ifdef HASIPV6 s = socket(PF_INET6, SOCK_STREAM, 0); if (s == -1) return -1; if (fcntl(s, F_SETFD, 1) == -1) { close(s); return -1; } if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt) == -1) { close(s); return -1; } blocking_disable(s); return s; #endif errno = EPROTONOSUPPORT; return -1; } if (type == XSOCKET_V4) { s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) return -1; if (fcntl(s, F_SETFD, 1) == -1) { close(s); return -1; } blocking_disable(s); return s; } errno = EPROTO; return -1; } dq-20240101/xsocket_type.c000066400000000000000000000003451454446775700152670ustar00rootroot00000000000000#include "byte.h" #include "xsocket.h" int xsocket_type(const unsigned char *ip) { if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { return XSOCKET_V4; } else { return XSOCKET_V6; } } dq-20240101/xsocket_udp.c000066400000000000000000000017501454446775700150770ustar00rootroot00000000000000/* 20131117 Jan Mojzis Public domain. */ #include #include #include #include #include #include #include "hasipv6.h" #include "blocking.h" #include "e.h" #include "xsocket.h" int xsocket_udp(int type) { int s; #ifdef HASIPV6 int opt = 1; #endif if (type == XSOCKET_V6) { #ifdef HASIPV6 s = socket(PF_INET6, SOCK_DGRAM, 0); if (s == -1) return -1; if (fcntl(s, F_SETFD, 1) == -1) { close(s); return -1; } if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt) == -1) { close(s); return -1; } blocking_disable(s); return s; #endif errno = EPROTONOSUPPORT; return -1; } if (type == XSOCKET_V4) { s = socket(PF_INET, SOCK_DGRAM, 0); if (s == -1) return -1; if (fcntl(s, F_SETFD, 1) == -1) { close(s); return -1; } blocking_disable(s); return s; } errno = EPROTO; return -1; }