Subversion Repositories Kolibri OS

Rev

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

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