Subversion Repositories Kolibri OS

Rev

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

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