Subversion Repositories Kolibri OS

Rev

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

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