Subversion Repositories Kolibri OS

Rev

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