Subversion Repositories Kolibri OS

Rev

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

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