Subversion Repositories Kolibri OS

Rev

Rev 1196 | 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: 983 $
  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           = 30 ; 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.         mov     ecx, eax
  139.         and     ecx, [SUBNET_LIST+edx]
  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.         jz      .not_in_list
  150.         mov     esi, ARPTable + ARP_ENTRY.IP
  151.   .scan_loop:
  152.         scasd
  153.         jz      .found_it
  154.         add     esi, ARP_ENTRY.size - 4
  155.         loop    .scan_loop
  156.   .not_in_list:
  157.  
  158.         DEBUGF 1,"IP not found on list, preparing for ARP request\n"
  159.  
  160.    ; if not, reserve an entry in list and send an ARP request packet
  161.  
  162.         push    eax
  163.  
  164.         push    word ARP_REQUEST_TTL
  165.         push    word ARP_AWAITING_RESPONSE
  166.         push    dword 0
  167.         push    word 0
  168.         push    eax
  169.         call    ARP_add_entry
  170.  
  171.         cmp     eax, -1
  172.         je      .full
  173.  
  174.         pop     eax
  175.         call    ARP_create_request
  176.  
  177.         ret
  178.  
  179.   .found_it:
  180.         DEBUGF 1,"Found MAC! (%u-%u-%u-%u-%u-%u)\n",[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2
  181.         movzx  eax, word [esi]
  182.         mov    ebx, [esi+2]
  183.  
  184.         ret
  185.  
  186.   .full:
  187.         add     esp, 4
  188.         mov     eax, -1
  189.         ret
  190.  
  191.  
  192. ;---------------------------------------------------------------------------
  193. ;
  194. ; ARP_create_packet
  195. ;
  196. ; IN:  ip in eax
  197. ;
  198. ; OUT: /
  199. ;
  200. ;---------------------------------------------------------------------------
  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     word [edi + ARP_Packet.HardwareType], 0x0100 ;Ethernet
  225.         mov     word [edi + ARP_Packet.ProtocolType], 0x0008 ;IP
  226.         mov     byte [edi + ARP_Packet.HardwareSize], 6   ;MAC-addr length
  227.         mov     byte [edi + ARP_Packet.ProtocolSize], 4   ;IP-addr length
  228.         mov     word [edi + ARP_Packet.Opcode], ARP_REQ_OPCODE      ;Request
  229.  
  230.         add     edi, ARP_Packet.SenderMAC                       ; sendermac
  231.         lea     esi, [edx + ETH_DEVICE.mac]                     ;
  232.         movsw                                                   ;
  233.         movsd                                                   ;
  234.  
  235.         pop     eax
  236.         stosd                                                   ;
  237.  
  238.         xor     eax, eax                                        ; destmac
  239.         movsw                                                   ;
  240.         movsw                                                   ;
  241.  
  242.         pop     eax
  243.         movsd                                                   ;
  244.  
  245.         DEBUGF 1,"ARP Packet for device %x created successfully\n", edx
  246.  
  247.         call    esi
  248.  
  249.         inc     [ARP_PACKETS_TX+4*edi]
  250.  
  251.         ret
  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.         movsx   esi, word [ebx + ARP_ENTRY.TTL]
  282.         cmp     esi, 0xFFFFFFFF
  283.         je      .timer_loop_end  ;if TTL==0xFFFF then it's static entry
  284.  
  285.         test    esi, esi
  286.         jnz     .timer_loop_end_with_dec  ;if TTL!=0
  287.  
  288.         ; Ok, TTL is 0
  289.         ;if Status==AWAITING_RESPONSE and TTL==0
  290.         ;then we have to change it to ARP_RESPONSE_TIMEOUT
  291.         cmp     word [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
  292.         jne     @f
  293.  
  294.         mov     word [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
  295.         mov     word [ebx + ARP_ENTRY.TTL], word 0x000A   ;10 sec
  296.         jmp     .timer_loop_end
  297.  
  298.   @@:
  299.         ;if TTL==0 and Status==VALID_MAPPING, we have to delete it
  300.         ;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too
  301.         mov     esi, dword[NumARP]
  302.         sub     esi, ecx          ;esi=index of entry, will be deleted
  303.  
  304.         call    ARP_del_entry
  305.  
  306.         jmp     .timer_loop_end
  307.  
  308.  
  309. .timer_loop_end_with_dec:
  310.  
  311.         dec     word [ebx + ARP_ENTRY.TTL]  ;decrease TTL
  312.  
  313. .timer_loop_end:
  314.  
  315.         add     ebx, ARP_ENTRY.size
  316.         loop    .timer_loop
  317.  
  318. .exit:
  319.  
  320.         ret
  321.  
  322. ;---------------------------------------------------------------------------
  323. ;
  324. ; ARP_add_entry (or update)
  325. ;
  326. ; IN: arp entry in stack: esp     .IP
  327. ;                         esp+4   .MAC
  328. ;                         esp+10  .Status
  329. ;                         esp+12  .TTL
  330. ;                         esp+14
  331. ;
  332. ; OUT: eax = entry #, -1 on error
  333. ;
  334. ;---------------------------------------------------------------------------
  335.  
  336. ; TODO: use a mutex
  337.  
  338. align 4
  339. ARP_add_entry:
  340.  
  341.         mov     ecx, [NumARP]
  342.         test    ecx, ecx
  343.         jz      .add
  344.  
  345.         mov     eax, dword[esp + ARP_ENTRY.MAC]
  346.         mov     bx , word[esp + ARP_ENTRY.MAC + 4]
  347.         mov     esi, ARPTable
  348.  
  349. .loop:
  350.         cmp     dword [esi + ARP_ENTRY.MAC], eax
  351.         jne     .maybe_next
  352.         cmp     word [esi + ARP_ENTRY.MAC + 4], bx
  353.         jne     .maybe_next
  354.  
  355.         cmp     dword[esi + ARP_ENTRY.TTL], 0xFFFF ; static entry
  356.         jne     .notstatic
  357.         cmp     dword[esp + ARP_ENTRY.TTL], 0xFFFF
  358.         jne     .exit
  359. .notstatic:
  360.  
  361.         mov     ebx, [NumARP]
  362.         xchg    ebx, ecx
  363.         sub     ecx, ebx
  364.         jmp     .add
  365.  
  366. .maybe_next:
  367.         add     esi, ARP_ENTRY.size
  368.         loop    .loop
  369.  
  370.         mov     ecx, [NumARP]
  371.         cmp     ecx, ARP_TABLE_SIZE
  372.         jge     .full
  373.  
  374. .add:
  375.  
  376.         push    ecx
  377.         imul    ecx, ARP_ENTRY.size
  378.         lea     edi, [ecx + ARPTable]
  379.         lea     esi, [esp + 4]
  380.         mov     ecx, ARP_ENTRY.size/2
  381.         repz    movsw
  382.  
  383.         inc     [NumARP]
  384.         pop     eax
  385.  
  386. .exit:
  387.  
  388.         add     esp, 14
  389.         ret
  390.  
  391. .full:
  392.  
  393.         mov     eax, -1
  394.         jmp     .exit
  395.  
  396.  
  397.  
  398. ;---------------------------------------------------------------------------
  399. ;
  400. ; ARP_del_entry
  401. ;
  402. ; IN: entry # in esi
  403. ; OUT: /
  404. ;
  405. ;---------------------------------------------------------------------------
  406.  
  407. align 4
  408. ARP_del_entry:
  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.         cld
  420.         rep     movsw
  421.  
  422.         dec     [NumARP] ;decrease arp-entries counter
  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.  
  442. align 4
  443. ARP_handler:
  444.  
  445.         DEBUGF  1,"ARP_Handler - start\n"
  446.         cmp     ecx, 28
  447.         jl      .exit
  448.  
  449.         cmp     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE  ; Is this a reply packet?
  450.         jne     .maybe_request
  451.  
  452.         mov     ecx, [NumARP]
  453.         test    ecx, ecx
  454.         jz      .exit
  455.  
  456.         mov     eax, [esp]
  457.         mov     eax, [eax + ARP_Packet.SenderIP]
  458.         mov     esi, ARPTable+ARP_ENTRY.IP
  459.  
  460.   .loop:
  461.         scasd
  462.         jz      .gotit
  463.         add     esi, ARP_ENTRY.size-4
  464.         loop    .loop
  465.  
  466.         jmp     .exit
  467.  
  468.   .gotit:
  469.         cmp     [esi-4+ARP_ENTRY.Status], 0x0300   ;if it is a static entry, dont touch it
  470.         je      .exit
  471.  
  472.         mov     [esi-4+ARP_ENTRY.Status], ARP_VALID_MAPPING
  473.         mov     [esi+ARP_ENTRY.TTL-4], ARP_ENTRY_TTL
  474.  
  475.         mov     ebx, [esp]
  476.         mov     eax, dword [ebx + ARP_Packet.SenderMAC]
  477.         mov     dword [esi+ARP_ENTRY.MAC-4], eax
  478.         mov     ax , word [ebx + ARP_Packet.SenderMAC + 4]
  479.         mov     word [esi+ARP_ENTRY.MAC-4+4], ax
  480.  
  481.         jmp     .exit
  482.  
  483.  
  484. ;------
  485.  
  486.  
  487.   .maybe_request:
  488.         cmp     word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE  ; Is this a request packet?
  489.         jne     .exit
  490.  
  491.         call    ETH_struc2dev
  492.         DEBUGF  1,"ARP Packet came from device: %u\n", edi
  493.         inc     [ARP_PACKETS_RX+4*edi]
  494.         cmp     edi, -1
  495.         jz      .exit
  496.  
  497.         mov     eax, edi
  498.         shl     eax, 2
  499.         add     eax, IP_LIST
  500.         mov     eax, [eax]
  501.         cmp     eax, [edx + ARP_Packet.TargetIP]                ; Is it looking for my IP address?
  502.         jnz     .exit
  503.         push    eax
  504.         push    edi
  505.  
  506. ; OK, it is a request for one of our MAC addresses. Build the frame and send it
  507. ; We can reuse the buffer.  (faster then using ARP_create_packet)
  508.  
  509.         cld
  510.         lea     esi, [edx + ARP_Packet.SenderMAC]
  511.         lea     edi, [edx + ARP_Packet.TargetMAC]
  512.         movsd                                                   ; Move Sender Mac to Dest MAC
  513.         movsw                                                   ;
  514.         movsd                                                   ; Move sender IP to Dest IP
  515.  
  516.         pop     esi
  517.         mov     esi, [ETH_DRV_LIST + 4*esi]
  518.         lea     esi, [esi + ETH_DEVICE.mac]
  519.         lea     edi, [edx + ARP_Packet.SenderMAC]
  520.         movsd                                                   ; Copy MAC address from in MAC_LIST
  521.         movsw                                                   ;
  522.         pop     eax
  523.         stosd                                                   ; Write our IP
  524.  
  525.         mov     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE
  526.  
  527. ; Now, Fill in ETHERNET header
  528.  
  529.         mov     edi, [esp]
  530.         lea     esi, [edx + ARP_Packet.TargetMAC]
  531.         movsd
  532.         movsw
  533.         lea     esi, [edx + ARP_Packet.SenderMAC]
  534.         movsd
  535.         movsw
  536. ;        mov     ax , ETHER_ARP
  537. ;        stosw
  538.  
  539.         jmp     ETH_Sender                                      ; And send it!
  540.  
  541.      .exit:
  542.         call    kernel_free
  543.         add     esp, 4                                          ; pop (balance stack)
  544.  
  545.         DEBUGF 1,"ARP_Handler - fail\n"
  546.         ret
  547.  
  548.  
  549.  
  550.  
  551. ;---------------------------------------------------------------------------
  552. ;
  553. ; ARP_API
  554. ;
  555. ; This function is called by system function 75
  556. ;
  557. ; IN:  subfunction number in bl
  558. ;      device number in bh
  559. ;      ecx, edx, .. depends on subfunction
  560. ;
  561. ; OUT:
  562. ;
  563. ;---------------------------------------------------------------------------
  564.  
  565. align 4
  566. ARP_API:
  567.  
  568.         movzx   eax, bh
  569.         shl     eax, 2
  570.  
  571.         test    bl, bl
  572.         jz      .packets_tx     ; 0
  573.         dec     bl
  574.         jz      .packets_rx     ; 1
  575.         dec     bl
  576.         jz      .entries        ; 2
  577.         dec     bl
  578.         jz      .read           ; 3
  579.         dec     bl
  580.         jz      .write          ; 4
  581.         dec     bl
  582.         jz      .remove         ; 5
  583.         dec     bl
  584.  
  585. .error:
  586.         mov     eax, -1
  587.         ret
  588.  
  589. .packets_tx:
  590.         add     eax, ARP_PACKETS_TX
  591.         mov     eax, [eax]
  592.         ret
  593.  
  594. .packets_rx:
  595.         add     eax, ARP_PACKETS_RX
  596.         mov     eax, [eax]
  597.         ret
  598.  
  599. .entries:
  600.         mov     eax, [NumARP]
  601.         ret
  602.  
  603. .read:
  604.         cmp     ecx, [NumARP]
  605.         jge     .error
  606.         ; edi = pointer to buffer
  607.         ; ecx = # entry
  608.         imul    ecx, ARP_ENTRY.size
  609.         add     ecx, ARPTable
  610.         mov     esi, ecx
  611.         mov     ecx, ARP_ENTRY.size/2
  612.         rep     movsw
  613.  
  614.         xor     eax, eax
  615.         ret
  616.  
  617. .write:
  618.         ; esi = pointer to buffer
  619.         sub     esp, ARP_ENTRY.size
  620.         mov     edi, esp
  621.         mov     ecx, ARP_ENTRY.size/2
  622.         rep     movsw
  623.         jmp     ARP_add_entry        ;out: eax = entry number, -1 on error
  624.  
  625. .remove:
  626.         ; ecx = # entry
  627.         mov     esi, ecx
  628.         call    ARP_del_entry
  629.         ret
  630.  
  631.