Subversion Repositories Kolibri OS

Rev

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