Rev 1257 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1257 | Rev 1473 | ||
---|---|---|---|
Line 14... | Line 14... | ||
14 | ;; GNU GENERAL PUBLIC LICENSE ;; |
14 | ;; GNU GENERAL PUBLIC LICENSE ;; |
15 | ;; Version 2, June 1991 ;; |
15 | ;; Version 2, June 1991 ;; |
16 | ;; ;; |
16 | ;; ;; |
17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Line 18... | Line 18... | ||
18 | 18 | ||
Line 19... | Line 19... | ||
19 | $Revision: 1257 $ |
19 | $Revision: 1473 $ |
Line 20... | Line 20... | ||
20 | 20 | ||
Line 111... | Line 111... | ||
111 | ; pointer to IP Packet data in edx |
111 | ; pointer to IP Packet data in edx |
112 | ; OUT: / |
112 | ; OUT: / |
113 | ; |
113 | ; |
114 | ;----------------------------------------------------------------- |
114 | ;----------------------------------------------------------------- |
115 | align 4 |
115 | align 4 |
116 | IPv4_handler: ; TODO: clean up this mess |
116 | IPv4_handler: ; TODO: implement handler for IP options |
117 | ; for instance, there should be only one piece of code wich make the jump to an underlying protocol, and not two.. |
- | |
118 | ; TODO2: add code for IPv4 sockets (raw sockets) |
117 | ; TODO2: add code for IPv4 sockets (raw sockets) |
Line 119... | Line 118... | ||
119 | 118 | ||
Line 120... | Line -... | ||
120 | DEBUGF 1,"IP_Handler - start\n" |
- | |
Line -... | Line 119... | ||
- | 119 | DEBUGF 1,"IP_Handler - start\n" |
|
121 | 120 | ||
- | 121 | ||
122 | push edx ebx |
122 | ;------------------------------------------- |
- | 123 | ; Check if the packet still has time to live |
|
- | 124 | ||
- | 125 | cmp byte [edx + IPv4_Packet.TimeToLive], 0 |
|
- | 126 | je .dump |
|
- | 127 | ||
123 | 128 | ;-------------------------------------- |
|
- | 129 | ; First, check if IP packet has options |
|
- | 130 | ||
- | 131 | movzx eax, [edx + IPv4_Packet.VersionAndIHL] |
|
- | 132 | and al , 0x0f ; get IHL(header length) |
|
- | 133 | cmp al , 0x05 ; IHL!= 5*4(20 bytes) |
|
- | 134 | jnz .has_options |
|
- | 135 | ||
Line 124... | Line 136... | ||
124 | ; save checksum, and clear it in original packet |
136 | |
125 | mov di , [edx + IPv4_Packet.HeaderChecksum] |
- | |
126 | mov word [edx + IPv4_Packet.HeaderChecksum], 0 |
- | |
127 | 137 | ;------------------------------- |
|
128 | ; Re-calculate checksum |
138 | ; Now, re-calcualte the checksum |
129 | movzx ecx, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field |
- | |
130 | and ecx, 0x0000000F ; |
- | |
131 | shl cx , 2 ; |
139 | |
132 | mov esi, edx |
- | |
133 | xor edx, edx |
- | |
134 | call checksum_1 |
- | |
135 | call checksum_2 |
140 | ; Re-calculate checksum |
- | 141 | push edx ebx |
|
- | 142 | mov esi, edx |
|
- | 143 | call checksum_ip_header |
|
136 | 144 | pop ebx edx |
|
Line 137... | Line 145... | ||
137 | ; now compare the two.. |
145 | |
- | 146 | ; now see if it was correct |
|
- | 147 | cmp [edx + IPv4_Packet.HeaderChecksum], 0 |
|
- | 148 | jne .dump ; if checksum isn't valid then dump packet |
|
- | 149 | ||
- | 150 | DEBUGF 1,"IPv4 Checksum is correct\n" |
|
Line 138... | Line 151... | ||
138 | cmp dx, di |
151 | |
139 | pop ebx edx |
152 | ;------------------------------------------------------- |
140 | jne .dump ; if checksum isn't valid then dump packet |
153 | ; Time to find out what interface this packet belongs to |
- | 154 | ||
141 | 155 | ; Therefore we will scan the current list of IP's |
|
- | 156 | ||
142 | DEBUGF 1,"IPv4 Checksum is correct\n",di |
157 | mov eax, [edx + IPv4_Packet.DestinationAddress] |
- | 158 | mov edi, BROADCAST |
|
- | 159 | mov ecx, MAX_IP+1 |
|
- | 160 | ||
Line -... | Line 161... | ||
- | 161 | .find_ip_loop: |
|
143 | 162 | cmp eax, dword [edi] |
|
144 | mov eax, [edx + IPv4_Packet.DestinationAddress] |
163 | jz .ip_ok |
145 | mov edi, BROADCAST |
164 | add edi, 4 |
Line 146... | Line 165... | ||
146 | mov ecx, MAX_IP+1 |
165 | dec ecx |
Line -... | Line 166... | ||
- | 166 | jnz .find_ip_loop |
|
- | 167 | ||
147 | repnz scasd |
168 | ; it was not on the list, perhaps it's a loopback ? |
Line -... | Line 169... | ||
- | 169 | not eax |
|
- | 170 | test eax, 127 shl 24 ; 127.x.x.x |
|
- | 171 | jz .ip_ok |
|
- | 172 | ||
148 | jz .ip_ok |
173 | ; TODO: we need to check for broadcasts (other then 255.255.255.255) |
149 | 174 | ||
150 | not eax |
175 | DEBUGF 2,"Destination address does not match!\n" |
151 | test eax, 127 shl 24 ; 127.x.x.x |
176 | |
152 | jz .ip_ok |
177 | jmp .dump |
Line 153... | Line -... | ||
153 | - | ||
154 | ; TODO: we need to check for broadcasts (other then 255.255.255.255) |
- | |
155 | - | ||
156 | jmp .dump |
- | |
Line 157... | Line -... | ||
157 | - | ||
158 | .ip_ok: |
- | |
Line 159... | Line -... | ||
159 | call ETH_struc2dev ; TODO: make this work on other protocols too! |
- | |
160 | inc [IP_PACKETS_RX+4*edi] |
- | |
Line -... | Line 178... | ||
- | 178 | ||
- | 179 | ||
- | 180 | ;--------------------------------------------------- |
|
161 | DEBUGF 1,"packet comes from %u.%u.%u.%u\n",\ |
181 | ; Now we can update stats and find the device number |
162 | [edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1 |
182 | |
- | 183 | .ip_ok: |
|
- | 184 | call ETH_struc2dev ; TODO: make this work on other protocols too! |
|
- | 185 | inc [IP_PACKETS_RX+4*edi] |
|
- | 186 | DEBUGF 1,"Packet comes from %u.%u.%u.%u\n",\ |
|
Line -... | Line 187... | ||
- | 187 | [edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1 |
|
- | 188 | ||
163 | 189 | ||
164 | mov al , [edx + IPv4_Packet.VersionAndIHL] |
- | |
Line 165... | Line 190... | ||
165 | and al , 0x0f ; get IHL(header length) |
190 | |
166 | cmp al , 0x05 ; IHL!= 5*4(20 bytes) |
191 | |
167 | jnz .dump ; TODO: dont dump packets wich have optional fiels !!! /!\ |
192 | ;---------------------------------- |
168 | 193 | ; Check if the packet is fragmented |
|
169 | cmp byte [edx + IPv4_Packet.TimeToLive], 0 |
- | |
170 | je .dump |
194 | |
171 | 195 | test [edx + IPv4_Packet.FlagsAndFragmentOffset], 1 shl 5 ; Is 'more fragments' flag set ? |
|
172 | movzx eax, word [edx + IPv4_Packet.FlagsAndFragmentOffset] |
196 | jnz .has_fragments ; If so, we definately have a fragmented packet |
Line 173... | Line 197... | ||
173 | xchg al , ah |
197 | |
174 | 198 | test [edx + IPv4_Packet.FlagsAndFragmentOffset], 0xff1f ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets |
|
- | 199 | jnz .is_last_fragment |
|
- | 200 | ||
- | 201 | ||
175 | test ax , 1 shl 13 ; Is 'more fragments' flag set ? |
202 | |
176 | jnz .yes_fragments ; If so, we definately have a fragmented packet |
- | |
177 | - | ||
178 | test ax , 0x1fff ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets |
203 | ;------------------------------------------------------------------- |
Line 179... | Line 204... | ||
179 | jnz .last_fragment |
204 | ; No, it's just a regular IP packet, pass it to the higher protocols |
180 | 205 | ||
Line 201... | Line 226... | ||
201 | je UDP_handler |
226 | je UDP_handler |
Line 202... | Line 227... | ||
202 | 227 | ||
203 | cmp al , IP_PROTO_ICMP |
228 | cmp al , IP_PROTO_ICMP |
Line 204... | Line 229... | ||
204 | je ICMP_handler |
229 | je ICMP_handler |
Line 205... | Line 230... | ||
205 | 230 | ||
206 | DEBUGF 1,"unknown protocol: %u\n",al |
231 | DEBUGF 2,"unknown Internet protocol: %u\n", al |
207 | 232 | ||
208 | .dump: |
233 | .dump: |
209 | DEBUGF 1,"IP_Handler - done\n" |
234 | DEBUGF 2,"IP_Handler - dumping\n" |
210 | ; inc [dumped_rx_count] |
235 | ; inc [dumped_rx_count] |
Line -... | Line 236... | ||
- | 236 | call kernel_free |
|
- | 237 | add esp, 4 ; pop (balance stack) |
|
- | 238 | ret |
|
- | 239 | ||
211 | call kernel_free |
240 | |
- | 241 | ;--------------------------- |
|
- | 242 | ; Fragmented packet handler |
|
212 | add esp, 4 ; pop (balance stack) |
243 | |
- | 244 | ||
213 | ret |
245 | .has_fragments: |
Line 214... | Line 246... | ||
214 | 246 | movzx eax, [edx + IPv4_Packet.FlagsAndFragmentOffset] |
|
215 | 247 | xchg al , ah |
|
- | 248 | shl ax , 3 |
|
- | 249 | ||
- | 250 | DEBUGF 1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_Packet.Identification]:4 |
|
- | 251 | ||
- | 252 | test ax , ax ; Is this the first packet of the fragment? |
|
- | 253 | jz .is_first_fragment |
|
- | 254 | ||
- | 255 | ||
- | 256 | ;------------------------------------------------------- |
|
- | 257 | ; We have a fragmented IP packet, but it's not the first |
|
- | 258 | ||
- | 259 | DEBUGF 1,"Middle fragmented packet received!\n" |
|
- | 260 | ||
- | 261 | call IPv4_find_fragment_slot |
|
- | 262 | cmp esi, -1 |
|
- | 263 | je .dump |
|
- | 264 | ||
- | 265 | mov word [esi + FRAGMENT_slot.ttl], 15 ; Reset the ttl |
|
- | 266 | mov esi, [esi + FRAGMENT_slot.ptr] |
|
- | 267 | or edi, -1 |
|
- | 268 | .find_last_entry: ; The following routine will try to find the last entry |
|
- | 269 | cmp edi, [esi + FRAGMENT_entry.PrevPtr] |
|
- | 270 | jne .destroy_slot ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!) |
|
- | 271 | mov edi, esi |
|
- | 272 | mov esi, [esi + FRAGMENT_entry.NextPtr] |
|
- | 273 | cmp esi, -1 |
|
- | 274 | jne .find_last_entry |
|
- | 275 | ; We found the last entry (pointer is now in edi) |
|
- | 276 | ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure |
|
- | 277 | ||
- | 278 | pop eax ; pointer to packet |
|
- | 279 | mov [edi + FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry |
|
- | 280 | mov [eax + FRAGMENT_entry.NextPtr], -1 |
|
Line -... | Line 281... | ||
- | 281 | mov [eax + FRAGMENT_entry.PrevPtr], edi |
|
- | 282 | mov [eax + FRAGMENT_entry.Owner], ebx |
|
- | 283 | ||
- | 284 | add esp, 4 |
|
216 | .yes_fragments: |
285 | ret |
217 | shl ax , 3 |
286 | |
218 | DEBUGF 1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_Packet.Identification]:4 |
287 | |
219 | 288 | ;------------------------------------ |
|
220 | test ax , ax ; Is this the first packet of the fragment? |
289 | ; We have received the first fragment |
Line 248... | Line 317... | ||
248 | 317 | ||
249 | add esp, 4 ; balance stack and exit |
318 | add esp, 4 ; balance stack and exit |
Line -... | Line 319... | ||
- | 319 | ret |
|
- | 320 | ||
Line 250... | Line -... | ||
250 | ret |
- | |
251 | - | ||
252 | - | ||
253 | - | ||
254 | .not_first_fragment: |
- | |
255 | DEBUGF 1,"Middle fragmented packet received!\n" |
- | |
256 | - | ||
257 | call .find_fragment_slot |
- | |
258 | cmp esi, -1 |
- | |
259 | je .dump |
- | |
260 | - | ||
261 | mov word [esi + FRAGMENT_slot.ttl], 15 ; Reset the ttl |
- | |
262 | mov esi, [esi + FRAGMENT_slot.ptr] |
- | |
263 | or edi, -1 |
- | |
264 | .find_last_entry: ; The following routine will try to find the last entry |
- | |
265 | cmp edi, [esi + FRAGMENT_entry.PrevPtr] |
- | |
266 | jne .destroy_slot ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!) |
- | |
267 | mov edi, esi |
- | |
268 | mov esi, [esi + FRAGMENT_entry.NextPtr] |
- | |
269 | cmp esi, -1 |
- | |
270 | jne .find_last_entry |
- | |
271 | ; We found the last entry (pointer is noww in edi) |
- | |
272 | ; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure |
- | |
273 | - | ||
274 | pop eax ; pointer to packet |
- | |
275 | mov [edi + FRAGMENT_entry.NextPtr], eax ; update pointer of previous entry to the new entry |
- | |
276 | mov [eax + FRAGMENT_entry.NextPtr], -1 |
- | |
277 | mov [eax + FRAGMENT_entry.PrevPtr], edi |
- | |
278 | mov [eax + FRAGMENT_entry.Owner], ebx |
- | |
279 | - | ||
280 | add esp, 4 |
- | |
281 | ret |
321 | |
282 | 322 | ;----------------------------------- |
|
- | 323 | ; We have received the last fragment |
|
283 | 324 | ||
284 | 325 | .is_last_fragment: |
|
285 | .last_fragment: |
326 | DEBUGF 1,"Last fragmented packet received!\n" |
Line 286... | Line 327... | ||
286 | DEBUGF 1,"Last fragmented packet received!\n" |
327 | |
287 | call .find_fragment_slot |
328 | call IPv4_find_fragment_slot |
288 | cmp esi, -1 |
329 | cmp esi, -1 |
289 | je .dump |
330 | je .dump |
- | 331 | ||
290 | 332 | mov esi, [esi + FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer |
|
291 | mov esi, [esi + FRAGMENT_slot.ptr] ; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer |
333 | push esi |
292 | push esi |
334 | xor eax, eax |
293 | xor eax, eax ; |
335 | or edi, -1 |
294 | or edi, -1 |
336 | |
Line 367... | Line 409... | ||
367 | and cx, 3 ; |
409 | and cx, 3 ; |
368 | rep movsb ; |
410 | rep movsb ; |
Line 369... | Line 411... | ||
369 | 411 | ||
370 | push eax |
412 | push eax |
- | 413 | push edx ; Push pointer to fragment onto stack |
|
371 | push edx ; Push pointer to fragment onto stack |
414 | mov ebx, [edx + FRAGMENT_entry.Owner] ; we need to remeber the owner, in case this is the last packet |
372 | mov edx, [edx + FRAGMENT_entry.NextPtr] ; Set edx to the next pointer |
415 | mov edx, [edx + FRAGMENT_entry.NextPtr] ; Set edx to the next pointer |
373 | call kernel_free ; free the previous fragment buffer (this uses the value from stack) |
416 | call kernel_free ; free the previous fragment buffer (this uses the value from stack) |
374 | pop eax |
417 | pop eax |
375 | cmp edx, -1 ; Check if it is last fragment in chain |
418 | cmp edx, -1 ; Check if it is last fragment in chain |
Line 379... | Line 422... | ||
379 | xchg cl, ch |
422 | xchg cl, ch |
380 | mov edx, eax |
423 | mov edx, eax |
381 | mov word [edx + IPv4_Packet.TotalLength], cx |
424 | mov word [edx + IPv4_Packet.TotalLength], cx |
382 | add esp, 8 |
425 | add esp, 8 |
Line 383... | Line 426... | ||
383 | 426 | ||
- | 427 | xchg cl, ch ; |
|
384 | xchg cl, ch ; This prints the IP packet to the debug board (usefull when using serial output debug..) |
428 | |
385 | push ecx ;;;; |
429 | push ecx ;;;; |
- | 430 | push eax ;;;; |
|
386 | push eax ;;;; |
431 | |
387 | ; mov esi, edx ; |
432 | ; mov esi, edx ; This prints the IP packet to the debug board (usefull when using serial output debug..) |
388 | ; ; |
433 | ; ; |
389 | ; @@: ; |
434 | ; @@: ; |
390 | ; lodsb ; |
435 | ; lodsb ; |
391 | ; DEBUGF 1,"%x ", eax:2 ; |
436 | ; DEBUGF 1,"%x ", eax:2 ; |
Line 392... | Line 437... | ||
392 | ; loop @r ; |
437 | ; loop @r ; |
393 | - | ||
394 | movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field |
- | |
395 | and ax, 0x000F ; |
- | |
396 | shl ax, 2 ; |
- | |
397 | - | ||
Line -... | Line 438... | ||
- | 438 | ||
398 | sub ecx, eax |
439 | jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr |
399 | 440 | ||
400 | 441 | .destroy_slot_pop: |
|
401 | add eax, edx |
442 | add esp, 4 |
402 | push eax |
- | |
403 | mov al , [edx + IPv4_Packet.Protocol] |
443 | .destroy_slot: |
Line 404... | Line -... | ||
404 | mov esi, [edx + IPv4_Packet.SourceAddress] |
- | |
405 | mov edi, [edx + IPv4_Packet.DestinationAddress] |
- | |
Line 406... | Line -... | ||
406 | pop edx ; Offset to data (tcp/udp/icmp/.. Packet) |
- | |
407 | - | ||
Line 408... | Line -... | ||
408 | cmp al , IP_PROTO_TCP |
- | |
409 | je TCP_handler |
- | |
Line -... | Line 444... | ||
- | 444 | DEBUGF 1,"Destroy fragment slot!\n" |
|
410 | 445 | ; TODO! |
|
Line 411... | Line 446... | ||
411 | cmp al , IP_PROTO_UDP |
446 | jmp .dump |
412 | je UDP_handler |
447 | |
Line 413... | Line -... | ||
413 | - | ||
Line 414... | Line -... | ||
414 | cmp al , IP_PROTO_ICMP |
- | |
415 | je ICMP_handler_fragments |
- | |
416 | - | ||
417 | DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al |
- | |
418 | - | ||
419 | call kernel_free |
- | |
Line 420... | Line 448... | ||
420 | add esp, 8 ; pop (balance stack) |
448 | |
421 | 449 | ||
Line 437... | Line 465... | ||
437 | ; |
465 | ; |
438 | ; IN: pointer to fragmented packet in edx ; TODO: the RFC says we should check protocol too |
466 | ; IN: pointer to fragmented packet in edx ; TODO: the RFC says we should check protocol too |
439 | ; OUT: pointer to slot in edi, -1 on error |
467 | ; OUT: pointer to slot in edi, -1 on error |
440 | ; |
468 | ; |
441 | ;----------------------------------------------------------------- |
469 | ;----------------------------------------------------------------- |
442 | 470 | align 4 |
|
443 | .find_fragment_slot: |
471 | IPv4_find_fragment_slot: |
Line 444... | Line 472... | ||
444 | 472 | ||
445 | push eax ebx ecx edx |
473 | push eax ebx ecx edx |
446 | mov ax , word [edx + IPv4_Packet.Identification] |
474 | mov ax , word [edx + IPv4_Packet.Identification] |
447 | mov ecx, MAX_FRAGMENTS |
475 | mov ecx, MAX_FRAGMENTS |
Line 579... | Line 607... | ||
579 | pop ecx |
607 | pop ecx |
580 | mov [edi + IPv4_Packet.SourceAddress], ecx |
608 | mov [edi + IPv4_Packet.SourceAddress], ecx |
581 | pop ecx |
609 | pop ecx |
582 | mov [edi + IPv4_Packet.DestinationAddress], ecx |
610 | mov [edi + IPv4_Packet.DestinationAddress], ecx |
Line 583... | Line 611... | ||
583 | 611 | ||
584 | push eax ebx edx |
- | |
585 | ; calculate checksum |
- | |
586 | xor edx, edx |
612 | push eax edx esi |
587 | mov esi, edi |
- | |
588 | mov ecx, IPv4_Packet.DataOrOptional |
- | |
589 | call checksum_1 |
613 | mov esi, edi |
590 | call checksum_2 |
- | |
591 | mov [edi + IPv4_Packet.HeaderChecksum], dx |
614 | call checksum_ip_header |
592 | pop edx ebx eax ecx |
615 | pop esi edx eax ecx |
Line 593... | Line 616... | ||
593 | add edi, IPv4_Packet.DataOrOptional |
616 | add edi, IPv4_Packet.DataOrOptional |
Line 594... | Line 617... | ||
594 | 617 |