110 lines
3.9 KiB
Racket
110 lines
3.9 KiB
Racket
#lang typed/racket/base
|
|
;; DNS drivers using racket-typed-matrix.
|
|
|
|
(require racket/set)
|
|
(require racket/match)
|
|
(require "codec.rkt")
|
|
(require racket-typed-matrix/sugar-typed)
|
|
(require racket-typed-matrix/drivers/udp)
|
|
(require racket-typed-matrix/support/pseudo-substruct)
|
|
|
|
(provide (struct-out bad-dns-packet-repr)
|
|
BadDnsPacket bad-dns-packet bad-dns-packet?
|
|
BadDnsPacketPattern bad-dns-packet-pattern bad-dns-packet-pattern?
|
|
|
|
(struct-out dns-request-repr)
|
|
DNSRequest dns-request dns-request?
|
|
DNSRequestPattern dns-request-pattern dns-request-pattern?
|
|
|
|
(struct-out dns-reply-repr)
|
|
DNSReply dns-reply dns-reply?
|
|
DNSReplyPattern dns-reply-pattern dns-reply-pattern?
|
|
|
|
dns-read-driver
|
|
dns-write-driver
|
|
dns-spy)
|
|
|
|
(struct: (TDetail TSource TSink TReason)
|
|
bad-dns-packet-repr
|
|
([detail : TDetail] [source : TSource] [sink : TSink] [reason : TReason]) #:transparent)
|
|
(pseudo-substruct: (bad-dns-packet-repr Any UdpAddress UdpAddress Symbol)
|
|
BadDnsPacket bad-dns-packet bad-dns-packet?)
|
|
(pseudo-substruct: (bad-dns-packet-repr Any
|
|
(U Wild UdpAddressPattern)
|
|
(U Wild UdpAddressPattern)
|
|
(U Wild Symbol))
|
|
BadDnsPacketPattern bad-dns-packet-pattern bad-dns-packet-pattern?)
|
|
|
|
(struct: (TMessage TSource TSink)
|
|
dns-request-repr
|
|
([message : TMessage] [source : TSource] [sink : TSink]) #:transparent)
|
|
(pseudo-substruct: (dns-request-repr DNSMessage UdpAddress UdpAddress)
|
|
DNSRequest dns-request dns-request?)
|
|
(pseudo-substruct: (dns-request-repr (U Wild DNSMessage)
|
|
(U Wild UdpAddressPattern)
|
|
(U Wild UdpAddressPattern))
|
|
DNSRequestPattern dns-request-pattern dns-request-pattern?)
|
|
|
|
(struct: (TMessage TSource TSink)
|
|
dns-reply-repr
|
|
([message : TMessage] [source : TSource] [sink : TSink]) #:transparent)
|
|
(pseudo-substruct: (dns-reply-repr DNSMessage UdpAddress UdpAddress)
|
|
DNSReply dns-reply dns-reply?)
|
|
(pseudo-substruct: (dns-reply-repr (U Wild DNSMessage)
|
|
(U Wild UdpAddressPattern)
|
|
(U Wild UdpAddressPattern))
|
|
DNSReplyPattern dns-reply-pattern dns-reply-pattern?)
|
|
|
|
(: dns-read-driver : UdpAddress -> (Transition Void))
|
|
(define (dns-read-driver s)
|
|
(transition: (void) : Void
|
|
(at-meta-level
|
|
(endpoint: : Void
|
|
#:subscriber (udp-packet-pattern (wild) s (wild))
|
|
[(udp-packet source (== s) #"")
|
|
(begin (log-info "Debug dump packet received")
|
|
(send-message `(debug-dump)))]
|
|
[(udp-packet source (== s) body)
|
|
(send-message
|
|
(with-handlers ((exn:fail? (lambda (e)
|
|
(bad-dns-packet body source s 'unparseable))))
|
|
(define message (packet->dns-message body))
|
|
(case (dns-message-direction message)
|
|
((request) (dns-request message source s))
|
|
((response) (dns-reply message source s)))))]))))
|
|
|
|
(: dns-write-driver : UdpAddress -> (Transition Void))
|
|
(define (dns-write-driver s)
|
|
(: translate : DNSMessage UdpAddress -> (ActionTree Void))
|
|
(define (translate message sink)
|
|
(with-handlers ((exn:fail? (lambda (e)
|
|
(send-message (bad-dns-packet message s sink 'unencodable)))))
|
|
(at-meta-level
|
|
(send-message (udp-packet s sink (dns-message->packet message))))))
|
|
(transition: (void) : Void
|
|
(endpoint: : Void
|
|
#:subscriber (dns-request (wild) s (wild))
|
|
[(dns-request message (== s) sink) (translate message sink)])
|
|
(endpoint: : Void
|
|
#:subscriber (dns-reply (wild) s (wild))
|
|
[(dns-reply message (== s) sink) (translate message sink)])))
|
|
|
|
(: dns-spy : -> (Transition Void))
|
|
(define (dns-spy)
|
|
(transition: (void) : Void
|
|
(endpoint: : Void
|
|
#:subscriber (wild) #:observer
|
|
[(dns-request message source sink)
|
|
(begin (log-info (format "DNS: ~v asks ~v ~v~n : ~v"
|
|
source sink (dns-message-id message)
|
|
(dns-message-questions message)))
|
|
(void))]
|
|
[(dns-reply message source sink)
|
|
(begin (log-info (format "DNS: ~v answers ~v~n : ~v"
|
|
source sink
|
|
message))
|
|
(void))]
|
|
[x
|
|
(begin (log-info (format "DNS: ~v" x))
|
|
(void))])))
|