Subversion Repositories Kolibri OS

Rev

Rev 1530 | 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: 1542 $
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
;-----------------------------------------------------------------
1529 hidnplayr 44
macro	UDP_init {
1159 hidnplayr 45
 
46
	xor	eax, eax
47
	mov	edi, UDP_PACKETS_TX
48
	mov	ecx, 2*MAX_IP
49
	rep	stosd
1529 hidnplayr 50
}
1159 hidnplayr 51
 
52
 
1529 hidnplayr 53
macro	UDP_checksum	IP1, IP2  { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
54
 
55
; Pseudoheader
56
	mov	edx, IP_PROTO_UDP
57
 
1530 hidnplayr 58
	add	dl, [IP1+1]
59
	adc	dh, [IP1+0]
60
	adc	dl, [IP1+3]
61
	adc	dh, [IP1+2]
1529 hidnplayr 62
 
1530 hidnplayr 63
	adc	dl, [IP2+1]
64
	adc	dh, [IP2+0]
65
	adc	dl, [IP2+3]
66
	adc	dh, [IP2+2]
1529 hidnplayr 67
 
68
	adc	dl, cl ; byte[esi+UDP_Packet.Length+1]
69
	adc	dh, ch ; byte[esi+UDP_Packet.Length+0]
70
 
71
; Done with pseudoheader, now do real header
72
	adc	dl, byte[esi+UDP_Packet.SourcePort+1]
73
	adc	dh, byte[esi+UDP_Packet.SourcePort+0]
74
 
75
	adc	dl, byte[esi+UDP_Packet.DestinationPort+1]
76
	adc	dh, byte[esi+UDP_Packet.DestinationPort+0]
77
 
78
	adc	dl, byte[esi+UDP_Packet.Length+1]
79
	adc	dh, byte[esi+UDP_Packet.Length+0]
80
 
81
	adc	edx, 0
82
 
83
; Done with header, now do data
84
	push	esi
85
	movzx	ecx, [esi+UDP_Packet.Length]
86
	rol	cx , 8
87
	sub	cx , UDP_Packet.Data
88
	add	esi, UDP_Packet.Data
89
 
90
	call	checksum_1
91
	call	checksum_2
92
	pop	esi
93
 
94
	add	[esi+UDP_Packet.Checksum], dx	; this final instruction will set or clear ZF :)
95
 
96
}
97
 
98
 
1159 hidnplayr 99
;-----------------------------------------------------------------
100
;
1514 hidnplayr 101
; UDP_input:
1159 hidnplayr 102
;
1514 hidnplayr 103
;  Called by IPv4_input,
1159 hidnplayr 104
;  this procedure will inject the udp data diagrams in the application sockets.
105
;
1529 hidnplayr 106
;  IN:   [esp]  = Pointer to buffer
107
;       [esp+4] = size of buffer
108
;       ebx = ptr to device struct
109
;       ecx = UDP Packet size
110
;       edx = ptr to UDP header
1484 hidnplayr 111
;
112
;       esi = ipv4 source address
113
;       edi = ipv4 dest   address
114
;
1159 hidnplayr 115
;  OUT: /
116
;
117
;-----------------------------------------------------------------
1206 hidnplayr 118
align 4
1514 hidnplayr 119
UDP_input:
1159 hidnplayr 120
 
1514 hidnplayr 121
	DEBUGF	1,"UDP_input, size:%u\n", ecx
1473 hidnplayr 122
 
1482 hidnplayr 123
; First validate, checksum:
1530 hidnplayr 124
	neg	[edx+UDP_Packet.Checksum]	; substract chechksum from 0
1529 hidnplayr 125
	jz	.no_checksum			; if checksum is zero, it is considered valid and we continue processing
126
						; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
1159 hidnplayr 127
 
1483 hidnplayr 128
	push	edx
1529 hidnplayr 129
	push	edi
130
	push	esi
1249 hidnplayr 131
	mov	esi, edx
1529 hidnplayr 132
	UDP_checksum (esp), (esp+4)
133
	pop	edi
134
	pop	esi	; we dont need it, but it is smaller then add esp, 4
1483 hidnplayr 135
	pop	edx
1484 hidnplayr 136
	jnz	.checksum_mismatch
1249 hidnplayr 137
 
1473 hidnplayr 138
  .no_checksum:
139
	DEBUGF	1,"UDP Checksum is correct\n"
140
 
1159 hidnplayr 141
	; Look for a socket where
142
	; IP Packet UDP Destination Port = local Port
143
	; IP Packet SA = Remote IP
144
 
1206 hidnplayr 145
	mov	eax, net_sockets
1159 hidnplayr 146
  .try_more:
1473 hidnplayr 147
	mov	si , [edx + UDP_Packet.DestinationPort]   ; get the local port from the IP Packet's UDP header
1514 hidnplayr 148
	rol	si , 8
1159 hidnplayr 149
  .next_socket:
1514 hidnplayr 150
	mov	eax, [eax + SOCKET.NextPtr]
1206 hidnplayr 151
	or	eax, eax
1159 hidnplayr 152
	jz	.dump
1514 hidnplayr 153
	cmp	[eax + SOCKET.Domain], AF_INET4
1159 hidnplayr 154
	jne	.next_socket
1542 hidnplayr 155
	cmp	[eax + SOCKET.Protocol], IP_PROTO_UDP
1159 hidnplayr 156
	jne	.next_socket
1514 hidnplayr 157
	cmp	[eax + UDP_SOCKET.LocalPort], si
1206 hidnplayr 158
	jne	.next_socket
1159 hidnplayr 159
 
1514 hidnplayr 160
	DEBUGF	1,"using socket: %x\n", eax
1208 hidnplayr 161
 
1514 hidnplayr 162
	;;; TODO: when packet is processed, check more sockets!
1159 hidnplayr 163
 
1514 hidnplayr 164
	cmp	[eax + IP_SOCKET.RemoteIP], 0xffffffff
165
	je	@f
166
	cmp	[eax + IP_SOCKET.RemoteIP], edi 	; edi is the packets source address
167
	jne	.try_more
168
       @@:
1159 hidnplayr 169
 
1514 hidnplayr 170
	cmp	[eax + UDP_SOCKET.firstpacket], 0
1335 hidnplayr 171
	jz	.updateport
1159 hidnplayr 172
 
1473 hidnplayr 173
	mov	si, [edx + UDP_Packet.SourcePort]
1514 hidnplayr 174
	rol	si, 8
175
	cmp	[eax + UDP_SOCKET.RemotePort], si
1206 hidnplayr 176
	jne	.dump
1159 hidnplayr 177
 
1473 hidnplayr 178
	push	ebx
1514 hidnplayr 179
	lea	ebx, [eax + SOCKET.lock]
1337 hidnplayr 180
	call	wait_mutex
1473 hidnplayr 181
	pop	ebx
1337 hidnplayr 182
 
1514 hidnplayr 183
  .updatesock:
184
	inc	[UDP_PACKETS_RX]
1473 hidnplayr 185
	DEBUGF	1,"Found valid UDP packet for socket %x\n", eax
1206 hidnplayr 186
	lea	esi, [edx + UDP_Packet.Data]
187
	movzx	ecx, [edx + UDP_Packet.Length]
188
	rol	cx , 8
189
	sub	cx , UDP_Packet.Data
1159 hidnplayr 190
 
1514 hidnplayr 191
	jmp	SOCKET_input
1159 hidnplayr 192
 
1335 hidnplayr 193
  .updateport:
1473 hidnplayr 194
	push	ebx
1514 hidnplayr 195
	lea	ebx, [eax + SOCKET.lock]
1337 hidnplayr 196
	call	wait_mutex
1473 hidnplayr 197
	pop	ebx
1337 hidnplayr 198
 
1473 hidnplayr 199
	mov	si, [edx + UDP_Packet.SourcePort]
1514 hidnplayr 200
	rol	si, 8
201
	DEBUGF	1,"Changing remote port to: %u\n", si
202
	mov	[eax + UDP_SOCKET.RemotePort], si
203
	inc	[eax + UDP_SOCKET.firstpacket]
1335 hidnplayr 204
 
1514 hidnplayr 205
	jmp	.updatesock
1335 hidnplayr 206
 
1483 hidnplayr 207
 
1473 hidnplayr 208
  .checksum_mismatch:
209
 
210
	DEBUGF	2,"UDP_Handler - checksum mismatch\n"
211
 
1206 hidnplayr 212
  .dump:
1159 hidnplayr 213
	call	kernel_free
214
	add	esp, 4 ; pop (balance stack)
1473 hidnplayr 215
	DEBUGF	2,"UDP_Handler - dumping\n"
1159 hidnplayr 216
 
217
	ret
218
 
219
 
220
 
221
 
222
;-----------------------------------------------------------------
223
;
1514 hidnplayr 224
; UDP_output
1159 hidnplayr 225
;
1249 hidnplayr 226
; IN: eax = socket pointer
227
;     ecx = number of bytes to send
228
;     esi = pointer to data
1159 hidnplayr 229
;
230
;-----------------------------------------------------------------
231
 
1249 hidnplayr 232
align 4
1514 hidnplayr 233
UDP_output:
1159 hidnplayr 234
 
1514 hidnplayr 235
	DEBUGF	1,"UDP_output: socket:%x, bytes: %u, data ptr: %x\n", eax, ecx, esi
1249 hidnplayr 236
 
1514 hidnplayr 237
	mov	dx, [eax + UDP_SOCKET.RemotePort]
238
	DEBUGF	1,"remote port: %u\n", dx
239
	rol	dx, 8
240
	rol	edx, 16
241
	mov	dx, [eax + UDP_SOCKET.LocalPort]
242
	DEBUGF	1,"local port: %u\n", dx
243
	rol	dx, 8
1159 hidnplayr 244
 
1514 hidnplayr 245
	mov	ebx, [eax + IP_SOCKET.LocalIP]
246
	mov	eax, [eax + IP_SOCKET.RemoteIP]
247
 
1529 hidnplayr 248
	mov	di, IP_PROTO_UDP shl 8 + 128
1482 hidnplayr 249
	sub	esp, 8						; Data ptr and data size will be placed here
1159 hidnplayr 250
	add	ecx, UDP_Packet.Data
251
 
1514 hidnplayr 252
;;; TODO: fragment id
1249 hidnplayr 253
	push	edx esi
1529 hidnplayr 254
	call	IPv4_output
1514 hidnplayr 255
	jz	.fail
1159 hidnplayr 256
 
1482 hidnplayr 257
	mov	[esp + 8], eax					; pointer to buffer start
258
	mov	[esp + 8 + 4], edx				; buffer size
1159 hidnplayr 259
 
1249 hidnplayr 260
	mov	[edi + UDP_Packet.Length], cx
1529 hidnplayr 261
	rol	[edi + UDP_Packet.Length], 8
1249 hidnplayr 262
 
1159 hidnplayr 263
	pop	esi
1249 hidnplayr 264
	push	edi ecx
265
	sub	ecx, UDP_Packet.Data
1159 hidnplayr 266
	add	edi, UDP_Packet.Data
267
	shr	ecx, 2
268
	rep	movsd
1249 hidnplayr 269
	mov	ecx, [esp]
1251 clevermous 270
	and	ecx, 3
1159 hidnplayr 271
	rep	movsb
1249 hidnplayr 272
	pop	ecx edi
1159 hidnplayr 273
 
1514 hidnplayr 274
	pop	dword [edi + UDP_Packet.SourcePort]
1159 hidnplayr 275
 
1482 hidnplayr 276
; Checksum
1249 hidnplayr 277
	mov	esi, edi
1529 hidnplayr 278
	mov	[edi + UDP_Packet.Checksum], 0
279
	UDP_checksum (edi-4), (edi-8)				; TODO: fix this, IPv4 packet could have options..
1159 hidnplayr 280
 
1206 hidnplayr 281
	inc	[UDP_PACKETS_TX]
282
 
1482 hidnplayr 283
	DEBUGF	1,"Sending UDP Packet to device %x\n", ebx
1159 hidnplayr 284
 
1519 hidnplayr 285
	call	[ebx + NET_DEVICE.transmit]
286
	ret
1529 hidnplayr 287
 
1206 hidnplayr 288
  .fail:
1529 hidnplayr 289
	DEBUGF	1,"UDP_output: failed\n"
290
	add	esp, 4+4+8
291
	xor	eax, eax
1206 hidnplayr 292
	ret
1159 hidnplayr 293
 
294
 
1206 hidnplayr 295
 
1159 hidnplayr 296
;---------------------------------------------------------------------------
297
;
298
; UDP_API
299
;
300
; This function is called by system function 75
301
;
302
; IN:  subfunction number in bl
303
;      device number in bh
304
;      ecx, edx, .. depends on subfunction
305
;
306
; OUT:
307
;
308
;---------------------------------------------------------------------------
309
 
310
align 4
311
UDP_API:
312
 
313
	movzx	eax, bh
314
	shl	eax, 2
315
 
316
	test	bl, bl
317
	jz	.packets_tx	; 0
318
	dec	bl
319
	jz	.packets_rx	; 1
320
 
321
.error:
322
	mov	eax, -1
323
	ret
324
 
325
.packets_tx:
326
	add	eax, UDP_PACKETS_TX
327
	mov	eax, [eax]
328
	ret
329
 
330
.packets_rx:
331
	add	eax, UDP_PACKETS_RX
332
	mov	eax, [eax]
333
	ret