Subversion Repositories Kolibri OS

Rev

Rev 1249 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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