Rev 1530 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1530 | Rev 1542 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2010. 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 | ;; UDP.INC ;; |
6 | ;; UDP.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 | ;; Written by hidnplayr@kolibrios.org ;; |
10 | ;; Written by hidnplayr@kolibrios.org ;; |
11 | ;; ;; |
11 | ;; ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
13 | ;; Version 2, June 1991 ;; |
13 | ;; Version 2, June 1991 ;; |
14 | ;; ;; |
14 | ;; ;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
16 | 16 | ||
17 | $Revision: 1530 $ |
17 | $Revision: 1542 $ |
18 | 18 | ||
19 | 19 | ||
20 | struct UDP_Packet |
20 | struct UDP_Packet |
21 | .SourcePort dw ? |
21 | .SourcePort dw ? |
22 | .DestinationPort dw ? |
22 | .DestinationPort dw ? |
23 | .Length dw ? ; Length of (UDP Header + Data) |
23 | .Length dw ? ; Length of (UDP Header + Data) |
24 | .Checksum dw ? |
24 | .Checksum dw ? |
25 | .Data: |
25 | .Data: |
26 | 26 | ||
27 | ends |
27 | ends |
28 | 28 | ||
29 | 29 | ||
30 | align 4 |
30 | align 4 |
31 | uglobal |
31 | uglobal |
32 | UDP_PACKETS_TX rd MAX_IP |
32 | UDP_PACKETS_TX rd MAX_IP |
33 | UDP_PACKETS_RX rd MAX_IP |
33 | UDP_PACKETS_RX rd MAX_IP |
34 | endg |
34 | endg |
35 | 35 | ||
36 | 36 | ||
37 | ;----------------------------------------------------------------- |
37 | ;----------------------------------------------------------------- |
38 | ; |
38 | ; |
39 | ; UDP_init |
39 | ; UDP_init |
40 | ; |
40 | ; |
41 | ; This function resets all UDP variables |
41 | ; This function resets all UDP variables |
42 | ; |
42 | ; |
43 | ;----------------------------------------------------------------- |
43 | ;----------------------------------------------------------------- |
44 | macro UDP_init { |
44 | macro UDP_init { |
45 | 45 | ||
46 | xor eax, eax |
46 | xor eax, eax |
47 | mov edi, UDP_PACKETS_TX |
47 | mov edi, UDP_PACKETS_TX |
48 | mov ecx, 2*MAX_IP |
48 | mov ecx, 2*MAX_IP |
49 | rep stosd |
49 | rep stosd |
50 | } |
50 | } |
51 | 51 | ||
52 | 52 | ||
53 | macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx |
53 | macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx |
54 | 54 | ||
55 | ; Pseudoheader |
55 | ; Pseudoheader |
56 | mov edx, IP_PROTO_UDP |
56 | mov edx, IP_PROTO_UDP |
57 | 57 | ||
58 | add dl, [IP1+1] |
58 | add dl, [IP1+1] |
59 | adc dh, [IP1+0] |
59 | adc dh, [IP1+0] |
60 | adc dl, [IP1+3] |
60 | adc dl, [IP1+3] |
61 | adc dh, [IP1+2] |
61 | adc dh, [IP1+2] |
62 | 62 | ||
63 | adc dl, [IP2+1] |
63 | adc dl, [IP2+1] |
64 | adc dh, [IP2+0] |
64 | adc dh, [IP2+0] |
65 | adc dl, [IP2+3] |
65 | adc dl, [IP2+3] |
66 | adc dh, [IP2+2] |
66 | adc dh, [IP2+2] |
67 | 67 | ||
68 | adc dl, cl ; byte[esi+UDP_Packet.Length+1] |
68 | adc dl, cl ; byte[esi+UDP_Packet.Length+1] |
69 | adc dh, ch ; byte[esi+UDP_Packet.Length+0] |
69 | adc dh, ch ; byte[esi+UDP_Packet.Length+0] |
70 | 70 | ||
71 | ; Done with pseudoheader, now do real header |
71 | ; Done with pseudoheader, now do real header |
72 | adc dl, byte[esi+UDP_Packet.SourcePort+1] |
72 | adc dl, byte[esi+UDP_Packet.SourcePort+1] |
73 | adc dh, byte[esi+UDP_Packet.SourcePort+0] |
73 | adc dh, byte[esi+UDP_Packet.SourcePort+0] |
74 | 74 | ||
75 | adc dl, byte[esi+UDP_Packet.DestinationPort+1] |
75 | adc dl, byte[esi+UDP_Packet.DestinationPort+1] |
76 | adc dh, byte[esi+UDP_Packet.DestinationPort+0] |
76 | adc dh, byte[esi+UDP_Packet.DestinationPort+0] |
77 | 77 | ||
78 | adc dl, byte[esi+UDP_Packet.Length+1] |
78 | adc dl, byte[esi+UDP_Packet.Length+1] |
79 | adc dh, byte[esi+UDP_Packet.Length+0] |
79 | adc dh, byte[esi+UDP_Packet.Length+0] |
80 | 80 | ||
81 | adc edx, 0 |
81 | adc edx, 0 |
82 | 82 | ||
83 | ; Done with header, now do data |
83 | ; Done with header, now do data |
84 | push esi |
84 | push esi |
85 | movzx ecx, [esi+UDP_Packet.Length] |
85 | movzx ecx, [esi+UDP_Packet.Length] |
86 | rol cx , 8 |
86 | rol cx , 8 |
87 | sub cx , UDP_Packet.Data |
87 | sub cx , UDP_Packet.Data |
88 | add esi, UDP_Packet.Data |
88 | add esi, UDP_Packet.Data |
89 | 89 | ||
90 | call checksum_1 |
90 | call checksum_1 |
91 | call checksum_2 |
91 | call checksum_2 |
92 | pop esi |
92 | pop esi |
93 | 93 | ||
94 | add [esi+UDP_Packet.Checksum], dx ; this final instruction will set or clear ZF :) |
94 | add [esi+UDP_Packet.Checksum], dx ; this final instruction will set or clear ZF :) |
95 | 95 | ||
96 | } |
96 | } |
97 | 97 | ||
98 | 98 | ||
99 | ;----------------------------------------------------------------- |
99 | ;----------------------------------------------------------------- |
100 | ; |
100 | ; |
101 | ; UDP_input: |
101 | ; UDP_input: |
102 | ; |
102 | ; |
103 | ; Called by IPv4_input, |
103 | ; Called by IPv4_input, |
104 | ; this procedure will inject the udp data diagrams in the application sockets. |
104 | ; this procedure will inject the udp data diagrams in the application sockets. |
105 | ; |
105 | ; |
106 | ; IN: [esp] = Pointer to buffer |
106 | ; IN: [esp] = Pointer to buffer |
107 | ; [esp+4] = size of buffer |
107 | ; [esp+4] = size of buffer |
108 | ; ebx = ptr to device struct |
108 | ; ebx = ptr to device struct |
109 | ; ecx = UDP Packet size |
109 | ; ecx = UDP Packet size |
110 | ; edx = ptr to UDP header |
110 | ; edx = ptr to UDP header |
111 | ; |
111 | ; |
112 | ; esi = ipv4 source address |
112 | ; esi = ipv4 source address |
113 | ; edi = ipv4 dest address |
113 | ; edi = ipv4 dest address |
114 | ; |
114 | ; |
115 | ; OUT: / |
115 | ; OUT: / |
116 | ; |
116 | ; |
117 | ;----------------------------------------------------------------- |
117 | ;----------------------------------------------------------------- |
118 | align 4 |
118 | align 4 |
119 | UDP_input: |
119 | UDP_input: |
120 | 120 | ||
121 | DEBUGF 1,"UDP_input, size:%u\n", ecx |
121 | DEBUGF 1,"UDP_input, size:%u\n", ecx |
122 | 122 | ||
123 | ; First validate, checksum: |
123 | ; First validate, checksum: |
124 | neg [edx+UDP_Packet.Checksum] ; substract chechksum from 0 |
124 | neg [edx+UDP_Packet.Checksum] ; substract chechksum from 0 |
125 | jz .no_checksum ; if checksum is zero, it is considered valid and we continue processing |
125 | jz .no_checksum ; if checksum is zero, it is considered valid and we continue processing |
126 | ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct |
126 | ; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct |
127 | 127 | ||
128 | push edx |
128 | push edx |
129 | push edi |
129 | push edi |
130 | push esi |
130 | push esi |
131 | mov esi, edx |
131 | mov esi, edx |
132 | UDP_checksum (esp), (esp+4) |
132 | UDP_checksum (esp), (esp+4) |
133 | pop edi |
133 | pop edi |
134 | pop esi ; we dont need it, but it is smaller then add esp, 4 |
134 | pop esi ; we dont need it, but it is smaller then add esp, 4 |
135 | pop edx |
135 | pop edx |
136 | jnz .checksum_mismatch |
136 | jnz .checksum_mismatch |
137 | 137 | ||
138 | .no_checksum: |
138 | .no_checksum: |
139 | DEBUGF 1,"UDP Checksum is correct\n" |
139 | DEBUGF 1,"UDP Checksum is correct\n" |
140 | 140 | ||
141 | ; Look for a socket where |
141 | ; Look for a socket where |
142 | ; IP Packet UDP Destination Port = local Port |
142 | ; IP Packet UDP Destination Port = local Port |
143 | ; IP Packet SA = Remote IP |
143 | ; IP Packet SA = Remote IP |
144 | 144 | ||
145 | mov eax, net_sockets |
145 | mov eax, net_sockets |
146 | .try_more: |
146 | .try_more: |
147 | mov si , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header |
147 | mov si , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header |
148 | rol si , 8 |
148 | rol si , 8 |
149 | .next_socket: |
149 | .next_socket: |
150 | mov eax, [eax + SOCKET.NextPtr] |
150 | mov eax, [eax + SOCKET.NextPtr] |
151 | or eax, eax |
151 | or eax, eax |
152 | jz .dump |
152 | jz .dump |
153 | cmp [eax + SOCKET.Domain], AF_INET4 |
153 | cmp [eax + SOCKET.Domain], AF_INET4 |
154 | jne .next_socket |
154 | jne .next_socket |
155 | cmp [eax + SOCKET.Type], IP_PROTO_UDP |
155 | cmp [eax + SOCKET.Protocol], IP_PROTO_UDP |
156 | jne .next_socket |
156 | jne .next_socket |
157 | cmp [eax + UDP_SOCKET.LocalPort], si |
157 | cmp [eax + UDP_SOCKET.LocalPort], si |
158 | jne .next_socket |
158 | jne .next_socket |
159 | 159 | ||
160 | DEBUGF 1,"using socket: %x\n", eax |
160 | DEBUGF 1,"using socket: %x\n", eax |
161 | 161 | ||
162 | ;;; TODO: when packet is processed, check more sockets! |
162 | ;;; TODO: when packet is processed, check more sockets! |
163 | 163 | ||
164 | cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff |
164 | cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff |
165 | je @f |
165 | je @f |
166 | cmp [eax + IP_SOCKET.RemoteIP], edi ; edi is the packets source address |
166 | cmp [eax + IP_SOCKET.RemoteIP], edi ; edi is the packets source address |
167 | jne .try_more |
167 | jne .try_more |
168 | @@: |
168 | @@: |
169 | 169 | ||
170 | cmp [eax + UDP_SOCKET.firstpacket], 0 |
170 | cmp [eax + UDP_SOCKET.firstpacket], 0 |
171 | jz .updateport |
171 | jz .updateport |
172 | 172 | ||
173 | mov si, [edx + UDP_Packet.SourcePort] |
173 | mov si, [edx + UDP_Packet.SourcePort] |
174 | rol si, 8 |
174 | rol si, 8 |
175 | cmp [eax + UDP_SOCKET.RemotePort], si |
175 | cmp [eax + UDP_SOCKET.RemotePort], si |
176 | jne .dump |
176 | jne .dump |
177 | 177 | ||
178 | push ebx |
178 | push ebx |
179 | lea ebx, [eax + SOCKET.lock] |
179 | lea ebx, [eax + SOCKET.lock] |
180 | call wait_mutex |
180 | call wait_mutex |
181 | pop ebx |
181 | pop ebx |
182 | 182 | ||
183 | .updatesock: |
183 | .updatesock: |
184 | inc [UDP_PACKETS_RX] |
184 | inc [UDP_PACKETS_RX] |
185 | DEBUGF 1,"Found valid UDP packet for socket %x\n", eax |
185 | DEBUGF 1,"Found valid UDP packet for socket %x\n", eax |
186 | lea esi, [edx + UDP_Packet.Data] |
186 | lea esi, [edx + UDP_Packet.Data] |
187 | movzx ecx, [edx + UDP_Packet.Length] |
187 | movzx ecx, [edx + UDP_Packet.Length] |
188 | rol cx , 8 |
188 | rol cx , 8 |
189 | sub cx , UDP_Packet.Data |
189 | sub cx , UDP_Packet.Data |
190 | 190 | ||
191 | jmp SOCKET_input |
191 | jmp SOCKET_input |
192 | 192 | ||
193 | .updateport: |
193 | .updateport: |
194 | push ebx |
194 | push ebx |
195 | lea ebx, [eax + SOCKET.lock] |
195 | lea ebx, [eax + SOCKET.lock] |
196 | call wait_mutex |
196 | call wait_mutex |
197 | pop ebx |
197 | pop ebx |
198 | 198 | ||
199 | mov si, [edx + UDP_Packet.SourcePort] |
199 | mov si, [edx + UDP_Packet.SourcePort] |
200 | rol si, 8 |
200 | rol si, 8 |
201 | DEBUGF 1,"Changing remote port to: %u\n", si |
201 | DEBUGF 1,"Changing remote port to: %u\n", si |
202 | mov [eax + UDP_SOCKET.RemotePort], si |
202 | mov [eax + UDP_SOCKET.RemotePort], si |
203 | inc [eax + UDP_SOCKET.firstpacket] |
203 | inc [eax + UDP_SOCKET.firstpacket] |
204 | 204 | ||
205 | jmp .updatesock |
205 | jmp .updatesock |
206 | 206 | ||
207 | 207 | ||
208 | .checksum_mismatch: |
208 | .checksum_mismatch: |
209 | 209 | ||
210 | DEBUGF 2,"UDP_Handler - checksum mismatch\n" |
210 | DEBUGF 2,"UDP_Handler - checksum mismatch\n" |
211 | 211 | ||
212 | .dump: |
212 | .dump: |
213 | call kernel_free |
213 | call kernel_free |
214 | add esp, 4 ; pop (balance stack) |
214 | add esp, 4 ; pop (balance stack) |
215 | DEBUGF 2,"UDP_Handler - dumping\n" |
215 | DEBUGF 2,"UDP_Handler - dumping\n" |
216 | 216 | ||
217 | ret |
217 | ret |
218 | 218 | ||
219 | 219 | ||
220 | 220 | ||
221 | 221 | ||
222 | ;----------------------------------------------------------------- |
222 | ;----------------------------------------------------------------- |
223 | ; |
223 | ; |
224 | ; UDP_output |
224 | ; UDP_output |
225 | ; |
225 | ; |
226 | ; IN: eax = socket pointer |
226 | ; IN: eax = socket pointer |
227 | ; ecx = number of bytes to send |
227 | ; ecx = number of bytes to send |
228 | ; esi = pointer to data |
228 | ; esi = pointer to data |
229 | ; |
229 | ; |
230 | ;----------------------------------------------------------------- |
230 | ;----------------------------------------------------------------- |
231 | 231 | ||
232 | align 4 |
232 | align 4 |
233 | UDP_output: |
233 | UDP_output: |
234 | 234 | ||
235 | DEBUGF 1,"UDP_output: socket:%x, bytes: %u, data ptr: %x\n", eax, ecx, esi |
235 | DEBUGF 1,"UDP_output: socket:%x, bytes: %u, data ptr: %x\n", eax, ecx, esi |
236 | 236 | ||
237 | mov dx, [eax + UDP_SOCKET.RemotePort] |
237 | mov dx, [eax + UDP_SOCKET.RemotePort] |
238 | DEBUGF 1,"remote port: %u\n", dx |
238 | DEBUGF 1,"remote port: %u\n", dx |
239 | rol dx, 8 |
239 | rol dx, 8 |
240 | rol edx, 16 |
240 | rol edx, 16 |
241 | mov dx, [eax + UDP_SOCKET.LocalPort] |
241 | mov dx, [eax + UDP_SOCKET.LocalPort] |
242 | DEBUGF 1,"local port: %u\n", dx |
242 | DEBUGF 1,"local port: %u\n", dx |
243 | rol dx, 8 |
243 | rol dx, 8 |
244 | 244 | ||
245 | mov ebx, [eax + IP_SOCKET.LocalIP] |
245 | mov ebx, [eax + IP_SOCKET.LocalIP] |
246 | mov eax, [eax + IP_SOCKET.RemoteIP] |
246 | mov eax, [eax + IP_SOCKET.RemoteIP] |
247 | 247 | ||
248 | mov di, IP_PROTO_UDP shl 8 + 128 |
248 | mov di, IP_PROTO_UDP shl 8 + 128 |
249 | sub esp, 8 ; Data ptr and data size will be placed here |
249 | sub esp, 8 ; Data ptr and data size will be placed here |
250 | add ecx, UDP_Packet.Data |
250 | add ecx, UDP_Packet.Data |
251 | 251 | ||
252 | ;;; TODO: fragment id |
252 | ;;; TODO: fragment id |
253 | push edx esi |
253 | push edx esi |
254 | call IPv4_output |
254 | call IPv4_output |
255 | jz .fail |
255 | jz .fail |
256 | 256 | ||
257 | mov [esp + 8], eax ; pointer to buffer start |
257 | mov [esp + 8], eax ; pointer to buffer start |
258 | mov [esp + 8 + 4], edx ; buffer size |
258 | mov [esp + 8 + 4], edx ; buffer size |
259 | 259 | ||
260 | mov [edi + UDP_Packet.Length], cx |
260 | mov [edi + UDP_Packet.Length], cx |
261 | rol [edi + UDP_Packet.Length], 8 |
261 | rol [edi + UDP_Packet.Length], 8 |
262 | 262 | ||
263 | pop esi |
263 | pop esi |
264 | push edi ecx |
264 | push edi ecx |
265 | sub ecx, UDP_Packet.Data |
265 | sub ecx, UDP_Packet.Data |
266 | add edi, UDP_Packet.Data |
266 | add edi, UDP_Packet.Data |
267 | shr ecx, 2 |
267 | shr ecx, 2 |
268 | rep movsd |
268 | rep movsd |
269 | mov ecx, [esp] |
269 | mov ecx, [esp] |
270 | and ecx, 3 |
270 | and ecx, 3 |
271 | rep movsb |
271 | rep movsb |
272 | pop ecx edi |
272 | pop ecx edi |
273 | 273 | ||
274 | pop dword [edi + UDP_Packet.SourcePort] |
274 | pop dword [edi + UDP_Packet.SourcePort] |
275 | 275 | ||
276 | ; Checksum |
276 | ; Checksum |
277 | mov esi, edi |
277 | mov esi, edi |
278 | mov [edi + UDP_Packet.Checksum], 0 |
278 | mov [edi + UDP_Packet.Checksum], 0 |
279 | UDP_checksum (edi-4), (edi-8) ; TODO: fix this, IPv4 packet could have options.. |
279 | UDP_checksum (edi-4), (edi-8) ; TODO: fix this, IPv4 packet could have options.. |
280 | 280 | ||
281 | inc [UDP_PACKETS_TX] |
281 | inc [UDP_PACKETS_TX] |
282 | 282 | ||
283 | DEBUGF 1,"Sending UDP Packet to device %x\n", ebx |
283 | DEBUGF 1,"Sending UDP Packet to device %x\n", ebx |
284 | 284 | ||
285 | call [ebx + NET_DEVICE.transmit] |
285 | call [ebx + NET_DEVICE.transmit] |
286 | ret |
286 | ret |
287 | 287 | ||
288 | .fail: |
288 | .fail: |
289 | DEBUGF 1,"UDP_output: failed\n" |
289 | DEBUGF 1,"UDP_output: failed\n" |
290 | add esp, 4+4+8 |
290 | add esp, 4+4+8 |
291 | xor eax, eax |
291 | xor eax, eax |
292 | ret |
292 | ret |
293 | 293 | ||
294 | 294 | ||
295 | 295 | ||
296 | ;--------------------------------------------------------------------------- |
296 | ;--------------------------------------------------------------------------- |
297 | ; |
297 | ; |
298 | ; UDP_API |
298 | ; UDP_API |
299 | ; |
299 | ; |
300 | ; This function is called by system function 75 |
300 | ; This function is called by system function 75 |
301 | ; |
301 | ; |
302 | ; IN: subfunction number in bl |
302 | ; IN: subfunction number in bl |
303 | ; device number in bh |
303 | ; device number in bh |
304 | ; ecx, edx, .. depends on subfunction |
304 | ; ecx, edx, .. depends on subfunction |
305 | ; |
305 | ; |
306 | ; OUT: |
306 | ; OUT: |
307 | ; |
307 | ; |
308 | ;--------------------------------------------------------------------------- |
308 | ;--------------------------------------------------------------------------- |
309 | 309 | ||
310 | align 4 |
310 | align 4 |
311 | UDP_API: |
311 | UDP_API: |
312 | 312 | ||
313 | movzx eax, bh |
313 | movzx eax, bh |
314 | shl eax, 2 |
314 | shl eax, 2 |
315 | 315 | ||
316 | test bl, bl |
316 | test bl, bl |
317 | jz .packets_tx ; 0 |
317 | jz .packets_tx ; 0 |
318 | dec bl |
318 | dec bl |
319 | jz .packets_rx ; 1 |
319 | jz .packets_rx ; 1 |
320 | 320 | ||
321 | .error: |
321 | .error: |
322 | mov eax, -1 |
322 | mov eax, -1 |
323 | ret |
323 | ret |
324 | 324 | ||
325 | .packets_tx: |
325 | .packets_tx: |
326 | add eax, UDP_PACKETS_TX |
326 | add eax, UDP_PACKETS_TX |
327 | mov eax, [eax] |
327 | mov eax, [eax] |
328 | ret |
328 | ret |
329 | 329 | ||
330 | .packets_rx: |
330 | .packets_rx: |
331 | add eax, UDP_PACKETS_RX |
331 | add eax, UDP_PACKETS_RX |
332 | mov eax, [eax] |
332 | mov eax, [eax] |
333 | ret |
333 | ret |