Subversion Repositories Kolibri OS

Rev

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