Subversion Repositories Kolibri OS

Rev

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

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