client-side DNS TCP
Dimitris Gravanis
dimgrav at gmail.com
Sat Jul 8 15:21:35 UTC 2017
Hi Stefan,
Thank you very much for your detailed input, it helped me significantly.
My main obstacle right now is to determine how are TCP/UDP headers
implemented in Samba. I've figured out UDP, it's pretty straightforward
for the client, but TCP is a bit more complicated and the libraries that
include TCP definitions are a lot. I'm using source4/dns_server as my
main guide, putting it together with talloc, tevent and tsocket. It's a
bit of a maze :).
Regarding branches, is it ok, in terms of permissions/licensing, if I
use a repo at my GitHub and move at git.Samba.org at a later point?
Thanks again and enjoy your weekend,
Dimitris
On 07/07/2017 08:03 πμ, Stefan Metzmacher wrote:
> Hi Dimitris,
>
>> I'm trying to put together the standard for the client-side DNS TCP
>> calls in libcli/dns/dns.c, libdns.h and dns.h, so that I can then work
>> on switching from UDP for packages larger than 512 bytes. I'm using
>> source4/dns_server/dns_server.c and dns_server for cross-referencing and
>> to figure out how exactly should I make the client implementation.
> I'd say for dns updates we should only use tcp.
>
> Do you have some work in progress branch somewhere?
>
>> I've gone through RFC 1035/768/793/2548/7766, but I'm still getting a
>> bit overwhelmed from the custom headers and APIs that are used in Samba.
>> To my understanding, dns_server.c/.h cover the stream, socket and
>> binding over TCP and most functions from dns_server.c that handle the
>> above, could be directly implemented to libcli/dns.c, am I correct? Do I
>> use the same memory and tevent context that is used for UDP requests?
>>
>> Both talloc and tevent have given me a bit of a hard time, information
>> overload!
> But once you get around it you'll never want to use something else:-)
>
>> I've also looked into PIDL and found the definition for TSIG records,
>> along with a "fake" TSIG definition, could you tell me what exactly this
>> is, since I didn't come across it in RFC 284
> dns_fake_tsig_rec is what RFC 2845 3.4.2. "TSIG Variables" is about:
> Source Field Name Notes
> -----------------------------------------------------------------------
> TSIG RR NAME Key name, in canonical wire format
> TSIG RR CLASS (Always ANY in the current specification)
> TSIG RR TTL (Always 0 in the current specification)
> TSIG RDATA Algorithm Name in canonical wire format
> TSIG RDATA Time Signed in network byte order
> TSIG RDATA Fudge in network byte order
> TSIG RDATA Error in network byte order
> TSIG RDATA Other Len in network byte order
> TSIG RDATA Other Data exactly as transmitted
>
> While dns_tsig_record is "RDATA" from RFC 2845 2.3. Record Format:
> Field Name Data Type Notes
> --------------------------------------------------------------
> Algorithm Name domain-name Name of the algorithm
> in domain name syntax.
> Time Signed u_int48_t seconds since 1-Jan-70 UTC.
> Fudge u_int16_t seconds of error permitted
> in Time Signed.
> MAC Size u_int16_t number of octets in MAC.
> MAC octet stream defined by Algorithm Name.
> Original ID u_int16_t original message ID
> Error u_int16_t expanded RCODE covering
> TSIG processing.
> Other Len u_int16_t length, in octets, of
> Other Data.
> Other Data octet stream empty unless Error == BADTIME
>
> Basically the signature generation needs to use the original
> dns packet and:
> - remove the bytes from dns_tsig_record
> - count down the arcount field in the buffer
> - construct a blob using dns_fake_tsig_rec and append that
> - pass the constructed buffer to gensec_sign_packet()
> - rebuild the dns packet buffer with the signature (MAC) field of
> dns_tsig_record filled with the signature from gensec_sign_packet().
>
> See dns_verify_tsig() in source4/dns_server/dns_crypto.c
> for the checking function that verifies the client request
> and dns_sign_tsig() and dns_tsig_compute_mac() for the
> MAC generated in the server response, which should be validated
> by the client.
>
>> I checked this
>> <http://www.csd.uoc.gr/%7Ehy556/material/tutorials/cs556-3rd-tutorial.pdf>
>> tutorial as well (it's from a Greek University), though it uses Sockets,
>> it helped me put all those RFCs in perspective.
> It's good have some low level understanding, but our high level code
> should deal with all these nasty details.
>
> That's why we have the tdgram (for udp) and tstream (for tcp) abstractions.
>
> I guess for one DNS "transaction/call" (request and response) you'll
> need to have a call chain like:
>
> 1. prepare the request buffer:
> 2. submit the buffer with tstream_writev_send() or tdgram_sendto_send()
> 3. register a callback, which uses tstream_writev_recv() or
> tdgram_sendto_recv() to get the result.
> 4. use tstream_read_pdu_blob_send() (similar to dns_tcp_call_loop())
> or tdgram_recvfrom_send() (similar to dns_udp_call_loop()) to
> wait for the servers response.
> 5. register a callback, which uses tstream_read_pdu_blob_recv() or
> tdgram_recvfrom_recv() to get the response buffer.
> 6. parse the response buffer.
>
> I guess you want to implement a low level
> dns_client_call_send/recv() which takes the
> request buffer and returns the response buffer,
> it will basically cover steps 2-5.
> And then you have multiple wrapper on top
> of it, e.g. dns_client_update_send/recv()
> or dns_client_query_send/recv(), which hide
> the preparation of the request buffer (including a
> signature generation).
>
> metze
>
More information about the samba-technical
mailing list