Subversion Repositories Kolibri OS

Rev

Rev 1200 | 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: 1206 $
  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 + ARP_ENTRY.MAC]
  349.         mov     bx , word[esp + 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 + 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.         pop     ebx    ; return addr
  390.         add     esp, ARP_ENTRY.size
  391.         DEBUGF 1,"Exiting\n"
  392.         jmp     ebx
  393.  
  394. .error:
  395.  
  396.         DEBUGF 1,"error! \n"
  397.  
  398.         mov     eax, -1
  399.         jmp     .exit
  400.  
  401.  
  402. ;---------------------------------------------------------------------------
  403. ;
  404. ; ARP_del_entry
  405. ;
  406. ; IN: entry # in esi
  407. ; OUT: /
  408. ;
  409. ;---------------------------------------------------------------------------
  410.  
  411. align 4
  412. ARP_del_entry:
  413.  
  414.         DEBUGF 1,"ARP del entry %u, total entrys: %u\n", esi, [NumARP]
  415.  
  416.         cmp     esi, [NumARP]
  417.         jge     .error
  418.  
  419.         DEBUGF 1,"deleting the entry..\n"
  420.  
  421.         imul    esi, ARP_ENTRY.size
  422.  
  423.         mov     ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY.size
  424.         sub     ecx, esi
  425.  
  426.         lea     edi, [ebx + esi]            ;edi=ptr to entry that should be deleted
  427.         lea     esi, [edi + ARP_ENTRY.size] ;esi=ptr to next entry
  428.  
  429.         shr     ecx,1      ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER!
  430.         rep     movsw
  431.  
  432.         dec     [NumARP] ;decrease arp-entries counter
  433. .error:
  434.         ret
  435.  
  436.  
  437.  
  438.  
  439. ;-----------------------------------------------------
  440. ;
  441. ; ARP_Handler:
  442. ;
  443. ;  This function handles ARP protocol over ethernet
  444. ;  (other protocols may follow in the future)
  445. ;
  446. ;  IN:  Pointer to buffer in [esp]
  447. ;       size of buffer in [esp+4]
  448. ;       packet size (without ethernet header) in ecx
  449. ;  OUT: /
  450. ;
  451. ;-----------------------------------------------------
  452.  
  453. align 4
  454. ARP_handler:
  455.  
  456.         DEBUGF  1,"ARP_Handler - start\n"
  457.         cmp     ecx, 28
  458.         jl      .exit
  459.  
  460.         cmp     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE  ; Is this a reply packet?
  461.         jne     .maybe_request
  462.  
  463.         DEBUGF  1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\
  464.         [edx + ARP_Packet.SenderIP]:1,[edx + ARP_Packet.SenderIP+1]:1,[edx + ARP_Packet.SenderIP+2]:1,[edx + ARP_Packet.SenderIP+3]:1,
  465.  
  466.         mov     ecx, [NumARP]
  467.         test    ecx, ecx
  468.         jz      .exit
  469.  
  470.         mov     eax, [edx + ARP_Packet.SenderIP]
  471.         mov     esi, ARPTable+ARP_ENTRY.IP
  472.  
  473.   .loop:
  474.         cmp     [esi], eax
  475.         je      .gotit
  476.         add     esi, ARP_ENTRY.size
  477.         loop    .loop
  478.  
  479.         jmp     .exit
  480.  
  481.   .gotit:
  482.  
  483.         DEBUGF  1,"ARP_Handler - found matching entry\n"
  484.  
  485.         cmp     [esi+ARP_ENTRY.Status], 0x0300   ;if it is a static entry, dont touch it
  486.         je      .exit
  487.  
  488.         DEBUGF  1,"ARP_Handler - updating entry\n"
  489.  
  490.         mov     [esi+ARP_ENTRY.Status], ARP_VALID_MAPPING
  491.         mov     [esi+ARP_ENTRY.TTL], ARP_ENTRY_TTL
  492.  
  493.         mov     eax, dword [edx + ARP_Packet.SenderMAC]
  494.         mov     dword [esi+ARP_ENTRY.MAC], eax
  495.         mov     ax , word [edx + ARP_Packet.SenderMAC + 4]
  496.         mov     word [esi+ARP_ENTRY.MAC+4], ax
  497.  
  498.         jmp     .exit
  499.  
  500.  
  501. ;------
  502.  
  503.  
  504.   .maybe_request:
  505.         cmp     word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE  ; Is this a request packet?
  506.         jne     .exit
  507.  
  508.         call    ETH_struc2dev
  509.         DEBUGF  1,"ARP Request packet through device: %u\n", edi
  510.         inc     [ARP_PACKETS_RX+4*edi]
  511.         cmp     edi, -1
  512.         jz      .exit
  513.  
  514.         mov     eax, edi
  515.         shl     eax, 2
  516.         add     eax, IP_LIST
  517.         mov     eax, [eax]
  518.         cmp     eax, [edx + ARP_Packet.TargetIP]                ; Is it looking for my IP address?
  519.         jnz     .exit
  520.         push    eax
  521.         push    edi
  522.  
  523. ; OK, it is a request for one of our MAC addresses. Build the frame and send it
  524. ; We can reuse the buffer.  (faster then using ARP_create_packet)
  525.  
  526.         cld
  527.         lea     esi, [edx + ARP_Packet.SenderMAC]
  528.         lea     edi, [edx + ARP_Packet.TargetMAC]
  529.         movsd                                                   ; Move Sender Mac to Dest MAC
  530.         movsw                                                   ;
  531.         movsd                                                   ; Move sender IP to Dest IP
  532.  
  533.         pop     esi
  534.         mov     esi, [ETH_DRV_LIST + 4*esi]
  535.         lea     esi, [esi + ETH_DEVICE.mac]
  536.         lea     edi, [edx + ARP_Packet.SenderMAC]
  537.         movsd                                                   ; Copy MAC address from in MAC_LIST
  538.         movsw                                                   ;
  539.         pop     eax
  540.         stosd                                                   ; Write our IP
  541.  
  542.         mov     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE
  543.  
  544. ; Now, Fill in ETHERNET header
  545.  
  546.         mov     edi, [esp]
  547.         lea     esi, [edx + ARP_Packet.TargetMAC]
  548.         movsd
  549.         movsw
  550.         lea     esi, [edx + ARP_Packet.SenderMAC]
  551.         movsd
  552.         movsw
  553. ;        mov     ax , ETHER_ARP
  554. ;        stosw
  555.  
  556.         DEBUGF  1,"ARP_Handler - Sending reply \n"
  557.  
  558.         jmp     ETH_Sender                                      ; And send it!
  559.  
  560.      .exit:
  561.         call    kernel_free
  562.         add     esp, 4                                          ; pop (balance stack)
  563.  
  564.         DEBUGF 1,"ARP_Handler - exiting\n"
  565.         ret
  566.  
  567.  
  568.  
  569.  
  570. ;---------------------------------------------------------------------------
  571. ;
  572. ; ARP_API
  573. ;
  574. ; This function is called by system function 75
  575. ;
  576. ; IN:  subfunction number in bl
  577. ;      device number in bh
  578. ;      ecx, edx, .. depends on subfunction
  579. ;
  580. ; OUT:
  581. ;
  582. ;---------------------------------------------------------------------------
  583.  
  584. align 4
  585. ARP_API:
  586.  
  587.         movzx   eax, bh
  588.         shl     eax, 2
  589.  
  590.         test    bl, bl
  591.         jz      .packets_tx     ; 0
  592.         dec     bl
  593.         jz      .packets_rx     ; 1
  594.         dec     bl
  595.         jz      .entries        ; 2
  596.         dec     bl
  597.         jz      .read           ; 3
  598.         dec     bl
  599.         jz      .write          ; 4
  600.         dec     bl
  601.         jz      .remove         ; 5
  602.         dec     bl
  603.  
  604. .error:
  605.         mov     eax, -1
  606.         ret
  607.  
  608. .packets_tx:
  609.         add     eax, ARP_PACKETS_TX
  610.         mov     eax, [eax]
  611.         ret
  612.  
  613. .packets_rx:
  614.         add     eax, ARP_PACKETS_RX
  615.         mov     eax, [eax]
  616.         ret
  617.  
  618. .entries:
  619.         mov     eax, [NumARP]
  620.         ret
  621.  
  622. .read:
  623.         cmp     ecx, [NumARP]
  624.         jge     .error
  625.         ; edi = pointer to buffer
  626.         ; ecx = # entry
  627.         imul    ecx, ARP_ENTRY.size
  628.         add     ecx, ARPTable
  629.         mov     esi, ecx
  630.         mov     ecx, ARP_ENTRY.size/2
  631.         rep     movsw
  632.  
  633.         xor     eax, eax
  634.         ret
  635.  
  636. .write:
  637.         ; esi = pointer to buffer
  638.         sub     esp, ARP_ENTRY.size
  639.         mov     edi, esp
  640.         mov     ecx, ARP_ENTRY.size/2
  641.         rep     movsw
  642.         jmp     ARP_add_entry        ;out: eax = entry number, -1 on error
  643.  
  644. .remove:
  645.         ; ecx = # entry
  646.         mov     esi, ecx
  647.         call    ARP_del_entry
  648.         ret
  649.  
  650.