Subversion Repositories Kolibri OS

Rev

Rev 1337 | 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: 1473 $
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
 
1473 hidnplayr 77
	DEBUGF	1,"UDP_Handler\n"
78
 
79
	cmp	[edx + UDP_Packet.Checksum], 0
80
	jz	.no_checksum
1249 hidnplayr 81
	; First validate, checksum:
1159 hidnplayr 82
 
1249 hidnplayr 83
	pusha
84
 
85
	push	cx
1473 hidnplayr 86
	rol	word [esp], 8
1249 hidnplayr 87
	push	word IP_PROTO_UDP shl 8
88
	push	edi
89
	push	esi
90
 
1254 hidnplayr 91
	mov	di, [edx + UDP_Packet.Checksum]
1473 hidnplayr 92
	mov	[edx + UDP_Packet.Checksum], 0
1254 hidnplayr 93
 
1249 hidnplayr 94
	mov	esi, edx
95
	xor	edx, edx
96
	call	checksum_1
1473 hidnplayr 97
	call	checksum_pseudoheader
1249 hidnplayr 98
	call	checksum_2
99
 
1254 hidnplayr 100
	cmp	di, dx
1249 hidnplayr 101
	popa
1473 hidnplayr 102
	jne	.checksum_mismatch ;dump
1249 hidnplayr 103
 
104
 
1473 hidnplayr 105
  .no_checksum:
106
 
107
	DEBUGF	1,"UDP Checksum is correct\n"
108
 
1159 hidnplayr 109
	; Look for a socket where
110
	; IP Packet UDP Destination Port = local Port
111
	; IP Packet SA = Remote IP
112
 
1206 hidnplayr 113
	mov	eax, net_sockets
1159 hidnplayr 114
  .try_more:
1473 hidnplayr 115
	mov	si , [edx + UDP_Packet.DestinationPort]   ; get the local port from the IP Packet's UDP header
1159 hidnplayr 116
  .next_socket:
1249 hidnplayr 117
	mov	eax, [eax + SOCKET_head.NextPtr]
1206 hidnplayr 118
	or	eax, eax
1159 hidnplayr 119
	jz	.dump
1249 hidnplayr 120
	cmp	[eax + SOCKET_head.Domain], AF_INET4
1159 hidnplayr 121
	jne	.next_socket
1249 hidnplayr 122
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 123
	jne	.next_socket
1473 hidnplayr 124
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], si
1206 hidnplayr 125
	jne	.next_socket
1159 hidnplayr 126
 
1473 hidnplayr 127
	DEBUGF	1,"found socket with matching domain, type and localport\n"
1208 hidnplayr 128
 
1159 hidnplayr 129
	; For dhcp, we must allow any remote server to respond.
130
	; I will accept the first incoming response to be the one
131
	; I bind to, if the socket is opened with a destination IP address of
132
	; 255.255.255.255
1249 hidnplayr 133
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff
1206 hidnplayr 134
	je	.ok1
1159 hidnplayr 135
 
1473 hidnplayr 136
	mov	esi, [esp]
137
	mov	esi, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet   FIXME
138
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], esi
1159 hidnplayr 139
	jne	.try_more					      ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
140
 
1208 hidnplayr 141
 
1473 hidnplayr 142
	DEBUGF	1,"Remote Ip matches\n"
1206 hidnplayr 143
  .ok1:
1159 hidnplayr 144
 
1335 hidnplayr 145
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket], 0
146
	jz	.updateport
1159 hidnplayr 147
 
1473 hidnplayr 148
	mov	si, [edx + UDP_Packet.SourcePort]
149
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
1206 hidnplayr 150
	jne	.dump
1159 hidnplayr 151
 
1473 hidnplayr 152
	push	ebx
1337 hidnplayr 153
	lea	ebx, [eax + SOCKET_head.lock]
154
	call	wait_mutex
1473 hidnplayr 155
	pop	ebx
1337 hidnplayr 156
 
1206 hidnplayr 157
  .ok2:
1159 hidnplayr 158
 
1473 hidnplayr 159
	DEBUGF	1,"Found valid UDP packet for socket %x\n", eax
1206 hidnplayr 160
	lea	esi, [edx + UDP_Packet.Data]
161
	movzx	ecx, [edx + UDP_Packet.Length]
162
	rol	cx , 8
163
	sub	cx , UDP_Packet.Data
1159 hidnplayr 164
 
1206 hidnplayr 165
	inc	[UDP_PACKETS_RX]
1159 hidnplayr 166
 
1249 hidnplayr 167
	pop	edi
168
	add	esp, 4
169
 
170
	sub	esi, edi
171
	xchg	esi, edi
172
	jmp	socket_internal_receiver
173
 
174
 
1335 hidnplayr 175
  .updateport:
176
 
1473 hidnplayr 177
	push	ebx
1337 hidnplayr 178
	lea	ebx, [eax + SOCKET_head.lock]
179
	call	wait_mutex
1473 hidnplayr 180
	pop	ebx
1337 hidnplayr 181
 
1473 hidnplayr 182
	mov	si, [edx + UDP_Packet.SourcePort]
183
	DEBUGF	1,"Changing remote port to: %x\n", si
184
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], si
1335 hidnplayr 185
	inc	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.firstpacket]
186
 
187
	jmp	.ok2
188
 
1473 hidnplayr 189
  .checksum_mismatch:
190
 
191
	DEBUGF	2,"UDP_Handler - checksum mismatch\n"
192
 
193
	mov	esi, [esp]
194
	mov	ecx, [esp + 4]
195
       @@:			   ;
196
	lodsb			   ;
197
	DEBUGF	2,"%x ", eax:2	   ;
198
	loop	@r		   ;
199
 
1206 hidnplayr 200
  .dump:
1159 hidnplayr 201
	call	kernel_free
202
	add	esp, 4 ; pop (balance stack)
1473 hidnplayr 203
	DEBUGF	2,"UDP_Handler - dumping\n"
1159 hidnplayr 204
 
205
	ret
206
 
207
 
208
 
209
 
210
;-----------------------------------------------------------------
211
;
1249 hidnplayr 212
; UDP_socket_send
1159 hidnplayr 213
;
1249 hidnplayr 214
; IN: eax = socket pointer
215
;     ecx = number of bytes to send
216
;     esi = pointer to data
1159 hidnplayr 217
;
218
;-----------------------------------------------------------------
219
 
1249 hidnplayr 220
align 4
221
UDP_socket_send:
1159 hidnplayr 222
 
1249 hidnplayr 223
	mov	edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
224
	DEBUGF	1,"local port: %x, remote port: %x\n",\
225
	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
226
	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
227
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
228
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
229
 
1473 hidnplayr 230
	DEBUGF	1,"Create UDP Packet (size=%u)\n",ecx
1159 hidnplayr 231
 
1249 hidnplayr 232
	mov	di , IP_PROTO_UDP
233
	sub	esp, 8						; reserve some place in stack for later
1473 hidnplayr 234
								; Create a part of the pseudoheader in stack,
1249 hidnplayr 235
	push	dword IP_PROTO_UDP shl 8
1159 hidnplayr 236
	add	ecx, UDP_Packet.Data
237
 
1249 hidnplayr 238
; TODO: fill in:   dx  = fragment id
1159 hidnplayr 239
 
1249 hidnplayr 240
	push	edx esi
1196 hidnplayr 241
	call	IPv4_create_packet				; TODO: figure out a way to choose between IPv4 and IPv6
1159 hidnplayr 242
	cmp	edi, -1
1206 hidnplayr 243
	je	.fail
1159 hidnplayr 244
 
1251 clevermous 245
	mov	[esp + 8 + 4], eax				; pointer to buffer start
1254 hidnplayr 246
	mov	[esp + 8 + 4 + 4], edx				; buffer size
1159 hidnplayr 247
 
1249 hidnplayr 248
	rol	cx, 8
249
	mov	[edi + UDP_Packet.Length], cx
1251 clevermous 250
	mov	[esp + 8 + 2], cx
1249 hidnplayr 251
	ror	cx, 8
252
 
1159 hidnplayr 253
	pop	esi
1249 hidnplayr 254
	push	edi ecx
255
	sub	ecx, UDP_Packet.Data
1159 hidnplayr 256
	add	edi, UDP_Packet.Data
257
	shr	ecx, 2
258
	rep	movsd
1249 hidnplayr 259
	mov	ecx, [esp]
1251 clevermous 260
	and	ecx, 3
1159 hidnplayr 261
	rep	movsb
1249 hidnplayr 262
	pop	ecx edi
1159 hidnplayr 263
 
1254 hidnplayr 264
	pop	dword [edi + UDP_Packet.SourcePort]		; fill in both portnumbers
1249 hidnplayr 265
	mov	[edi + UDP_Packet.Checksum], 0			; set it to zero, to calculate checksum
1159 hidnplayr 266
 
1249 hidnplayr 267
; Checksum for UDP header + data
268
	xor	edx, edx
269
	mov	esi, edi
270
	call	checksum_1
271
; Checksum for pseudoheader
1335 hidnplayr 272
	pushd	[edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
1254 hidnplayr 273
	pushd	[edi-8] ; source address
1473 hidnplayr 274
	call	checksum_pseudoheader
1249 hidnplayr 275
; Now create the final checksum and store it in UDP header
276
	call	checksum_2
277
	mov	[edi + UDP_Packet.Checksum], dx
1159 hidnplayr 278
 
1206 hidnplayr 279
	inc	[UDP_PACKETS_TX]
280
 
1473 hidnplayr 281
	DEBUGF	1,"Sending UDP Packet to device %x\n", ebx	;
1249 hidnplayr 282
	jmp	ETH_sender				       ;
1159 hidnplayr 283
 
1206 hidnplayr 284
  .fail:
285
	; todo: queue the packet
1249 hidnplayr 286
	add	esp, 8+12+8
1206 hidnplayr 287
	ret
1159 hidnplayr 288
 
289
 
1206 hidnplayr 290
 
1249 hidnplayr 291
 
1159 hidnplayr 292
;---------------------------------------------------------------------------
293
;
294
; UDP_API
295
;
296
; This function is called by system function 75
297
;
298
; IN:  subfunction number in bl
299
;      device number in bh
300
;      ecx, edx, .. depends on subfunction
301
;
302
; OUT:
303
;
304
;---------------------------------------------------------------------------
305
 
306
align 4
307
UDP_API:
308
 
309
	movzx	eax, bh
310
	shl	eax, 2
311
 
312
	test	bl, bl
313
	jz	.packets_tx	; 0
314
	dec	bl
315
	jz	.packets_rx	; 1
316
 
317
.error:
318
	mov	eax, -1
319
	ret
320
 
321
.packets_tx:
322
	add	eax, UDP_PACKETS_TX
323
	mov	eax, [eax]
324
	ret
325
 
326
.packets_rx:
327
	add	eax, UDP_PACKETS_RX
328
	mov	eax, [eax]
329
	ret