Subversion Repositories Kolibri OS

Rev

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

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