186 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Factor
		
	
	
 | 
						|
USING: kernel continuations
 | 
						|
       combinators
 | 
						|
       sequences
 | 
						|
       math
 | 
						|
       random
 | 
						|
       unicode.case
 | 
						|
       accessors symbols
 | 
						|
       combinators.lib combinators.cleave
 | 
						|
       newfx
 | 
						|
       dns dns.cache ;
 | 
						|
 | 
						|
IN: dns.recursive
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: root-dns-servers ( -- servers )
 | 
						|
  {
 | 
						|
    "192.5.5.241"
 | 
						|
    "192.112.36.4"
 | 
						|
    "128.63.2.53"
 | 
						|
    "192.36.148.17"
 | 
						|
    "192.58.128.30"
 | 
						|
    "193.0.14.129"
 | 
						|
    "199.7.83.42"
 | 
						|
    "202.12.27.33"
 | 
						|
    "198.41.0.4"
 | 
						|
  } ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: {name-type-class} ( obj -- seq )
 | 
						|
  [ name>> >lower ] [ type>> ] [ class>> ] tri {3} ;
 | 
						|
 | 
						|
: rr=query? ( rr query -- ? ) [ {name-type-class} ] bi@ = ;
 | 
						|
 | 
						|
: rr-filter ( rrs query -- rrs ) [ rr=query? ] curry filter ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: answer-hits ( message -- rrs )
 | 
						|
  [ answer-section>> ] [ message-query ] bi rr-filter ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: name-hits ( message -- rrs )
 | 
						|
  [ answer-section>> ] [ message-query clone A >>type ] bi rr-filter ;
 | 
						|
 | 
						|
: cname-hits ( message -- rrs )
 | 
						|
  [ answer-section>> ] [ message-query clone CNAME >>type ] bi rr-filter ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: authority-hits ( message -- rrs )
 | 
						|
  authority-section>> [ type>> NS = ] filter ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
SYMBOLS: ANSWERED NO-NAME-SERVERS UNCLASSIFIED ;
 | 
						|
 | 
						|
: classify-message ( message -- symbol )
 | 
						|
    {
 | 
						|
      { [ dup rcode>> NAME-ERROR     = ] [ drop NAME-ERROR      ] }
 | 
						|
      { [ dup rcode>> SERVER-FAILURE = ] [ drop SERVER-FAILURE  ] }
 | 
						|
      { [ dup answer-hits empty? not   ] [ drop ANSWERED        ] }
 | 
						|
      { [ dup cname-hits  empty? not   ] [ drop CNAME           ] }
 | 
						|
      { [ dup authority-hits empty?    ] [ drop NO-NAME-SERVERS ] }
 | 
						|
      { [ t                            ] [ drop UNCLASSIFIED    ] }
 | 
						|
    }
 | 
						|
  cond ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
DEFER: name->ip
 | 
						|
 | 
						|
! : name->ip/f ( name -- ip/f ) [ name->ip ] [ drop f ] recover ;
 | 
						|
 | 
						|
! : extract-ns-ips ( message -- ips )
 | 
						|
!   authority-hits [ rdata>> name->ip/f ] map [ ] filter ;
 | 
						|
 | 
						|
: extract-ns-ips ( message -- ips )
 | 
						|
  authority-hits [ rdata>> name->ip ] map [ ] filter ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: (recursive-query) ( query servers -- message )
 | 
						|
  dup random                                 ! query servers server
 | 
						|
  pick query->message 0 >>rd                 ! query servers server message
 | 
						|
  over ask-server                            ! query servers server message
 | 
						|
  cache-message                              ! query servers server message
 | 
						|
  dup classify-message                       ! query servers server message sym
 | 
						|
    {
 | 
						|
      { NAME-ERROR      [ -roll 3drop ] }
 | 
						|
      { ANSWERED        [ -roll 3drop ] }
 | 
						|
      { CNAME           [ -roll 3drop ] }
 | 
						|
      { NO-NAME-SERVERS [ -roll 3drop ] }
 | 
						|
      {
 | 
						|
        SERVER-FAILURE
 | 
						|
        [
 | 
						|
          -roll                              ! message query servers server
 | 
						|
          remove                             ! message query servers
 | 
						|
          dup empty?
 | 
						|
            [ 2drop ]
 | 
						|
            [ rot drop (recursive-query) ]
 | 
						|
          if
 | 
						|
        ]
 | 
						|
      }
 | 
						|
      [                                      ! query servers server message sym
 | 
						|
        drop nip nip                         ! query message
 | 
						|
        extract-ns-ips                       ! query ips
 | 
						|
        (recursive-query)
 | 
						|
      ]
 | 
						|
    }
 | 
						|
  case ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: cdr-name ( name -- name ) dup CHAR: . index 1+ tail ;
 | 
						|
 | 
						|
: cache-get-ns ( name -- seq/f ) NS IN query boa cache-get ;
 | 
						|
 | 
						|
: name->servers ( name -- servers )
 | 
						|
    {
 | 
						|
      { [ dup "" = ]         [ drop root-dns-servers ] }
 | 
						|
      { [ dup cache-get-ns ] [ cache-get-ns [ rdata>> name->ip ] map ] }
 | 
						|
      { [ t ]                [ cdr-name name->servers ] }
 | 
						|
    }
 | 
						|
  cond ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: recursive-query ( query -- message )
 | 
						|
  dup name>> name->servers (recursive-query) ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: canonical/cache ( name -- name )
 | 
						|
  dup CNAME IN query boa cache-get dup [ nip 1st rdata>> ] [ drop ] if ;
 | 
						|
 | 
						|
: name->ip/cache ( name -- ip/f )
 | 
						|
  canonical/cache
 | 
						|
  A IN query boa cache-get dup [ random rdata>> ] [ ] if ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
:  name-hits? ( message -- message ? ) dup  name-hits empty? not ;
 | 
						|
: cname-hits? ( message -- message ? ) dup cname-hits empty? not ;
 | 
						|
 | 
						|
! : name->ip/server ( name -- ip-or-f )
 | 
						|
!   A IN query boa root-dns-servers recursive-query ! message
 | 
						|
!     {
 | 
						|
!       { [ name-hits? ]  [ name-hits  random rdata>>          ] }
 | 
						|
!       { [ cname-hits? ] [ cname-hits random rdata>> name->ip ] }
 | 
						|
!       { [ t           ] [ drop f ] }
 | 
						|
!     }
 | 
						|
!   cond ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
: name->ip/server ( name -- ip-or-f )
 | 
						|
  A IN query boa recursive-query ! message
 | 
						|
    {
 | 
						|
      { [ name-hits? ]  [ name-hits  random rdata>>          ] }
 | 
						|
      { [ cname-hits? ] [ cname-hits random rdata>> name->ip ] }
 | 
						|
      { [ t           ] [ drop f ] }
 | 
						|
    }
 | 
						|
  cond ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 | 
						|
 | 
						|
! : name->ip ( name -- ip )
 | 
						|
!   { [ name->ip/cache ] [ name->ip/server ] [ name-error ] } 1|| ;
 | 
						|
 | 
						|
: name->ip ( name -- ip )
 | 
						|
  dup name->ip/cache dup
 | 
						|
    [ nip ]
 | 
						|
    [
 | 
						|
      drop dup name->ip/server dup
 | 
						|
        [ nip ]
 | 
						|
        [ drop name-error ]
 | 
						|
      if
 | 
						|
    ]
 | 
						|
  if ;
 | 
						|
 | 
						|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 |