Subversion Repositories Kolibri OS

Rev

Rev 7682 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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