Subversion Repositories Kolibri OS

Rev

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