Rev 1249 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1249 | Rev 1251 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2009. 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: 1249 $ |
17 | $Revision: 1251 $ |
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 | ; IN: / |
43 | ; IN: / |
44 | ; OUT: / |
44 | ; OUT: / |
45 | ; |
45 | ; |
46 | ;----------------------------------------------------------------- |
46 | ;----------------------------------------------------------------- |
47 | align 4 |
47 | align 4 |
48 | UDP_init: |
48 | UDP_init: |
49 | 49 | ||
50 | xor eax, eax |
50 | xor eax, eax |
51 | mov edi, UDP_PACKETS_TX |
51 | mov edi, UDP_PACKETS_TX |
52 | mov ecx, 2*MAX_IP |
52 | mov ecx, 2*MAX_IP |
53 | rep stosd |
53 | rep stosd |
54 | 54 | ||
55 | ret |
55 | ret |
56 | 56 | ||
57 | 57 | ||
58 | 58 | ||
59 | ;----------------------------------------------------------------- |
59 | ;----------------------------------------------------------------- |
60 | ; |
60 | ; |
61 | ; UDP_Handler: |
61 | ; UDP_Handler: |
62 | ; |
62 | ; |
63 | ; Called by IPv4_handler, |
63 | ; Called by IPv4_handler, |
64 | ; this procedure will inject the udp data diagrams in the application sockets. |
64 | ; this procedure will inject the udp data diagrams in the application sockets. |
65 | ; |
65 | ; |
66 | ; IN: Pointer to buffer in [esp] |
66 | ; IN: Pointer to buffer in [esp] |
67 | ; size of buffer in [esp+4] |
67 | ; size of buffer in [esp+4] |
68 | ; pointer to device struct in ebx |
68 | ; pointer to device struct in ebx |
69 | ; UDP Packet size in ecx |
69 | ; UDP Packet size in ecx |
70 | ; pointer to UDP Packet data in edx |
70 | ; pointer to UDP Packet data in edx |
71 | ; OUT: / |
71 | ; OUT: / |
72 | ; |
72 | ; |
73 | ;----------------------------------------------------------------- |
73 | ;----------------------------------------------------------------- |
74 | align 4 |
74 | align 4 |
75 | UDP_handler: |
75 | UDP_handler: |
76 | 76 | ||
77 | DEBUGF 1,"UDP_Handler\n" |
77 | DEBUGF 1,"UDP_Handler\n" |
78 | ; First validate, checksum: |
78 | ; First validate, checksum: |
79 | 79 | ||
80 | DEBUGF 1,"Real UDP checksum: %x\n", [edx + UDP_Packet.Checksum]:4 |
80 | DEBUGF 1,"Real UDP checksum: %x\n", [edx + UDP_Packet.Checksum]:4 |
81 | mov [edx + UDP_Packet.Checksum], 0 |
81 | mov [edx + UDP_Packet.Checksum], 0 |
82 | 82 | ||
83 | pusha |
83 | pusha |
84 | 84 | ||
85 | rol cx, 8 |
85 | rol cx, 8 |
86 | push cx |
86 | push cx |
87 | rol cx, 8 |
87 | rol cx, 8 |
88 | push word IP_PROTO_UDP shl 8 |
88 | push word IP_PROTO_UDP shl 8 |
89 | push edi |
89 | push edi |
90 | push esi |
90 | push esi |
91 | 91 | ||
92 | mov esi, edx |
92 | mov esi, edx |
93 | xor edx, edx |
93 | xor edx, edx |
94 | call checksum_1 |
94 | call checksum_1 |
95 | ; Checksum for pseudoheader |
95 | ; Checksum for pseudoheader |
96 | mov ecx, 12 |
96 | mov ecx, 12 |
97 | mov esi, esp |
97 | mov esi, esp |
98 | call checksum_1 |
98 | call checksum_1 |
99 | add esp, 12 |
99 | add esp, 12 |
100 | call checksum_2 |
100 | call checksum_2 |
101 | 101 | ||
102 | popa |
102 | popa |
103 | 103 | ||
104 | 104 | ||
105 | 105 | ||
106 | ; Look for a socket where |
106 | ; Look for a socket where |
107 | ; IP Packet UDP Destination Port = local Port |
107 | ; IP Packet UDP Destination Port = local Port |
108 | ; IP Packet SA = Remote IP |
108 | ; IP Packet SA = Remote IP |
109 | 109 | ||
110 | mov eax, net_sockets |
110 | mov eax, net_sockets |
111 | .try_more: |
111 | .try_more: |
112 | mov bx , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header |
112 | mov bx , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header |
113 | .next_socket: |
113 | .next_socket: |
114 | mov eax, [eax + SOCKET_head.NextPtr] |
114 | mov eax, [eax + SOCKET_head.NextPtr] |
115 | or eax, eax |
115 | or eax, eax |
116 | jz .dump |
116 | jz .dump |
117 | cmp [eax + SOCKET_head.Domain], AF_INET4 |
117 | cmp [eax + SOCKET_head.Domain], AF_INET4 |
118 | jne .next_socket |
118 | jne .next_socket |
119 | cmp [eax + SOCKET_head.Type], IP_PROTO_UDP |
119 | cmp [eax + SOCKET_head.Type], IP_PROTO_UDP |
120 | jne .next_socket |
120 | jne .next_socket |
121 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx |
121 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx |
122 | jne .next_socket |
122 | jne .next_socket |
123 | 123 | ||
124 | DEBUGF 1,"found socket with matching domain, type and localport\n" |
124 | DEBUGF 1,"found socket with matching domain, type and localport\n" |
125 | 125 | ||
126 | ; For dhcp, we must allow any remote server to respond. |
126 | ; For dhcp, we must allow any remote server to respond. |
127 | ; I will accept the first incoming response to be the one |
127 | ; I will accept the first incoming response to be the one |
128 | ; I bind to, if the socket is opened with a destination IP address of |
128 | ; I bind to, if the socket is opened with a destination IP address of |
129 | ; 255.255.255.255 |
129 | ; 255.255.255.255 |
130 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff |
130 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff |
131 | je .ok1 |
131 | je .ok1 |
132 | 132 | ||
133 | mov ebx, [esp] |
133 | mov ebx, [esp] |
134 | mov ebx, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet FIXME |
134 | mov ebx, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet FIXME |
135 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx |
135 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx |
136 | jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination |
136 | jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination |
137 | 137 | ||
138 | 138 | ||
139 | DEBUGF 1,"Remote Ip matches\n" |
139 | DEBUGF 1,"Remote Ip matches\n" |
140 | .ok1: |
140 | .ok1: |
141 | 141 | ||
142 | mov bx, [edx + UDP_Packet.SourcePort] ; Remote port must be 0, or equal to sourceport of packet |
142 | mov bx, [edx + UDP_Packet.SourcePort] ; Remote port must be 0, or equal to sourceport of packet |
143 | 143 | ||
144 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], 0 |
144 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], 0 |
145 | je .ok2 |
145 | je .ok2 |
146 | 146 | ||
147 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx |
147 | cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx |
148 | jne .dump |
148 | jne .dump |
149 | 149 | ||
150 | .ok2: |
150 | .ok2: |
151 | 151 | ||
152 | DEBUGF 1,"Found valid UDP packet for socket %x\n", eax |
152 | DEBUGF 1,"Found valid UDP packet for socket %x\n", eax |
153 | lea esi, [edx + UDP_Packet.Data] |
153 | lea esi, [edx + UDP_Packet.Data] |
154 | movzx ecx, [edx + UDP_Packet.Length] |
154 | movzx ecx, [edx + UDP_Packet.Length] |
155 | rol cx , 8 |
155 | rol cx , 8 |
156 | sub cx , UDP_Packet.Data |
156 | sub cx , UDP_Packet.Data |
157 | mov dx , bx |
157 | mov dx , bx |
158 | 158 | ||
159 | 159 | ||
160 | lea ebx, [eax + SOCKET_head.lock] |
160 | lea ebx, [eax + SOCKET_head.lock] |
161 | call wait_mutex |
161 | call wait_mutex |
162 | mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], dx ; update remote port number |
162 | mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], dx ; update remote port number |
163 | mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], edi |
163 | mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], edi |
164 | inc [UDP_PACKETS_RX] |
164 | inc [UDP_PACKETS_RX] |
165 | 165 | ||
166 | pop edi |
166 | pop edi |
167 | add esp, 4 |
167 | add esp, 4 |
168 | 168 | ||
169 | sub esi, edi |
169 | sub esi, edi |
170 | xchg esi, edi |
170 | xchg esi, edi |
171 | jmp socket_internal_receiver |
171 | jmp socket_internal_receiver |
172 | 172 | ||
173 | 173 | ||
174 | .dump: |
174 | .dump: |
175 | DEBUGF 1,"Dumping UDP packet\n" |
175 | DEBUGF 1,"Dumping UDP packet\n" |
176 | call kernel_free |
176 | call kernel_free |
177 | add esp, 4 ; pop (balance stack) |
177 | add esp, 4 ; pop (balance stack) |
178 | 178 | ||
179 | ret |
179 | ret |
180 | 180 | ||
181 | 181 | ||
182 | 182 | ||
183 | 183 | ||
184 | ;----------------------------------------------------------------- |
184 | ;----------------------------------------------------------------- |
185 | ; |
185 | ; |
186 | ; UDP_socket_send |
186 | ; UDP_socket_send |
187 | ; |
187 | ; |
188 | ; IN: eax = socket pointer |
188 | ; IN: eax = socket pointer |
189 | ; ecx = number of bytes to send |
189 | ; ecx = number of bytes to send |
190 | ; esi = pointer to data |
190 | ; esi = pointer to data |
191 | ; |
191 | ; |
192 | ;----------------------------------------------------------------- |
192 | ;----------------------------------------------------------------- |
193 | 193 | ||
194 | align 4 |
194 | align 4 |
195 | UDP_socket_send: |
195 | UDP_socket_send: |
196 | 196 | ||
197 | mov edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once |
197 | mov edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once |
198 | DEBUGF 1,"local port: %x, remote port: %x\n",\ |
198 | DEBUGF 1,"local port: %x, remote port: %x\n",\ |
199 | [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\ |
199 | [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\ |
200 | [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4 |
200 | [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4 |
201 | mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] |
201 | mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] |
202 | mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
202 | mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
203 | 203 | ||
204 | DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx |
204 | DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx |
205 | 205 | ||
206 | mov di , IP_PROTO_UDP |
206 | mov di , IP_PROTO_UDP |
207 | 207 | ||
208 | sub esp, 8 ; reserve some place in stack for later |
208 | sub esp, 8 ; reserve some place in stack for later |
209 | 209 | ||
210 | ; Create the pseudoheader in stack, |
210 | ; Create the pseudoheader in stack, |
211 | ; (now that we still have all the variables that are needed.) |
211 | ; (now that we still have all the variables that are needed.) |
212 | push dword IP_PROTO_UDP shl 8 |
212 | push dword IP_PROTO_UDP shl 8 |
213 | push eax |
- | |
214 | push ebx |
- | |
215 | 213 | ||
216 | add ecx, UDP_Packet.Data |
214 | add ecx, UDP_Packet.Data |
217 | 215 | ||
218 | ; TODO: fill in: dx = fragment id |
216 | ; TODO: fill in: dx = fragment id |
219 | 217 | ||
220 | push edx esi |
218 | push edx esi |
221 | call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
219 | call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
222 | cmp edi, -1 |
220 | cmp edi, -1 |
223 | je .fail |
221 | je .fail |
224 | 222 | ||
225 | mov [esp + 8 + 12], eax ; pointer to buffer start |
223 | mov [esp + 8 + 4], eax ; pointer to buffer start |
226 | mov [esp + 8 + 12 + 4], edx ; buffer size |
224 | mov [esp + 8 + 4 + 4], edx ; buffer size |
227 | 225 | ||
228 | rol cx, 8 |
226 | rol cx, 8 |
229 | mov [edi + UDP_Packet.Length], cx |
227 | mov [edi + UDP_Packet.Length], cx |
230 | mov [esp + 8 + 10], cx |
228 | mov [esp + 8 + 2], cx |
231 | ror cx, 8 |
229 | ror cx, 8 |
232 | 230 | ||
233 | pop esi |
231 | pop esi |
234 | push edi ecx |
232 | push edi ecx |
235 | sub ecx, UDP_Packet.Data |
233 | sub ecx, UDP_Packet.Data |
236 | add edi, UDP_Packet.Data |
234 | add edi, UDP_Packet.Data |
237 | shr ecx, 2 |
235 | shr ecx, 2 |
238 | rep movsd |
236 | rep movsd |
239 | mov ecx, [esp] |
237 | mov ecx, [esp] |
240 | and cx , 3 |
238 | and ecx, 3 |
241 | rep movsb |
239 | rep movsb |
242 | pop ecx edi |
240 | pop ecx edi |
243 | 241 | ||
244 | pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers |
242 | pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers |
245 | mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum |
243 | mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum |
246 | 244 | ||
247 | ; Checksum for UDP header + data |
245 | ; Checksum for UDP header + data |
248 | xor edx, edx |
246 | xor edx, edx |
249 | mov esi, edi |
247 | mov esi, edi |
250 | call checksum_1 |
248 | call checksum_1 |
251 | ; Checksum for pseudoheader |
249 | ; Checksum for pseudoheader |
- | 250 | pushd [edi-4] ; destination address |
|
- | 251 | pushd [edi-8] ; source address |
|
252 | mov ecx, 12 |
252 | mov ecx, 12 |
253 | mov esi, esp |
253 | mov esi, esp |
254 | call checksum_1 |
254 | call checksum_1 |
255 | add esp, 12 ; remove the pseudoheader from stack |
255 | add esp, 12 ; remove the pseudoheader from stack |
256 | ; Now create the final checksum and store it in UDP header |
256 | ; Now create the final checksum and store it in UDP header |
257 | call checksum_2 |
257 | call checksum_2 |
258 | mov [edi + UDP_Packet.Checksum], dx |
258 | mov [edi + UDP_Packet.Checksum], dx |
259 | 259 | ||
260 | inc [UDP_PACKETS_TX] |
260 | inc [UDP_PACKETS_TX] |
261 | 261 | ||
262 | DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ; |
262 | DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ; |
263 | jmp ETH_sender ; |
263 | jmp ETH_sender ; |
264 | 264 | ||
265 | .fail: |
265 | .fail: |
266 | ; todo: queue the packet |
266 | ; todo: queue the packet |
267 | add esp, 8+12+8 |
267 | add esp, 8+12+8 |
268 | ret |
268 | ret |
269 | 269 | ||
270 | 270 | ||
271 | 271 | ||
272 | 272 | ||
273 | ;--------------------------------------------------------------------------- |
273 | ;--------------------------------------------------------------------------- |
274 | ; |
274 | ; |
275 | ; UDP_API |
275 | ; UDP_API |
276 | ; |
276 | ; |
277 | ; This function is called by system function 75 |
277 | ; This function is called by system function 75 |
278 | ; |
278 | ; |
279 | ; IN: subfunction number in bl |
279 | ; IN: subfunction number in bl |
280 | ; device number in bh |
280 | ; device number in bh |
281 | ; ecx, edx, .. depends on subfunction |
281 | ; ecx, edx, .. depends on subfunction |
282 | ; |
282 | ; |
283 | ; OUT: |
283 | ; OUT: |
284 | ; |
284 | ; |
285 | ;--------------------------------------------------------------------------- |
285 | ;--------------------------------------------------------------------------- |
286 | 286 | ||
287 | align 4 |
287 | align 4 |
288 | UDP_API: |
288 | UDP_API: |
289 | 289 | ||
290 | movzx eax, bh |
290 | movzx eax, bh |
291 | shl eax, 2 |
291 | shl eax, 2 |
292 | 292 | ||
293 | test bl, bl |
293 | test bl, bl |
294 | jz .packets_tx ; 0 |
294 | jz .packets_tx ; 0 |
295 | dec bl |
295 | dec bl |
296 | jz .packets_rx ; 1 |
296 | jz .packets_rx ; 1 |
297 | 297 | ||
298 | .error: |
298 | .error: |
299 | mov eax, -1 |
299 | mov eax, -1 |
300 | ret |
300 | ret |
301 | 301 | ||
302 | .packets_tx: |
302 | .packets_tx: |
303 | add eax, UDP_PACKETS_TX |
303 | add eax, UDP_PACKETS_TX |
304 | mov eax, [eax] |
304 | mov eax, [eax] |
305 | ret |
305 | ret |
306 | 306 | ||
307 | .packets_rx: |
307 | .packets_rx: |
308 | add eax, UDP_PACKETS_RX |
308 | add eax, UDP_PACKETS_RX |
309 | mov eax, [eax] |
309 | mov eax, [eax] |
310 | ret |
310 | ret |