Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;  ARP.INC                                                     ;;
  7. ;;                                                              ;;
  8. ;;  Address Resolution Protocol                                 ;;
  9. ;;                                                              ;;
  10. ;;  Last revision: 10.11.2006                                   ;;
  11. ;;                                                              ;;
  12. ;;  This file contains the following:                           ;;
  13. ;;   arp_table_manager - Manages an ARPTable                    ;;
  14. ;;   arp_request - Sends an ARP request on the ethernet         ;;
  15. ;;   arp_handler - Called when an ARP packet is received        ;;
  16. ;;                                                              ;;
  17. ;;  Changes history:                                            ;;
  18. ;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net          ;;
  19. ;;   11.11.2006 - [Johnny_B] and [smb]                          ;;
  20. ;;                                                              ;;
  21. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  22.  
  23. $Revision: 739 $
  24.  
  25.  
  26. ARP_NO_ENTRY                equ  0
  27. ARP_VALID_MAPPING           equ  1
  28. ARP_AWAITING_RESPONSE       equ  2
  29. ARP_RESPONSE_TIMEOUT        equ  3
  30.  
  31. struc ARP_ENTRY     ;=14 bytes
  32. {  .IP       dd  ?  ;+00
  33.    .MAC      dp  ?  ;+04
  34.    .Status   dw  ?  ;+10
  35.    .TTL      dw  ?  ;+12 : ( in seconds )
  36. }
  37.  
  38. virtual at 0
  39.   ARP_ENTRY ARP_ENTRY
  40. end virtual
  41.  
  42. ; The TTL field is decremented every second, and is deleted when it
  43. ; reaches 0. It is refreshed every time a packet is received
  44. ; If the TTL field is 0xFFFF it is a static entry and is never deleted
  45. ; The status field can be the following values:
  46. ; 0x0000  entry not used
  47. ; 0x0001  entry holds a valid mapping
  48. ; 0x0002  entry contains an IP address, awaiting ARP response
  49. ; 0x0003  No response received to ARP request.
  50. ; The last status value is provided to allow the network layer to delete
  51. ; a packet that is queued awaiting an ARP response
  52.  
  53.  
  54. ; The follow is the ARP Table.
  55. ; This table must be manually updated and the kernel recompilied if
  56. ; changes are made to it.
  57. ; Empty entries are filled with zeros
  58.  
  59. ARP_ENTRY_SIZE              equ     14          ; Number of bytes per entry
  60. ARP_TABLE_SIZE              equ     20          ; Size of table
  61. ARP_TABLE_ENTRIES           equ     0           ; Number of static entries in the table
  62.  
  63. ;TO ADD A STATIC ENTRY, DONT FORGET, PUT "ARPTable" from "uglobal" to "iglobal"!!!
  64. ;AND ALSO - IP and MAC have net byte-order, BUT STATUS AND TTL HAVE A MIRROR BYTE-ORDER!!!
  65. uglobal
  66.   ARPTable:
  67. ;example, static entry ->  db  11,22,33,44, 0x11,0x22,0x33,0x44,0x55,0x66, 0x01,0x00, 0xFF,0xFF
  68.   times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE  db 0
  69. endg
  70.  
  71. iglobal
  72.   NumARP:        dd    ARP_TABLE_ENTRIES
  73.   ARPTable_ptr   dd    ARPTable   ;pointer to ARPTable
  74. endg
  75.  
  76. ARP_REQ_OPCODE              equ     0x0100  ;request
  77. ARP_REP_OPCODE              equ     0x0200  ;reply
  78.  
  79. struc ARP_PACKET
  80. {  .HardwareType dw   ?  ;+00
  81.    .ProtocolType dw   ?  ;+02
  82.    .HardwareSize db   ?  ;+04
  83.    .ProtocolSize db   ?  ;+05
  84.    .Opcode       dw   ?  ;+06
  85.    .SenderMAC    dp   ?  ;+08
  86.    .SenderIP     dd   ?  ;+14
  87.    .TargetMAC    dp   ?  ;+18
  88.    .TargetIP     dd   ?  ;+24
  89. }
  90.  
  91. virtual at 0
  92.   ARP_PACKET ARP_PACKET
  93. end virtual
  94.  
  95.  
  96.  
  97. ;***************************************************************************
  98. ;   Function
  99. ;      arp_table_manager  [by Johnny_B]
  100. ;
  101. ;   Description
  102. ;     Does a most required operations with ARP-table
  103. ;  IN:
  104. ;   Operation: see Opcode's constants below
  105. ;       Index: Index of entry in the ARP-table
  106. ;       Extra: Extra parameter for some Opcodes
  107. ;  OUT:
  108. ;   EAX = Returned value depends on opcodes, more detailed see below
  109. ;
  110. ;***************************************************************************
  111. ;Opcode's constants
  112. ARP_TABLE_ADD                 equ  1
  113. ARP_TABLE_DEL                 equ  2
  114. ARP_TABLE_GET                 equ  3
  115. ARP_TABLE_GET_ENTRIES_NUMBER  equ  4
  116. ARP_TABLE_IP_TO_MAC           equ  5
  117. ARP_TABLE_TIMER               equ  6
  118.  
  119. ;Index's constants
  120. EXTRA_IS_ARP_PACKET_PTR  equ  0   ;if Extra contain pointer to ARP_PACKET
  121. EXTRA_IS_ARP_ENTRY_PTR   equ  -1  ;if Extra contain pointer to ARP_ENTRY
  122.  
  123. align 4
  124. proc arp_table_manager stdcall uses ebx esi edi ecx edx,\
  125.     Opcode:DWORD,Index:DWORD,Extra:DWORD
  126.  
  127.     mov     ebx, dword[ARPTable_ptr]   ;ARPTable base
  128.     mov     ecx, dword[NumARP]         ;ARP-entries counter
  129.  
  130.     mov     eax, dword[Opcode]
  131.     cmp     eax, ARP_TABLE_TIMER
  132.     je      .timer
  133.     cmp     eax, ARP_TABLE_ADD
  134.     je      .add
  135.     cmp     eax, ARP_TABLE_DEL
  136.     je      .del
  137.     cmp     eax, ARP_TABLE_GET
  138.     je      .get
  139.     cmp     eax, ARP_TABLE_IP_TO_MAC
  140.     je      .ip_to_mac
  141.     cmp     eax, ARP_TABLE_GET_ENTRIES_NUMBER
  142.     je      .get_entries_number
  143.     jmp     .exit     ;if unknown opcode
  144.  
  145.  
  146. ;;BEGIN TIMER
  147. ;;Description: it must be callback every second. It is responsible for removing expired routes.
  148. ;;IN:   Operation: ARP_TABLE_TIMER
  149. ;;      Index: must be zero
  150. ;;      Extra: must be zero
  151. ;;OUT:
  152. ;;  EAX=not defined
  153. ;;
  154. .timer:
  155.     test    ecx, ecx
  156.     jz      .exit    ;if NumARP=0 nothing to do
  157.     sub     ecx, ARP_TABLE_ENTRIES  ;ecx=dynamic entries number
  158.     jz      .exit    ;if NumARP=number of static entries then exit
  159.  
  160.     add     ebx, ARP_TABLE_ENTRIES*ARP_ENTRY_SIZE  ;ebx=dynamic entries base
  161.  
  162.   .timer_loop:
  163.     movsx   esi, word [ebx + ARP_ENTRY.TTL]
  164.     cmp     esi, 0xFFFFFFFF
  165.     je      .timer_loop_end  ;if TTL==0xFFFF then it's static entry
  166.  
  167.     test    esi, esi
  168.     jnz     .timer_loop_end_with_dec  ;if TTL!=0
  169.  
  170.     ; Ok, TTL is 0
  171.     ;if Status==AWAITING_RESPONSE and TTL==0
  172.     ;then we have to change it to ARP_RESPONSE_TIMEOUT
  173.     cmp     word [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
  174.     jne     @f
  175.  
  176.     mov     word [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
  177.     mov     word [ebx + ARP_ENTRY.TTL], word 0x000A   ;10 sec
  178.     jmp     .timer_loop_end
  179.  
  180.   @@:
  181.     ;if TTL==0 and Status==VALID_MAPPING, we have to delete it
  182.     ;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too
  183.     mov     esi, dword[NumARP]
  184.     sub     esi, ecx          ;esi=index of entry, will be deleted
  185.     stdcall arp_table_manager,ARP_TABLE_DEL,esi,0 ;opcode,index,extra
  186.     jmp     .timer_loop_end
  187.  
  188.  
  189.   .timer_loop_end_with_dec:
  190.     dec     word [ebx + ARP_ENTRY.TTL]  ;decrease TTL
  191.   .timer_loop_end:
  192.     add     ebx, ARP_ENTRY_SIZE
  193.     loop    .timer_loop
  194.  
  195.     jmp     .exit
  196. ;;END TIMER
  197.  
  198. ;;BEGIN ADD
  199. ;;Description: it adds an entry in the table. If ARP-table already
  200. ;;             contains same IP, it will be updated.
  201. ;;IN:   Operation: ARP_TABLE_ADD
  202. ;;      Index: specifies what contains Extra-parameter
  203. ;;      Extra: if Index==EXTRA_IS_ARP_PACKET_PTR,
  204. ;;             then Extra contains pointer to ARP_PACKET,
  205. ;;             otherwise Extra contains pointer to ARP_ENTRY
  206. ;;OUT:
  207. ;;  EAX=index of entry, that has been added
  208. ;;
  209. .add:
  210.  
  211.     sub     esp, ARP_ENTRY_SIZE   ;Allocate ARP_ENTRY_SIZE byte in stack
  212.  
  213.     mov     esi, [Extra]   ;pointer
  214.     mov     edi, [Index]   ;opcode
  215.  
  216.     cmp     edi, EXTRA_IS_ARP_PACKET_PTR
  217.     je      .arp_packet_to_entry ;if Extra contain ptr to ARP_PACKET and we have to form arp-entry
  218.                                  ;else it contain ptr to arp-entry
  219.  
  220.     cld
  221.           ; esi already has been loaded
  222.     mov     edi, esp      ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add)
  223.     mov     ecx,ARP_ENTRY_SIZE/2  ;ARP_ENTRY_SIZE must be even number!!!
  224.     rep     movsw    ;copy
  225.     jmp     .search
  226.  
  227.   .arp_packet_to_entry:
  228.     mov     edx, dword[esi + ARP_PACKET.SenderIP] ;esi=base of ARP_PACKET
  229.     mov     [esp + ARP_ENTRY.IP], edx
  230.  
  231.     cld
  232.     lea     esi, [esi + ARP_PACKET.SenderMAC]
  233.     lea     edi, [esp + ARP_ENTRY.MAC]
  234.     movsd
  235.     movsw
  236.     mov     word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING  ; specify the type - a valid entry
  237.     mov     word[esp + ARP_ENTRY.TTL], 0x0E10    ; = 1 hour
  238.  
  239.   .search:
  240.     mov     edx, dword[esp + ARP_ENTRY.IP]  ;edx=IP-address, which we'll search
  241.     mov     ecx, dword[NumARP]              ;ecx=ARP-entries counter
  242.     jecxz   .add_to_end                     ;if ARP-entries number == 0
  243.     imul    eax, ecx, ARP_ENTRY_SIZE        ;eax=current table size(in bytes)
  244.   @@:
  245.     sub     eax, ARP_ENTRY_SIZE
  246.     cmp     dword[ebx + eax + ARP_ENTRY.IP], edx
  247.     loopnz  @b
  248.     jz      .replace       ; found, replace existing entry, ptr to it is in eax
  249.  
  250.   .add_to_end:
  251.     ;else add to end
  252.     or      eax,-1    ;set eax=0xFFFFFFFF if adding is impossible
  253.     mov     ecx, dword[NumARP]
  254.     cmp     ecx, ARP_TABLE_SIZE
  255.     je      .add_exit   ;if arp-entries number is equal to arp-table maxsize
  256.  
  257.     imul    eax, dword[NumARP], ARP_ENTRY_SIZE ;eax=ptr to end of ARPTable
  258.     inc     dword [NumARP]    ;increase ARP-entries counter
  259.  
  260.   .replace:
  261.     cld
  262.     mov     esi, esp              ;esp=base of ARP-entry, that will be added
  263.     lea     edi, [ebx + eax]      ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add)
  264.     mov     ecx,ARP_ENTRY_SIZE/2  ;ARP_ENTRY_SIZE must be even number!!!
  265.     rep     movsw
  266.  
  267.     mov     ecx, ARP_ENTRY_SIZE
  268.     xor     edx, edx  ;"div" takes operand from EDX:EAX
  269.     div     ecx       ;eax=index of entry, which has been added
  270.  
  271. .add_exit:
  272.     add     esp, ARP_ENTRY_SIZE   ;free stack
  273.     jmp     .exit
  274. ;;END ADD
  275.  
  276. ;;BEGIN DEL
  277. ;;Description: it deletes an entry in the table.
  278. ;;IN:   Operation: ARP_TABLE_DEL
  279. ;;      Index: index of entry, that should be deleted
  280. ;;      Extra: must be zero
  281. ;;OUT:
  282. ;;  EAX=not defined
  283. ;;
  284. .del:
  285.     mov     esi, [Index]
  286.     imul    esi, ARP_ENTRY_SIZE
  287.  
  288.     mov     ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE
  289.     sub     ecx, esi
  290.  
  291.     lea     edi, [ebx + esi]            ;edi=ptr to entry that should be deleted
  292.     lea     esi, [edi + ARP_ENTRY_SIZE] ;esi=ptr to next entry
  293.  
  294.     shr     ecx,1      ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER!
  295.     cld
  296.     rep     movsw
  297.  
  298.     dec     dword[NumARP] ;decrease arp-entries counter
  299.     jmp     .exit
  300. ;;END DEL
  301.  
  302. ;;BEGIN GET
  303. ;;Description: it reads an entry of table into buffer.
  304. ;;IN:   Operation: ARP_TABLE_GET
  305. ;;      Index: index of entry, that should be read
  306. ;;      Extra: pointer to buffer for reading(size must be equal to ARP_ENTRY_SIZE)
  307. ;;OUT:
  308. ;;  EAX=not defined
  309. ;;
  310. .get:
  311.     mov     esi, [Index]
  312.     imul    esi, ARP_ENTRY_SIZE   ;esi=ptr to required ARP_ENTRY
  313.     mov     edi, [Extra]          ;edi=buffer for reading
  314.     mov     ecx, ARP_ENTRY_SIZE/2 ; must be even number!!!
  315.     cld
  316.     rep     movsw
  317.     jmp     .exit
  318. ;;END GET
  319.  
  320. ;;BEGIN IP_TO_MAC
  321. ;;Description: it gets an IP from Index, scans each entry in the table and writes
  322. ;;             MAC, that relates to specified IP, into buffer specified in Extra.
  323. ;;             And if it cannot find an IP-address in the table, it does an ARP-request of that.
  324. ;;IN:   Operation: ARP_TABLE_IP_TO_MAC
  325. ;;      Index: IP that should be transformed into MAC
  326. ;;      Extra: pointer to buffer where will be written the MAC-address.
  327. ;;OUT:
  328. ;;  EAX=ARP table entry status code.
  329. ;;      If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request.
  330. ;;      If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system.
  331. ;;      If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long.
  332. ;;      If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC.
  333. ;;
  334. ;;  If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet
  335. ;;  resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this
  336. ;;  function with 1sec delay. sure, only if it not return a valid MAC after a first call.
  337. ;;  
  338. .ip_to_mac:
  339.  
  340.     xor     eax, eax
  341.     mov     edi, dword[Extra]
  342.     cld
  343.     stosd
  344.     stosw
  345.  
  346.  
  347.     ; first, check destination IP to see if it is on 'this' network.
  348.     ; The test is:
  349.     ; if ( destIP & subnet_mask == stack_ip & subnet_mask )
  350.     ;   destination is local
  351.     ; else
  352.     ;  destination is remote, so pass to gateway
  353.  
  354.     mov     eax, [Index]       ;eax=required IP
  355.     mov     esi, eax
  356.     and     esi, [subnet_mask]
  357.     mov     ecx, [stack_ip]
  358.     and     ecx, [subnet_mask]
  359.     cmp     esi, ecx
  360.     je      @f        ;if we and target IP are located in the same network
  361.     mov     eax, [gateway_ip]
  362.     mov     [Index], eax
  363.   @@:
  364.  
  365.     cmp     dword[NumARP], 0
  366.     je      .ip_to_mac_send_request ;if ARP-table not contain an entries, we have to request IP.
  367.                                     ;EAX will be containing a zero, it's equal to ARP_NO_ENTRY
  368.  
  369.     mov     ecx, dword[NumARP]
  370.     imul    esi, ecx, ARP_ENTRY_SIZE  ;esi=current ARP-table size
  371.  
  372.   @@:
  373.     sub     esi, ARP_ENTRY_SIZE
  374.     cmp     [ebx + esi], eax         ; ebx=ARPTable base
  375.     loopnz  @b                       ; Return back if non match
  376.     jnz     .ip_to_mac_send_request  ; and request IP->MAC if none found in the table
  377.  
  378.     ; Return the entry status in eax
  379.     movzx   eax, word[ebx + esi + ARP_ENTRY.Status]
  380.  
  381.     ; esi holds index
  382.     cld
  383.     lea     esi, [ebx + esi + ARP_ENTRY.MAC]
  384.     mov     edi, [Extra]   ;edi=ptr to buffer for write MAC
  385.     movsd
  386.     movsw
  387.     jmp     .exit
  388.  
  389.   .ip_to_mac_send_request:
  390.     stdcall arp_request,[Index],stack_ip,node_addr  ;TargetIP,SenderIP_ptr,SenderMAC_ptr
  391.     mov     eax, ARP_NO_ENTRY
  392.     jmp     .exit
  393.  
  394. ;;END IP_TO_MAC
  395.  
  396. ;;BEGIN GET_ENTRIES_NUMBER
  397. ;;Description: returns an ARP-entries number in the ARPTable
  398. ;;IN:   Operation: ARP_TABLE_GET_ENTRIES_NUMBER
  399. ;;      Index: must be zero
  400. ;;      Extra: must be zero
  401. ;;OUT:
  402. ;;  EAX=ARP-entries number in the ARPTable
  403.   .get_entries_number:
  404.     mov     eax, dword[NumARP]
  405.     jmp     .exit
  406. ;;END GET_ENTRIES_NUMBER
  407.  
  408. .exit:
  409.     ret
  410. endp
  411.  
  412.  
  413. ;***************************************************************************
  414. ;   Function
  415. ;      arp_handler
  416. ;
  417. ;   Description
  418. ;      Called when an ARP packet is received on the ethernet
  419. ;      Header + Data is in Ether_buffer[]
  420. ;       It looks to see if the packet is a request to resolve this Hosts
  421. ;       IP address. If it is, send the ARP reply packet.
  422. ;      This Hosts IP address is in dword [stack_ip]  ( in network format )
  423. ;       This Hosts MAC address is in node_addr[6]
  424. ;      All registers may be destroyed
  425. ;
  426. ;***************************************************************************
  427. arp_handler:
  428.     ; Is this a REQUEST?
  429.     ; Is this a request for My Host IP
  430.     ; Yes - So construct a response message.
  431.     ; Send this message to the ethernet card for transmission
  432.  
  433.     stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_PACKET_PTR,ETH_FRAME.Data + ARP_PACKET
  434.  
  435.     inc     dword[arp_rx_count] ;increase ARP-packets counter
  436.  
  437.     cmp     word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REQ_OPCODE  ; Is this a request packet?
  438.     jne     .exit            ; No - so exit
  439.  
  440.     mov     eax, [stack_ip]
  441.     cmp     eax, dword[ETH_FRAME.Data + ARP_PACKET.TargetIP]         ; Is it looking for my IP address?
  442.     jne     .exit            ; No - so quit now
  443.  
  444.     ; OK, it is a request for my MAC address. Build the frame and send it
  445.     ; We can reuse the packet.
  446.  
  447.     mov     word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REP_OPCODE
  448.  
  449.     cld
  450.     mov     esi, ETH_FRAME.Data + ARP_PACKET.SenderMAC
  451.     mov     edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC
  452.     movsd
  453.     movsw
  454.  
  455.     mov     esi, ETH_FRAME.Data + ARP_PACKET.SenderIP
  456.     mov     edi, ETH_FRAME.Data + ARP_PACKET.TargetIP
  457.     movsd
  458.  
  459.     mov     esi, node_addr
  460.     mov     edi, ETH_FRAME.Data + ARP_PACKET.SenderMAC
  461.     movsd
  462.     movsw
  463.  
  464.     mov     esi, stack_ip
  465.     mov     edi, ETH_FRAME.Data + ARP_PACKET.SenderIP
  466.     movsd
  467.  
  468.     ; Now, send it!
  469.     mov     edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC   ;ptr to destination MAC address
  470.     mov     bx, ETHER_ARP               ;type of protocol
  471.     mov     ecx, 28                     ;data size
  472.     mov     esi, ETH_FRAME.Data + ARP_PACKET             ;ptr to data
  473.     push    ebp
  474.     call    dword [drvr_transmit]       ;transmit packet
  475.     pop     ebp
  476.  
  477.   .exit:
  478.     ret
  479.  
  480.  
  481. ;***************************************************************************
  482. ;   Function
  483. ;      arp_request  [by Johnny_B]
  484. ;
  485. ;   Description
  486. ;      Sends an ARP request on the ethernet
  487. ;   IN:
  488. ;     TargetIP      : requested IP address
  489. ;     SenderIP_ptr  : POINTER to sender's IP address(our system's address)
  490. ;     SenderMAC_ptr : POINTER to sender's MAC address(our system's address)
  491. ;   OUT:
  492. ;     EAX=0 (if all is ok), otherwise EAX is not defined
  493. ;
  494. ;      EBX,ESI,EDI will be saved
  495. ;
  496. ;***************************************************************************
  497. proc arp_request stdcall uses ebx esi edi,\
  498.     TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD
  499.  
  500.     inc     dword[arp_tx_count]  ; increase counter
  501.  
  502.     sub     esp, 28  ; allocate memory for ARP_PACKET
  503.  
  504.     mov     word[esp + ARP_PACKET.HardwareType],0x0100 ;Ethernet
  505.     mov     word[esp + ARP_PACKET.ProtocolType],0x0008 ;IP
  506.     mov     byte[esp + ARP_PACKET.HardwareSize],0x06   ;MAC-addr length
  507.     mov     byte[esp + ARP_PACKET.ProtocolSize],0x04   ;IP-addr length
  508.     mov     word[esp + ARP_PACKET.Opcode],0x0100       ;Request
  509.  
  510.     cld
  511.     mov     esi,[SenderMAC_ptr]
  512.     lea     edi,[esp + ARP_PACKET.SenderMAC]       ;Our MAC-addr
  513.     movsd
  514.     movsw
  515.  
  516.     mov     esi,[SenderIP_ptr]
  517.     lea     edi,[esp + ARP_PACKET.SenderIP]        ;Our IP-addr
  518.     movsd
  519.  
  520.     xor     eax, eax
  521.     lea     edi, [esp + ARP_PACKET.TargetMAC]      ;Required MAC-addr(zeroed)
  522.     stosd
  523.     stosw
  524.  
  525.     mov     esi, dword[TargetIP]
  526.     mov     dword[esp + ARP_PACKET.TargetIP],esi   ;Required IP-addr(we get it as function parameter)
  527.  
  528.     ; Now, send it!
  529.     mov     edi, broadcast_add     ; Pointer to 48 bit destination address
  530.     mov     bx, ETHER_ARP          ; Type of packet
  531.     mov     ecx, 28                ; size of packet
  532.     lea     esi, [esp + ARP_PACKET]; pointer to packet data
  533.     push    ebp
  534.     call    dword [drvr_transmit]  ; Call the drivers transmit function
  535.     pop     ebp
  536.  
  537.     add     esp, 28  ; free memory, allocated before for ARP_PACKET
  538.  
  539.     ; Add an entry in the ARP table, awaiting response
  540.     sub     esp, ARP_ENTRY_SIZE    ;allocate memory for ARP-entry
  541.  
  542.     mov     esi, dword[TargetIP]
  543.     mov     dword[esp + ARP_ENTRY.IP],esi
  544.  
  545.     lea     edi, [esp + ARP_ENTRY.MAC]
  546.     xor     eax, eax
  547.     stosd
  548.     stosw
  549.  
  550.     mov     word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
  551.     mov     word[esp + ARP_ENTRY.TTL], 0x000A  ; 10 seconds
  552.  
  553.     stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_ENTRY_PTR,esp
  554.     add     esp, ARP_ENTRY_SIZE  ; free memory
  555.  
  556. .exit:
  557.     ret
  558. endp
  559.