Subversion Repositories Kolibri OS

Rev

Rev 1251 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  ARP.INC                                                        ;;
  7. ;;                                                                 ;;
  8. ;;  Part of the tcp/ip network stack for KolibriOS                 ;;
  9. ;;                                                                 ;;
  10. ;;  Based on the work of [Johnny_B] and [smb]                      ;;
  11. ;;                                                                 ;;
  12. ;;    Written by hidnplayr@kolibrios.org                           ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19.  
  20. $Revision: 1257 $
  21.  
  22.  
  23. ARP_NO_ENTRY            equ  0
  24. ARP_VALID_MAPPING       equ  1
  25. ARP_AWAITING_RESPONSE   equ  2
  26. ARP_RESPONSE_TIMEOUT    equ  3
  27.  
  28. ARP_REQUEST_TTL         = 20 ; in seconds
  29. ARP_ENTRY_TTL           = 600 ; in seconds
  30.  
  31. ETHER_ARP               equ  0x0608
  32.  
  33. ARP_REQ_OPCODE          equ  0x0100  ; request
  34. ARP_REP_OPCODE          equ  0x0200  ; reply
  35.  
  36. ARP_TABLE_SIZE          equ  20      ; Size of table
  37.  
  38. struct ARP_ENTRY
  39.        .IP              dd  ?
  40.        .MAC             dp  ?
  41.        .Status          dw  ?
  42.        .TTL             dw  ?  ; in seconds
  43.        .size:
  44. ends
  45.  
  46. struct ARP_Packet
  47.        .HardwareType    dw  ?
  48.        .ProtocolType    dw  ?
  49.        .HardwareSize    db  ?
  50.        .ProtocolSize    db  ?
  51.        .Opcode          dw  ?
  52.        .SenderMAC       dp  ?
  53.        .SenderIP        dd  ?
  54.        .TargetMAC       dp  ?
  55.        .TargetIP        dd  ?
  56. ends
  57.  
  58.  
  59. ; The TTL field is decremented every second, and is deleted when it
  60. ; reaches 0. It is refreshed every time a packet is received
  61. ; If the TTL field is 0xFFFF it is a static entry and is never deleted
  62. ; The status field can be the following values:
  63. ; 0x0000  entry not used
  64. ; 0x0001  entry holds a valid mapping
  65. ; 0x0002  entry contains an IP address, awaiting ARP response
  66. ; 0x0003  No response received to ARP request.
  67. ; The last status value is provided to allow the network layer to delete
  68. ; a packet that is queued awaiting an ARP response
  69.  
  70. align 4
  71. uglobal
  72.  
  73.         NumARP          dd ?
  74.         ARPTable        rb ARP_ENTRY.size * ARP_TABLE_SIZE
  75.  
  76.         ARP_PACKETS_TX  rd  MAX_NET_DEVICES
  77.         ARP_PACKETS_RX  rd  MAX_NET_DEVICES
  78.  
  79.  
  80. endg
  81.  
  82.  
  83.  
  84. ;-----------------------------------------------------------------
  85. ;
  86. ; ARP_init
  87. ;
  88. ;  This function resets all ARP variables
  89. ;
  90. ;  IN:  /
  91. ;  OUT: /
  92. ;
  93. ;-----------------------------------------------------------------
  94. align 4
  95. ARP_init:
  96.  
  97.         xor     eax, eax
  98.  
  99.         mov     [NumARP], eax
  100.  
  101.         mov     edi, ARP_PACKETS_TX
  102.         mov     ecx, 2*MAX_NET_DEVICES
  103.         rep     stosd
  104.  
  105.         ret
  106.  
  107.  
  108. ;-----------------------------------------------------------------
  109. ;
  110. ; ARP_IP_to_MAC
  111. ;
  112. ;  This function resets all ARP variables
  113. ;
  114. ;  IN: eax = IPv4 address
  115. ;  OUT: eax = -1 on error, else eax = first two bytes of mac
  116. ;                   ( high 16 bits are zero)
  117. ;       ebx = last four bytes of mac                                  ; TODO: special eax value for 'request send'
  118. ;
  119. ;-----------------------------------------------------------------
  120. align 4
  121. ARP_IP_to_MAC:
  122.  
  123.         DEBUGF 1,"ARP_IP_to_MAC\n"
  124.  
  125.     ; first, check destination IP to see if it is on 'this' network.
  126.     ; The test is:
  127.     ; if ( destIP & subnet_mask == stack_ip & subnet_mask )
  128.     ;   destination is local
  129.     ; else
  130.     ;  destination is remote, so pass to gateway
  131.  
  132.         xor     edx, edx ; TODO: find device num in edx
  133.  
  134.         mov     ebx, [IP_LIST+edx]
  135.         and     ebx, [SUBNET_LIST+edx]
  136.  
  137.         mov     ecx, eax
  138.         and     ecx, [SUBNET_LIST+edx]
  139.  
  140.         cmp     ecx, ebx
  141.         je      .local
  142.  
  143.         mov     eax, [GATEWAY_LIST+edx]
  144.         DEBUGF 1,"requested IP is not on subnet, using gateway\n"
  145.  
  146.   .local:
  147.    ; try to find it on the list
  148.         mov     ecx, [NumARP]
  149.         test    ecx, ecx
  150.         jz      .not_in_list
  151.         mov     esi, ARPTable + ARP_ENTRY.IP
  152.   .scan_loop:
  153.         cmp     [esi], eax
  154.         je      .found_it
  155.         add     esi, ARP_ENTRY.size
  156.         loop    .scan_loop
  157.   .not_in_list:
  158.  
  159.         DEBUGF 1,"IP not found on list, preparing for ARP request\n"
  160.  
  161.    ; if not, reserve an entry in list and send an ARP request packet
  162.  
  163.         push    eax
  164.  
  165.         push    word ARP_REQUEST_TTL
  166.         push    word ARP_AWAITING_RESPONSE
  167.         push    dword 0
  168.         push    word 0
  169.         push    eax
  170.         call    ARP_add_entry
  171.  
  172.         cmp     eax, -1
  173.         je      .full
  174.  
  175.         pop     eax
  176.         call    ARP_create_request
  177.  
  178.         ret
  179.  
  180.   .found_it:
  181.         add    esi, ARP_ENTRY.MAC
  182.         DEBUGF 1,"Found MAC! (%x-%x-%x-%x-%x-%x)\n",[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2
  183.         movzx  eax, word [esi]
  184.         mov    ebx, [esi+2]
  185.  
  186.         ret
  187.  
  188.   .full:
  189.         add     esp, 4
  190.         mov     eax, -1
  191.         ret
  192.  
  193.  
  194. ;---------------------------------------------------------------------------
  195. ;
  196. ; ARP_create_packet
  197. ;
  198. ; IN:  ip in eax
  199. ;
  200. ; OUT: /
  201. ;
  202. ;---------------------------------------------------------------------------
  203. align 4
  204. ARP_create_request:
  205.  
  206.         DEBUGF 1,"Create ARP Packet\n"
  207.  
  208.         call    IPv4_dest_to_dev
  209.  
  210.         push    eax                                             ; DestIP
  211.         mov     eax, [IP_LIST+4*edi]                            ; senderIP
  212.         push    eax
  213.  
  214.         mov     edi, [ETH_DRV_LIST + 4*edi]
  215.         lea     eax, [edi + ETH_DEVICE.mac]
  216.         mov     ebx, ETH_BROADCAST
  217.         mov     ecx, 60 ; minimum packet size
  218.         mov     edx, edi ;;;
  219.         mov     di , ETHER_ARP
  220.         call    ETH_create_packet
  221.         cmp     edi, -1
  222.         je      .exit
  223.  
  224.         mov     ecx, eax
  225.  
  226.         mov     [edi + ARP_Packet.HardwareType], 0x0100 ;Ethernet
  227.         mov     [edi + ARP_Packet.ProtocolType], 0x0008 ;IP
  228.         mov     [edi + ARP_Packet.HardwareSize], 6   ;MAC-addr length
  229.         mov     [edi + ARP_Packet.ProtocolSize], 4   ;IP-addr length
  230.         mov     [edi + ARP_Packet.Opcode], ARP_REQ_OPCODE      ;Request
  231.  
  232.         add     edi, ARP_Packet.SenderMAC                       ; sendermac
  233.         lea     esi, [ebx + ETH_DEVICE.mac]                     ;
  234.         movsw                                                   ;
  235.         movsd                                                   ;
  236.         pop     eax                                             ;
  237.         stosd                                                   ;
  238.         mov     eax, -1                                         ; destmac
  239.         stosd                                                   ;
  240.         stosw                                                   ;
  241.         pop     eax
  242.         stosd                                                   ;
  243.  
  244.         DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
  245.  
  246.         push    edx ecx
  247.         jmp     ETH_sender
  248.  
  249.   .exit:
  250.         add     esp, 8
  251.         DEBUGF 1,"Create ARP Packet - failed\n"
  252.         mov     eax, -1
  253.         ret
  254.  
  255.  
  256.  
  257. ;---------------------------------------------------------------------------
  258. ;
  259. ; ARP_decrease_entry_ttls
  260. ;
  261. ; IN: /
  262. ; OUT: /
  263. ;
  264. ;---------------------------------------------------------------------------
  265. align 4
  266. ARP_decrease_entry_ttls:
  267.  
  268.         mov     ecx, [NumARP]
  269.         test    ecx, ecx
  270.         jz      .exit
  271.  
  272.         mov     ebx, ARPTable
  273.  
  274. .timer_loop:
  275.  
  276.         cmp     [ebx + ARP_ENTRY.TTL], 0xFFFF
  277.         je      .timer_loop_end  ;if TTL==0xFFFF then it's static entry
  278.  
  279.         cmp     [ebx + ARP_ENTRY.TTL], 0
  280.         jnz     .timer_loop_end_with_dec  ;if TTL!=0
  281.  
  282.         ; Ok, TTL is 0
  283.         ;if Status==AWAITING_RESPONSE and TTL==0
  284.         ;then we have to change it to ARP_RESPONSE_TIMEOUT
  285.         cmp     [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
  286.         jne     @f
  287.  
  288.         mov     [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
  289.         mov     [ebx + ARP_ENTRY.TTL], word 0x000A   ;10 sec
  290.         jmp     .timer_loop_end
  291.  
  292.   @@:
  293.         ;if TTL==0 and Status==VALID_MAPPING, we have to delete it
  294.         ;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too
  295.         mov     esi, [NumARP]
  296.         sub     esi, ecx          ;esi=index of entry, will be deleted
  297.  
  298.         push    ebx ecx
  299.         call    ARP_del_entry
  300.         pop     ecx ebx
  301.  
  302.         jmp     .timer_loop_end
  303.  
  304.  
  305. .timer_loop_end_with_dec:
  306.  
  307.         dec     [ebx + ARP_ENTRY.TTL]  ;decrease TTL
  308.  
  309. .timer_loop_end:
  310.  
  311.         add     ebx, ARP_ENTRY.size
  312.         loop    .timer_loop
  313.  
  314. .exit:
  315.  
  316.         ret
  317.  
  318. ;-----------------------------------------------------------------
  319. ;
  320. ; ARP_add_entry (or update)
  321. ;
  322. ; IN: arp entry in stack: esp     .IP
  323. ;                         esp+4   .MAC
  324. ;                         esp+10  .Status
  325. ;                         esp+12  .TTL
  326. ;                         esp+14
  327. ;
  328. ; OUT: eax = entry #, -1 on error
  329. ;
  330. ;-----------------------------------------------------------------   ; TODO: use a mutex
  331. align 4
  332. ARP_add_entry:
  333.  
  334.         DEBUGF 1,"ARP add entry: "
  335.  
  336.         mov     ecx, [NumARP]
  337.         test    ecx, ecx
  338.         jz      .add
  339.  
  340.         mov     eax, dword[esp + 4 + ARP_ENTRY.MAC]
  341.         mov     bx , word[esp + 4 + ARP_ENTRY.MAC + 4]
  342.         mov     esi, ARPTable
  343.  
  344. .loop:
  345.         cmp     dword [esi + ARP_ENTRY.MAC], eax
  346.         jne     .maybe_next
  347.         cmp     word [esi + ARP_ENTRY.MAC + 4], bx
  348.         jne     .maybe_next
  349.  
  350.         cmp     dword[esi + ARP_ENTRY.TTL], 0xFFFF ; static entry
  351.         jne     .notstatic
  352.         cmp     dword[esp + 4 + ARP_ENTRY.TTL], 0xFFFF
  353.         jne     .error
  354. .notstatic:
  355.  
  356.         mov     ebx, [NumARP]
  357.         xchg    ebx, ecx
  358.         sub     ecx, ebx
  359.         jmp     .add
  360.  
  361. .maybe_next:
  362.         add     esi, ARP_ENTRY.size
  363.         loop    .loop
  364.  
  365.         mov     ecx, [NumARP]
  366.         cmp     ecx, ARP_TABLE_SIZE
  367.         jge     .error
  368.  
  369. .add:
  370.         push    ecx
  371.         imul    ecx, ARP_ENTRY.size
  372.         lea     edi, [ecx + ARPTable]
  373.         lea     esi, [esp + 8]
  374.         mov     ecx, ARP_ENTRY.size/2
  375.         repz    movsw
  376.  
  377.         inc     [NumARP]
  378.         pop     eax
  379.  
  380. .exit:
  381.         DEBUGF 1,"Exiting\n"
  382.         ret     ARP_ENTRY.size
  383.  
  384. .error:
  385.  
  386.         DEBUGF 1,"error! \n"
  387.  
  388.         mov     eax, -1
  389.         jmp     .exit
  390.  
  391.  
  392. ;-----------------------------------------------------------------
  393. ;
  394. ; ARP_del_entry
  395. ;
  396. ; IN: entry # in esi
  397. ; OUT: /
  398. ;
  399. ;-----------------------------------------------------------------
  400. align 4
  401. ARP_del_entry:
  402.  
  403.         DEBUGF 1,"ARP del entry %u, total entrys: %u\n", esi, [NumARP]
  404.  
  405.         cmp     esi, [NumARP]
  406.         jge     .error
  407.  
  408.         DEBUGF 1,"deleting the entry..\n"
  409.  
  410.         imul    esi, ARP_ENTRY.size
  411.  
  412.         mov     ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY.size
  413.         sub     ecx, esi
  414.  
  415.         lea     edi, [ebx + esi]            ;edi=ptr to entry that should be deleted
  416.         lea     esi, [edi + ARP_ENTRY.size] ;esi=ptr to next entry
  417.  
  418.         shr     ecx,1      ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER!
  419.         rep     movsw
  420.  
  421.         dec     [NumARP] ;decrease arp-entries counter
  422. .error:
  423.         ret
  424.  
  425.  
  426.  
  427.  
  428. ;-----------------------------------------------------------------
  429. ;
  430. ; ARP_Handler:
  431. ;
  432. ;  This function handles ARP protocol over ethernet
  433. ;  (other protocols may follow in the future)
  434. ;
  435. ;  IN:  Pointer to buffer in [esp]
  436. ;       size of buffer in [esp+4]
  437. ;       packet size (without ethernet header) in ecx
  438. ;  OUT: /
  439. ;
  440. ;-----------------------------------------------------------------
  441. align 4
  442. ARP_handler:
  443.  
  444.         DEBUGF  1,"ARP_Handler - start\n"
  445.         cmp     ecx, 28
  446.         jl      .exit
  447.  
  448.         cmp     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE  ; Is this a reply packet?
  449.         jne     .maybe_request
  450.  
  451.         DEBUGF  1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\
  452.         [edx + ARP_Packet.SenderIP]:1,[edx + ARP_Packet.SenderIP+1]:1,[edx + ARP_Packet.SenderIP+2]:1,[edx + ARP_Packet.SenderIP+3]:1,
  453.  
  454.         mov     ecx, [NumARP]
  455.         test    ecx, ecx
  456.         jz      .exit
  457.  
  458.         mov     eax, [edx + ARP_Packet.SenderIP]
  459.         mov     esi, ARPTable+ARP_ENTRY.IP
  460.  
  461.   .loop:
  462.         cmp     [esi], eax
  463.         je      .gotit
  464.         add     esi, ARP_ENTRY.size
  465.         loop    .loop
  466.  
  467.         jmp     .exit
  468.  
  469.   .gotit:
  470.  
  471.         DEBUGF  1,"ARP_Handler - found matching entry\n"
  472.  
  473.         cmp     [esi+ARP_ENTRY.Status], 0x0300   ;if it is a static entry, dont touch it
  474.         je      .exit
  475.  
  476.         DEBUGF  1,"ARP_Handler - updating entry\n"
  477.  
  478.         mov     [esi+ARP_ENTRY.Status], ARP_VALID_MAPPING
  479.         mov     [esi+ARP_ENTRY.TTL], ARP_ENTRY_TTL
  480.  
  481.         mov     eax, dword [edx + ARP_Packet.SenderMAC]
  482.         mov     dword [esi+ARP_ENTRY.MAC], eax
  483.         mov     ax , word [edx + ARP_Packet.SenderMAC + 4]
  484.         mov     word [esi+ARP_ENTRY.MAC+4], ax
  485.  
  486.         jmp     .exit
  487.  
  488.  
  489. ;------
  490.  
  491.  
  492.   .maybe_request:
  493.         cmp     word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE  ; Is this a request packet?
  494.         jne     .exit
  495.  
  496.         call    ETH_struc2dev
  497.         DEBUGF  1,"ARP Request packet through device: %u\n", edi
  498.         inc     [ARP_PACKETS_RX+4*edi]
  499.         cmp     edi, -1
  500.         jz      .exit
  501.  
  502.         mov     eax, edi
  503.         shl     eax, 2
  504.         add     eax, IP_LIST
  505.         mov     eax, [eax]
  506.         cmp     eax, [edx + ARP_Packet.TargetIP]                ; Is it looking for my IP address?
  507.         jnz     .exit
  508.         push    eax
  509.         push    edi
  510.  
  511. ; OK, it is a request for one of our MAC addresses. Build the frame and send it
  512. ; We can reuse the buffer.  (faster then using ARP_create_packet)
  513.  
  514.         cld
  515.         lea     esi, [edx + ARP_Packet.SenderMAC]
  516.         lea     edi, [edx + ARP_Packet.TargetMAC]
  517.         movsd                                                   ; Move Sender Mac to Dest MAC
  518.         movsw                                                   ;
  519.         movsd                                                   ; Move sender IP to Dest IP
  520.  
  521.         pop     esi
  522.         mov     esi, [ETH_DRV_LIST + 4*esi]
  523.         lea     esi, [esi + ETH_DEVICE.mac]
  524.         lea     edi, [edx + ARP_Packet.SenderMAC]
  525.         movsd                                                   ; Copy MAC address from in MAC_LIST
  526.         movsw                                                   ;
  527.         pop     eax
  528.         stosd                                                   ; Write our IP
  529.  
  530.         mov     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE
  531.  
  532. ; Now, Fill in ETHERNET header
  533.  
  534.         mov     edi, [esp]
  535.         lea     esi, [edx + ARP_Packet.TargetMAC]
  536.         movsd
  537.         movsw
  538.         lea     esi, [edx + ARP_Packet.SenderMAC]
  539.         movsd
  540.         movsw
  541. ;        mov     ax , ETHER_ARP
  542. ;        stosw
  543.  
  544.         DEBUGF  1,"ARP_Handler - Sending reply \n"
  545.  
  546.         jmp     ETH_sender                                      ; And send it!
  547.  
  548.      .exit:
  549.         call    kernel_free
  550.         add     esp, 4                                          ; pop (balance stack)
  551.  
  552.         DEBUGF 1,"ARP_Handler - exiting\n"
  553.         ret
  554.  
  555.  
  556.  
  557.  
  558. ;-----------------------------------------------------------------
  559. ;
  560. ; ARP_API
  561. ;
  562. ; This function is called by system function 75
  563. ;
  564. ; IN:  subfunction number in bl
  565. ;      device number in bh
  566. ;      ecx, edx, .. depends on subfunction
  567. ;
  568. ; OUT:  ?
  569. ;
  570. ;-----------------------------------------------------------------
  571. align 4
  572. ARP_API:
  573.  
  574.         movzx   eax, bh
  575.         shl     eax, 2
  576.  
  577.         test    bl, bl
  578.         jz      .packets_tx     ; 0
  579.         dec     bl
  580.         jz      .packets_rx     ; 1
  581.         dec     bl
  582.         jz      .entries        ; 2
  583.         dec     bl
  584.         jz      .read           ; 3
  585.         dec     bl
  586.         jz      .write          ; 4
  587.         dec     bl
  588.         jz      .remove         ; 5
  589.         dec     bl
  590.  
  591. .error:
  592.         mov     eax, -1
  593.         ret
  594.  
  595. .packets_tx:
  596.         add     eax, ARP_PACKETS_TX
  597.         mov     eax, [eax]
  598.         ret
  599.  
  600. .packets_rx:
  601.         add     eax, ARP_PACKETS_RX
  602.         mov     eax, [eax]
  603.         ret
  604.  
  605. .entries:
  606.         mov     eax, [NumARP]
  607.         ret
  608.  
  609. .read:
  610.         cmp     ecx, [NumARP]
  611.         jge     .error
  612.         ; edi = pointer to buffer
  613.         ; ecx = # entry
  614.         imul    ecx, ARP_ENTRY.size
  615.         add     ecx, ARPTable
  616.         mov     esi, ecx
  617.         mov     ecx, ARP_ENTRY.size/2
  618.         rep     movsw
  619.  
  620.         xor     eax, eax
  621.         ret
  622.  
  623. .write:
  624.         ; esi = pointer to buffer
  625.         sub     esp, ARP_ENTRY.size
  626.         mov     edi, esp
  627.         mov     ecx, ARP_ENTRY.size/2
  628.         rep     movsw
  629.         call    ARP_add_entry        ;out: eax = entry number, -1 on error
  630.         ret
  631.  
  632. .remove:
  633.         ; ecx = # entry
  634.         mov     esi, ecx
  635.         call    ARP_del_entry
  636.         ret
  637.  
  638.