Subversion Repositories Kolibri OS

Rev

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