Subversion Repositories Kolibri OS

Rev

Rev 1482 | 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: 1483 $
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
 
1483 hidnplayr 77
	DEBUGF	1,"UDP_Handler, checksum:%x, size:%u\n", [edx+UDP_Packet.Checksum]:4, ecx
1473 hidnplayr 78
 
1482 hidnplayr 79
; First validate, checksum:
80
	cmp    [edx + UDP_Packet.Checksum], 0
81
	jz     .no_checksum
1159 hidnplayr 82
 
1483 hidnplayr 83
	push	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
 
1483 hidnplayr 90
	pop	edx
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
 
1483 hidnplayr 125
;        mov     esi, [esp] ; start of data (ethernet header)
126
;        mov     esi, [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet   FIXME
127
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], edi ;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
 
1483 hidnplayr 178
 
1473 hidnplayr 179
  .checksum_mismatch:
180
 
181
	DEBUGF	2,"UDP_Handler - checksum mismatch\n"
182
 
1482 hidnplayr 183
;        mov     esi, edx
184
;       @@:                         ;
185
;        lodsb                      ;
186
;        DEBUGF  2,"%x ", eax:2     ;
187
;        loop    @r                 ;
1473 hidnplayr 188
 
1206 hidnplayr 189
  .dump:
1159 hidnplayr 190
	call	kernel_free
191
	add	esp, 4 ; pop (balance stack)
1473 hidnplayr 192
	DEBUGF	2,"UDP_Handler - dumping\n"
1159 hidnplayr 193
 
194
	ret
195
 
196
 
197
 
198
 
199
;-----------------------------------------------------------------
200
;
1249 hidnplayr 201
; UDP_socket_send
1159 hidnplayr 202
;
1249 hidnplayr 203
; IN: eax = socket pointer
204
;     ecx = number of bytes to send
205
;     esi = pointer to data
1159 hidnplayr 206
;
207
;-----------------------------------------------------------------
208
 
1249 hidnplayr 209
align 4
210
UDP_socket_send:
1159 hidnplayr 211
 
1249 hidnplayr 212
	mov	edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
213
	DEBUGF	1,"local port: %x, remote port: %x\n",\
214
	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
215
	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
216
	mov	ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
217
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
218
 
1473 hidnplayr 219
	DEBUGF	1,"Create UDP Packet (size=%u)\n",ecx
1159 hidnplayr 220
 
1249 hidnplayr 221
	mov	di , IP_PROTO_UDP
1482 hidnplayr 222
	sub	esp, 8						; Data ptr and data size will be placed here
1159 hidnplayr 223
	add	ecx, UDP_Packet.Data
224
 
1249 hidnplayr 225
; TODO: fill in:   dx  = fragment id
1159 hidnplayr 226
 
1249 hidnplayr 227
	push	edx esi
1196 hidnplayr 228
	call	IPv4_create_packet				; TODO: figure out a way to choose between IPv4 and IPv6
1159 hidnplayr 229
	cmp	edi, -1
1206 hidnplayr 230
	je	.fail
1159 hidnplayr 231
 
1482 hidnplayr 232
	mov	[esp + 8], eax					; pointer to buffer start
233
	mov	[esp + 8 + 4], edx				; buffer size
1159 hidnplayr 234
 
1249 hidnplayr 235
	rol	cx, 8
236
	mov	[edi + UDP_Packet.Length], cx
237
	ror	cx, 8
238
 
1159 hidnplayr 239
	pop	esi
1249 hidnplayr 240
	push	edi ecx
241
	sub	ecx, UDP_Packet.Data
1159 hidnplayr 242
	add	edi, UDP_Packet.Data
243
	shr	ecx, 2
244
	rep	movsd
1249 hidnplayr 245
	mov	ecx, [esp]
1251 clevermous 246
	and	ecx, 3
1159 hidnplayr 247
	rep	movsb
1249 hidnplayr 248
	pop	ecx edi
1159 hidnplayr 249
 
1254 hidnplayr 250
	pop	dword [edi + UDP_Packet.SourcePort]		; fill in both portnumbers
1249 hidnplayr 251
	mov	[edi + UDP_Packet.Checksum], 0			; set it to zero, to calculate checksum
1159 hidnplayr 252
 
1482 hidnplayr 253
; Checksum
1249 hidnplayr 254
	mov	esi, edi
1335 hidnplayr 255
	pushd	[edi-4] ; destination address           ; TODO: fix this, IPv4 packet could have options..
1254 hidnplayr 256
	pushd	[edi-8] ; source address
1482 hidnplayr 257
	call	UDP_checksum
1159 hidnplayr 258
 
1206 hidnplayr 259
	inc	[UDP_PACKETS_TX]
260
 
1482 hidnplayr 261
	DEBUGF	1,"Sending UDP Packet to device %x\n", ebx
262
	jmp	ETH_sender
1159 hidnplayr 263
 
1206 hidnplayr 264
  .fail:
265
	; todo: queue the packet
1249 hidnplayr 266
	add	esp, 8+12+8
1206 hidnplayr 267
	ret
1159 hidnplayr 268
 
269
 
1206 hidnplayr 270
 
1249 hidnplayr 271
 
1482 hidnplayr 272
;-----------------------------------------------------------------
273
;
274
; checksum_udp
275
;
276
; This is the fast procedure to create or check a UDP header
277
;  - To create a new checksum, the checksum field must be set to 0 before computation
278
;  - To check an existing checksum, leave the checksum as is,
279
;     and it will be 0 after this procedure, if it was correct
280
;
281
;  IN:  push source ip
282
;       push dest ip
283
;       esi = packet ptr
284
;
285
;  OUT: checksum is filled in in packet! (but also in dx)
286
;
287
;-----------------------------------------------------------------
288
 
289
align 4
290
UDP_checksum:
291
 
292
; Pseudoheader
293
	mov	edx, IP_PROTO_UDP		; NO shl 8 here ! (it took me ages to figure this one out)
294
 
295
	add	dl, [esp+1+4]
296
	adc	dh, [esp+0+4]
297
	adc	dl, [esp+3+4]
298
	adc	dh, [esp+2+4]
299
 
300
	adc	dl, [esp+1+8]
301
	adc	dh, [esp+0+8]
302
	adc	dl, [esp+3+8]
303
	adc	dh, [esp+2+8]
304
 
305
 
1483 hidnplayr 306
	adc	dl, cl ; byte[esi+UDP_Packet.Length+1]
307
	adc	dh, ch ; byte[esi+UDP_Packet.Length+0]
308
 
1482 hidnplayr 309
; Done with pseudoheader, now do real header
310
	adc	dl, byte[esi+UDP_Packet.SourcePort+1]
311
	adc	dh, byte[esi+UDP_Packet.SourcePort+0]
312
 
313
	adc	dl, byte[esi+UDP_Packet.DestinationPort+1]
314
	adc	dh, byte[esi+UDP_Packet.DestinationPort+0]
315
 
316
	adc	dl, byte[esi+UDP_Packet.Length+1]
317
	adc	dh, byte[esi+UDP_Packet.Length+0]
318
 
319
	adc	edx, 0
320
 
321
; Done with header, now do data
322
	push	esi
323
	movzx	ecx, [esi+UDP_Packet.Length]
324
	rol	cx , 8
325
	sub	cx , UDP_Packet.Data
326
	add	esi, UDP_Packet.Data
327
 
328
	call	checksum_1
329
	call	checksum_2
330
	pop	esi
331
 
332
	neg	[esi+UDP_Packet.Checksum]	    ; zero will stay zero so we just get the checksum
333
	add	[esi+UDP_Packet.Checksum], dx	    ;  , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
334
 
335
	ret	8
336
 
337
 
338
 
339
 
1159 hidnplayr 340
;---------------------------------------------------------------------------
341
;
342
; UDP_API
343
;
344
; This function is called by system function 75
345
;
346
; IN:  subfunction number in bl
347
;      device number in bh
348
;      ecx, edx, .. depends on subfunction
349
;
350
; OUT:
351
;
352
;---------------------------------------------------------------------------
353
 
354
align 4
355
UDP_API:
356
 
357
	movzx	eax, bh
358
	shl	eax, 2
359
 
360
	test	bl, bl
361
	jz	.packets_tx	; 0
362
	dec	bl
363
	jz	.packets_rx	; 1
364
 
365
.error:
366
	mov	eax, -1
367
	ret
368
 
369
.packets_tx:
370
	add	eax, UDP_PACKETS_TX
371
	mov	eax, [eax]
372
	ret
373
 
374
.packets_rx:
375
	add	eax, UDP_PACKETS_RX
376
	mov	eax, [eax]
377
	ret