Subversion Repositories Kolibri OS

Rev

Rev 2301 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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