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
15 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
17 TUPLE: query name type class ;
19 TUPLE: rr name type class ttl rdata ;
23 TUPLE: mx preference exchange ;
25 TUPLE: soa mname rname serial refresh retry expire minimum ;
28 id qr opcode aa tc rd ra z rcode
34 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
36 : random-id ( -- id ) 2 16 ^ random ;
38 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
40 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
42 SYMBOLS: A NS MD MF CNAME SOA MB MG MR NULL WKS PTR HINFO MINFO MX TXT AAAA ;
44 : type-table ( -- table )
65 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
67 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
69 SYMBOLS: IN CS CH HS ;
71 : class-table ( -- table )
79 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
81 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
83 SYMBOLS: QUERY IQUERY STATUS ;
85 : opcode-table ( -- table )
92 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
94 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
96 SYMBOLS: NO-ERROR FORMAT-ERROR SERVER-FAILURE NAME-ERROR NOT-IMPLEMENTED
99 : rcode-table ( -- table )
105 { NOT-IMPLEMENTED 4 }
109 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
111 : <message> ( -- message )
122 { } >>question-section
124 { } >>authority-section
125 { } >>additional-section ;
127 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
129 : ip->ba ( ip -- ba ) "." split [ string>number ] map >byte-array ;
131 : ipv6->ba ( ip -- ba ) ":" split [ 16 base> ] map [ 2 >be ] map concat ;
133 : label->ba ( label -- ba ) [ >byte-array ] [ length ] bi prefix ;
135 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
137 : uint8->ba ( n -- ba ) 1 >be ;
138 : uint16->ba ( n -- ba ) 2 >be ;
139 : uint32->ba ( n -- ba ) 4 >be ;
140 : uint64->ba ( n -- ba ) 8 >be ;
142 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
144 : dn->ba ( dn -- ba ) "." split [ label->ba ] map concat ;
146 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
148 : query->ba ( query -- ba )
151 [ type>> type-table of uint16->ba ]
152 [ class>> class-table of uint16->ba ]
156 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
158 : hinfo->ba ( rdata -- ba )
163 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
165 : mx->ba ( rdata -- ba )
166 [ preference>> uint16->ba ]
167 [ exchange>> dn->ba ]
170 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
172 : soa->ba ( rdata -- ba )
176 [ serial>> uint32->ba ]
177 [ refresh>> uint32->ba ]
178 [ retry>> uint32->ba ]
179 [ expire>> uint32->ba ]
180 [ minimum>> uint32->ba ]
184 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
186 : rdata->ba ( type rdata -- ba )
190 { HINFO [ hinfo->ba ] }
199 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
201 : rr->ba ( rr -- ba )
204 [ type>> type-table of uint16->ba ]
205 [ class>> class-table of uint16->ba ]
208 [ type>> ] [ rdata>> ] bi rdata->ba
209 [ length uint16->ba ] [ ] bi append
214 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
216 : header-bits-ba ( message -- ba )
219 [ opcode>> opcode-table of 11 shift ]
225 [ rcode>> rcode-table of 0 shift ]
227 <arr> sum uint16->ba ;
229 : message->ba ( message -- ba )
233 [ question-section>> length uint16->ba ]
234 [ answer-section>> length uint16->ba ]
235 [ authority-section>> length uint16->ba ]
236 [ additional-section>> length uint16->ba ]
237 [ question-section>> [ query->ba ] map concat ]
238 [ answer-section>> [ rr->ba ] map concat ]
239 [ authority-section>> [ rr->ba ] map concat ]
240 [ additional-section>> [ rr->ba ] map concat ]
244 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
246 : get-single ( ba i -- n ) at ;
247 : get-double ( ba i -- n ) dup 2 + subseq be> ;
248 : get-quad ( ba i -- n ) dup 4 + subseq be> ;
250 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
252 : label-length ( ba i -- length ) get-single ;
254 : skip-label ( ba i -- ba i ) 2dup label-length + 1 + ;
256 : null-label? ( ba i -- ? ) get-single 0 = ;
258 : get-label ( ba i -- label ) [ 1 + ] [ skip-label nip ] 2bi subseq >string ;
260 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
262 : bit-test ( a b -- ? ) bitand 0 = not ;
264 : pointer? ( ba i -- ? ) get-single BIN: 11000000 bit-test ;
266 : pointer ( ba i -- val ) get-double BIN: 0011111111111111 bitand ;
268 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
270 : skip-name ( ba i -- ba i )
272 { [ 2dup null-label? ] [ 1 + ] }
273 { [ 2dup pointer? ] [ 2 + ] }
274 { [ t ] [ skip-label skip-name ] }
278 : get-name ( ba i -- name )
280 { [ 2dup null-label? ] [ 2drop "" ] }
281 { [ 2dup pointer? ] [ dupd pointer get-name ] }
286 [ skip-label get-name ]
294 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
296 : get-query ( ba i -- query )
300 [ 0 + get-double type-table key-of ]
301 [ 2 + get-double class-table key-of ]
306 : skip-query ( ba i -- ba i ) skip-name 4 + ;
308 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
310 : get-mx ( ba i -- mx ) [ get-double ] [ 2 + get-double ] 2bi mx boa ;
312 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
314 : get-soa ( ba i -- soa )
317 [ skip-name get-name ]
333 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
335 : get-ip ( ba i -- ip ) dup 4 + subseq >array [ number>string ] map "." join ;
337 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
339 : get-ipv6 ( ba i -- ip )
340 dup 16 + subseq 2 group [ be> 16 >base ] map ":" join ;
342 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
344 : get-rdata ( ba i type -- rdata )
346 { CNAME [ get-name ] }
352 { AAAA [ get-ipv6 ] }
356 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
358 : get-rr ( ba i -- rr )
363 [ 0 + get-double type-table key-of ]
364 [ 2 + get-double class-table key-of ]
366 [ [ 10 + ] [ get-double type-table key-of ] 2bi get-rdata ]
372 : skip-rr ( ba i -- ba i ) skip-name 8 + 2dup get-double + 2 + ;
374 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
376 : get-question-section ( ba i count -- seq ba i )
377 [ drop [ skip-query ] [ get-query ] 2bi ] map -rot ;
379 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
381 : get-rr-section ( ba i count -- seq ba i )
382 [ drop [ skip-rr ] [ get-rr ] 2bi ] map -rot ;
384 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
386 : >> ( x n -- y ) neg shift ;
388 : get-header-bits ( ba i -- qr opcode aa tc rd ra z rcode )
391 [ 15 >> BIN: 1 bitand ]
392 [ 11 >> BIN: 111 bitand opcode-table key-of ]
393 [ 10 >> BIN: 1 bitand ]
394 [ 9 >> BIN: 1 bitand ]
395 [ 8 >> BIN: 1 bitand ]
396 [ 7 >> BIN: 1 bitand ]
397 [ 4 >> BIN: 111 bitand ]
398 [ BIN: 1111 bitand rcode-table key-of ]
402 : parse-message ( ba -- message )
406 [ 2 + get-header-bits ]
418 get-question-section r>
425 2cleave message boa ;
427 : ba->message ( ba -- message ) parse-message ;
429 : with-message-bytes ( ba quot -- ) >r ba->message r> 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 ] }