2 USING: kernel byte-arrays combinators strings arrays sequences splitting
4 math math.functions math.parser random
6 io io.binary io.sockets io.encodings.binary
14 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
16 TUPLE: query name type class ;
18 TUPLE: rr name type class ttl rdata ;
22 TUPLE: mx preference exchange ;
24 TUPLE: soa mname rname serial refresh retry expire minimum ;
27 id qr opcode aa tc rd ra z rcode
33 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
35 : random-id ( -- id ) 2 16 ^ random ;
37 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
39 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
41 SYMBOLS: A NS MD MF CNAME SOA MB MG MR NULL WKS PTR HINFO MINFO MX TXT AAAA ;
43 : type-table ( -- table )
64 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
66 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
68 SYMBOLS: IN CS CH HS ;
70 : class-table ( -- table )
78 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
80 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
82 SYMBOLS: QUERY IQUERY STATUS ;
84 : opcode-table ( -- table )
91 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
93 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
95 SYMBOLS: NO-ERROR FORMAT-ERROR SERVER-FAILURE NAME-ERROR NOT-IMPLEMENTED
98 : rcode-table ( -- table )
104 { NOT-IMPLEMENTED 4 }
108 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
110 : <message> ( -- message )
121 { } >>question-section
123 { } >>authority-section
124 { } >>additional-section ;
126 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
128 : ip->ba ( ip -- ba ) "." split [ string>number ] map >byte-array ;
130 : ipv6->ba ( ip -- ba ) ":" split [ 16 base> ] map [ 2 >be ] map concat ;
132 : label->ba ( label -- ba ) [ >byte-array ] [ length ] bi prefix ;
134 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
136 : uint8->ba ( n -- ba ) 1 >be ;
137 : uint16->ba ( n -- ba ) 2 >be ;
138 : uint32->ba ( n -- ba ) 4 >be ;
139 : uint64->ba ( n -- ba ) 8 >be ;
141 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
143 : dn->ba ( dn -- ba ) "." split [ label->ba ] map concat ;
145 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
147 : query->ba ( query -- ba )
150 [ type>> type-table of uint16->ba ]
151 [ class>> class-table of uint16->ba ]
155 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
157 : hinfo->ba ( rdata -- ba )
162 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
164 : mx->ba ( rdata -- ba )
165 [ preference>> uint16->ba ]
166 [ exchange>> dn->ba ]
169 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
171 : soa->ba ( rdata -- ba )
175 [ serial>> uint32->ba ]
176 [ refresh>> uint32->ba ]
177 [ retry>> uint32->ba ]
178 [ expire>> uint32->ba ]
179 [ minimum>> uint32->ba ]
183 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
185 : rdata->ba ( type rdata -- ba )
189 { HINFO [ hinfo->ba ] }
198 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
200 : rr->ba ( rr -- ba )
203 [ type>> type-table of uint16->ba ]
204 [ class>> class-table of uint16->ba ]
207 [ type>> ] [ rdata>> ] bi rdata->ba
208 [ length uint16->ba ] [ ] bi append
213 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
215 : header-bits-ba ( message -- ba )
218 [ opcode>> opcode-table of 11 shift ]
224 [ rcode>> rcode-table of 0 shift ]
226 <arr> sum uint16->ba ;
228 : message->ba ( message -- ba )
232 [ question-section>> length uint16->ba ]
233 [ answer-section>> length uint16->ba ]
234 [ authority-section>> length uint16->ba ]
235 [ additional-section>> length uint16->ba ]
236 [ question-section>> [ query->ba ] map concat ]
237 [ answer-section>> [ rr->ba ] map concat ]
238 [ authority-section>> [ rr->ba ] map concat ]
239 [ additional-section>> [ rr->ba ] map concat ]
243 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
245 : get-single ( ba i -- n ) at ;
246 : get-double ( ba i -- n ) dup 2 + subseq be> ;
247 : get-quad ( ba i -- n ) dup 4 + subseq be> ;
249 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
251 : label-length ( ba i -- length ) get-single ;
253 : skip-label ( ba i -- ba i ) 2dup label-length + 1 + ;
255 : null-label? ( ba i -- ? ) get-single 0 = ;
257 : get-label ( ba i -- label ) [ 1 + ] [ skip-label nip ] 2bi subseq >string ;
259 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
261 : bit-test ( a b -- ? ) bitand 0 = not ;
263 : pointer? ( ba i -- ? ) get-single BIN: 11000000 bit-test ;
265 : pointer ( ba i -- val ) get-double BIN: 0011111111111111 bitand ;
267 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
269 : skip-name ( ba i -- ba i )
271 { [ 2dup null-label? ] [ 1 + ] }
272 { [ 2dup pointer? ] [ 2 + ] }
273 { [ t ] [ skip-label skip-name ] }
277 : get-name ( ba i -- name )
279 { [ 2dup null-label? ] [ 2drop "" ] }
280 { [ 2dup pointer? ] [ dupd pointer get-name ] }
285 [ skip-label get-name ]
293 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
295 : get-query ( ba i -- query )
299 [ 0 + get-double type-table key-of ]
300 [ 2 + get-double class-table key-of ]
305 : skip-query ( ba i -- ba i ) skip-name 4 + ;
307 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
309 : get-mx ( ba i -- mx ) [ get-double ] [ 2 + get-double ] 2bi mx boa ;
311 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
313 : get-soa ( ba i -- soa )
316 [ skip-name get-name ]
332 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
334 : get-ip ( ba i -- ip ) dup 4 + subseq >array [ number>string ] map "." join ;
336 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
338 : get-ipv6 ( ba i -- ip )
339 dup 16 + subseq 2 group [ be> 16 >base ] map ":" join ;
341 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
343 : get-rdata ( ba i type -- rdata )
345 { CNAME [ get-name ] }
351 { AAAA [ get-ipv6 ] }
355 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
357 : get-rr ( ba i -- rr )
362 [ 0 + get-double type-table key-of ]
363 [ 2 + get-double class-table key-of ]
365 [ [ 10 + ] [ get-double type-table key-of ] 2bi get-rdata ]
371 : skip-rr ( ba i -- ba i ) skip-name 8 + 2dup get-double + 2 + ;
373 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
375 : get-question-section ( ba i count -- seq ba i )
376 [ drop [ skip-query ] [ get-query ] 2bi ] map -rot ;
378 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
380 : get-rr-section ( ba i count -- seq ba i )
381 [ drop [ skip-rr ] [ get-rr ] 2bi ] map -rot ;
383 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
385 : >> ( x n -- y ) neg shift ;
387 : get-header-bits ( ba i -- qr opcode aa tc rd ra z rcode )
390 [ 15 >> BIN: 1 bitand ]
391 [ 11 >> BIN: 111 bitand opcode-table key-of ]
392 [ 10 >> BIN: 1 bitand ]
393 [ 9 >> BIN: 1 bitand ]
394 [ 8 >> BIN: 1 bitand ]
395 [ 7 >> BIN: 1 bitand ]
396 [ 4 >> BIN: 111 bitand ]
397 [ BIN: 1111 bitand rcode-table key-of ]
401 : parse-message ( ba -- message )
405 [ 2 + get-header-bits ]
417 [ get-question-section ]
425 2cleave message boa ;
427 : ba->message ( ba -- message ) parse-message ;
429 : with-message-bytes ( ba quot -- ) [ ba->message ] dip call message->ba ; inline
431 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
433 : send-receive-udp ( ba server -- ba )
434 f 0 <inet4> <datagram>
436 [ send ] [ receive drop ] bi
440 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
442 : send-receive-tcp ( ba server -- ba )
443 [ dup length 2 >be prepend ] [ ] bi*
451 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
453 : >dns-inet4 ( obj -- inet4 )
459 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
461 : ask-server ( message server -- message )
462 [ message->ba ] [ >dns-inet4 ] bi*
464 send-receive-udp parse-message
466 [ drop send-receive-tcp parse-message ]
470 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
472 : dns-servers ( -- seq ) V{ } ;
474 : dns-server ( -- server ) dns-servers random ;
476 : ask ( message -- message ) dns-server ask-server ;
478 : query->message ( query -- message ) <message> swap {1} >>question-section ;
480 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
482 : message-query ( message -- query ) question-section>> 1st ;
484 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
486 ERROR: name-error name ;
488 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
490 : fully-qualified ( name -- name )
492 { [ dup empty? ] [ "." append ] }
493 { [ dup peek CHAR: . = ] [ ] }
494 { [ t ] [ "." append ] }