Subversion Repositories Kolibri OS

Rev

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

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