Merge branch 'master' of git://factorcode.org/git/factor
[factor/jcg.git] / extra / dns / server / server.factor
blobd8a8adc88e7b583981b0698404b18b8e42fb2a2d
2 USING: kernel combinators sequences sets math threads namespaces continuations
3        debugger io io.sockets unicode.case accessors destructors
4        combinators.cleave combinators.short-circuit 
5        newfx fry
6        dns dns.util dns.misc ;
8 IN: dns.server
10 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12 SYMBOL: records-var
14 : records ( -- records ) records-var get ;
16 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
18 : {name-type-class} ( obj -- array )
19   { [ name>> >lower ] [ type>> ] [ class>> ] } <arr> ;
21 : rr=query? ( obj obj -- ? ) [ {name-type-class} ] bi@ = ;
23 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
25 : matching-rrs  ( query -- rrs ) records [ rr=query? ] with filter ;
27 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28 ! zones
29 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
31 : zones    ( -- names ) records [ type>> NS  = ] filter [ name>> ] map prune ;
32 : my-zones ( -- names ) records [ type>> SOA = ] filter [ name>> ] map ;
34 : delegated-zones ( -- names ) zones my-zones diff ;
36 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
37 ! name->zone
38 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
40 : name->zone ( name -- zone/f )
41   zones sort-largest-first [ name-in-domain? ] with find nip ;
43 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
44 ! name->authority
45 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
47 : name->authority ( name -- rrs-ns ) name->zone NS IN query boa matching-rrs ;
49 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50 ! extract-names
51 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
53 : rr->rdata-names ( rr -- names/f )
54     {
55       { [ dup type>> NS    = ] [ rdata>>            {1} ] }
56       { [ dup type>> MX    = ] [ rdata>> exchange>> {1} ] }
57       { [ dup type>> CNAME = ] [ rdata>>            {1} ] }
58       { [ t ]                  [ drop f ] }
59     }
60   cond ;
62 : extract-rdata-names ( message -- names )
63   [ answer-section>> ] [ authority-section>> ] bi append
64   [ rr->rdata-names ] map concat ;
66 : extract-names ( message -- names )
67   [ message-query name>> ] [ extract-rdata-names ] bi prefix-on ;
69 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
70 ! fill-authority
71 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
73 : fill-authority ( message -- message )
74   dup
75     extract-names [ name->authority ] map concat prune
76     over answer-section>> diff
77   >>authority-section ;
79 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
80 ! fill-additional
81 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83 : name->rrs-a ( name -- rrs-a ) A IN query boa matching-rrs ;
85 : fill-additional ( message -- message )
86   dup
87     extract-rdata-names [ name->rrs-a ] map concat prune
88     over answer-section>> diff
89   >>additional-section ;
91 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
92 ! query->rrs
93 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
95 DEFER: query->rrs
97 : matching-rrs? ( query -- rrs/f ) matching-rrs [ empty? ] [ drop f ] [ ] 1if ;
99 : matching-cname? ( query -- rrs/f )
100   [ ] [ clone CNAME >>type matching-rrs ] bi ! query rrs
101   [ empty? not ]
102     [ 1st swap clone over rdata>> >>name query->rrs prefix-on ]
103     [ 2drop f ]
104   1if ;
106 : query->rrs ( query -- rrs/f ) { [ matching-rrs? ] [ matching-cname? ] } 1|| ;
108 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
109 ! have-answers
110 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
112 : have-answers ( message -- message/f )
113   dup message-query query->rrs
114   [ empty? ]
115     [ 2drop f ]
116     [ >>answer-section fill-authority fill-additional ]
117   1if ;
119 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
120 ! have-delegates?
121 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
123 : cdr-name ( name -- name ) dup CHAR: . index 1+ tail ;
125 : is-soa? ( name -- ? ) SOA IN query boa matching-rrs empty? not ;
127 : have-ns? ( name -- rrs/f )
128   NS IN query boa matching-rrs [ empty? ] [ drop f ] [ ] 1if ;
130 : name->delegates ( name -- rrs-ns )
131     {
132       [ "" =    { } and ]
133       [ is-soa? { } and ]
134       [ have-ns? ]
135       [ cdr-name name->delegates ]
136     }
137   1|| ;
139 : have-delegates ( message -- message/f )
140   dup message-query name>> name->delegates ! message rrs-ns
141   [ empty? ]
142     [ 2drop f ]
143     [
144       dup [ rdata>> A IN query boa matching-rrs ] map concat
145                                            ! message rrs-ns rrs-a
146       [ >>authority-section ]
147       [ >>additional-section ]
148       bi*
149     ]
150   1if ;
152 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
153 ! outsize-zones
154 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
156 : outside-zones ( message -- message/f )
157   dup message-query name>> name->zone f =
158     [ ]
159     [ drop f ]
160   if ;
162 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
163 ! is-nx
164 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
166 : is-nx ( message -- message/f )
167   [ message-query name>> records [ name>> = ] with filter empty? ]
168     [
169       NAME-ERROR >>rcode
170       dup
171         message-query name>> name->zone SOA IN query boa matching-rrs
172       >>authority-section
173     ]
174     [ drop f ]
175   1if ;
177 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
179 : none-of-type ( message -- message )
180   dup
181     message-query name>> name->zone SOA IN query boa matching-rrs
182   >>authority-section ;
184 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
186 : find-answer ( message -- message )
187     {
188       [ have-answers   ]
189       [ have-delegates ]
190       [ outside-zones  ]
191       [ is-nx          ]
192       [ none-of-type   ]
193     }
194   1|| ;
196 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
198 : (handle-request) ( packet -- )
199   [ [ find-answer ] with-message-bytes ] change-data respond ;
201 : handle-request ( packet -- ) [ (handle-request) ] curry in-thread ;
203 : receive-loop ( socket -- )
204   [ receive-packet handle-request ] [ receive-loop ] bi ;
206 : loop ( addr-spec -- )
207   [ <datagram> '[ _ [ receive-loop ] with-disposal ] try ] [ loop ] bi ;