Subversion Repositories Kolibri OS

Rev

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