Subversion Repositories Kolibri OS

Rev

Rev 339 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;
  2. ; ETH.INC
  3. ;
  4. ; made by hidnplayr (hidnplayr@gmail.com) for KolibriOS
  5. ;
  6. ; The given code before every macro is only a simple example
  7. ;
  8. ;
  9. ; HISTORY
  10. ;
  11. ; v1.0: august 2006  original release
  12. ; v1.1: december 2006 bugfixes and improvements
  13. ; v1.2: februari 2007 more bugfixes and improvements
  14.  
  15. macro mov arg1,arg2 {
  16.     if arg1 eq arg2
  17.     else
  18.     mov arg1,arg2
  19.     end if
  20. }
  21.  
  22. TCB_LISTEN = 1
  23. TCB_SYN_SENT = 2
  24. TCB_SYN_RECEIVED = 3
  25. TCB_ESTABLISHED = 4
  26. TCB_FIN_WAIT_1 = 5
  27. TCB_FIN_WAIT_2 = 6
  28. TCB_CLOSE_WAIT = 7
  29. TCB_CLOSING = 8
  30. TCB_LAST_ASK = 9
  31. TCB_TIME_WAIT = 10
  32. TCB_CLOSED = 11
  33.  
  34. PASSIVE = 0
  35. ACTIVE = 1
  36.  
  37. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  38.  
  39. macro eth.get_IP IP {
  40.     mov  ebx,1
  41.     mov  eax,52
  42.     mcall
  43.  
  44.     mov  IP ,eax
  45. }
  46.  
  47. macro eth.get_GATEWAY GATEWAY {
  48.     mov  ebx,9
  49.     mov  eax,52
  50.     mcall
  51.     mov GATEWAY ,eax
  52. }
  53.  
  54. macro eth.get_SUBNET SUBNET {
  55.     mov  ebx,10
  56.     mov  eax,52
  57.     mcall
  58.     mov SUBNET ,eax
  59. }
  60.  
  61. macro eth.get_DNS DNS {
  62.     mov  ebx,13
  63.     mov  eax,52
  64.     mcall
  65.     mov  DNS ,eax
  66. }
  67.  
  68. macro eth.set_IP IP {
  69.     mov  ecx,IP
  70.     mov  ebx,3
  71.     mov  eax,52
  72.     mcall
  73. }
  74.  
  75. macro eth.set_GATEWAY GATEWAY {
  76.     mov  ecx,GATEWAY
  77.     mov  ebx,11
  78.     mov  eax,52
  79.     mcall
  80. }
  81.  
  82. macro eth.set_SUBNET SUBNET {
  83.     mov  ecx,SUBNET
  84.     mov  ebx,12
  85.     mov  eax,52
  86.     mcall
  87. }
  88.  
  89. macro eth.set_DNS DNS {
  90.     mov  ecx,DNS
  91.     mov  ebx,14
  92.     mov  eax,52
  93.     mcall
  94. }
  95.  
  96. macro eth.set_network_drv conf {
  97.     mov  ecx,conf
  98.     mov  ebx,2
  99.     mov  eax,52
  100.     mcall
  101. }
  102.  
  103. macro eth.open_udp local,remote,ip,socket {
  104.     mov  ecx, local
  105.     mov  edx, remote
  106.     mov  esi, ip
  107.     mov  ebx, 0
  108.     mov  eax, 53
  109.     mcall
  110.  
  111.     mov  socket,eax
  112. }
  113.  
  114. macro eth.close_udp socket {
  115.     mov  ecx, socket
  116.     mov  ebx, 1
  117.     mov  eax, 53
  118.     mcall
  119. }
  120.  
  121. macro eth.poll socket {
  122.     mov  ecx, socket
  123.     mov  ebx, 2
  124.     mov  eax, 53
  125.     mcall
  126. }
  127.  
  128. macro eth.read_byte socket, result {
  129.     mov  ecx, socket
  130.     mov  ebx, 3
  131.     mov  eax, 53
  132.     mcall
  133.  
  134.     mov  result,bl
  135. }
  136.  
  137. macro eth.read_packet socket, result, buffersize {
  138.     mov  esi, buffersize
  139.     mov  edx, result
  140.     mov  ecx, socket
  141.     mov  ebx, 11
  142.     mov  eax, 53
  143.     mcall
  144. }
  145.  
  146. macro eth.write_udp socket,length,msg,verify {
  147.     mov  ecx, socket
  148.     mov  edx, length
  149.     mov  esi, msg
  150.     mov  ebx, 4
  151.     mov  eax, 53
  152.     mcall
  153.  
  154.     if verify eq 1
  155.     call verifysend
  156.     end if
  157.  
  158. }
  159.  
  160. verifysend:
  161.     test eax,eax
  162.     jnz  @f
  163.     ret
  164. @@:
  165.     pusha
  166.     mov  eax,5
  167.     mov  ebx,100
  168.     mcall
  169.     popa
  170.     mcall
  171. ret
  172.  
  173. macro eth.open_tcp local,remote,ip,passive,socket {
  174.  
  175.     mov  ecx, local
  176.     mov  edx, remote
  177.     mov  esi, ip
  178.     mov  edi, passive      ; 0 = PASSIVE open
  179.     mov  ebx, 5
  180.     mov  eax, 53
  181.     mcall
  182.  
  183.     mov  socket,eax
  184. }
  185.  
  186. macro eth.socket_status socket,result {
  187.     mov  ecx, socket
  188.     mov  ebx, 6
  189.     mov  eax, 53
  190.     mcall
  191.  
  192.     mov  result,eax
  193. }
  194.  
  195. macro eth.write_tcp socket,length,msg,verify {
  196.     mov  ecx, socket
  197.     mov  edx, length
  198.     mov  esi, msg
  199.     mov  ebx, 7
  200.     mov  eax, 53
  201.     mcall
  202.  
  203.     if verify eq 1
  204.     call verifysend
  205.     end if
  206. }
  207.  
  208. macro eth.read_mac mac {
  209.     mov  eax, 52
  210.     mov  ebx, 15
  211.     xor  ecx, ecx
  212.     pusha
  213.     mcall
  214.     mov  dword[mac],eax
  215.     popa
  216.     add  cl, 4
  217.     mcall
  218.     mov  word[mac+4],ax
  219.  
  220. }
  221.  
  222. macro eth.close_tcp socket {
  223.     mov  ecx, socket
  224.     mov  ebx, 8
  225.     mov  eax, 53
  226.     mcall
  227. }
  228.  
  229. macro eth.check_port port,result {
  230.     mov  ecx, port
  231.     mov  ebx, 9
  232.     mov  eax, 53
  233.     mcall
  234.  
  235.     mov  result,eax
  236. }
  237.  
  238. macro eth.check_cable result {
  239.     mov  ebx, 10
  240.     mov  eax, 53
  241.     mcall
  242.  
  243.     mov  result,eax
  244. }
  245.  
  246. macro eth.status status {
  247.     mov  ebx, 255
  248.     mov  ecx, 6
  249.     mov  eax, 53
  250.     mcall
  251.  
  252.     mov  status,eax
  253. }
  254.  
  255. macro eth.search_port port,result {
  256.     mov  edx,port
  257.    @@:
  258.     inc  edx
  259.     eth.check_port edx,eax
  260.     cmp  eax,0
  261.     je   @r
  262.     mov  result,edx
  263. }
  264.  
  265. macro eth.ARP_PROBE address{
  266.  
  267.     mov  edx,address
  268.     mov  eax,52
  269.     mov  ebx,16
  270.     xor  ecx,ecx
  271.     mcall
  272.  
  273. }
  274.  
  275.  
  276. macro eth.ARP_ANNOUNCE address{
  277.  
  278.     mov  edx,address
  279.     mov  eax,52
  280.     mov  ebx,16
  281.     xor  ecx,ecx
  282.     inc  ecx
  283.     mcall
  284.  
  285. }
  286.  
  287. macro eth.read_data socket,dest,endptr,bufferl {
  288. local .getdata,.loop,.end
  289.     mov     eax, dest
  290.     mov     endptr, eax
  291.  
  292. .getdata:
  293.     cmp     endptr, bufferl
  294.     jg      .end
  295.  
  296.     eth.read_packet socket, endptr, 0
  297.     add     endptr,eax
  298.  
  299.     test    eax, eax
  300.     jnz     .getdata
  301.  
  302.     xor     edx, edx
  303. .loop:
  304.     eth.poll socket
  305.  
  306.     test    eax, eax
  307.     jnz     .getdata
  308.  
  309.     mov     eax,5
  310.     mov     ebx,1
  311.     mcall
  312.  
  313.     inc     edx
  314.     cmp     edx,30
  315.     jl      .loop
  316.  
  317. .end:
  318. }
  319.  
  320. macro eth.wait_for_data socket,TIMEOUT,abort {
  321.     mov   edx,TIMEOUT
  322.  
  323.    @@:
  324.     eth.poll socket
  325.  
  326.     cmp   eax,0
  327.     jne   @f
  328.  
  329.     dec   edx
  330.     jz    abort
  331.  
  332.     mov   eax,5                               ; wait here for event
  333.     mov   ebx,10
  334.     mcall
  335.  
  336.     jmp   @r
  337.    @@:
  338.  
  339. }
  340.  
  341.  
  342. ; The function 'resolve' resolves the address in edx and puts the resulting IP in eax.
  343. ; When the input is an IP-adress, the function will output this IP in eax.
  344. ; If something goes wrong, the result in eax should be 0
  345. ;
  346. ; example:
  347. ;
  348. ; resolve query1,IP,PORT
  349. ; resolve '192.168.0.1',IP,PORT
  350. ; resolve query2,IP,PORT
  351. ;
  352. ; query1 db 'www.google.com',0
  353. ; query2 db '49.78.84.45',0
  354. ; IP     dd ?
  355. ; PORT   dd ?
  356.  
  357. macro resolve query,result {
  358.  
  359. if    query eqtype 0
  360.  mov   edx,query
  361. else
  362.  local ..string, ..label
  363.  jmp   ..label
  364.  ..string db query,0
  365.  ..label:
  366.  mov   edx,..string
  367. end   if
  368.  
  369. call  __resolve
  370.  
  371. mov   result,eax
  372.  
  373. }
  374.  
  375. if used __resolve
  376.  
  377. __resolve:
  378.  
  379. if __DEBUG__ eq 1
  380. DEBUGF 1,'DNS: Resolving started\n'
  381. end if
  382.  
  383.     ; This code validates if the query is an IP containing 4 numbers and 3 dots
  384.  
  385.  
  386.     push    edx               ; push edx (query address) onto stack
  387.     xor     al, al            ; make al (dot count) zero
  388.  
  389.    @@:
  390.     cmp     byte[edx],'0'     ; check if this byte is a number, if not jump to no_IP
  391.     jl      no_IP             ;
  392.     cmp     byte[edx],'9'     ;
  393.     jg      no_IP             ;
  394.  
  395.     inc     edx               ; the byte was a number, so lets check the next byte
  396.  
  397.     cmp     byte[edx],0       ; is this byte zero? (have we reached end of query?)
  398.     jz      @f                ; jump to next @@ then
  399.     cmp     byte[edx],':'
  400.     jz      @f
  401.  
  402.     cmp     byte[edx],'.'     ; is this byte a dot?
  403.     jne     @r                ; if not, jump to previous @@
  404.  
  405.     inc     al                ; the byte was a dot so increment al(dot count)
  406.     inc     edx               ; next byte
  407.     jmp     @r                ; lets check for numbers again (jump to previous @@)
  408.  
  409.    @@:                        ; we reach this when end of query reached
  410.     cmp     al,3              ; check if there where 3 dots
  411.     jnz     no_IP             ; if not, jump to no_IP (this is where the DNS will take over)
  412.  
  413.     ; The following code will convert this IP into a dword and output it in eax
  414.     ; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
  415.  
  416.     pop     esi               ; edx (query address) was pushed onto stack and is now popped in esi
  417.  
  418.     xor     edx, edx          ; result
  419.     xor     eax, eax          ; current character
  420.     xor     ebx, ebx          ; current byte
  421.  
  422. .outer_loop:
  423.     shl     edx, 8
  424.     add     edx, ebx
  425.     xor     ebx, ebx
  426. .inner_loop:
  427.     lodsb
  428.     test    eax, eax
  429.     jz      .finish
  430.     cmp     al, '.'
  431.     jz      .outer_loop
  432.     sub     eax, '0'
  433.     imul    ebx, 10
  434.     add     ebx, eax
  435.     jmp     .inner_loop
  436. .finish:
  437.     shl     edx, 8
  438.     add     edx, ebx
  439.  
  440.     bswap   edx               ; we want little endian order
  441.     mov     eax, edx
  442.  
  443.     ret
  444.  
  445.  
  446. no_IP:
  447.  
  448.     pop     edx
  449.  
  450.     ; The query is not an IP address, we will send the query to a DNS server and hope for answer ;)
  451. if __DEBUG__ eq 1
  452.     DEBUGF 1,'DNS: The query is no ip, Building request string from:%u\n',edx
  453. end if
  454.  
  455.     ; Build the request string
  456.     mov     eax, 0x00010100
  457.     mov     [dnsMsg], eax
  458.     mov     eax, 0x00000100
  459.     mov     [dnsMsg+4], eax
  460.     mov     eax, 0x00000000
  461.     mov     [dnsMsg+8], eax
  462.  
  463.     ; domain name goes in at dnsMsg+12
  464.     mov     esi, dnsMsg + 12                     ; location of label length
  465.     mov     edi, dnsMsg + 13                     ; label start
  466.     mov     ecx, 12                              ; total string length so far
  467.  
  468. td002:
  469.     mov     [esi], byte 0
  470.     inc     ecx
  471.  
  472. td0021:
  473.     mov     al, [edx]
  474.  
  475.     cmp     al, 0
  476.     je      td001                                ; we have finished the string translation
  477.  
  478.     cmp     al, '.'
  479.     je      td004                                ; we have finished the label
  480.  
  481.     inc     byte [esi]
  482.     inc     ecx
  483.     mov     [edi], al
  484.     inc     edi
  485.     inc     edx
  486.     jmp     td0021
  487.  
  488. td004:
  489.     mov     esi, edi
  490.     inc     edi
  491.     inc     edx
  492.     jmp     td002
  493.  
  494.     ; write label len + label text
  495. td001:
  496.     mov     [edi], byte 0
  497.     inc     ecx
  498.     inc     edi
  499.     mov     [edi], dword 0x01000100
  500.     add     ecx, 4
  501.  
  502.     mov     [dnsMsgLen], ecx                     ; We'll need the length of the message when we send it
  503.     ; Now, lets send this and wait for an answer
  504.  
  505.     eth.search_port 1024,edx                     ; Find a free port starting from 1025 and store in edx
  506.     eth.get_DNS esi                              ; Read DNS IP from stack into esi
  507.     eth.open_udp edx,53,esi,[socketNum]              ; First, open socket
  508. if __DEBUG__ eq 1
  509.     DEBUGF 1,'DNS: Socket opened: %u (port %u)\n',[socketNum],ecx
  510. end if
  511.     eth.write_udp [socketNum],[dnsMsgLen],dnsMsg     ; Write to socket ( request DNS lookup )
  512. if __DEBUG__ eq 1
  513.     DEBUGF 1,'DNS: Data written, length:%u offset:%u\n',[dnsMsgLen],dnsMsg
  514.     DEBUGF 1,'DNS: Waiting for data: (timeout is %us)\n',TIMEOUT
  515. end if
  516.     eth.wait_for_data [socketNum],TIMEOUT,abort  ; Now, we wait for data from remote
  517.     eth.read_data dword[socketNum],dnsMsg,dword[dnsMsgLen],dnsMsg+BUFFER      ; Read the data into the buffer
  518. if __DEBUG__ eq 1
  519.     DEBUGF 1,'Data received, offset:%u buffer size:%u length:%u\n',dnsMsg,BUFFER,esi-dnsMsg
  520. end if
  521.     eth.close_udp [socketNum]                        ; We're done, close the socket
  522. if __DEBUG__ eq 1
  523.     DEBUGF 1,'Closed Socket\n'
  524. end if
  525.  
  526.     ; Now parse the message to get the host IP. Man, this is complicated. It's described in RFC 1035
  527.     ; 1) Validate that we have an answer with > 0 responses
  528.     ; 2) Find the answer record with TYPE 0001 ( host IP )
  529.     ; 3) Finally, copy the IP address to the display
  530.     ; Note: The response is in dnsMsg, the end of the buffer is pointed to by [dnsMsgLen]
  531.  
  532.     mov     esi, dnsMsg
  533.  
  534.     mov     al, [esi+2]                          ; Is this a response to my question?
  535.     and     al, 0x80
  536.     cmp     al, 0x80
  537.     jne     abort
  538. if __DEBUG__ eq 1
  539.     DEBUGF 1,'DNS: It was a response to my question\n'
  540. end if
  541.  
  542.     mov     al, [esi+3]                          ; Were there any errors?
  543.     and     al, 0x0F
  544.     cmp     al, 0x00
  545.     jne     abort
  546.  
  547. if __DEBUG__ eq 1
  548.     DEBUGF 1,'DNS: There were no errors\n'
  549. end if
  550.  
  551.     mov     ax, [esi+6]                          ; Is there ( at least 1 ) answer?
  552.     cmp     ax, 0x00
  553.     je      abort
  554.  
  555.     ; Header validated. Scan through and get my answer
  556.     add     esi, 12                              ; Skip to the question field
  557.     call    skipName                             ; Skip through the question field
  558.     add     esi, 4                               ; skip past the questions qtype, qclass
  559.  
  560. ctr002z:
  561.     ; Now at the answer. There may be several answers, find the right one ( TYPE = 0x0001 )
  562.     call    skipName
  563.     mov     ax, [esi]
  564.     cmp     ax, 0x0100                           ; Is this the IP address answer?
  565.     jne     ctr002c
  566.     add     esi, 10                              ; Yes! Point eax to the first byte of the IP address
  567.     mov     eax,[esi]
  568.  
  569.     ret
  570.  
  571.  
  572. ctr002c:                                         ; Skip through the answer, move to the next
  573.     add     esi, 8
  574.     movzx   eax, byte [esi+1]
  575.     mov     ah, [esi]
  576.     add     esi, eax
  577.     add     esi, 2
  578.  
  579.     cmp     esi, [dnsMsgLen]                     ; Have we reached the end of the msg? This is an error condition, should not happen
  580.     jl      ctr002z                              ; Check next answer
  581.  
  582. abort:
  583. if __DEBUG__ eq 1
  584.     DEBUGF 1,'DNS: Something went wrong, aborting\n'
  585. end if
  586.     xor     eax,eax
  587.  
  588.     ret
  589.  
  590.  
  591. skipName:
  592.     ; Increment esi to the first byte past the name field
  593.     ; Names may use compressed labels. Normally do.
  594.     ; RFC 1035 page 30 gives details
  595.     mov     al, [esi]
  596.     cmp     al, 0
  597.     je      sn_exit
  598.     and     al, 0xc0
  599.     cmp     al, 0xc0
  600.     je      sn001
  601.  
  602.     movzx   eax, byte [esi]
  603.     inc     eax
  604.     add     esi, eax
  605.     jmp     skipName
  606.  
  607. sn001:
  608.     add     esi, 2                               ; A pointer is always at the end
  609.     ret
  610.  
  611. sn_exit:
  612.     inc     esi
  613.     ret
  614.  
  615. dnsMsgLen:      dd 0
  616. socketNum:      dd 0xFFFF
  617.  
  618. if ~defined dnsMsg
  619. dnsMsg:         rb BUFFER
  620. end if
  621.  
  622. end if
  623.  
  624.  
  625.  
  626.  
  627.