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