Subversion Repositories Kolibri OS

Rev

Rev 2629 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2629 Rev 2731
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2012. 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
;;  IPv4.INC                                                       ;;
6
;;  IPv4.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: 2629 $
19
$Revision: 2731 $
20
 
20
 
21
MAX_FRAGMENTS           = 64
21
MAX_FRAGMENTS                   = 64
22
MAX_IP                  = MAX_NET_DEVICES
22
MAX_IP                          = MAX_NET_DEVICES
23
IP_MAX_INTERFACES       = MAX_IP
23
IP_MAX_INTERFACES               = MAX_IP
24
 
24
 
25
struct  IPv4_header
25
struct  IPv4_header
26
 
26
 
27
        VersionAndIHL          db  ?  ; Version[0-3 bits] and IHL(header length)[4-7 bits]
27
        VersionAndIHL           db ?    ; Version[0-3 bits] and IHL(header length)[4-7 bits]
28
        TypeOfService          db  ?  ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
28
        TypeOfService           db ?    ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
29
        TotalLength            dw  ?
29
        TotalLength             dw ?
30
        Identification         dw  ?
30
        Identification          dw ?
31
        FlagsAndFragmentOffset dw  ?  ; Flags[0-2] and FragmentOffset[3-15]
31
        FlagsAndFragmentOffset  dw ?    ; Flags[0-2] and FragmentOffset[3-15]
32
        TimeToLive             db  ?  ;
32
        TimeToLive              db ?    ;
33
        Protocol               db  ?
33
        Protocol                db ?
34
        HeaderChecksum         dw  ?
34
        HeaderChecksum          dw ?
35
        SourceAddress          dd  ?
35
        SourceAddress           dd ?
36
        DestinationAddress     dd  ?
36
        DestinationAddress      dd ?
37
 
37
 
38
ends
38
ends
39
 
39
 
40
struct  FRAGMENT_slot
40
struct  FRAGMENT_slot
41
 
41
 
42
        ttl                    dw  ?  ; Time to live for this entry, 0 for empty slot's
42
        ttl                     dw ?    ; Time to live for this entry, 0 for empty slot's
43
        id                     dw  ?  ; Identification field from IP header
43
        id                      dw ?    ; Identification field from IP header
44
        SrcIP                  dd  ?  ; .. from IP header
44
        SrcIP                   dd ?    ; .. from IP header
45
        DstIP                  dd  ?  ; .. from IP header
45
        DstIP                   dd ?    ; .. from IP header
46
        ptr                    dd  ?  ; Pointer to first packet
46
        ptr                     dd ?    ; Pointer to first packet
47
 
47
 
48
ends
48
ends
49
 
49
 
50
struct  FRAGMENT_entry                 ; This structure will replace the ethernet header in fragmented ip packets
50
struct  FRAGMENT_entry                  ; This structure will replace the ethernet header in fragmented ip packets
51
 
51
 
52
        PrevPtr                dd  ?  ; Pointer to previous fragment entry  (-1 for first packet)
52
        PrevPtr                 dd ?    ; Pointer to previous fragment entry  (-1 for first packet)
53
        NextPtr                dd  ?  ; Pointer to next fragment entry (-1 for last packet)
53
        NextPtr                 dd ?    ; Pointer to next fragment entry (-1 for last packet)
54
        Owner                  dd  ?  ; Pointer to structure of driver
54
        Owner                   dd ?    ; Pointer to structure of driver
55
                               rb  2  ; to match ethernet header size          ; TODO: fix this hack
55
                                rb 2    ; to match ethernet header size         ;;; FIXME
56
                                      ; Ip header begins here (we will need the IP header to re-construct the complete packet)
56
                                        ; Ip header begins here (we will need the IP header to re-construct the complete packet)
57
ends
57
ends
58
 
58
 
59
 
59
 
60
align 4
60
align 4
61
uglobal
61
uglobal
62
 
62
 
63
        IP_LIST         rd  MAX_IP
63
        IP_LIST         rd MAX_IP
64
        SUBNET_LIST     rd  MAX_IP
64
        SUBNET_LIST     rd MAX_IP
65
        DNS_LIST        rd  MAX_IP
65
        DNS_LIST        rd MAX_IP
66
        GATEWAY_LIST    rd  MAX_IP
66
        GATEWAY_LIST    rd MAX_IP
-
 
67
        BROADCAST_LIST  rd MAX_IP
67
 
68
 
68
        IP_PACKETS_TX   rd  MAX_IP
69
        IP_PACKETS_TX   rd MAX_IP
69
        IP_PACKETS_RX   rd  MAX_IP
70
        IP_PACKETS_RX   rd MAX_IP
70
 
71
 
71
        FRAGMENT_LIST   rb  MAX_FRAGMENTS * sizeof.FRAGMENT_slot
72
        FRAGMENT_LIST   rb MAX_FRAGMENTS * sizeof.FRAGMENT_slot
72
endg
73
endg
73
 
74
 
74
 
75
 
75
;-----------------------------------------------------------------
76
;-----------------------------------------------------------------
76
;
77
;
77
; IPv4_init
78
; IPv4_init
78
;
79
;
79
;  This function resets all IP variables
80
;  This function resets all IP variables
80
;
81
;
81
;-----------------------------------------------------------------
82
;-----------------------------------------------------------------
82
macro   IPv4_init {
83
macro   IPv4_init {
83
 
84
 
84
        xor     eax, eax
85
        xor     eax, eax
85
        mov     edi, IP_LIST
86
        mov     edi, IP_LIST
86
        mov     ecx, 4*MAX_IP
-
 
87
        rep     stosd
-
 
88
 
-
 
89
        mov     edi, FRAGMENT_LIST
-
 
90
        mov     ecx, sizeof.FRAGMENT_slot*MAX_FRAGMENTS/4 + 2*MAX_IP
87
        mov     ecx, 7*MAX_IP + (sizeof.FRAGMENT_slot*MAX_FRAGMENTS)/4
91
        rep     stosd
88
        rep     stosd
92
 
89
 
93
}
90
}
94
 
91
 
95
 
92
 
96
;-----------------------------------------------------------------
93
;-----------------------------------------------------------------
97
;
94
;
98
; Decrease TimeToLive of all fragment slots
95
; Decrease TimeToLive of all fragment slots
99
;
96
;
100
;-----------------------------------------------------------------
97
;-----------------------------------------------------------------
101
macro IPv4_decrease_fragment_ttls {
98
macro IPv4_decrease_fragment_ttls {
102
 
99
 
103
local   .loop
100
local   .loop, .next
104
 
101
 
105
        mov     esi, FRAGMENT_LIST
102
        mov     esi, FRAGMENT_LIST
106
        mov     ecx, MAX_FRAGMENTS
103
        mov     ecx, MAX_FRAGMENTS
107
  .loop:
104
  .loop:
108
        cmp     [esi + FRAGMENT_slot.ttl], 0
105
        cmp     [esi + FRAGMENT_slot.ttl], 0
109
        je      .try_next
106
        je      .next
110
        dec     [esi + FRAGMENT_slot.ttl]
107
        dec     [esi + FRAGMENT_slot.ttl]
-
 
108
        jz      .died
-
 
109
  .next:
-
 
110
        add     esi, sizeof.FRAGMENT_slot
-
 
111
        dec     ecx
111
        jnz     .try_next
112
        jnz     .loop
-
 
113
        jmp     .done
-
 
114
 
-
 
115
  .died:
112
        DEBUGF 1,"Fragment slot timed-out!\n"
116
        DEBUGF 1,"Fragment slot timed-out!\n"
113
;;; TODO: clear all entry's of timed-out slot
117
;;; TODO: clear all entry's of timed-out slot
114
  .try_next:
-
 
115
        add     esi, 4
118
        jmp     .next
-
 
119
 
116
        loop    .loop
120
  .done:
117
}
121
}
118
 
122
 
119
 
123
 
120
 
124
 
121
macro IPv4_checksum ptr {
125
macro IPv4_checksum ptr {
122
 
126
 
123
; This is the fast procedure to create or check an IP header without options
127
; This is the fast procedure to create or check an IP header without options
124
; To create a new checksum, the checksum field must be set to 0 before computation
128
; To create a new checksum, the checksum field must be set to 0 before computation
125
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
129
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
126
 
130
 
127
        push    ebx
131
        push    ebx
128
        xor     ebx, ebx
132
        xor     ebx, ebx
129
        add     bl, [ptr+1]
133
        add     bl, [ptr+1]
130
        adc     bh, [ptr+0]
134
        adc     bh, [ptr+0]
131
 
135
 
132
        adc     bl, [ptr+3]
136
        adc     bl, [ptr+3]
133
        adc     bh, [ptr+2]
137
        adc     bh, [ptr+2]
134
 
138
 
135
        adc     bl, [ptr+5]
139
        adc     bl, [ptr+5]
136
        adc     bh, [ptr+4]
140
        adc     bh, [ptr+4]
137
 
141
 
138
        adc     bl, [ptr+7]
142
        adc     bl, [ptr+7]
139
        adc     bh, [ptr+6]
143
        adc     bh, [ptr+6]
140
 
144
 
141
        adc     bl, [ptr+9]
145
        adc     bl, [ptr+9]
142
        adc     bh, [ptr+8]
146
        adc     bh, [ptr+8]
143
 
147
 
144
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
148
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
145
 
149
 
146
        adc     bl, [ptr+13]
150
        adc     bl, [ptr+13]
147
        adc     bh, [ptr+12]
151
        adc     bh, [ptr+12]
148
 
152
 
149
        adc     bl, [ptr+15]
153
        adc     bl, [ptr+15]
150
        adc     bh, [ptr+14]
154
        adc     bh, [ptr+14]
151
 
155
 
152
        adc     bl, [ptr+17]
156
        adc     bl, [ptr+17]
153
        adc     bh, [ptr+16]
157
        adc     bh, [ptr+16]
154
 
158
 
155
        adc     bl, [ptr+19]
159
        adc     bl, [ptr+19]
156
        adc     bh, [ptr+18]
160
        adc     bh, [ptr+18]
157
 
161
 
158
        adc     ebx, 0
162
        adc     ebx, 0
159
 
163
 
160
        push    ecx
164
        push    ecx
161
        mov     ecx, ebx
165
        mov     ecx, ebx
162
        shr     ecx, 16
166
        shr     ecx, 16
163
        and     ebx, 0xffff
167
        and     ebx, 0xffff
164
        add     ebx, ecx
168
        add     ebx, ecx
165
 
169
 
166
        mov     ecx, ebx
170
        mov     ecx, ebx
167
        shr     ecx, 16
171
        shr     ecx, 16
168
        add     ebx, ecx
172
        add     ebx, ecx
169
 
173
 
170
        not     bx
174
        not     bx
171
        jnz     .not_zero
175
        jnz     .not_zero
172
        dec     bx
176
        dec     bx
173
  .not_zero:
177
  .not_zero:
174
        xchg    bl, bh
178
        xchg    bl, bh
175
        pop     ecx
179
        pop     ecx
176
 
180
 
177
        neg     word [ptr+10]           ; zero will stay zero so we just get the checksum
181
        neg     word [ptr+10]           ; zero will stay zero so we just get the checksum
178
        add     word [ptr+10], bx       ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
182
        add     word [ptr+10], bx       ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
179
        pop     ebx
183
        pop     ebx
180
 
184
 
181
}
185
}
182
 
186
 
183
 
187
 
184
 
188
 
185
;-----------------------------------------------------------------
189
;-----------------------------------------------------------------
186
;
190
;
187
; IPv4_input:
191
; IPv4_input:
188
;
192
;
189
;  Will check if IP Packet isnt damaged
193
;  Will check if IPv4 Packet isnt damaged
190
;  and call appropriate handler. (TCP/UDP/ICMP/..)
194
;  and call appropriate handler. (TCP/UDP/ICMP/..)
191
;
195
;
192
;  It will also re-construct fragmented packets
196
;  It will also re-construct fragmented packets
193
;
197
;
194
;  IN:  Pointer to buffer in [esp]
198
;  IN:  Pointer to buffer in [esp]
195
;       size of buffer in [esp+4]
199
;       size of buffer in [esp+4]
196
;       pointer to device struct in ebx
200
;       pointer to device struct in ebx
197
;       pointer to IP header in edx
201
;       pointer to IPv4 header in edx
198
;       size of IP packet in ecx
202
;       size of IPv4 packet in ecx
199
;  OUT: /
203
;  OUT: /
200
;
204
;
201
;-----------------------------------------------------------------
205
;-----------------------------------------------------------------
202
align 4
206
align 4
203
IPv4_input:      ; TODO: add code for raw sockets
207
IPv4_input:                                                     ; TODO: add IPv4 raw sockets support
204
 
208
 
-
 
209
        DEBUGF  1,"IPv4_input, packet from: %u.%u.%u.%u ",\
205
        DEBUGF  1,"IPv4_input, packet from: %u.%u.%u.%u ",\
210
        [edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
206
        [edx + IPv4_header.SourceAddress]:1,[edx + IPv4_header.SourceAddress + 1]:1,[edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
211
        [edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
207
        DEBUGF  1,"to: %u.%u.%u.%u\n",\
212
        DEBUGF  1,"to: %u.%u.%u.%u\n",\
208
        [edx + IPv4_header.DestinationAddress]:1,[edx + IPv4_header.DestinationAddress + 1]:1,[edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
-
 
209
 
-
 
210
;-------------------------------------------
-
 
211
; Check if the packet still has time to live
-
 
212
 
213
        [edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
213
        cmp     byte [edx + IPv4_header.TimeToLive], 0
-
 
214
        je      .dump
214
        [edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
215
 
215
 
216
;-------------------------------
216
;-------------------------------
217
; Now, re-calculate the checksum
217
; re-calculate the checksum
218
 
218
 
219
        IPv4_checksum edx
219
        IPv4_checksum edx
220
        jnz     .dump                                           ; if checksum isn't valid then dump packet
220
        jnz     .dump                                           ; if checksum isn't valid then dump packet
221
 
221
 
222
        DEBUGF  1,"IPv4 Checksum is correct\n"
222
        DEBUGF  1,"IPv4 Checksum is correct\n"
223
 
223
 
224
;-----------------------------------
224
;-----------------------------------
225
; Check if destination IP is correct
225
; Check if destination IP is correct
226
 
226
 
227
        call    NET_ptr_to_num
227
        call    NET_ptr_to_num
228
        shl     edi, 2
228
        shl     edi, 2
229
 
229
 
230
        ; check if it matches local ip
230
        ; check if it matches local ip
231
 
231
 
232
        mov     eax, [IP_LIST+edi]
232
        mov     eax, [edx + IPv4_header.DestinationAddress]
233
        cmp     [edx + IPv4_header.DestinationAddress], eax
233
        cmp     eax, [IP_LIST+edi]
234
        je      .ip_ok
234
        je      .ip_ok
235
 
235
 
236
        ; check for broadcast
-
 
237
 
-
 
238
        mov     eax, [SUBNET_LIST+edi]
-
 
239
        not     eax
236
        ; check for broadcast (IP or (not SUBNET))
240
        or      eax, [IP_LIST+edi]
237
 
241
        cmp     [edx + IPv4_header.DestinationAddress], eax
238
        cmp     eax, [BROADCAST_LIST+edi]
242
        je      .ip_ok
239
        je      .ip_ok
243
 
240
 
244
        ; or a special broadcast
-
 
245
 
241
        ; or a special broadcast (255.255.255.255)
246
        cmp     [edx + IPv4_header.DestinationAddress], -1
242
 
247
        je      .ip_ok
243
        cmp     eax, 0xffffffff
248
 
244
        je      .ip_ok
-
 
245
 
249
        ; maybe it's a multicast then
246
        ; maybe it's a multicast (224.0.0.0/4)
250
 
247
 
251
        mov     eax, [edx + IPv4_header.DestinationAddress]
248
        and     eax, 0x0fffffff
252
        and     eax, 0xff000000
249
        cmp     eax, 224
253
;        cmp     eax, 224 shl 24
250
        je      .ip_ok
254
;        je      .ip_ok
251
 
255
 
252
        ; or a loopback address (127.0.0.0/8)
256
        ; or a loopback address
253
 
257
 
254
        and     eax, 0x00ffffff
258
        cmp     eax, 127 shl 24
255
        cmp     eax, 127
259
        je      .ip_ok
256
        je      .ip_ok
260
 
257
 
261
        ; or it's not meant for us..
258
        ; or it's just not meant for us.. :(
262
 
259
 
263
        DEBUGF  2,"Destination address does not match!\n"
260
        DEBUGF  2,"IPv4_input - Destination address does not match!\n"
264
        jmp     .dump
261
        jmp     .dump
265
 
262
 
266
;------------------------
263
;------------------------
267
; Now we can update stats
264
; Now we can update stats
268
 
265
 
269
  .ip_ok:
266
  .ip_ok:
270
        inc     [IP_PACKETS_RX+edi]
267
        inc     [IP_PACKETS_RX+edi]
271
 
268
 
272
;----------------------------------
269
;----------------------------------
273
; Check if the packet is fragmented
270
; Check if the packet is fragmented
274
 
271
 
275
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 1 shl 5     ; Is 'more fragments' flag set ?
272
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 1 shl 5     ; Is 'more fragments' flag set ?
276
        jnz     .has_fragments                                          ; If so, we definately have a fragmented packet
273
        jnz     .has_fragments                                          ; If so, we definately have a fragmented packet
277
 
274
 
278
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 0xff1f      ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
275
        test    [edx + IPv4_header.FlagsAndFragmentOffset], 0xff1f      ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
279
        jnz     .is_last_fragment
276
        jnz     .is_last_fragment
280
 
277
 
281
;-------------------------------------------------------------------
278
;-------------------------------------------------------------------
282
; No, it's just a regular IP packet, pass it to the higher protocols
279
; No, it's just a regular IP packet, pass it to the higher protocols
283
 
280
 
284
  .handle_it:                                                   ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
281
  .handle_it:                                                   ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
285
 
282
 
286
        movzx   esi, [edx + IPv4_header.VersionAndIHL]          ; Calculate Header length by using IHL field
283
        movzx   esi, [edx + IPv4_header.VersionAndIHL]          ; Calculate Header length by using IHL field
287
        and     esi, 0x0000000f                                 ;
284
        and     esi, 0x0000000f                                 ;
288
        shl     esi, 2                                          ;
285
        shl     esi, 2                                          ;
289
 
286
 
290
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
287
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
291
        xchg    cl , ch                                         ;
288
        xchg    cl, ch                                          ;
292
        sub     ecx, esi                                        ;
289
        sub     ecx, esi                                        ;
293
 
290
 
294
        lea     edi, [edx + IPv4_header.SourceAddress]          ; make edi ptr to source and dest IPv4 address
291
        lea     edi, [edx + IPv4_header.SourceAddress]          ; make edi ptr to source and dest IPv4 address
295
        mov     al , [edx + IPv4_header.Protocol]
292
        mov     al, [edx + IPv4_header.Protocol]
296
        add     esi, edx                                        ; make esi ptr to data
293
        add     esi, edx                                        ; make esi ptr to data
297
 
294
 
298
        cmp     al, IP_PROTO_TCP
295
        cmp     al, IP_PROTO_TCP
299
        je      TCP_input
296
        je      TCP_input
300
 
297
 
301
        cmp     al, IP_PROTO_UDP
298
        cmp     al, IP_PROTO_UDP
302
        je      UDP_input
299
        je      UDP_input
303
 
300
 
304
        cmp     al, IP_PROTO_ICMP
301
        cmp     al, IP_PROTO_ICMP
305
        je      ICMP_input
302
        je      ICMP_input
306
 
303
 
307
        DEBUGF  2,"unknown Internet protocol: %u\n", al
304
        DEBUGF  2,"IPv4_input - unknown protocol: %u\n", al
308
 
305
 
309
  .dump:
306
  .dump:
310
        DEBUGF  2,"IP_Handler - dumping\n"
307
        DEBUGF  2,"IPv4_input - dumping\n"
311
;        inc     [dumped_rx_count]
308
;        inc     [dumped_rx_count]
312
        call    kernel_free
309
        call    kernel_free
313
        add     esp, 4                                          ; pop (balance stack)
310
        add     esp, 4                                          ; pop (balance stack)
314
        ret
311
        ret
315
 
312
 
316
 
313
 
317
;---------------------------
314
;---------------------------
318
; Fragmented packet handler
315
; Fragmented packet handler
319
 
316
 
320
 
317
 
321
  .has_fragments:
318
  .has_fragments:
322
        movzx   eax, [edx + IPv4_header.FlagsAndFragmentOffset]
319
        movzx   eax, [edx + IPv4_header.FlagsAndFragmentOffset]
323
        xchg    al , ah
320
        xchg    al , ah
324
        shl     ax , 3
321
        shl     ax , 3
325
 
322
 
326
        DEBUGF  1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_header.Identification]:4
323
        DEBUGF  1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_header.Identification]:4
327
 
324
 
328
        test    ax , ax                                         ; Is this the first packet of the fragment?
325
        test    ax , ax                                         ; Is this the first packet of the fragment?
329
        jz      .is_first_fragment
326
        jz      .is_first_fragment
330
 
327
 
331
 
328
 
332
;-------------------------------------------------------
329
;-------------------------------------------------------
333
; We have a fragmented IP packet, but it's not the first
330
; We have a fragmented IP packet, but it's not the first
334
 
331
 
335
        DEBUGF  1,"Middle fragmented packet received!\n"
332
        DEBUGF  1,"Middle fragmented packet received!\n"
336
 
333
 
337
        call    IPv4_find_fragment_slot
334
        call    IPv4_find_fragment_slot
338
        cmp     esi, -1
335
        cmp     esi, -1
339
        je      .dump
336
        je      .dump
340
 
337
 
341
        mov     [esi + FRAGMENT_slot.ttl], 15                   ; Reset the ttl
338
        mov     [esi + FRAGMENT_slot.ttl], 15                   ; Reset the ttl
342
        mov     esi, [esi + FRAGMENT_slot.ptr]
339
        mov     esi, [esi + FRAGMENT_slot.ptr]
343
        or      edi, -1
340
        or      edi, -1
344
  .find_last_entry:                                             ; The following routine will try to find the last entry
341
  .find_last_entry:                                             ; The following routine will try to find the last entry
345
        cmp     edi, [esi + FRAGMENT_entry.PrevPtr]
342
        cmp     edi, [esi + FRAGMENT_entry.PrevPtr]
346
        jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
343
        jne     .destroy_slot                                   ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
347
        mov     edi, esi
344
        mov     edi, esi
348
        mov     esi, [esi + FRAGMENT_entry.NextPtr]
345
        mov     esi, [esi + FRAGMENT_entry.NextPtr]
349
        cmp     esi, -1
346
        cmp     esi, -1
350
        jne     .find_last_entry
347
        jne     .find_last_entry
351
                                                                ; We found the last entry (pointer is now in edi)
348
                                                                ; We found the last entry (pointer is now in edi)
352
                                                                ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
349
                                                                ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
353
 
350
 
354
        pop     eax                                             ; pointer to packet
351
        pop     eax                                             ; pointer to packet
355
        mov     [edi + FRAGMENT_entry.NextPtr], eax             ; update pointer of previous entry to the new entry
352
        mov     [edi + FRAGMENT_entry.NextPtr], eax             ; update pointer of previous entry to the new entry
356
        mov     [eax + FRAGMENT_entry.NextPtr], -1
353
        mov     [eax + FRAGMENT_entry.NextPtr], -1
357
        mov     [eax + FRAGMENT_entry.PrevPtr], edi
354
        mov     [eax + FRAGMENT_entry.PrevPtr], edi
358
        mov     [eax + FRAGMENT_entry.Owner], ebx
355
        mov     [eax + FRAGMENT_entry.Owner], ebx
359
 
356
 
360
        add     esp, 4
357
        add     esp, 4
361
        ret
358
        ret
362
 
359
 
363
 
360
 
364
;------------------------------------
361
;------------------------------------
365
; We have received the first fragment
362
; We have received the first fragment
366
 
363
 
367
  .is_first_fragment:
364
  .is_first_fragment:
368
        DEBUGF  1,"First fragmented packet received!\n"
365
        DEBUGF  1,"First fragmented packet received!\n"
369
                                                                ; try to locate a free slot..
366
                                                                ; try to locate a free slot..
370
        mov     ecx, MAX_FRAGMENTS
367
        mov     ecx, MAX_FRAGMENTS
371
        mov     esi, FRAGMENT_LIST
368
        mov     esi, FRAGMENT_LIST
372
  .find_free_slot:
369
  .find_free_slot:
373
        cmp     word [esi + FRAGMENT_slot.ttl], 0
370
        cmp     word [esi + FRAGMENT_slot.ttl], 0
374
        je      .found_free_slot
371
        je      .found_free_slot
375
        add     esi, sizeof.FRAGMENT_slot
372
        add     esi, sizeof.FRAGMENT_slot
376
        loop    .find_free_slot
373
        loop    .find_free_slot
377
        jmp     .dump                                           ; If no free slot was found, dump the packet
374
        jmp     .dump                                           ; If no free slot was found, dump the packet
378
 
375
 
379
  .found_free_slot:                                             ; We found a free slot, let's fill in the FRAGMENT_slot structure
376
  .found_free_slot:                                             ; We found a free slot, let's fill in the FRAGMENT_slot structure
380
        mov     [esi + FRAGMENT_slot.ttl], 15                   ; RFC recommends 15 secs as ttl
377
        mov     [esi + FRAGMENT_slot.ttl], 15                   ; RFC recommends 15 secs as ttl
381
        mov     ax , [edx + IPv4_header.Identification]
378
        mov     ax , [edx + IPv4_header.Identification]
382
        mov     [esi + FRAGMENT_slot.id], ax
379
        mov     [esi + FRAGMENT_slot.id], ax
383
        mov     eax,[edx + IPv4_header.SourceAddress]
380
        mov     eax,[edx + IPv4_header.SourceAddress]
384
        mov     [esi + FRAGMENT_slot.SrcIP], eax
381
        mov     [esi + FRAGMENT_slot.SrcIP], eax
385
        mov     eax, [edx + IPv4_header.DestinationAddress]
382
        mov     eax, [edx + IPv4_header.DestinationAddress]
386
        mov     [esi + FRAGMENT_slot.DstIP], eax
383
        mov     [esi + FRAGMENT_slot.DstIP], eax
387
        pop     eax
384
        pop     eax
388
        mov     [esi + FRAGMENT_slot.ptr], eax
385
        mov     [esi + FRAGMENT_slot.ptr], eax
389
                                                                ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
386
                                                                ; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
390
        mov     [eax + FRAGMENT_entry.NextPtr], -1
387
        mov     [eax + FRAGMENT_entry.NextPtr], -1
391
        mov     [eax + FRAGMENT_entry.PrevPtr], -1
388
        mov     [eax + FRAGMENT_entry.PrevPtr], -1
392
        mov     [eax + FRAGMENT_entry.Owner], ebx
389
        mov     [eax + FRAGMENT_entry.Owner], ebx
393
 
390
 
394
        add     esp, 4                                          ; balance stack and exit
391
        add     esp, 4                                          ; balance stack and exit
395
        ret
392
        ret
396
 
393
 
397
 
394
 
398
;-----------------------------------
395
;-----------------------------------
399
; We have received the last fragment
396
; We have received the last fragment
400
 
397
 
401
  .is_last_fragment:
398
  .is_last_fragment:
402
        DEBUGF  1,"Last fragmented packet received!\n"
399
        DEBUGF  1,"Last fragmented packet received!\n"
403
 
400
 
404
        call    IPv4_find_fragment_slot
401
        call    IPv4_find_fragment_slot
405
        cmp     esi, -1
402
        cmp     esi, -1
406
        je      .dump
403
        je      .dump
407
 
404
 
408
        mov     esi, [esi + FRAGMENT_slot.ptr]                  ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
405
        mov     esi, [esi + FRAGMENT_slot.ptr]                  ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
409
        push    esi
406
        push    esi
410
        xor     eax, eax
407
        xor     eax, eax
411
        or      edi, -1
408
        or      edi, -1
412
 
409
 
413
  .count_bytes:
410
  .count_bytes:
414
        cmp     [esi + FRAGMENT_entry.PrevPtr], edi
411
        cmp     [esi + FRAGMENT_entry.PrevPtr], edi
415
        jne     .destroy_slot_pop                                               ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
412
        jne     .destroy_slot_pop                                               ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
416
        mov     cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength]       ; Add total length
413
        mov     cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength]       ; Add total length
417
        xchg    cl, ch
414
        xchg    cl, ch
418
        DEBUGF  1,"Packet size: %u\n", cx
415
        DEBUGF  1,"Packet size: %u\n", cx
419
        add     ax, cx
416
        add     ax, cx
420
        movzx   cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL]     ; Sub Header length
417
        movzx   cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL]     ; Sub Header length
421
        and     cx, 0x000F
418
        and     cx, 0x000F
422
        shl     cx, 2
419
        shl     cx, 2
423
        DEBUGF  1,"Header size: %u\n", cx
420
        DEBUGF  1,"Header size: %u\n", cx
424
        sub     ax, cx
421
        sub     ax, cx
425
        mov     edi, esi
422
        mov     edi, esi
426
        mov     esi, [esi + FRAGMENT_entry.NextPtr]
423
        mov     esi, [esi + FRAGMENT_entry.NextPtr]
427
        cmp     esi, -1
424
        cmp     esi, -1
428
        jne     .count_bytes
425
        jne     .count_bytes
429
 
426
 
430
        mov     esi, [esp+4]
427
        mov     esi, [esp+4]
431
        mov     [edi + FRAGMENT_entry.NextPtr], esi                            ; Add this packet to the chain, this simplifies the following code
428
        mov     [edi + FRAGMENT_entry.NextPtr], esi                            ; Add this packet to the chain, this simplifies the following code
432
        mov     [esi + FRAGMENT_entry.NextPtr], -1
429
        mov     [esi + FRAGMENT_entry.NextPtr], -1
433
        mov     [esi + FRAGMENT_entry.PrevPtr], edi
430
        mov     [esi + FRAGMENT_entry.PrevPtr], edi
434
        mov     [esi + FRAGMENT_entry.Owner], ebx
431
        mov     [esi + FRAGMENT_entry.Owner], ebx
435
 
432
 
436
        mov     cx, [edx + IPv4_header.TotalLength]                            ; Note: This time we dont substract Header length
433
        mov     cx, [edx + IPv4_header.TotalLength]                            ; Note: This time we dont substract Header length
437
        xchg    cl , ch
434
        xchg    cl , ch
438
        DEBUGF  1,"Packet size: %u\n", cx
435
        DEBUGF  1,"Packet size: %u\n", cx
439
        add     ax , cx
436
        add     ax , cx
440
        DEBUGF  1,"Total Received data size: %u\n", eax
437
        DEBUGF  1,"Total Received data size: %u\n", eax
441
 
438
 
442
        push    eax
439
        push    eax
443
        mov     ax , [edx + IPv4_header.FlagsAndFragmentOffset]
440
        mov     ax , [edx + IPv4_header.FlagsAndFragmentOffset]
444
        xchg    al , ah
441
        xchg    al , ah
445
        shl     ax , 3
442
        shl     ax , 3
446
        add     cx , ax
443
        add     cx , ax
447
        pop     eax
444
        pop     eax
448
        DEBUGF  1,"Total Fragment size: %u\n", ecx
445
        DEBUGF  1,"Total Fragment size: %u\n", ecx
449
 
446
 
450
        cmp     ax, cx
447
        cmp     ax, cx
451
        jne     .destroy_slot_pop
448
        jne     .destroy_slot_pop
452
 
449
 
453
        push    eax
450
        push    eax
454
        push    eax
451
        push    eax
455
        call    kernel_alloc
452
        call    kernel_alloc
456
        test    eax, eax
453
        test    eax, eax
457
        je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
454
        je      .destroy_slot_pop                                                       ; If we dont have enough space to allocate the buffer, discard all packets in slot
458
        mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
455
        mov     edx, [esp+4]                                                            ; Get pointer to first fragment entry back in edx
459
 
456
 
460
  .rebuild_packet_loop:
457
  .rebuild_packet_loop:
461
        movzx   ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset]   ; Calculate the fragment offset
458
        movzx   ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset]   ; Calculate the fragment offset
462
        xchg    cl , ch                                                                 ;  intel byte order
459
        xchg    cl , ch                                                                 ;  intel byte order
463
        shl     cx , 3                                                                  ;   multiply by 8 and clear first 3 bits
460
        shl     cx , 3                                                                  ;   multiply by 8 and clear first 3 bits
464
        DEBUGF  1,"Fragment offset: %u\n", cx
461
        DEBUGF  1,"Fragment offset: %u\n", cx
465
 
462
 
466
        lea     edi, [eax + ecx]                                                        ; Notice that edi will be equal to eax for first fragment
463
        lea     edi, [eax + ecx]                                                        ; Notice that edi will be equal to eax for first fragment
467
        movzx   ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL]            ; Find header size (in ebx) of fragment
464
        movzx   ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL]            ; Find header size (in ebx) of fragment
468
        and     bx , 0x000F                                                             ;
465
        and     bx , 0x000F                                                             ;
469
        shl     bx , 2                                                                  ;
466
        shl     bx , 2                                                                  ;
470
 
467
 
471
        lea     esi, [edx + sizeof.FRAGMENT_entry]                                        ; Set esi to the correct begin of fragment
468
        lea     esi, [edx + sizeof.FRAGMENT_entry]                                        ; Set esi to the correct begin of fragment
472
        movzx   ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.TotalLength]              ; Calculate total length of fragment
469
        movzx   ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.TotalLength]              ; Calculate total length of fragment
473
        xchg    cl, ch                                                                  ;  intel byte order
470
        xchg    cl, ch                                                                  ;  intel byte order
474
 
471
 
475
        cmp     edi, eax                                                                ; Is this packet the first fragment ?
472
        cmp     edi, eax                                                                ; Is this packet the first fragment ?
476
        je      .first_fragment
473
        je      .first_fragment
477
        sub     cx, bx                                                                  ; If not, dont copy the header
474
        sub     cx, bx                                                                  ; If not, dont copy the header
478
        add     esi, ebx                                                                ;
475
        add     esi, ebx                                                                ;
479
  .first_fragment:
476
  .first_fragment:
480
 
477
 
481
        push    cx                                                                      ; First copy dword-wise, then byte-wise
478
        push    cx                                                                      ; First copy dword-wise, then byte-wise
482
        shr     cx, 2                                                                   ;
479
        shr     cx, 2                                                                   ;
483
        rep     movsd                                                                   ;
480
        rep     movsd                                                                   ;
484
        pop     cx                                                                      ;
481
        pop     cx                                                                      ;
485
        and     cx, 3                                                                   ;
482
        and     cx, 3                                                                   ;
486
        rep     movsb                                                                   ;
483
        rep     movsb                                                                   ;
487
 
484
 
488
        push    eax
485
        push    eax
489
        push    edx                                                                     ; Push pointer to fragment onto stack
486
        push    edx                                                                     ; Push pointer to fragment onto stack
490
        mov     ebx, [edx + FRAGMENT_entry.Owner]                                       ; we need to remeber the owner, in case this is the last packet
487
        mov     ebx, [edx + FRAGMENT_entry.Owner]                                       ; we need to remeber the owner, in case this is the last packet
491
        mov     edx, [edx + FRAGMENT_entry.NextPtr]                                     ; Set edx to the next pointer
488
        mov     edx, [edx + FRAGMENT_entry.NextPtr]                                     ; Set edx to the next pointer
492
        call    kernel_free                                                             ; free the previous fragment buffer (this uses the value from stack)
489
        call    kernel_free                                                             ; free the previous fragment buffer (this uses the value from stack)
493
        pop     eax
490
        pop     eax
494
        cmp     edx, -1                                                                 ; Check if it is last fragment in chain
491
        cmp     edx, -1                                                                 ; Check if it is last fragment in chain
495
        jne     .rebuild_packet_loop
492
        jne     .rebuild_packet_loop
496
 
493
 
497
        pop     ecx
494
        pop     ecx
498
        xchg    cl, ch
495
        xchg    cl, ch
499
        mov     edx, eax
496
        mov     edx, eax
500
        mov     [edx + IPv4_header.TotalLength], cx
497
        mov     [edx + IPv4_header.TotalLength], cx
501
        add     esp, 8
498
        add     esp, 8
-
 
499
        xchg    cl, ch
-
 
500
        push    ecx
502
 
-
 
503
        xchg    cl, ch              ;
-
 
504
 
-
 
505
        push    ecx                ;;;;
-
 
506
        push    eax                ;;;;
-
 
507
 
-
 
508
;        mov     esi, edx           ;  This prints the IP packet to the debug board (usefull when using serial output debug..)
-
 
509
;                                   ;
501
 
510
;        packet_to_debug
-
 
511
 
502
        push    eax
512
        jmp     .handle_it          ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
503
        jmp     .handle_it          ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
513
 
504
 
514
  .destroy_slot_pop:
505
  .destroy_slot_pop:
515
        add     esp, 4
506
        add     esp, 4
516
  .destroy_slot:
507
  .destroy_slot:
517
        DEBUGF  1,"Destroy fragment slot!\n"
508
        DEBUGF  1,"Destroy fragment slot!\n"
518
        ; TODO!
509
        ; TODO!
519
        jmp     .dump
510
        jmp     .dump
520
 
511
 
521
 
512
 
522
 
513
 
523
 
514
 
524
 
515
 
525
;-----------------------------------------------------------------
516
;-----------------------------------------------------------------
526
;
517
;
527
; find fragment slot
518
; find fragment slot
528
;
519
;
529
; IN: pointer to fragmented packet in edx
520
; IN: pointer to fragmented packet in edx
530
; OUT: pointer to slot in edi, -1 on error
521
; OUT: pointer to slot in esi, -1 on error
531
;
522
;
532
;-----------------------------------------------------------------
523
;-----------------------------------------------------------------
533
align 4
524
align 4
534
IPv4_find_fragment_slot:
525
IPv4_find_fragment_slot:
535
 
526
 
536
;;; TODO: the RFC says we should check protocol number too
527
;;; TODO: the RFC says we should check protocol number too
537
 
528
 
538
        push    eax ebx ecx edx
529
        push    eax ebx ecx edx
539
        mov     ax , [edx + IPv4_header.Identification]
530
        mov     ax , [edx + IPv4_header.Identification]
540
        mov     ecx, MAX_FRAGMENTS
531
        mov     ecx, MAX_FRAGMENTS
541
        mov     esi, FRAGMENT_LIST
532
        mov     esi, FRAGMENT_LIST
542
        mov     ebx, [edx + IPv4_header.SourceAddress]
533
        mov     ebx, [edx + IPv4_header.SourceAddress]
543
        mov     edx, [edx + IPv4_header.DestinationAddress]
534
        mov     edx, [edx + IPv4_header.DestinationAddress]
544
  .find_slot:
535
  .find_slot:
545
        cmp     [esi + FRAGMENT_slot.id], ax
536
        cmp     [esi + FRAGMENT_slot.id], ax
546
        jne     .try_next
537
        jne     .try_next
547
        cmp     [esi + FRAGMENT_slot.SrcIP], ebx
538
        cmp     [esi + FRAGMENT_slot.SrcIP], ebx
548
        jne     .try_next
539
        jne     .try_next
549
        cmp     [esi + FRAGMENT_slot.DstIP], edx
540
        cmp     [esi + FRAGMENT_slot.DstIP], edx
550
        je      .found_slot
541
        je      .found_slot
551
  .try_next:
542
  .try_next:
552
        add     esi, sizeof.FRAGMENT_slot
543
        add     esi, sizeof.FRAGMENT_slot
553
        loop    .find_slot
544
        loop    .find_slot
554
;        pop     edx ebx
545
;        pop     edx ebx
555
        or      esi, -1
546
        or      esi, -1
556
;        ret
547
;        ret
557
 
548
 
558
  .found_slot:
549
  .found_slot:
559
        pop     edx ecx ebx eax
550
        pop     edx ecx ebx eax
560
        ret
551
        ret
561
 
552
 
562
 
553
 
563
;------------------------------------------------------------------
554
;------------------------------------------------------------------
564
;
555
;
565
; IPv4_output
556
; IPv4_output
566
;
557
;
567
; IN: eax = dest ip
558
; IN: eax = dest ip
568
;     ebx = source ip
559
;     ebx = source ip
569
;     ecx = data length
560
;     ecx = data length
570
;     dx  = fragment id
561
;     dx  = fragment id
571
;     di  = TTL shl 8 + protocol
562
;     di  = TTL shl 8 + protocol
572
;
563
;
573
; OUT: eax = pointer to buffer start
564
; OUT: eax = pointer to buffer start
574
;      ebx = pointer to device struct (needed for sending procedure)
565
;      ebx = pointer to device struct (needed for sending procedure)
575
;      ecx = unchanged (packet size of embedded data)
566
;      ecx = unchanged (packet size of embedded data)
576
;      edx = size of complete buffer
567
;      edx = size of complete buffer
577
;      edi = pointer to start of data (0 on error)
568
;      edi = pointer to start of data (0 on error)
578
;
569
;
579
;------------------------------------------------------------------
570
;------------------------------------------------------------------
580
align 4
571
align 4
581
IPv4_output:
572
IPv4_output:
582
 
573
 
583
        DEBUGF  1,"IPv4_output: size=%u\n", ecx
574
        DEBUGF  1,"IPv4_output: size=%u\n", ecx
584
 
575
 
585
        cmp     ecx, 65500              ; Max IPv4 packet size
576
        cmp     ecx, 65500              ; Max IPv4 packet size
586
        ja      .too_large
577
        ja      .too_large
587
 
578
 
588
        push    ecx eax ebx dx di
579
        push    ecx eax ebx dx di
589
 
580
 
590
        call    ARP_IP_to_MAC
581
        call    ARP_IP_to_MAC
591
 
582
 
592
        test    eax, 0xffff0000         ; error bits
583
        test    eax, 0xffff0000         ; error bits
593
        jnz     .arp_error
584
        jnz     .arp_error
594
 
585
 
595
        push    ebx     ; push the mac
586
        push    ebx     ; push the mac
596
        push    ax
587
        push    ax
597
 
588
 
598
        call    IPv4_dest_to_dev
589
        call    IPv4_dest_to_dev
599
        inc     [IP_PACKETS_TX+edi]
590
        inc     [IP_PACKETS_TX+edi]
600
        mov     ebx, [NET_DRV_LIST+edi]
591
        mov     ebx, [NET_DRV_LIST+edi]
601
        lea     eax, [ebx + ETH_DEVICE.mac]
592
        lea     eax, [ebx + ETH_DEVICE.mac]
602
        mov     edx, esp
593
        mov     edx, esp
603
        mov     ecx, [esp + 18]
594
        mov     ecx, [esp + 18]
604
        add     ecx, sizeof.IPv4_header
595
        add     ecx, sizeof.IPv4_header
605
        mov     di , ETHER_IPv4
596
        mov     di , ETHER_IPv4
606
        call    ETH_output
597
        call    ETH_output
607
        jz      .eth_error
598
        jz      .eth_error
608
 
599
 
609
        add     esp, 6  ; pop the mac
600
        add     esp, 6  ; pop the mac
610
 
601
 
611
        mov     [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
602
        mov     [edi + IPv4_header.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
612
        mov     [edi + IPv4_header.TypeOfService], 0    ; nothing special, just plain ip packet
603
        mov     [edi + IPv4_header.TypeOfService], 0    ; nothing special, just plain ip packet
613
        mov     [edi + IPv4_header.TotalLength], cx
604
        mov     [edi + IPv4_header.TotalLength], cx
614
        rol     [edi + IPv4_header.TotalLength], 8      ; internet byte order
605
        rol     [edi + IPv4_header.TotalLength], 8      ; internet byte order
615
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], 0x0000
606
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], 0x0000
616
        mov     [edi + IPv4_header.HeaderChecksum], 0
607
        mov     [edi + IPv4_header.HeaderChecksum], 0
617
        pop     word [edi + IPv4_header.TimeToLive]     ; ttl shl 8 + protocol
608
        pop     word [edi + IPv4_header.TimeToLive]     ; ttl shl 8 + protocol
618
;               [edi + IPv4_header.Protocol]
609
;               [edi + IPv4_header.Protocol]
619
        popw    [edi + IPv4_header.Identification]      ; fragment id
610
        popw    [edi + IPv4_header.Identification]      ; fragment id
620
        popd    [edi + IPv4_header.SourceAddress]
611
        popd    [edi + IPv4_header.SourceAddress]
621
        popd    [edi + IPv4_header.DestinationAddress]
612
        popd    [edi + IPv4_header.DestinationAddress]
622
 
613
 
623
        pop     ecx
614
        pop     ecx
624
 
615
 
625
        IPv4_checksum edi
616
        IPv4_checksum edi
626
        add     edi, sizeof.IPv4_header
617
        add     edi, sizeof.IPv4_header
627
        DEBUGF  1,"IPv4 Packet for device %x created successfully\n", ebx
618
        DEBUGF  1,"IPv4 Packet for device %x created successfully\n", ebx
628
        ret
619
        ret
629
 
620
 
630
  .eth_error:
621
  .eth_error:
631
        DEBUGF  1,"IPv4_output: ethernet error\n"
622
        DEBUGF  1,"IPv4_output: ethernet error\n"
632
        add     esp, 3*4+2*2+6
623
        add     esp, 3*4+2*2+6
633
        sub     edi, edi
624
        sub     edi, edi
634
        ret
625
        ret
635
 
626
 
636
  .arp_error:
627
  .arp_error:
637
        DEBUGF  1,"IPv4_output: ARP error (0x%x)\n", eax
628
        DEBUGF  1,"IPv4_output: ARP error (0x%x)\n", eax
638
        add     esp, 4+4+4+2+2
629
        add     esp, 4+4+4+2+2
639
        sub     edi, edi
630
        sub     edi, edi
640
        ret
631
        ret
641
 
632
 
642
  .too_large:
633
  .too_large:
643
        DEBUGF  1,"IPv4_output: error: Packet too large!\n"
634
        DEBUGF  1,"IPv4_output: error: Packet too large!\n"
644
        sub     edi, edi
635
        sub     edi, edi
645
        ret
636
        ret
646
 
637
 
647
 
638
 
648
 
639
 
649
 
640
 
650
 
641
 
651
;------------------------------------------------------------------
642
;------------------------------------------------------------------
652
;
643
;
653
; IPv4_output_raw
644
; IPv4_output_raw
654
;
645
;
655
; IN: eax = socket ptr
646
; IN: eax = socket ptr
656
;     ecx = data length
647
;     ecx = data length
657
;     esi = data ptr
648
;     esi = data ptr
658
;
649
;
659
; OUT: /
650
; OUT: /
660
;
651
;
661
;------------------------------------------------------------------
652
;------------------------------------------------------------------
662
align 4
653
align 4
663
IPv4_output_raw:
654
IPv4_output_raw:
664
 
655
 
665
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
656
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
666
 
657
 
667
        cmp     ecx, 1480               ;;;;; FIXME
658
        cmp     ecx, 1480               ;;;;; FIXME
668
        ja      .too_large
659
        ja      .too_large
669
 
660
 
670
        sub     esp, 8
661
        sub     esp, 8
671
        push    esi eax
662
        push    esi eax
672
 
663
 
673
        call    ARP_IP_to_MAC
664
        call    ARP_IP_to_MAC
674
 
665
 
675
        test    eax, 0xffff0000         ; error bits
666
        test    eax, 0xffff0000         ; error bits
676
        jnz     .arp_error
667
        jnz     .arp_error
677
 
668
 
678
  .continue:
669
  .continue:
679
 
670
 
680
        push    ebx     ; push the mac
671
        push    ebx     ; push the mac
681
        push    ax
672
        push    ax
682
 
673
 
683
        call    IPv4_dest_to_dev
674
        call    IPv4_dest_to_dev
684
        inc     [IP_PACKETS_TX+edi]
675
        inc     [IP_PACKETS_TX+edi]
685
        mov     ebx, [NET_DRV_LIST+edi]
676
        mov     ebx, [NET_DRV_LIST+edi]
686
        lea     eax, [ebx + ETH_DEVICE.mac]
677
        lea     eax, [ebx + ETH_DEVICE.mac]
687
        mov     edx, esp
678
        mov     edx, esp
688
        mov     ecx, [esp + 6+4]
679
        mov     ecx, [esp + 6+4]
689
        add     ecx, sizeof.IPv4_header
680
        add     ecx, sizeof.IPv4_header
690
        mov     di, ETHER_IPv4
681
        mov     di, ETHER_IPv4
691
        call    ETH_output
682
        call    ETH_output
692
        jz      .error
683
        jz      .error
693
 
684
 
694
        add     esp, 6  ; pop the mac
685
        add     esp, 6  ; pop the mac
695
 
686
 
696
        mov     dword[esp+4+4], edx
687
        mov     dword[esp+4+4], edx
697
        mov     dword[esp+4+4+4], eax
688
        mov     dword[esp+4+4+4], eax
698
 
689
 
699
        pop     eax esi
690
        pop     eax esi
700
;; todo: check socket options if we should add header, or just compute checksum
691
;; todo: check socket options if we should add header, or just compute checksum
701
 
692
 
702
        push    edi ecx
693
        push    edi ecx
703
        rep     movsb
694
        rep     movsb
704
        pop     ecx edi
695
        pop     ecx edi
705
 
696
 
706
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
697
;        [edi + IPv4_header.VersionAndIHL]              ; IPv4, normal length (no Optional header)
707
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
698
;        [edi + IPv4_header.TypeOfService]              ; nothing special, just plain ip packet
708
;        [edi + IPv4_header.TotalLength]
699
;        [edi + IPv4_header.TotalLength]
709
;        [edi + IPv4_header.TotalLength]                ; internet byte order
700
;        [edi + IPv4_header.TotalLength]                ; internet byte order
710
;        [edi + IPv4_header.FlagsAndFragmentOffset]
701
;        [edi + IPv4_header.FlagsAndFragmentOffset]
711
 
702
 
712
        mov     [edi + IPv4_header.HeaderChecksum], 0
703
        mov     [edi + IPv4_header.HeaderChecksum], 0
713
 
704
 
714
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
705
;        [edi + IPv4_header.TimeToLive]                 ; ttl shl 8 + protocol
715
;        [edi + IPv4_header.Protocol]
706
;        [edi + IPv4_header.Protocol]
716
;        [edi + IPv4_header.Identification]             ; fragment id
707
;        [edi + IPv4_header.Identification]             ; fragment id
717
;        [edi + IPv4_header.SourceAddress]
708
;        [edi + IPv4_header.SourceAddress]
718
;        [edi + IPv4_header.DestinationAddress]
709
;        [edi + IPv4_header.DestinationAddress]
719
 
710
 
720
        IPv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
711
        IPv4_checksum edi                       ;;;; todo: checksum for IP packet with options!
721
        add     edi, sizeof.IPv4_header
712
        add     edi, sizeof.IPv4_header
722
        DEBUGF  1,"IPv4 Packet for device %x created successfully\n", ebx
713
        DEBUGF  1,"IPv4 Packet for device %x created successfully\n", ebx
723
        call    [ebx + NET_DEVICE.transmit]
714
        call    [ebx + NET_DEVICE.transmit]
724
        ret
715
        ret
725
 
716
 
726
  .error:
717
  .error:
727
        add     esp, 6
718
        add     esp, 6
728
  .arp_error:
719
  .arp_error:
729
        add     esp, 8+4+4
720
        add     esp, 8+4+4
730
  .too_large:
721
  .too_large:
731
        DEBUGF  1,"IPv4_output_raw: Failed\n"
722
        DEBUGF  1,"IPv4_output_raw: Failed\n"
732
        sub     edi, edi
723
        sub     edi, edi
733
        ret
724
        ret
734
 
725
 
735
 
726
 
736
;--------------------------------------------------------
727
;--------------------------------------------------------
737
;
728
;
738
;
729
;
739
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
730
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
740
;     dword [esp+4] = buffer size
731
;     dword [esp+4] = buffer size
741
;     esi = pointer to ip header in that buffer
732
;     esi = pointer to ip header in that buffer
742
;     ecx = max size of fragments
733
;     ecx = max size of fragments
743
;
734
;
744
; OUT: /
735
; OUT: /
745
;
736
;
746
;--------------------------------------------------------
737
;--------------------------------------------------------
747
 
738
 
748
align 4
739
align 4
749
IPv4_fragment:
740
IPv4_fragment:
750
 
741
 
751
        DEBUGF 1,"IPv4_fragment\n"
742
        DEBUGF 1,"IPv4_fragment\n"
752
 
743
 
753
        and     ecx, not 111b   ; align 4
744
        and     ecx, not 111b   ; align 4
754
 
745
 
755
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
746
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
756
        jb      .err2
747
        jb      .err2
757
 
748
 
758
        push    esi ecx
749
        push    esi ecx
759
        mov     eax, [esi + IPv4_header.DestinationAddress]
750
        mov     eax, [esi + IPv4_header.DestinationAddress]
760
        call    ARP_IP_to_MAC
751
        call    ARP_IP_to_MAC
761
        pop     ecx esi
752
        pop     ecx esi
762
        cmp     eax, -1
753
        cmp     eax, -1
763
        jz      .err2
754
        jz      .err2
764
 
755
 
765
        push    ebx
756
        push    ebx
766
        push    ax
757
        push    ax
767
 
758
 
768
        mov     ebx, [NET_DRV_LIST]
759
        mov     ebx, [NET_DRV_LIST]
769
        lea     eax, [ebx + ETH_DEVICE.mac]
760
        lea     eax, [ebx + ETH_DEVICE.mac]
770
        push    eax
761
        push    eax
771
 
762
 
772
 
763
 
773
        push    esi                             ; ptr to ip header
764
        push    esi                             ; ptr to ip header
774
        sub     ecx, sizeof.IPv4_header         ; substract header size
765
        sub     ecx, sizeof.IPv4_header         ; substract header size
775
        push    ecx                             ; max data size
766
        push    ecx                             ; max data size
776
        push    dword 0                         ; offset
767
        push    dword 0                         ; offset
777
 
768
 
778
  .new_fragment:
769
  .new_fragment:
779
        DEBUGF 1,"Ipv4_fragment - new_fragmentn"
770
        DEBUGF 1,"Ipv4_fragment - new_fragmentn"
780
 
771
 
781
 
772
 
782
        mov     eax, [esp + 3*4]
773
        mov     eax, [esp + 3*4]
783
        lea     ebx, [esp + 4*4]
774
        lea     ebx, [esp + 4*4]
784
        mov     di , ETHER_IPv4
775
        mov     di , ETHER_IPv4
785
        call    ETH_output
776
        call    ETH_output
786
 
777
 
787
        cmp     edi, -1
778
        cmp     edi, -1
788
        jz      .err
779
        jz      .err
789
 
780
 
790
; copy header
781
; copy header
791
        mov     esi, [esp + 2*4]
782
        mov     esi, [esp + 2*4]
792
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
783
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
793
        rep     movsd
784
        rep     movsd
794
 
785
 
795
; copy data
786
; copy data
796
        mov     esi, [esp + 2*4]
787
        mov     esi, [esp + 2*4]
797
        add     esi, sizeof.IPv4_header
788
        add     esi, sizeof.IPv4_header
798
        add     esi, [esp]      ; offset
789
        add     esi, [esp]      ; offset
799
 
790
 
800
        mov     ecx, [esp + 1*4]
791
        mov     ecx, [esp + 1*4]
801
        DEBUGF 1,"IPv4_fragment - copying data (%u bytes)\n", ecx
792
        DEBUGF 1,"IPv4_fragment - copying data (%u bytes)\n", ecx
802
        rep     movsb
793
        rep     movsb
803
 
794
 
804
; now, correct header
795
; now, correct header
805
        mov     ecx, [esp + 1*4]
796
        mov     ecx, [esp + 1*4]
806
        add     ecx, sizeof.IPv4_header
797
        add     ecx, sizeof.IPv4_header
807
        xchg    cl, ch
798
        xchg    cl, ch
808
        mov     [edi + IPv4_header.TotalLength], cx
799
        mov     [edi + IPv4_header.TotalLength], cx
809
 
800
 
810
        mov     ecx, [esp]              ; offset
801
        mov     ecx, [esp]              ; offset
811
        xchg    cl, ch
802
        xchg    cl, ch
812
 
803
 
813
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
804
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
814
;        je      .last_fragment
805
;        je      .last_fragment
815
        or      cx, 1 shl 2             ; more fragments
806
        or      cx, 1 shl 2             ; more fragments
816
;  .last_fragment:
807
;  .last_fragment:
817
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
808
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
818
 
809
 
819
        mov     [edi + IPv4_header.HeaderChecksum], 0
810
        mov     [edi + IPv4_header.HeaderChecksum], 0
820
 
811
 
821
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
812
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
822
        mov     ecx, [esp + 1*4]
813
        mov     ecx, [esp + 1*4]
823
 
814
 
824
        push    edx eax
815
        push    edx eax
825
        IPv4_checksum edi
816
        IPv4_checksum edi
826
 
817
 
827
        call    [ebx + NET_DEVICE.transmit]
818
        call    [ebx + NET_DEVICE.transmit]
828
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
819
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
829
 
820
 
830
        mov     ecx,  [esp+4]
821
        mov     ecx,  [esp+4]
831
        add     [esp], ecx
822
        add     [esp], ecx
832
 
823
 
833
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
824
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
834
        add     ecx, [esp+3*4+6+4+4]    ; buff size
825
        add     ecx, [esp+3*4+6+4+4]    ; buff size
835
        sub     ecx, [esp+2*4]          ; ptr to ip header
826
        sub     ecx, [esp+2*4]          ; ptr to ip header
836
        add     ecx, [esp]              ; offset
827
        add     ecx, [esp]              ; offset
837
 
828
 
838
        DEBUGF 1,"Ipv4_fragment - bytes remaining: %u\n", ecx
829
        DEBUGF 1,"Ipv4_fragment - bytes remaining: %u\n", ecx
839
 
830
 
840
        cmp     ecx, [esp+1*4]
831
        cmp     ecx, [esp+1*4]
841
        jae     .new_fragment
832
        jae     .new_fragment
842
 
833
 
843
        mov     [esp+4], ecx            ; set fragment size to remaining packet size
834
        mov     [esp+4], ecx            ; set fragment size to remaining packet size
844
        jmp     .new_fragment
835
        jmp     .new_fragment
845
 
836
 
846
      .err:
837
      .err:
847
        DEBUGF 1,"Ipv4_fragment - failed\n"
838
        DEBUGF 1,"Ipv4_fragment - failed\n"
848
      .done:
839
      .done:
849
        add     esp, 12 + 4 + 6
840
        add     esp, 12 + 4 + 6
850
      .err2:
841
      .err2:
851
        DEBUGF 1,"Ipv4_fragment - dumping\n"
842
        DEBUGF 1,"Ipv4_fragment - dumping\n"
852
        call    kernel_free
843
        call    kernel_free
853
        add     esp, 4
844
        add     esp, 4
854
 
845
 
855
        ret
846
        ret
856
 
847
 
857
 
848
 
858
 
849
 
859
;---------------------------------------------------------------------------
850
;---------------------------------------------------------------------------
860
;
851
;
861
; IPv4_dest_to_dev
852
; IPv4_dest_to_dev
862
;
853
;
863
; IN:  eax = Destination IP
854
; IN:  eax = Destination IP
864
; OUT: edi = device id * 4
855
; OUT: edi = device id * 4
865
;
856
;
866
;---------------------------------------------------------------------------
857
;---------------------------------------------------------------------------
867
align 4
858
align 4
868
IPv4_dest_to_dev:
859
IPv4_dest_to_dev:
869
 
860
 
870
        cmp     eax, 0xffffffff
861
        cmp     eax, 0xffffffff
871
        je      .invalid
862
        je      .invalid
872
 
863
 
873
        xor     edi, edi
864
        xor     edi, edi
874
        mov     ecx, MAX_IP
865
        mov     ecx, MAX_IP
875
 
866
 
876
  .loop:
867
  .loop:
877
        mov     ebx, [IP_LIST+edi]
868
        mov     ebx, [IP_LIST+edi]
878
        and     ebx, [SUBNET_LIST+edi]
869
        and     ebx, [SUBNET_LIST+edi]
879
        jz      .next
870
        jz      .next
880
 
871
 
881
        mov     edx, eax
872
        mov     edx, eax
882
        and     edx, [SUBNET_LIST+edi]
873
        and     edx, [SUBNET_LIST+edi]
883
 
874
 
884
        cmp     ebx, edx
875
        cmp     ebx, edx
885
        je      .found_it
876
        je      .found_it
886
  .next:
877
  .next:
887
        add     edi, 4
878
        add     edi, 4
-
 
879
        dec     ecx
888
        loop    .loop
880
        jnz     .loop
889
 
881
 
890
  .invalid:
882
  .invalid:
891
        xor     edi, edi                        ; if none found, use device 0 as default device
883
        xor     edi, edi                        ; if none found, use device 0 as default device
892
 
884
 
893
  .found_it:
885
  .found_it:
894
        DEBUGF  1,"IPv4_dest_to_dev: %u\n", edi
886
        DEBUGF  1,"IPv4_dest_to_dev: %u\n", edi
895
 
887
 
896
        ret
888
        ret
897
 
889
 
898
 
890
 
899
 
891
 
900
;---------------------------------------------------------------------------
892
;---------------------------------------------------------------------------
901
;
893
;
902
; IPv4_get_frgmnt_num
894
; IPv4_get_frgmnt_num
903
;
895
;
904
; IN: /
896
; IN: /
905
; OUT: fragment number in ax
897
; OUT: fragment number in ax
906
;
898
;
907
;---------------------------------------------------------------------------
899
;---------------------------------------------------------------------------
908
align 4
900
align 4
909
IPv4_get_frgmnt_num:
901
IPv4_get_frgmnt_num:
910
        xor     ax, ax  ;;; TODO: replace this with real code
902
        xor     ax, ax  ;;; TODO: replace this with real code
911
 
903
 
912
        ret
904
        ret
913
 
905
 
914
 
906
 
915
;---------------------------------------------------------------------------
907
;---------------------------------------------------------------------------
916
;
908
;
917
; IPv4_API
909
; IPv4_API
918
;
910
;
919
; This function is called by system function 75
911
; This function is called by system function 75
920
;
912
;
921
; IN:  subfunction number in bl
913
; IN:  subfunction number in bl
922
;      device number in bh
914
;      device number in bh
923
;      ecx, edx, .. depends on subfunction
915
;      ecx, edx, .. depends on subfunction
924
;
916
;
925
; OUT:
917
; OUT:
926
;
918
;
927
;---------------------------------------------------------------------------
919
;---------------------------------------------------------------------------
928
align 4
920
align 4
929
IPv4_api:
921
IPv4_api:
930
 
922
 
931
        movzx   eax, bh
923
        movzx   eax, bh
932
        shl     eax, 2
924
        shl     eax, 2
933
 
925
 
934
        and     ebx, 0x000000ff
926
        and     ebx, 0x000000ff
935
        cmp     ebx, .number
927
        cmp     ebx, .number
936
        ja      .error
928
        ja      .error
937
        jmp     dword [.table + 4*ebx]
929
        jmp     dword [.table + 4*ebx]
938
 
930
 
939
  .table:
931
  .table:
940
        dd      .packets_tx     ; 0
932
        dd      .packets_tx     ; 0
941
        dd      .packets_rx     ; 1
933
        dd      .packets_rx     ; 1
942
        dd      .read_ip        ; 2
934
        dd      .read_ip        ; 2
943
        dd      .write_ip       ; 3
935
        dd      .write_ip       ; 3
944
        dd      .read_dns       ; 4
936
        dd      .read_dns       ; 4
945
        dd      .write_dns      ; 5
937
        dd      .write_dns      ; 5
946
        dd      .read_subnet    ; 6
938
        dd      .read_subnet    ; 6
947
        dd      .write_subnet   ; 7
939
        dd      .write_subnet   ; 7
948
        dd      .read_gateway   ; 8
940
        dd      .read_gateway   ; 8
949
        dd      .write_gateway  ; 9
941
        dd      .write_gateway  ; 9
950
  .number = ($ - .table) / 4 - 1
942
  .number = ($ - .table) / 4 - 1
951
 
943
 
952
  .error:
944
  .error:
953
        mov     eax, -1
945
        mov     eax, -1
954
        ret
946
        ret
955
 
947
 
956
  .packets_tx:
948
  .packets_tx:
957
        mov     eax, [IP_PACKETS_TX + eax]
949
        mov     eax, [IP_PACKETS_TX + eax]
958
        ret
950
        ret
959
 
951
 
960
  .packets_rx:
952
  .packets_rx:
961
        mov     eax, [IP_PACKETS_RX + eax]
953
        mov     eax, [IP_PACKETS_RX + eax]
962
        ret
954
        ret
963
 
955
 
964
  .read_ip:
956
  .read_ip:
965
        mov     eax, [IP_LIST + eax]
957
        mov     eax, [IP_LIST + eax]
966
        ret
958
        ret
967
 
959
 
968
  .write_ip:
960
  .write_ip:
969
        mov     [IP_LIST + eax], ecx
961
        mov     [IP_LIST + eax], ecx
-
 
962
 
-
 
963
        ; pre-calculate the local broadcast address
-
 
964
        mov     ebx, [SUBNET_LIST + eax]
-
 
965
        not     ebx
-
 
966
        or      ecx, ebx
-
 
967
        mov     [BROADCAST_LIST + eax], ecx
-
 
968
 
970
        xor     eax, eax
969
        xor     eax, eax
971
        ret
970
        ret
972
 
971
 
973
  .read_dns:
972
  .read_dns:
974
        mov     eax, [DNS_LIST + eax]
973
        mov     eax, [DNS_LIST + eax]
975
        ret
974
        ret
976
 
975
 
977
  .write_dns:
976
  .write_dns:
978
        mov     [DNS_LIST + eax], ecx
977
        mov     [DNS_LIST + eax], ecx
979
        xor     eax, eax
978
        xor     eax, eax
980
        ret
979
        ret
981
 
980
 
982
  .read_subnet:
981
  .read_subnet:
983
        mov     eax, [SUBNET_LIST + eax]
982
        mov     eax, [SUBNET_LIST + eax]
984
        ret
983
        ret
985
 
984
 
986
  .write_subnet:
985
  .write_subnet:
987
        mov     [SUBNET_LIST + eax], ecx
986
        mov     [SUBNET_LIST + eax], ecx
-
 
987
 
-
 
988
        ; pre-calculate the local broadcast address
-
 
989
        mov     ebx, [IP_LIST + eax]
-
 
990
        not     ecx
-
 
991
        or      ecx, ebx
-
 
992
        mov     [BROADCAST_LIST + eax], ecx
-
 
993
 
988
        xor     eax, eax
994
        xor     eax, eax
989
        ret
995
        ret
990
 
996
 
991
  .read_gateway:
997
  .read_gateway:
992
        mov     eax, [GATEWAY_LIST + eax]
998
        mov     eax, [GATEWAY_LIST + eax]
993
        ret
999
        ret
994
 
1000
 
995
  .write_gateway:
1001
  .write_gateway:
996
        mov     [GATEWAY_LIST + eax], ecx
1002
        mov     [GATEWAY_LIST + eax], ecx
997
        xor     eax, eax
1003
        xor     eax, eax
998
        ret
1004
        ret
999
 
1005
 
1000
>
1006
>
1001
 
1007
 
1002
>
1008
>
1003
 
1009
 
1004
>
1010
>
1005
 
1011
 
1006
>
1012
>
1007
 
1013
 
1008
>
1014
>
1009
 
1015
 
1010
>
1016
>
1011
 
1017
 
1012
>
1018
>
1013
 
1019
 
1014
>
1020
>
1015
 
1021
 
1016
>
1022
>
1017
 
1023
 
1018
>
1024
>
1019
 
1025
 
1020
>
1026
>
1021
 
1027
 
1022
>
1028
>
1023
 
1029
 
1024
>
1030
>
1025
 
1031
 
1026
>
1032
>
1027
 
1033
 
1028
>
1034
>
1029
 
1035
 
1030
>
1036
>
1031
 
1037
 
1032
>
1038
>
1033
 
1039
 
1034
>
1040
>
1035
 
1041
 
1036
>
1042
>
1037
 
1043
 
1038
>
1044
>
1039
 
1045
 
1040
>
1046
>
1041
 
1047
 
1042
>
1048
>
1043
 
1049
 
1044
>
1050
>
1045
 
1051
 
1046
>
1052
>
1047
 
1053
 
1048
>
1054
>
1049
 
1055
 
1050
>
1056
>
1051
 
1057
 
1052
>
1058
>
1053
 
1059
 
1054
>
1060
>
1055
 
1061
 
1056
>
1062
>
1057
;>
1063
;>
1058
;>
1064
;>
1059
;>
1065
;>
1060
;>
1066
;>
1061
;>
1067
;>
1062
;>
1068
;>