Subversion Repositories Kolibri OS

Rev

Rev 1530 | 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: 1533 $
  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.         loop    .loop
  126.         jmp     .exit
  127.  
  128.   .time_out:
  129.         cmp     [esi + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
  130.         jz      .response_timeout
  131.  
  132.         push    esi ecx
  133.         call    ARP_del_entry
  134.         pop     ecx esi
  135.  
  136.         jmp     .next
  137.  
  138.   .response_timeout:
  139.         mov     [esi + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
  140.         mov     [esi + ARP_ENTRY.TTL], 10
  141.  
  142.         jmp     .next
  143.  
  144.   .exit:
  145.  
  146. }
  147.  
  148.  
  149. ;-----------------------------------------------------------------
  150. ;
  151. ; ARP_input
  152. ;
  153. ;  IN:  Pointer to buffer in [esp]
  154. ;       size of buffer in [esp+4]
  155. ;       packet size (without ethernet header) in ecx
  156. ;  OUT: /
  157. ;
  158. ;-----------------------------------------------------------------
  159. align 4
  160. ARP_input:
  161.  
  162.         DEBUGF  1,"ARP_Handler - start\n"
  163.         cmp     ecx, 28
  164.         jl      .exit
  165.  
  166. ;---------------------
  167. ; Handle Reply packets
  168.  
  169.         cmp     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE
  170.         jne     .maybe_request
  171.  
  172.         DEBUGF  1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\
  173.         [edx + ARP_Packet.SenderIP]:1,[edx + ARP_Packet.SenderIP+1]:1,[edx + ARP_Packet.SenderIP+2]:1,[edx + ARP_Packet.SenderIP+3]:1,
  174.  
  175.         mov     ecx, [NumARP]
  176.         test    ecx, ecx
  177.         jz      .exit
  178.  
  179.         mov     eax, [edx + ARP_Packet.SenderIP]
  180.         mov     esi, ARP_table
  181.  
  182.   .loop:
  183.         cmp     [esi + ARP_ENTRY.IP], eax
  184.         je      .gotit
  185.         add     esi, ARP_ENTRY.size
  186.         loop    .loop
  187.  
  188.         jmp     .exit
  189.  
  190.   .gotit:
  191.         DEBUGF  1,"ARP_Handler - found matching entry\n"
  192.  
  193.         cmp     [esi+ARP_ENTRY.TTL], 0xffff             ; if it is a static entry, dont touch it
  194.         je      .exit
  195.  
  196.         DEBUGF  1,"ARP_Handler - updating entry\n"
  197.  
  198.         mov     [esi+ARP_ENTRY.Status], ARP_VALID_MAPPING
  199.         mov     [esi+ARP_ENTRY.TTL], ARP_ENTRY_TTL
  200.  
  201.         mov     eax, dword [edx + ARP_Packet.SenderMAC]
  202.         mov     dword [esi+ARP_ENTRY.MAC], eax
  203.         mov     ax , word [edx + ARP_Packet.SenderMAC + 4]
  204.         mov     word [esi+ARP_ENTRY.MAC+4], ax
  205.  
  206.         jmp     .exit
  207.  
  208.  
  209. ;-----------------------
  210. ; Handle Request packets
  211.  
  212.   .maybe_request:
  213.         cmp     word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE
  214.         jne     .exit
  215.  
  216.         call    NET_ptr_to_num
  217.         cmp     edi, -1
  218.         jz      .exit
  219.         DEBUGF  1,"ARP Request packet through device: %u\n", edi
  220.         inc     [ARP_PACKETS_RX+4*edi]
  221.  
  222.         mov     eax, [IP_LIST+4*edi]
  223.         cmp     eax, [edx + ARP_Packet.TargetIP]                ; Is it looking for my IP address?
  224.         jne     .exit                                           ; TODO: instead of quitting, update local entrys with matching IP's ?
  225.  
  226.         push    eax
  227.         push    edi
  228.  
  229. ; OK, it is a request for one of our MAC addresses.
  230. ; Build the frame and send it. We can reuse the buffer.  (faster then using ARP_create_packet)
  231.  
  232.         lea     esi, [edx + ARP_Packet.SenderMAC]
  233.         lea     edi, [edx + ARP_Packet.TargetMAC]
  234.         movsd                                                   ; Move Sender Mac to Dest MAC
  235.         movsw                                                   ;
  236.         movsd                                                   ; Move sender IP to Dest IP
  237.  
  238.         pop     esi
  239.         mov     esi, [NET_DRV_LIST + 4*esi]
  240.         lea     esi, [esi + ETH_DEVICE.mac]
  241.         lea     edi, [edx + ARP_Packet.SenderMAC]
  242.         movsd                                                   ; Copy MAC address from in MAC_LIST
  243.         movsw                                                   ;
  244.         pop     eax
  245.         stosd                                                   ; Write our IP
  246.  
  247.         mov     word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE
  248.  
  249. ; Now, Fill in ETHERNET header
  250.  
  251.         mov     edi, [esp]
  252.         lea     esi, [edx + ARP_Packet.TargetMAC]
  253.         movsd
  254.         movsw
  255.         lea     esi, [edx + ARP_Packet.SenderMAC]
  256.         movsd
  257.         movsw
  258. ;        mov     ax , ETHER_ARP
  259. ;        stosw
  260.  
  261.         DEBUGF  1,"ARP_Handler - Sending reply \n"
  262.  
  263.         call    [ebx + NET_DEVICE.transmit]
  264.         ret
  265.  
  266.      .exit:
  267.         call    kernel_free
  268.         add     esp, 4                                          ; pop (balance stack)
  269.  
  270.         DEBUGF  1,"ARP_Handler - exiting\n"
  271.         ret
  272.  
  273.  
  274. ;---------------------------------------------------------------------------
  275. ;
  276. ; ARP_output_request
  277. ;
  278. ; IN:  ip in eax
  279. ; OUT: /
  280. ;
  281. ;---------------------------------------------------------------------------
  282. align 4
  283. ARP_output_request:
  284.  
  285.         DEBUGF 1,"Create ARP Packet\n"
  286.  
  287.         call    IPv4_dest_to_dev
  288.         push    eax                             ; DestIP
  289.         pushd   [IP_LIST+edi]                   ; SenderIP
  290.  
  291.         mov     ebx, [NET_DRV_LIST+edi]         ; device ptr
  292.  
  293.         lea     eax, [ebx + ETH_DEVICE.mac]     ; local device mac
  294.         mov     edx, ETH_BROADCAST              ; broadcast mac
  295.         mov     ecx, ARP_Packet.size
  296.         mov     di, ETHER_ARP
  297.         call    ETH_output
  298.         jz      .exit
  299.  
  300.         mov     ecx, eax
  301.  
  302.         mov     [edi + ARP_Packet.HardwareType], 0x0100         ; Ethernet
  303.         mov     [edi + ARP_Packet.ProtocolType], 0x0008         ; IP
  304.         mov     [edi + ARP_Packet.HardwareSize], 6              ; MAC-addr length
  305.         mov     [edi + ARP_Packet.ProtocolSize], 4              ; IP-addr length
  306.         mov     [edi + ARP_Packet.Opcode], ARP_REQ_OPCODE       ; Request
  307.  
  308.         add     edi, ARP_Packet.SenderMAC
  309.  
  310.         lea     esi, [ebx + ETH_DEVICE.mac]     ; SenderMac
  311.         movsw                                   ;
  312.         movsd                                   ;
  313.         pop     eax                             ; SenderIP
  314.         stosd                                   ;
  315.  
  316.         mov     eax, -1                         ; DestMac
  317.         stosd                                   ;
  318.         stosw                                   ;
  319.         pop     eax                             ; DestIP
  320.         stosd                                   ;
  321.  
  322.         DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
  323.  
  324.         push    edx ecx
  325.         call    [ebx + NET_DEVICE.transmit]
  326.         ret
  327.  
  328.   .exit:
  329.         add     esp, 4+4
  330.         DEBUGF  1,"Create ARP Packet - failed\n"
  331.         sub     eax, eax
  332.         ret
  333.  
  334.  
  335. ;-----------------------------------------------------------------
  336. ;
  337. ; ARP_add_entry (or update)
  338. ;
  339. ; IN:  esi = ptr to entry (can easily be made on the stack)
  340. ; OUT: eax = entry #, -1 on error
  341. ;
  342. ;-----------------------------------------------------------------   ; TODO: use a mutex
  343. align 4
  344. ARP_add_entry:
  345.  
  346.         DEBUGF 1,"ARP add entry: "
  347.  
  348.         mov     ecx, [NumARP]
  349.         test    ecx, ecx                ; first entry?
  350.         jz      .add
  351.         cmp     ecx, ARP_TABLE_SIZE     ; list full ?
  352.         jge     .error
  353.  
  354.         mov     eax, dword[esi + ARP_ENTRY.MAC]
  355.         mov     bx , word[esi + ARP_ENTRY.MAC + 4]
  356.         mov     edi, ARP_table
  357.  
  358.   .loop:
  359.         cmp     dword [edi + ARP_ENTRY.MAC], eax        ; Check for duplicate MAC's
  360.         jne     .maybe_next                             ;
  361.         cmp     word [edi + ARP_ENTRY.MAC + 4], bx      ;
  362.         jne     .maybe_next                             ;
  363.  
  364.         cmp     dword[edi + ARP_ENTRY.TTL], 0xFFFF      ; static entry
  365.         jne     .notstatic
  366.         cmp     dword[esi + ARP_ENTRY.TTL], 0xFFFF
  367.         jne     .error
  368.   .notstatic:
  369.  
  370.         neg     ecx
  371.         add     ecx, [NumARP]
  372.         jmp     .add
  373.  
  374.   .maybe_next:
  375.         add     esi, ARP_ENTRY.size
  376.         loop    .loop
  377.  
  378.         mov     ecx, [NumARP]
  379.   .add:
  380.         push    ecx
  381.         imul    ecx, ARP_ENTRY.size
  382.         lea     edi, [ecx + ARP_table]
  383.         mov     ecx, ARP_ENTRY.size/2
  384.         rep     movsw
  385.  
  386.         lea     esi, [edi - ARP_ENTRY.size]
  387.         inc     [NumARP]
  388.         pop     eax
  389.         DEBUGF 1,"New entry created: %u\n", eax
  390.  
  391.   .exit:
  392.         DEBUGF 1,"Exiting\n"
  393.         ret
  394.  
  395.   .error:
  396.         DEBUGF 1,"error! \n"
  397.         mov     eax, -1
  398.         ret
  399.  
  400.  
  401. ;-----------------------------------------------------------------
  402. ;
  403. ; ARP_del_entry
  404. ;
  405. ; IN:  esi = ptr to arp entry
  406. ; OUT: /
  407. ;
  408. ;-----------------------------------------------------------------
  409. align 4
  410. ARP_del_entry:
  411.  
  412.         DEBUGF 1,"ARP del entry %x, total entrys: %u\n", esi, [NumARP]
  413.  
  414.         mov     ecx, ARP_table + (ARP_TABLE_SIZE - 1) * ARP_ENTRY.size
  415.         sub     ecx, esi
  416.         shr     ecx, 1
  417.  
  418.         mov     edi, esi
  419.         lea     esi, [edi + ARP_ENTRY.size]
  420.         rep     movsw
  421.  
  422.         dec     [NumARP]
  423.         DEBUGF 1,"ARP entry deleted\n"
  424.  
  425.         ret
  426.  
  427.  
  428.  
  429.  
  430.  
  431. ;-----------------------------------------------------------------
  432. ;
  433. ; ARP_IP_to_MAC
  434. ;
  435. ;  This function translates an IP address to a MAC address
  436. ;
  437. ;  IN:  eax = IPv4 address
  438. ;  OUT: eax = -1 on error, -2 means request send
  439. ;      else, ax = first two bytes of mac (high 16 bits of eax will be 0)
  440. ;       ebx = last four bytes of mac
  441. ;
  442. ;-----------------------------------------------------------------
  443. align 4
  444. ARP_IP_to_MAC:
  445.  
  446.         DEBUGF 1,"ARP_IP_to_MAC\n"
  447.  
  448.         cmp     eax, 0xffffffff
  449.         je      .broadcast
  450.  
  451. ; if ((Remote IP & subnet_mask) == (local IP & subnet_mask ))
  452. ; destination is on same subnet
  453. ; else, destination is remote and must use a gateway
  454.  
  455.         call    IPv4_dest_to_dev
  456.         mov     ebx, [IP_LIST + edi]
  457.         and     ebx, [SUBNET_LIST + edi]
  458.  
  459.         mov     ecx, eax
  460.         and     ecx, [SUBNET_LIST + edi]
  461.  
  462.         cmp     ecx, ebx
  463.         je      .local
  464.  
  465.         mov     eax, [GATEWAY_LIST + edi]
  466.         DEBUGF  1,"requested IP is not on subnet, using default gateway\n"
  467.  
  468. ;--------------------------------
  469. ; Try to find the IP in ARP_table
  470.  
  471.   .local:
  472.         mov     ecx, [NumARP]
  473.         test    ecx, ecx
  474.         jz      .not_in_list
  475.         mov     esi, ARP_table + ARP_ENTRY.IP
  476.   .scan_loop:
  477.         cmp     [esi], eax
  478.         je      .found_it
  479.         add     esi, ARP_ENTRY.size
  480.         loop    .scan_loop
  481.  
  482.   .not_in_list:
  483.         DEBUGF 1,"IP not found on list, preparing for ARP request\n"
  484.  
  485. ;--------------------
  486. ; Send an ARP request
  487.  
  488.         push    eax
  489.  
  490.         pushw   ARP_REQUEST_TTL
  491.         pushw   ARP_AWAITING_RESPONSE
  492.         pushd   0
  493.         pushw   0
  494.         pushd   eax
  495.         mov     esi, esp
  496.         call    ARP_add_entry
  497.         add     esp, ARP_ENTRY.size
  498.  
  499.         cmp     eax, -1
  500.         je      .full
  501.  
  502.         mov     ecx, eax
  503.         pop     eax
  504.         push    ecx
  505.         call    ARP_output_request
  506.  
  507. ;; TODO: check if driver could transmit packet
  508.  
  509.         pop     esi
  510.         imul    esi, ARP_ENTRY.size
  511.         add     esi, ARP_table
  512.  
  513.         mov     ecx, 25
  514.   .wait_loop:
  515.         cmp     [esi + ARP_ENTRY.Status], 1
  516.         je      .got_it
  517.         push    esi
  518.         mov     esi, 10
  519.         call    delay_ms
  520.         pop     esi
  521.         loop    .wait_loop
  522.  
  523.         mov     eax, -2         ; request send
  524.         ret
  525.  
  526.   .found_it:
  527.         DEBUGF  1,"found IP in ARPTable\n"
  528.         cmp     [esi + ARP_ENTRY.Status], 1
  529.         jne     .invalid
  530.  
  531.   .got_it:
  532.         movzx   eax, word [esi+ARP_ENTRY.MAC]
  533.         mov     ebx, dword[esi+ARP_ENTRY.MAC+2]
  534.         ret
  535.  
  536.   .invalid:
  537.         mov     eax, -1
  538.         ret
  539.  
  540.   .full:
  541.         DEBUGF  1,"ARP table is full!\n"
  542.         pop     eax
  543.         mov     eax, -1
  544.         ret
  545.  
  546.   .broadcast:
  547.         mov     eax, 0x0000ffff
  548.         mov     ebx, 0xffffffff
  549.         ret
  550.  
  551.  
  552. ;-----------------------------------------------------------------
  553. ;
  554. ; ARP_API
  555. ;
  556. ; This function is called by system function 75
  557. ;
  558. ; IN:  subfunction number in bl
  559. ;      device number in bh
  560. ;      ecx, edx, .. depends on subfunction
  561. ;
  562. ; OUT:  ?
  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, ARP_table
  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.         call    ARP_add_entry        ;out: eax = entry number, -1 on error
  620.         ret
  621.  
  622. .remove:
  623.         ; ecx = # entry
  624.         cmp     ecx, [NumARP]
  625.         jge     .error
  626.         imul    ecx, ARP_ENTRY.size
  627.         lea     esi, [ARP_table + ecx]
  628.         call    ARP_del_entry
  629.         ret
  630.  
  631.