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