Subversion Repositories Kolibri OS

Rev

Rev 3861 | Rev 5015 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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