Subversion Repositories Kolibri OS

Rev

Rev 6011 | Rev 7678 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. 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: 7535 $
  20.  
  21. ARP_NO_ENTRY            = 0
  22. ARP_VALID_MAPPING       = 1
  23. ARP_AWAITING_RESPONSE   = 2
  24. ARP_RESPONSE_TIMEOUT    = 3
  25.  
  26. ARP_REQUEST_TTL         = 31          ; 20 s
  27. ARP_ENTRY_TTL           = 937         ; 600 s
  28. ARP_STATIC_ENTRY        = -1
  29.  
  30. ARP_REQ_OPCODE          = 0x0100      ; request
  31. ARP_REP_OPCODE          = 0x0200      ; reply
  32.  
  33. ARP_TABLE_SIZE          = 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. uglobal
  59. align 4
  60.  
  61.         ARP_table       rb NET_DEVICES_MAX*(ARP_TABLE_SIZE * sizeof.ARP_entry)
  62.  
  63.         ARP_entries_num rd NET_DEVICES_MAX
  64.         ARP_PACKETS_TX  rd NET_DEVICES_MAX
  65.         ARP_PACKETS_RX  rd NET_DEVICES_MAX
  66.         ARP_CONFLICTS   rd NET_DEVICES_MAX
  67.  
  68.  
  69. endg
  70.  
  71.  
  72.  
  73. ;-----------------------------------------------------------------;
  74. ;                                                                 ;
  75. ; arp_init: Resets all ARP variables.                             ;
  76. ;                                                                 ;
  77. ;-----------------------------------------------------------------;
  78. macro arp_init {
  79.  
  80.         xor     eax, eax
  81.         mov     edi, ARP_entries_num
  82.         mov     ecx, 4*NET_DEVICES_MAX
  83.         rep stosd
  84.  
  85. }
  86.  
  87. ;-----------------------------------------------------------------;
  88. ;                                                                 ;
  89. ; arp_decrease_entry_ttls                                         ;
  90. ;                                                                 ;
  91. ;-----------------------------------------------------------------;
  92. macro arp_decrease_entry_ttls {
  93.  
  94. local   .loop
  95. local   .exit
  96.  
  97. ; The TTL field is decremented every second, and is deleted when it reaches 0.
  98. ; It is refreshed every time a packet is received.
  99. ; If the TTL field is 0xFFFF it is a static entry and is never deleted.
  100. ; The status field can be the following values:
  101. ; 0x0000  entry not used
  102. ; 0x0001  entry holds a valid mapping
  103. ; 0x0002  entry contains an IP address, awaiting ARP response
  104. ; 0x0003  No response received to ARP request.
  105. ; The last status value is provided to allow the network layer to delete
  106. ; a packet that is queued awaiting an ARP response
  107.  
  108.         xor     edi, edi
  109.   .loop_outer:
  110.         mov     ecx, [ARP_entries_num + 4*edi]
  111.         test    ecx, ecx
  112.         jz      .exit
  113.  
  114.         mov     esi, (ARP_TABLE_SIZE * sizeof.ARP_entry)
  115.         imul    esi, edi
  116.         add     esi, ARP_table
  117.   .loop:
  118.         cmp     [esi + ARP_entry.TTL], ARP_STATIC_ENTRY
  119.         je      .next
  120.  
  121.         dec     [esi + ARP_entry.TTL]
  122.         jz      .time_out
  123.  
  124.   .next:
  125.         add     esi, sizeof.ARP_entry
  126.         dec     ecx
  127.         jnz     .loop
  128.         jmp     .exit
  129.  
  130.   .time_out:
  131.         cmp     [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE
  132.         je      .response_timeout
  133.  
  134.         push    esi edi ecx
  135.         call    arp_del_entry
  136.         pop     ecx edi esi
  137.  
  138.         jmp     .next
  139.  
  140.   .response_timeout:
  141.         mov     [esi + ARP_entry.Status], ARP_RESPONSE_TIMEOUT
  142.         mov     [esi + ARP_entry.TTL], 10
  143.  
  144.         jmp     .next
  145.  
  146.   .exit:
  147.         inc     edi
  148.         cmp     edi, NET_DEVICES_MAX
  149.         jb      .loop_outer
  150.  
  151. }
  152.  
  153.  
  154. ;-----------------------------------------------------------------;
  155. ;                                                                 ;
  156. ; arp_input                                                       ;
  157. ;                                                                 ;
  158. ;  IN:  [esp] = Pointer to buffer                                 ;
  159. ;       [esp+4] = size of buffer                                  ;
  160. ;       ecx = packet size (without ethernet header)               ;
  161. ;       edx = packet ptr                                          ;
  162. ;       ebx = device ptr                                          ;
  163. ;                                                                 ;
  164. ;  OUT: /                                                         ;
  165. ;                                                                 ;
  166. ;-----------------------------------------------------------------;
  167. align 4
  168. arp_input:
  169.  
  170. ;-----------------------------------------
  171. ; Check validity and print some debug info
  172.  
  173.         cmp     ecx, sizeof.ARP_header
  174.         jb      .exit
  175.  
  176.         call    net_ptr_to_num4
  177.         cmp     edi, -1
  178.         jz      .exit
  179.  
  180.         inc     [ARP_PACKETS_RX + edi]          ; update stats
  181.  
  182.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: got packet from %u.%u.%u.%u (device*4=%u)\n",\
  183.         [edx + ARP_header.SenderIP]:1, [edx + ARP_header.SenderIP + 1]:1,\
  184.         [edx + ARP_header.SenderIP + 2]:1, [edx + ARP_header.SenderIP + 3]:1, edi
  185.  
  186. ;------------------------------
  187. ; First, check for IP collision
  188.  
  189.         mov     eax, [edx + ARP_header.SenderIP]
  190.         cmp     eax, [IP_LIST + edi]
  191.         je      .collision
  192.  
  193. ;---------------------
  194. ; Handle reply packets
  195.  
  196.         cmp     [edx + ARP_header.Opcode], ARP_REP_OPCODE
  197.         jne     .maybe_request
  198.  
  199.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: It's a reply\n"
  200.  
  201.         mov     ecx, [ARP_entries_num + edi]
  202.         test    ecx, ecx
  203.         jz      .exit
  204.  
  205.         mov     esi, edi
  206.         imul    esi, (ARP_TABLE_SIZE * sizeof.ARP_entry)/4
  207.         add     esi, ARP_table
  208.   .loop:
  209.         cmp     [esi + ARP_entry.IP], eax
  210.         je      .gotit
  211.         add     esi, sizeof.ARP_entry
  212.         dec     ecx
  213.         jnz     .loop
  214.  
  215.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: no matching entry found\n"
  216.         jmp     .exit
  217.  
  218.   .gotit:
  219.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: found matching entry\n"
  220.  
  221.         cmp     [esi + ARP_entry.TTL], ARP_STATIC_ENTRY         ; if it is a static entry, dont touch it
  222.         je      .exit
  223.  
  224.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: updating entry\n"
  225.  
  226.         mov     [esi + ARP_entry.Status], ARP_VALID_MAPPING
  227.         mov     [esi + ARP_entry.TTL], ARP_ENTRY_TTL
  228.  
  229.         mov     eax, dword [edx + ARP_header.SenderMAC]
  230.         mov     dword [esi + ARP_entry.MAC], eax
  231.         mov     cx, word [edx + ARP_header.SenderMAC + 4]
  232.         mov     word [esi + ARP_entry.MAC + 4], cx
  233.  
  234.         jmp     .exit
  235.  
  236. ;-----------------------
  237. ; Handle request packets
  238.  
  239.   .maybe_request:
  240.         cmp     [edx + ARP_header.Opcode], ARP_REQ_OPCODE
  241.         jne     .exit
  242.  
  243.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: its a request\n"
  244.  
  245.         mov     eax, [IP_LIST + edi]
  246.         cmp     eax, [edx + ARP_header.TargetIP]                ; Is it looking for my IP address?
  247.         jne     .exit
  248.  
  249.         push    eax
  250.         push    edi
  251.  
  252. ; OK, it is a request for one of our MAC addresses.
  253. ; Build the frame and send it. We can reuse the buffer.  (faster then using ARP_create_packet)
  254.  
  255.         lea     esi, [edx + ARP_header.SenderMAC]
  256.         lea     edi, [edx + ARP_header.TargetMAC]
  257.         movsd                                                   ; Move Sender Mac to Dest MAC
  258.         movsw                                                   ;
  259.         movsd                                                   ; Move sender IP to Dest IP
  260.  
  261.         pop     esi
  262.         mov     esi, [NET_DRV_LIST + esi]
  263.         lea     esi, [esi + ETH_DEVICE.mac]
  264.         lea     edi, [edx + ARP_header.SenderMAC]
  265.         movsd                                                   ; Copy MAC address from in MAC_LIST
  266.         movsw                                                   ;
  267.         pop     eax
  268.         stosd                                                   ; Write our IP
  269.  
  270.         mov     [edx + ARP_header.Opcode], ARP_REP_OPCODE
  271.  
  272. ; Now, Fill in ETHERNET header
  273.  
  274.         mov     edi, [esp]
  275.         add     edi, [edi + NET_BUFF.offset]
  276.         lea     esi, [edx + ARP_header.TargetMAC]
  277.         movsd
  278.         movsw
  279.         lea     esi, [edx + ARP_header.SenderMAC]
  280.         movsd
  281.         movsw
  282. ;        mov     ax , ETHER_ARP                                 ; It's already there, I'm sure of it!
  283. ;        stosw
  284.  
  285.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: Sending reply\n"
  286.  
  287.         call    [ebx + NET_DEVICE.transmit]
  288.         ret
  289.  
  290.   .collision:
  291.         inc     [ARP_CONFLICTS + edi]
  292.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: IP address conflict detected!\n"
  293.  
  294.   .exit:
  295.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: exiting\n"
  296.         call    net_buff_free
  297.         ret
  298.  
  299. ;-----------------------------------------------------------------;
  300. ;                                                                 ;
  301. ; arp_output_request                                              ;
  302. ;                                                                 ;
  303. ;  IN:  ebx = device ptr                                          ;
  304. ;       eax = IP                                                  ;
  305. ;                                                                 ;
  306. ; OUT:  scratched: probably everything                            ;
  307. ;                                                                 ;
  308. ;-----------------------------------------------------------------;
  309. align 4
  310. arp_output_request:
  311.  
  312.         push    eax
  313.  
  314.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_output_request: ip=%u.%u.%u.%u device=0x%x\n",\
  315.         [esp]:1, [esp + 1]:1, [esp + 2]:1, [esp + 3]:1, ebx
  316.  
  317.         mov     ax, ETHER_PROTO_ARP
  318.         mov     ecx, sizeof.ARP_header
  319.         mov     edx, ETH_BROADCAST              ; broadcast mac
  320.         call    eth_output
  321.         jz      .exit
  322.  
  323.         mov     [edi + ARP_header.HardwareType], 0x0100         ; Ethernet
  324.         mov     [edi + ARP_header.ProtocolType], 0x0008         ; IP
  325.         mov     [edi + ARP_header.HardwareSize], 6              ; MAC-addr length
  326.         mov     [edi + ARP_header.ProtocolSize], 4              ; IP-addr length
  327.         mov     [edi + ARP_header.Opcode], ARP_REQ_OPCODE       ; Request
  328.  
  329.         add     edi, ARP_header.SenderMAC
  330.         lea     esi, [ebx + ETH_DEVICE.mac]     ; SenderMac
  331.         movsw                                   ;
  332.         movsd                                   ;
  333.  
  334.         push    edi
  335.         call    net_ptr_to_num4
  336.         inc     [ARP_PACKETS_TX + edi]          ; assume we will succeed
  337.         lea     esi, [IP_LIST + edi]            ; SenderIP
  338.         pop     edi
  339.         movsd
  340.  
  341.         mov     esi, ETH_BROADCAST              ; DestMac
  342.         movsw                                   ;
  343.         movsd                                   ;
  344.         popd    [edi]                           ; DestIP
  345.  
  346.         push    eax
  347.         call    [ebx + NET_DEVICE.transmit]
  348.         ret
  349.  
  350.   .exit:
  351.         add     esp, 4
  352.         DEBUGF  DEBUG_NETWORK_ERROR, "ARP_output_request: send failed\n"
  353.         ret
  354.  
  355.  
  356. ;-----------------------------------------------------------------;
  357. ;                                                                 ;
  358. ; arp_add_entry: Add or update an entry in the ARP table.         ;
  359. ;                                                                 ;
  360. ;  IN:  esi = ptr to entry (can easily be made on the stack)      ;
  361. ;       edi = device num*4                                        ;
  362. ;                                                                 ;
  363. ; OUT:  eax = entry number on success                             ;
  364. ;       eax = -1 on error                                         ;
  365. ;       esi = ptr to newly created entry                          ;
  366. ;                                                                 ;
  367. ;-----------------------------------------------------------------;
  368. align 4
  369. arp_add_entry:
  370.  
  371. ; TODO: use a mutex to lock ARP table
  372.  
  373.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_add_entry: device=%u\n", edi
  374.  
  375.         mov     ecx, [ARP_entries_num + edi]
  376.         cmp     ecx, ARP_TABLE_SIZE                                     ; list full ?
  377.         jae     .full
  378.  
  379. ; From this point on, we can only fail if IP has a static entry, or if table is corrupt.
  380.  
  381.         inc     [ARP_entries_num + edi]                                 ; assume we will succeed
  382.  
  383.         push    edi
  384.         xor     ecx, ecx
  385.         imul    edi, ARP_TABLE_SIZE*sizeof.ARP_entry/4
  386.         add     edi, ARP_table
  387.         mov     eax, [esi + ARP_entry.IP]
  388.   .loop:
  389.         cmp     [edi + ARP_entry.Status], ARP_NO_ENTRY                  ; is this slot empty?
  390.         je      .add
  391.  
  392.         cmp     [edi + ARP_entry.IP], eax                               ; if not, check if it doesnt collide
  393.         jne     .maybe_next
  394.  
  395.         cmp     [edi + ARP_entry.TTL], ARP_STATIC_ENTRY                 ; ok, its the same IP, update it if not static
  396.         jne     .add
  397.  
  398.         DEBUGF  DEBUG_NETWORK_ERROR, "ARP_add_entry: failed, IP already has a static entry\n"
  399.         jmp     .error
  400.  
  401.   .maybe_next:                                                          ; try the next slot
  402.         add     edi, sizeof.ARP_entry
  403.         inc     ecx
  404.         cmp     ecx, ARP_TABLE_SIZE
  405.         jb      .loop
  406.  
  407.   .add:
  408.         push    ecx
  409.         mov     ecx, sizeof.ARP_entry/2
  410.         rep movsw
  411.         pop     ecx
  412.         lea     esi, [edi - sizeof.ARP_entry]
  413.         pop     edi
  414.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_add_entry: entry=%u\n", ecx
  415.  
  416.         ret
  417.  
  418.   .error:
  419.         pop     edi
  420.         dec     [ARP_entries_num + edi]
  421.         DEBUGF  DEBUG_NETWORK_ERROR, "ARP_add_entry_failed\n"
  422.   .full:
  423.         mov     eax, -1
  424.         ret
  425.  
  426.  
  427. ;-----------------------------------------------------------------;
  428. ;                                                                 ;
  429. ; arp_del_entry: Remove an entry from the ARP table.              ;
  430. ;                                                                 ;
  431. ; IN:   esi = ptr to arp entry                                    ;
  432. ;       edi = device number                                       ;
  433. ;                                                                 ;
  434. ; OUT:  /                                                         ;
  435. ;                                                                 ;
  436. ;-----------------------------------------------------------------;
  437. align 4
  438. arp_del_entry:
  439.  
  440. ; TODO: use a mutex to lock ARP table
  441.  
  442.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_del_entry: entry=0x%x entrys=%u\n", esi, [ARP_entries_num + 4*edi]
  443.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_del_entry: IP=%u.%u.%u.%u\n", \
  444.         [esi + ARP_entry.IP]:1, [esi + ARP_entry.IP + 1]:1, [esi + ARP_entry.IP + 2]:1, [esi + ARP_entry.IP + 3]:1
  445.  
  446.         push    edi
  447.         imul    edi, (ARP_TABLE_SIZE) * sizeof.ARP_entry
  448.         lea     ecx, [ARP_table + (ARP_TABLE_SIZE - 1) * sizeof.ARP_entry + edi]
  449.         sub     ecx, esi
  450.         shr     ecx, 1
  451.  
  452. ; move all trailing entries, sizeof.ARP_entry bytes to left.
  453.         mov     edi, esi
  454.         add     esi, sizeof.ARP_entry
  455.         rep movsw
  456.  
  457. ; now add an empty entry to the end (erasing previous one)
  458.         xor     eax, eax
  459.         mov     ecx, sizeof.ARP_entry/2
  460.         rep stosw
  461.  
  462.         pop     edi
  463.         dec     [ARP_entries_num + 4*edi]
  464.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_del_entry: success\n"
  465.  
  466.         ret
  467.  
  468.  
  469.  
  470.  
  471.  
  472. ;-----------------------------------------------------------------;
  473. ;                                                                 ;
  474. ; arp_ip_to_mac: Translate an IP address to a MAC address.        ;
  475. ;                                                                 ;
  476. ;  IN:  eax = IPv4 address                                        ;
  477. ;       edi = device number * 4                                   ;
  478. ;                                                                 ;
  479. ;  OUT: eax = -1 on error                                         ;
  480. ;       eax = -2 when request send                                ;
  481. ;       eax = first two bytes of mac on success                   ;
  482. ;       ebx = last four bytes of mac on success                   ;
  483. ;       edi = unchanged                                           ;
  484. ;                                                                 ;
  485. ;-----------------------------------------------------------------;
  486. align 4
  487. arp_ip_to_mac:
  488.  
  489.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: %u.%u", al, ah
  490.         rol     eax, 16
  491.         DEBUGF  DEBUG_NETWORK_VERBOSE, ".%u.%u device*4: %u\n", al, ah, edi
  492.         rol     eax, 16
  493.  
  494.         cmp     eax, 0xffffffff
  495.         je      .broadcast
  496.  
  497. ;--------------------------------
  498. ; Try to find the IP in ARP_table
  499.  
  500.         mov     ecx, [ARP_entries_num + edi]
  501.         test    ecx, ecx
  502.         jz      .not_in_list
  503.         mov     esi, edi
  504.         imul    esi, (sizeof.ARP_entry * ARP_TABLE_SIZE)/4
  505.         add     esi, ARP_table + ARP_entry.IP
  506.   .scan_loop:
  507.         cmp     [esi], eax
  508.         je      .found_it
  509.         add     esi, sizeof.ARP_entry
  510.         dec     ecx
  511.         jnz     .scan_loop
  512.  
  513.   .not_in_list:
  514.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: preparing for ARP request\n"
  515.  
  516.         push    eax edi                 ; save IP for ARP_output_request
  517. ; Now craft the ARP entry on the stack
  518.         pushw   ARP_REQUEST_TTL         ; TTL
  519.         pushw   ARP_AWAITING_RESPONSE   ; status
  520.         pushd   0                       ; mac
  521.         pushw   0
  522.         pushd   eax                     ; IP
  523.         mov     esi, esp
  524.  
  525. ; Add it to the list
  526.         call    arp_add_entry
  527.  
  528. ; Delete the temporary entry
  529.         add     esp, sizeof.ARP_entry   ; clear the entry from stack
  530.  
  531. ; If we could not add it to the list, give up
  532.         cmp     eax, -1                 ; did ARP_add_entry fail?
  533.         je      .full
  534.  
  535. ;-----------------------------------------------
  536. ; At this point, we got an ARP entry in the list
  537.  
  538. ; Now send a request packet on the network
  539.         pop     edi eax                 ; IP in eax, device number in ebx, for ARP_output_request
  540.  
  541.         push    esi edi
  542.         mov     ebx, [NET_DRV_LIST + edi]
  543.         call    arp_output_request
  544.         pop     edi esi
  545.   .found_it:
  546.         cmp     [esi + ARP_entry.Status], ARP_VALID_MAPPING             ; Does it have a MAC assigned?
  547.         je      .valid
  548.  
  549. if ARP_BLOCK
  550.  
  551.         cmp     [esi + ARP_entry.Status], ARP_AWAITING_RESPONSE         ; Are we waiting for reply from remote end?
  552.         jne     .give_up
  553.         push    esi
  554.         mov     esi, 10                 ; wait 10 ms
  555.         call    delay_ms
  556.         pop     esi
  557.         jmp     .found_it               ; now check again
  558.  
  559. else
  560.  
  561.         jmp     .give_up
  562.  
  563. end if
  564.  
  565.   .valid:
  566.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: found MAC\n"
  567.         movzx   eax, word[esi + ARP_entry.MAC]
  568.         mov     ebx, dword[esi + ARP_entry.MAC + 2]
  569.         ret
  570.  
  571.   .full:
  572.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: table is full!\n"
  573.         add     esp, 8
  574.   .give_up:
  575.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: entry has no valid mapping!\n"
  576.         mov     eax, -1
  577.         ret
  578.  
  579.   .broadcast:
  580.         mov     eax, 0x0000ffff
  581.         mov     ebx, 0xffffffff
  582.         ret
  583.  
  584.  
  585. ;-----------------------------------------------------------------;
  586. ;                                                                 ;
  587. ; arp_api: Part of system function 76.                            ;
  588. ;                                                                 ;
  589. ;  IN:  bl = subfunction number                                   ;
  590. ;       bh = device number                                        ;
  591. ;       ecx, edx, .. depends on subfunction                       ;
  592. ;                                                                 ;
  593. ; OUT:  depends on subfunction                                    ;
  594. ;                                                                 ;
  595. ;-----------------------------------------------------------------;
  596. align 4
  597. arp_api:
  598.  
  599.         movzx   eax, bh
  600.         shl     eax, 2
  601.  
  602.         and     ebx, 0xff
  603.         cmp     ebx, .number
  604.         ja      .error
  605.         jmp     dword [.table + 4*ebx]
  606.  
  607.   .table:
  608.         dd      .packets_tx     ; 0
  609.         dd      .packets_rx     ; 1
  610.         dd      .entries        ; 2
  611.         dd      .read           ; 3
  612.         dd      .write          ; 4
  613.         dd      .remove         ; 5
  614.         dd      .send_announce  ; 6
  615.         dd      .conflicts      ; 7
  616.   .number = ($ - .table) / 4 - 1
  617.  
  618.   .error:
  619.         mov     eax, -1
  620.         ret
  621.  
  622.   .packets_tx:
  623.         mov     eax, [ARP_PACKETS_TX + eax]
  624.         ret
  625.  
  626.   .packets_rx:
  627.         mov     eax, [ARP_PACKETS_RX + eax]
  628.         ret
  629.  
  630.   .conflicts:
  631.         mov     eax, [ARP_CONFLICTS + eax]
  632.         ret
  633.  
  634.   .entries:
  635.         mov     eax, [ARP_entries_num + eax]
  636.         ret
  637.  
  638.   .read:
  639.         cmp     ecx, [ARP_entries_num + eax]
  640.         jae     .error
  641.         shr     eax, 2
  642.         imul    eax, sizeof.ARP_entry*ARP_TABLE_SIZE
  643.         add     eax, ARP_table
  644.         ; edi = pointer to buffer
  645.         ; ecx = # entry
  646.         imul    ecx, sizeof.ARP_entry
  647.         lea     esi, [eax + ecx]
  648.         mov     ecx, sizeof.ARP_entry/2
  649.         rep movsw
  650.  
  651.         xor     eax, eax
  652.         ret
  653.  
  654.   .write:
  655.         ; esi = pointer to buffer
  656.         mov     edi, eax
  657.         call    arp_add_entry           ; out: eax = entry number, -1 on error
  658.         ret
  659.  
  660.   .remove:
  661.         ; ecx = # entry
  662.         cmp     ecx, [ARP_entries_num + eax]
  663.         jae     .error
  664.         imul    ecx, sizeof.ARP_entry
  665.         lea     esi, [ARP_table + ecx]
  666.         mov     edi, eax
  667.         shr     edi, 2
  668.         call    arp_del_entry
  669.         ret
  670.  
  671.   .send_announce:
  672.         mov     ebx, [NET_DRV_LIST + eax]
  673.         mov     eax, [IP_LIST + eax]
  674.         call    arp_output_request      ; now send a gratuitous ARP
  675.         ret
  676.  
  677.