Subversion Repositories Kolibri OS

Rev

Rev 261 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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