Subversion Repositories Kolibri OS

Rev

Rev 7679 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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