Subversion Repositories Kolibri OS

Rev

Rev 10051 | Details | Compare with Previous | Last modification | View Log | RSS feed

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