Subversion Repositories Kolibri OS

Rev

Rev 3600 | Rev 3602 | 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
 
179
        call    NET_ptr_to_num
180
        cmp     edi, -1
181
        jz      .exit
182
 
183
        inc     [ARP_PACKETS_RX + 4*edi]        ; update stats
184
 
3556 hidnplayr 185
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_input: got packet from %u.%u.%u.%u through device %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]
193
        cmp     eax, [IP_LIST + 4*edi]
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
 
3601 hidnplayr 204
        mov     ecx, [ARP_entries_num + 4*edi]
3545 hidnplayr 205
        test    ecx, ecx
206
        jz      .exit
207
 
3601 hidnplayr 208
        mov     esi, (ARP_TABLE_SIZE * sizeof.ARP_entry)
209
        imul    esi, edi
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
 
248
        mov     eax, [IP_LIST + 4*edi]
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
265
        mov     esi, [NET_DRV_LIST + 4*esi]
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:
293
        inc     [ARP_CONFLICTS + 4*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)
3601 hidnplayr 367
;      edi = device num
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
 
3601 hidnplayr 377
        mov     ecx, [ARP_entries_num + 4*edi]
3545 hidnplayr 378
        cmp     ecx, ARP_TABLE_SIZE                                     ; list full ?
3601 hidnplayr 379
        jae     .full
3545 hidnplayr 380
 
3601 hidnplayr 381
 
382
; From this point on, we can only fail if IP has a static entry, or if table is corrupt.
383
 
384
        inc     [ARP_entries_num + 4*edi]                               ; assume we will succeed
385
 
386
        push    edi
387
        xor     ecx, ecx
388
        imul    edi, ARP_TABLE_SIZE*sizeof.ARP_entry
389
        add     edi, ARP_table
390
        mov     eax, [edi + ARP_entry.IP]
3545 hidnplayr 391
  .loop:
392
        cmp     [edi + ARP_entry.Status], ARP_NO_ENTRY                  ; is this slot empty?
393
        je      .add
394
 
3601 hidnplayr 395
        cmp     [edi + ARP_entry.IP], eax                               ; if not, check if it doesnt collide
3545 hidnplayr 396
        jne     .maybe_next
397
 
398
        cmp     [edi + ARP_entry.TTL], ARP_STATIC_ENTRY                 ; ok, its the same IP, update it if not static
399
        jne     .add
400
 
3601 hidnplayr 401
        DEBUGF  DEBUG_NETWORK_ERROR, "ARP_add_entry: failed, IP already has a static entry\n"
402
        jmp     .error
403
 
3545 hidnplayr 404
  .maybe_next:                                                          ; try the next slot
405
        add     edi, sizeof.ARP_entry
3601 hidnplayr 406
        inc     ecx
407
        cmp     ecx, ARP_TABLE_SIZE
408
        jb      .loop
3545 hidnplayr 409
 
410
  .add:
3601 hidnplayr 411
        push    ecx
3545 hidnplayr 412
        mov     ecx, sizeof.ARP_entry/2
413
        rep     movsw
3601 hidnplayr 414
        pop     ecx
415
        lea     esi, [edi - sizeof.ARP_entry]
416
        pop     edi
417
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_add_entry: entry=%u\n", ecx
3545 hidnplayr 418
 
419
        ret
420
 
421
  .error:
3601 hidnplayr 422
        pop     edi
423
        dec     [ARP_entries_num + 4*edi]
424
        DEBUGF  DEBUG_NETWORK_ERROR, "ARP_add_entry_failed\n"
425
  .full:
3545 hidnplayr 426
        mov     eax, -1
427
        ret
428
 
429
 
430
;-----------------------------------------------------------------
431
;
432
; ARP_del_entry
433
;
3601 hidnplayr 434
; IN:   esi = ptr to arp entry
435
;       edi = device number
436
; OUT:  /
3545 hidnplayr 437
;
438
;-----------------------------------------------------------------
439
align 4
440
ARP_del_entry:
441
 
3601 hidnplayr 442
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_del_entry: entry=%x entrys=%u\n", esi, [ARP_entries_num + 4*edi]
3556 hidnplayr 443
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_del_entry: IP=%u.%u.%u.%u\n", \
3545 hidnplayr 444
        [esi + ARP_entry.IP]:1, [esi + ARP_entry.IP + 1]:1, [esi + ARP_entry.IP + 2]:1, [esi + ARP_entry.IP + 3]:1
445
 
3601 hidnplayr 446
        push    edi
447
        imul    edi, (ARP_TABLE_SIZE) * sizeof.ARP_entry
448
        lea     ecx, [ARP_table + (ARP_TABLE_SIZE - 1) * sizeof.ARP_entry + edi]
3545 hidnplayr 449
        sub     ecx, esi
450
        shr     ecx, 1
451
 
3601 hidnplayr 452
; move all trailing entries, sizeof.ARP_entry bytes to left.
3545 hidnplayr 453
        mov     edi, esi
454
        add     esi, sizeof.ARP_entry
455
        rep     movsw
456
 
3601 hidnplayr 457
; now add an empty entry to the end (erasing previous one)
3545 hidnplayr 458
        xor     eax, eax
459
        mov     ecx, sizeof.ARP_entry/2
460
        rep     stosw
461
 
3601 hidnplayr 462
        pop     edi
463
        dec     [ARP_entries_num + 4*edi]
3556 hidnplayr 464
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_del_entry: success\n"
3545 hidnplayr 465
 
466
        ret
467
 
468
 
469
 
470
 
471
 
472
;-----------------------------------------------------------------
473
;
474
; ARP_IP_to_MAC
475
;
476
;  This function translates an IP address to a MAC address
477
;
478
;  IN:  eax = IPv4 address
479
;       edi = device number
480
;  OUT: eax = -1 on error, -2 means request send
481
;      else, ax = first two bytes of mac (high 16 bits of eax will be 0)
482
;       ebx = last four bytes of mac
483
;       edi = unchanged
484
;
485
;-----------------------------------------------------------------
486
align 4
487
ARP_IP_to_MAC:
488
 
3556 hidnplayr 489
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: %u.%u", al, ah
3545 hidnplayr 490
        rol     eax, 16
3601 hidnplayr 491
        DEBUGF  DEBUG_NETWORK_VERBOSE, ".%u.%u device: %u\n", al, ah, edi
3545 hidnplayr 492
        rol     eax, 16
493
 
494
        cmp     eax, 0xffffffff
495
        je      .broadcast
496
 
497
;--------------------------------
498
; Try to find the IP in ARP_table
499
 
3601 hidnplayr 500
        mov     ecx, [ARP_entries_num + 4*edi]
3545 hidnplayr 501
        test    ecx, ecx
502
        jz      .not_in_list
503
        mov     esi, ARP_table + ARP_entry.IP
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
3601 hidnplayr 540
        mov     ebx, [NET_DRV_LIST + 4*edi]
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
3601 hidnplayr 551
        push    esi edi
3545 hidnplayr 552
        mov     esi, 10                 ; wait 10 ms
553
        call    delay_ms
3601 hidnplayr 554
        pop     edi 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"
3601 hidnplayr 565
        movzx   eax, word[edi + ARP_entry.MAC]
566
        mov     ebx, dword[edi + 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
;
587
; This function is called by system function 75
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
649
        rep     movsw
650
 
651
        xor     eax, eax
652
        ret
653
 
654
  .write:
655
        ; esi = pointer to buffer
3601 hidnplayr 656
        mov     edi, eax
657
        shr     edi, 2
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