Subversion Repositories Kolibri OS

Rev

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

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