Subversion Repositories Kolibri OS

Rev

Rev 1281 | 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
;;  SOCKET.INC                                                     ;;
7
;;                                                                 ;;
8
;;    Written by hidnplayr@kolibrios.org                           ;;
9
;;    based on code by mike.dld                                    ;;
10
;;                                                                 ;;
11
;;          GNU GENERAL PUBLIC LICENSE                             ;;
12
;;             Version 2, June 1991                                ;;
13
;;                                                                 ;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
1206 hidnplayr 16
$Revision: 1299 $
1159 hidnplayr 17
 
1249 hidnplayr 18
struct	SOCKET_head
1159 hidnplayr 19
	 .PrevPtr		dd ? ; pointer to previous socket in list
20
	 .NextPtr		dd ? ; pointer to next socket in list
21
	 .Number		dd ? ; socket number (unique within single process)
22
	 .PID			dd ? ; application process id
23
	 .Domain		dd ? ; INET/UNIX/..
24
	 .Type			dd ? ; RAW/UDP/TCP/...
1196 hidnplayr 25
	 .Protocol		dd ? ; ICMP/IPv4/ARP/
1249 hidnplayr 26
	 .lock			dd ? ; lock mutex
27
	 .end:
28
ends
29
 
30
struct	IPv4_SOCKET
31
	 .LocalIP		dd ?
32
	 .RemoteIP		dd ?
33
	 .SequenceNumber	dd ?
34
 
35
	; todo: add options (for func 8 and 9)
36
 
37
	 .end:
38
ends
39
 
40
struct	TCP_SOCKET
41
 
42
	 .LocalPort		dw ? ; In INET byte order
43
	 .RemotePort		dw ? ; In INET byte order
44
 
45
	 .backlog		dw ? ; Backlog
1256 clevermous 46
	 .backlog_cur		dw ? ; current size of queue for un-accept-ed connections
47
	 .last_ack_number	dd ? ; used only to let application know that ACK has been received
48
					; todo: may be use SND_UNA instead
49
					; todo: may be use events which allow additional information instead
50
					; todo: may be count acknowledged bytes (at least it has obvious sense)
1274 hidnplayr 51
	 .OrigRemoteIP		dd ? ; original remote IP address (used to reset to LISTEN state)
52
	 .OrigRemotePort	dw ? ; original remote port (used to reset to LISTEN state)
1254 hidnplayr 53
	 .wndsizeTimer		dd ? ; window size timer
54
 
55
	; Transmission control block
56
	 .state 		dd ? ; TCB state
57
	 .timer 		dd ? ; TCB timer (seconds)
58
	 .ISS			dd ? ; initial send sequence number
59
	 .IRS			dd ? ; initial receive sequence number
1196 hidnplayr 60
	 .SND_UNA		dd ? ; sequence number of unack'ed sent Packets
1249 hidnplayr 61
	 .SND_NXT		dd ? ; next send sequence number to use
1196 hidnplayr 62
	 .SND_WND		dd ? ; send window
63
	 .RCV_NXT		dd ? ; next receive sequence number to use
64
	 .RCV_WND		dd ? ; receive window
65
	 .SEG_LEN		dd ? ; segment length
66
	 .SEG_WND		dd ? ; segment window
1249 hidnplayr 67
 
68
	 .flags 		db ? ; packet flags
69
 
70
	 .end:
1159 hidnplayr 71
ends
72
 
1249 hidnplayr 73
struct	UDP_SOCKET
1159 hidnplayr 74
 
1249 hidnplayr 75
	 .LocalPort		dw ? ; In INET byte order
76
	 .RemotePort		dw ? ; In INET byte order
1159 hidnplayr 77
 
1249 hidnplayr 78
	 .end:
79
ends
80
 
81
struct	ICMP_SOCKET
82
 
83
	.Identifier		dw ? ;
84
 
85
	.end:
86
 
87
ends
88
 
89
struct	IPC_SOCKET
90
 
91
	.ConnectedTo		dd ? ; Socket number of other socket this one is connected to
92
 
93
	.end:
94
 
95
ends
96
 
1274 hidnplayr 97
struct	socket_queue_entry
98
	.data_ptr	dd ?
99
	.data_size	dd ?
100
	.offset 	dd ?
101
	.size:
102
ends
103
 
1249 hidnplayr 104
MAX_backlog		equ 20	     ; backlog for stream sockets
105
SOCKETBUFFSIZE		equ 4096     ; in bytes
106
SOCKET_QUEUE_SIZE	equ 10	     ; maximum number ofincoming packets queued for 1 socket
1257 hidnplayr 107
SOCKET_QUEUE_LOCATION	equ 2048     ; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
1249 hidnplayr 108
 
1159 hidnplayr 109
uglobal
110
	net_sockets	rd 2
111
	last_UDP_port	dw ? ; These values give the number of the last used ephemeral port
112
	last_TCP_port	dw ? ;
113
endg
114
 
115
 
1257 hidnplayr 116
;-----------------------------------------------------------------
1159 hidnplayr 117
;
118
; SOCKET_init
119
;
120
;  -
121
;
122
;  IN:  /
123
;  OUT: /
124
;
1257 hidnplayr 125
;-----------------------------------------------------------------
1159 hidnplayr 126
align 4
127
socket_init:
128
 
129
	mov	[net_sockets], 0
130
	mov	[net_sockets + 4], 0
131
 
132
	mov	[last_UDP_port], MIN_EPHEMERAL_PORT
133
	mov	[last_TCP_port], MIN_EPHEMERAL_PORT
134
 
135
	ret
136
 
137
 
1257 hidnplayr 138
;-----------------------------------------------------------------
1159 hidnplayr 139
;
140
; Socket API (function 74)
141
;
1257 hidnplayr 142
;-----------------------------------------------------------------
1159 hidnplayr 143
align 4
144
sys_socket:
1254 hidnplayr 145
	and	ebx, 0x000000FF ; should i remove this line ?
1256 clevermous 146
	cmp	bl , 8		; highest possible number
1254 hidnplayr 147
	jg	s_error
148
	lea	ebx, [.table + 4*ebx]
149
	jmp	dword [ebx]
1159 hidnplayr 150
 
1254 hidnplayr 151
.table:
152
	dd	socket_open	; 0
153
	dd	socket_close	; 1
154
	dd	socket_bind	; 2
155
	dd	socket_listen	; 3
156
	dd	socket_connect	; 4
157
	dd	socket_accept	; 5
158
	dd	socket_send	; 6
159
	dd	socket_recv	; 7
1257 hidnplayr 160
	dd	socket_get_opt	; 8
1254 hidnplayr 161
;        dd      socket_set_opt  ; 9
1159 hidnplayr 162
 
1254 hidnplayr 163
 
1185 hidnplayr 164
s_error:
1159 hidnplayr 165
	mov	dword [esp+32],-1
166
 
167
	ret
168
 
169
 
1257 hidnplayr 170
;-----------------------------------------------------------------
1159 hidnplayr 171
;
172
; SOCKET_open
173
;
174
;
175
;  IN:  domain in ecx
176
;       type in edx
1196 hidnplayr 177
;       protocol in esi
1159 hidnplayr 178
;  OUT: eax is socket num, -1 on error
179
;
1257 hidnplayr 180
;-----------------------------------------------------------------
1206 hidnplayr 181
align 4
1159 hidnplayr 182
socket_open:
183
 
184
	DEBUGF	1,"socket_open: domain: %u, type: %u",ecx, edx
185
 
186
	call	net_socket_alloc
187
	or	eax, eax
1185 hidnplayr 188
	jz	s_error
1159 hidnplayr 189
 
1249 hidnplayr 190
	mov	[eax + SOCKET_head.Domain], ecx
191
	mov	[eax + SOCKET_head.Type], edx
192
	mov	[eax + SOCKET_head.Protocol], esi
1159 hidnplayr 193
 
194
	stdcall net_socket_addr_to_num, eax
195
	DEBUGF	1,", socketnumber: %u\n", eax
196
 
1257 hidnplayr 197
	; TODO: if it is a tcp socket, set state to TCB_CLOSED
1254 hidnplayr 198
 
1159 hidnplayr 199
	mov	[esp+32], eax
200
 
201
	ret
202
 
203
 
204
 
1257 hidnplayr 205
;-----------------------------------------------------------------
1159 hidnplayr 206
;
207
; SOCKET_bind
208
;
209
;  IN:  socket number in ecx
210
;       pointer to sockaddr struct in edx
211
;       length of that struct in esi
212
;  OUT: 0 on success
213
;
1257 hidnplayr 214
;-----------------------------------------------------------------
1206 hidnplayr 215
align 4
1159 hidnplayr 216
socket_bind:
217
 
218
	DEBUGF	1,"Socket_bind: socknum: %u sockaddr: %x, length: %u, ",ecx,edx,esi
219
 
220
	stdcall net_socket_num_to_addr, ecx
221
	cmp	eax, -1
1185 hidnplayr 222
	jz	s_error
1159 hidnplayr 223
 
224
	cmp	esi, 2
1185 hidnplayr 225
	jl	s_error
1159 hidnplayr 226
 
227
	cmp	word [edx], AF_INET4
1249 hidnplayr 228
	je	.af_inet4
1159 hidnplayr 229
 
1249 hidnplayr 230
	cmp	word [edx], AF_UNIX
231
	je	.af_unix
232
 
233
	jmp	s_error
234
 
235
  .af_unix:
236
 
237
	; TODO: write code here
238
 
239
	mov	dword [esp+32],0
240
	ret
241
 
1159 hidnplayr 242
  .af_inet4:
243
 
244
	cmp	esi, 6
1185 hidnplayr 245
	jl	s_error
1159 hidnplayr 246
 
1249 hidnplayr 247
	mov	ecx, [eax + SOCKET_head.Type]
248
 
1159 hidnplayr 249
	mov	bx, word [edx + 2]
1206 hidnplayr 250
	DEBUGF	1,"local port: %x ",bx
1159 hidnplayr 251
	test	bx, bx
1206 hidnplayr 252
	jz	.find_free
1159 hidnplayr 253
 
1206 hidnplayr 254
	call	socket_check_port
255
	test	bx, bx
256
	je	s_error
257
	jmp	.got_port
1159 hidnplayr 258
 
1249 hidnplayr 259
    .find_free:
1159 hidnplayr 260
 
1206 hidnplayr 261
	call	socket_find_port
262
	test	bx, bx
263
	je	s_error
1159 hidnplayr 264
 
1249 hidnplayr 265
    .got_port:
1206 hidnplayr 266
	DEBUGF	1,"using port: %x ",bx
1249 hidnplayr 267
	mov	word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1159 hidnplayr 268
 
269
	mov	ebx, dword [edx + 4]
1249 hidnplayr 270
	mov	dword [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], ebx
1159 hidnplayr 271
 
272
	DEBUGF	1,"local ip: %u.%u.%u.%u\n",\
1249 hidnplayr 273
	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 0]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 1]:1,\
274
	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 2]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 3]:1
1159 hidnplayr 275
 
276
	mov	dword [esp+32],0
277
	ret
278
 
279
 
280
 
281
 
1257 hidnplayr 282
;-----------------------------------------------------------------
1159 hidnplayr 283
;
284
; SOCKET_connect
285
;
286
;
287
;  IN:  socket number in ecx
288
;       pointer to sockaddr struct in edx
289
;       length of that struct in esi
290
;  OUT: 0 on success
291
;
1257 hidnplayr 292
;-----------------------------------------------------------------
1159 hidnplayr 293
align 4
294
socket_connect:
295
 
296
	DEBUGF	1,"Socket_connect: socknum: %u sockaddr: %x, length: %u,",ecx,edx,esi
297
 
298
	stdcall net_socket_num_to_addr, ecx
299
	cmp	eax, -1
1185 hidnplayr 300
	jz	s_error
1159 hidnplayr 301
 
1254 hidnplayr 302
	cmp	esi, 8
1185 hidnplayr 303
	jl	s_error
1159 hidnplayr 304
 
305
	cmp	word [edx], AF_INET4
306
	je	.af_inet4
307
 
1185 hidnplayr 308
	jmp	s_error
1159 hidnplayr 309
 
310
  .af_inet4:
311
 
1249 hidnplayr 312
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 313
	je	.udp
314
 
1249 hidnplayr 315
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
1206 hidnplayr 316
	je	.tcp
1159 hidnplayr 317
 
1185 hidnplayr 318
	jmp	s_error
1159 hidnplayr 319
 
1254 hidnplayr 320
  .udp:
1159 hidnplayr 321
 
322
	mov	bx , word [edx + 2]
1249 hidnplayr 323
	mov	word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
1206 hidnplayr 324
	DEBUGF	1,"remote port: %x ",bx
1159 hidnplayr 325
 
326
	mov	ebx, dword [edx + 4]
1249 hidnplayr 327
	mov	dword [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
1159 hidnplayr 328
	DEBUGF	1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1
329
 
330
	mov	dword [esp+32],0
331
	ret
332
 
333
 
1254 hidnplayr 334
  .tcp:
335
	; TODO: set sequence number to random value
1159 hidnplayr 336
 
1281 hidnplayr 337
	lea	ebx, [eax + SOCKET_head.lock]
338
	call	wait_mutex
1159 hidnplayr 339
 
1254 hidnplayr 340
	; fill in remote port and IP
1159 hidnplayr 341
 
1254 hidnplayr 342
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0	   ; Reset the window timer.
343
											   ; TODO: figure out WTF this is
344
	mov	bx , word [edx + 2]
345
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], bx
346
	DEBUGF	1,"remote port: %x ",bx
1159 hidnplayr 347
 
1254 hidnplayr 348
	mov	ebx, dword [edx + 4]
349
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
1159 hidnplayr 350
 
1254 hidnplayr 351
	; check if local port and IP is ok
1159 hidnplayr 352
 
1254 hidnplayr 353
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], 0
354
	jne	@f
355
	push	[IP_LIST]	    ; device zero = default
356
	pop	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
357
       @@:
1159 hidnplayr 358
 
1254 hidnplayr 359
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], 0
360
	jne	@f
1159 hidnplayr 361
 
1254 hidnplayr 362
	mov	ecx, [eax + SOCKET_head.Type]
363
	call	socket_find_port
364
	test	bx, bx
365
	jz	s_error
1159 hidnplayr 366
 
1254 hidnplayr 367
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], bx
368
       @@:
1159 hidnplayr 369
 
370
 
1254 hidnplayr 371
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
372
	; now say hello to the remote tcp socket
1159 hidnplayr 373
 
1254 hidnplayr 374
	mov	bl, TH_SYN
1274 hidnplayr 375
	xor	ecx, ecx
376
	call	TCP_send
1159 hidnplayr 377
 
1254 hidnplayr 378
	mov	dword [esp+32],0
1159 hidnplayr 379
	ret
380
 
381
 
1257 hidnplayr 382
;-----------------------------------------------------------------
1159 hidnplayr 383
;
384
; SOCKET_listen
385
;
386
;
387
;  IN:  socket number in ecx
388
;       backlog in edx
389
;  OUT: eax is socket num, -1 on error
390
;
1257 hidnplayr 391
;-----------------------------------------------------------------
1206 hidnplayr 392
align 4
1159 hidnplayr 393
socket_listen:
394
 
395
	DEBUGF	1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx
396
 
397
	stdcall net_socket_num_to_addr, ecx
398
	cmp	eax, -1
1185 hidnplayr 399
	jz	s_error
1159 hidnplayr 400
 
1254 hidnplayr 401
	cmp	word [eax + SOCKET_head.Domain], AF_INET4
402
	jne	s_error
403
 
404
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
405
	jne	s_error
406
 
1159 hidnplayr 407
	cmp	edx, MAX_backlog
1256 clevermous 408
	jb	.ok
409
	mov	dx , MAX_backlog
1159 hidnplayr 410
  .ok:
411
 
1249 hidnplayr 412
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
1254 hidnplayr 413
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1159 hidnplayr 414
 
415
	mov	dword [esp+32], 0
416
	ret
417
 
418
 
1257 hidnplayr 419
;-----------------------------------------------------------------
1159 hidnplayr 420
;
421
; SOCKET_accept
422
;
423
;
424
;  IN:  socket number in ecx
425
;       addr in edx
426
;       addrlen in esi
427
;  OUT: eax is socket num, -1 on error
428
;
1257 hidnplayr 429
;-----------------------------------------------------------------
1206 hidnplayr 430
align 4
1159 hidnplayr 431
socket_accept:
432
 
433
	DEBUGF	1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi
434
 
435
	stdcall net_socket_num_to_addr, ecx
436
	or	eax, eax
1185 hidnplayr 437
	jz	s_error
1159 hidnplayr 438
	mov	esi, eax
439
 
1249 hidnplayr 440
	cmp	word [esi + SOCKET_head.Domain], AF_INET4
441
	je	.af_inet4
442
 
443
	jmp	s_error
444
 
445
  .af_inet4:
446
 
447
	cmp	[esi + SOCKET_head.Type], IP_PROTO_TCP
448
	je	.tcp
449
 
450
	jmp	s_error
451
 
452
  .tcp:
453
 
1256 clevermous 454
	lea	ebx, [esi + SOCKET_head.lock]
455
	call	wait_mutex
456
	movzx	eax, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
457
	test	eax, eax
458
	jz	.unlock_err
459
	dec	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
460
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + (eax-1)*4]
461
	mov	[esi + SOCKET_head.lock], 0
1257 hidnplayr 462
	stdcall net_socket_addr_to_num, eax
1159 hidnplayr 463
	mov	[esp+32], eax
464
	ret
1256 clevermous 465
  .unlock_err:
466
	mov	[esi + SOCKET_head.lock], 0
467
	jmp	s_error
1159 hidnplayr 468
 
469
 
1257 hidnplayr 470
;-----------------------------------------------------------------
1159 hidnplayr 471
;
472
; SOCKET_close
473
;
474
;
475
;  IN:  socket number in ecx
476
;  OUT: eax is socket num, -1 on error
477
;
1257 hidnplayr 478
;-----------------------------------------------------------------
1206 hidnplayr 479
align 4
1159 hidnplayr 480
socket_close:
481
 
482
	DEBUGF	1,"Socket_close: socknum: %u\n",ecx
483
 
484
	stdcall net_socket_num_to_addr, ecx
485
	or	eax, eax
1185 hidnplayr 486
	jz	s_error
1159 hidnplayr 487
 
1249 hidnplayr 488
	cmp	[eax + SOCKET_head.Domain], AF_INET4
489
	jne	s_error
1159 hidnplayr 490
 
1249 hidnplayr 491
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 492
	je	.udp
493
 
1249 hidnplayr 494
	cmp	[eax + SOCKET_head.Type], IP_PROTO_ICMP
1159 hidnplayr 495
	je	.icmp
496
 
1249 hidnplayr 497
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
1206 hidnplayr 498
	je	.tcp
1159 hidnplayr 499
 
1185 hidnplayr 500
	jmp	s_error
1159 hidnplayr 501
 
502
  .udp:
503
 
504
	stdcall net_socket_free, eax
505
	mov	dword [esp+32],0
506
	ret
507
 
508
 
509
  .icmp:
510
 
511
 
512
 
513
	ret
514
 
515
  .tcp:
1254 hidnplayr 516
	; first, remove all resend entries for this socket
1159 hidnplayr 517
 
1254 hidnplayr 518
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1159 hidnplayr 519
	je	.destroy_tcb
1254 hidnplayr 520
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
1159 hidnplayr 521
	je	.destroy_tcb
522
 
1281 hidnplayr 523
	; Send a fin, then enter finwait2 state
524
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_1
1159 hidnplayr 525
 
526
	mov	bl, TH_FIN
1274 hidnplayr 527
	xor	ecx, ecx
1281 hidnplayr 528
;        call    TCP_send
1159 hidnplayr 529
 
1281 hidnplayr 530
	;;;;;
1159 hidnplayr 531
 
532
 
533
  .destroy_tcb:
534
 
535
	stdcall net_socket_free, eax
536
	mov	dword [esp+32],0
537
	ret
538
 
539
 
540
 
541
 
1257 hidnplayr 542
;-----------------------------------------------------------------
1159 hidnplayr 543
;
544
; SOCKET_receive
545
;
546
;
547
;  IN:  socket number in ecx
1249 hidnplayr 548
;       addr to buffer in edx
549
;       length of buffer in esi
1159 hidnplayr 550
;       flags in edi
551
;  OUT: eax is number of bytes copied, -1 on error
552
;
1257 hidnplayr 553
;-----------------------------------------------------------------
1206 hidnplayr 554
align 4
1159 hidnplayr 555
socket_recv:
556
 
1281 hidnplayr 557
	DEBUGF	1,"Socket_receive: socknum: %u bufaddr: %x, buflength: %u, flags: %x\n",ecx,edx,esi,edi
1159 hidnplayr 558
	stdcall net_socket_num_to_addr, ecx		   ; get real socket address
559
	or	eax, eax
1185 hidnplayr 560
	jz	s_error
1159 hidnplayr 561
 
1281 hidnplayr 562
	mov	ebx, esi
563
 
1249 hidnplayr 564
	DEBUGF	1,"Socket pointer: %x\n", eax
1159 hidnplayr 565
 
1281 hidnplayr 566
	get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, s_error	; destroys esi and ecx
1159 hidnplayr 567
 
1281 hidnplayr 568
	mov	edi, edx					; addr to buffer
1249 hidnplayr 569
	mov	ecx, [esi + socket_queue_entry.data_size]
1159 hidnplayr 570
 
1249 hidnplayr 571
	DEBUGF	1,"Got %u bytes of data\n", ecx
1159 hidnplayr 572
 
1281 hidnplayr 573
	cmp	ecx, ebx
1249 hidnplayr 574
	jle	.large_enough
575
	DEBUGF	1,"Buffer too small...\n"
576
	jmp	s_error
577
  .large_enough:
1159 hidnplayr 578
 
1281 hidnplayr 579
	push	[esi + socket_queue_entry.data_ptr]		; save the buffer addr so we can clear it later
1249 hidnplayr 580
	mov	esi, [esi + socket_queue_entry.offset]
1281 hidnplayr 581
	add	esi, [esp]					; calculate the real data offset
1249 hidnplayr 582
	DEBUGF	1,"Source buffer: %x, real addr: %x\n", [esp], esi
1159 hidnplayr 583
 
1281 hidnplayr 584
	mov	dword[esp+32+4], ecx				; return number of bytes copied
1159 hidnplayr 585
 
1249 hidnplayr 586
	shr	ecx, 1
587
	jnc	.nb
588
	movsb
589
.nb:	shr	ecx, 1
590
	jnc	.nw
591
	movsw
1274 hidnplayr 592
.nw:	test	ecx, ecx
593
	jz	.nd
594
	rep	movsd
595
.nd:
1159 hidnplayr 596
 
1281 hidnplayr 597
	call	kernel_free					; todo: check if ALL applications had the chance to receive data
1159 hidnplayr 598
 
599
	ret
600
 
601
 
1257 hidnplayr 602
;-----------------------------------------------------------------
1159 hidnplayr 603
;
604
; SOCKET_send
605
;
606
;
607
;  IN:  socket number in ecx
1206 hidnplayr 608
;       pointer to data in edx
609
;       datalength in esi
1159 hidnplayr 610
;       flags in edi
611
;  OUT: -1 on error
612
;
1257 hidnplayr 613
;-----------------------------------------------------------------
1206 hidnplayr 614
align 4
1159 hidnplayr 615
socket_send:
616
 
617
	DEBUGF	1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi
618
 
619
	stdcall net_socket_num_to_addr, ecx		   ; get real socket address
620
	or	eax, eax
1185 hidnplayr 621
	jz	s_error
1159 hidnplayr 622
 
1249 hidnplayr 623
	cmp	word [eax + SOCKET_head.Domain], AF_INET4
1206 hidnplayr 624
	je	.af_inet4
625
 
626
	jmp	s_error
627
 
628
  .af_inet4:
1249 hidnplayr 629
	DEBUGF	1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
1206 hidnplayr 630
 
1249 hidnplayr 631
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
632
	je	.tcp
1159 hidnplayr 633
 
1249 hidnplayr 634
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 635
	je	.udp
636
 
1249 hidnplayr 637
	cmp	[eax + SOCKET_head.Type], SOCK_RAW
638
	je	.raw
1159 hidnplayr 639
 
1185 hidnplayr 640
	jmp	s_error
1159 hidnplayr 641
 
642
  .udp:
643
 
1206 hidnplayr 644
	DEBUGF	1,"type: UDP, "
1159 hidnplayr 645
 
1249 hidnplayr 646
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort],0
647
	jne	@f
1206 hidnplayr 648
 
1208 hidnplayr 649
	push	esi
1249 hidnplayr 650
	mov	ecx, [eax + SOCKET_head.Type]
1206 hidnplayr 651
	call	socket_find_port
652
	test	bx, bx
1208 hidnplayr 653
	pop	esi
1206 hidnplayr 654
	je	s_error
1249 hidnplayr 655
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 656
 
1249 hidnplayr 657
     @@:
1206 hidnplayr 658
 
1159 hidnplayr 659
	mov	ecx, esi
660
	mov	esi, edx
661
 
1249 hidnplayr 662
	call	UDP_socket_send
1159 hidnplayr 663
 
1263 clevermous 664
	and	dword [esp+32], 0
1159 hidnplayr 665
	ret
666
 
1249 hidnplayr 667
  .tcp:
1159 hidnplayr 668
 
1254 hidnplayr 669
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort],0
670
	jne	@f
671
 
672
	push	esi
673
	mov	ecx, [eax + SOCKET_head.Type]
674
	call	socket_find_port
675
	test	bx, bx
676
	pop	esi
677
	je	s_error
678
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], bx
679
 
680
     @@:
681
 
682
	mov	ecx, esi
683
	mov	esi, edx
1281 hidnplayr 684
	mov	bl, TH_PUSH + TH_ACK
1254 hidnplayr 685
 
1274 hidnplayr 686
	call	TCP_send
1254 hidnplayr 687
 
1249 hidnplayr 688
	mov	[esp+32], eax
689
	ret
1159 hidnplayr 690
 
1249 hidnplayr 691
  .raw:
692
	cmp	[eax + SOCKET_head.Protocol], IP_PROTO_IP
693
	je	.raw_ip
694
 
695
	cmp	[eax + SOCKET_head.Protocol], IP_PROTO_ICMP
696
	je	.raw_icmp
697
 
698
	jmp	s_error
699
 
700
 
701
  .raw_ip:
702
 
1254 hidnplayr 703
	;;;;;;
704
 
1159 hidnplayr 705
	mov	[esp+32], eax
706
	ret
707
 
708
 
1249 hidnplayr 709
  .raw_icmp:
710
 
711
;        sub     ecx, ICMP_Packet.Data
712
;        mov     esi, edx
713
;        push    ax
714
;        call    IPv4_get_frgmnt_num
715
;        mov     dx, ax
716
;        pop     ax
717
;        shl     edx, 16
718
;        mov     dh , [esi + ICMP_Packet.Type]
719
;        mov     dl , [esi + ICMP_Packet.Code]
720
;        mov     di , [esi + ICMP_Packet.Identifier]
721
;        mov     [eax + SOCKET.LocalPort], di            ; Set localport to the identifier number, so we can receive reply's
722
;        shl     edi, 16
723
;        mov     di , [esi + ICMP_Packet.SequenceNumber]
724
;        add     esi, ICMP_Packet.Data
725
;        mov     ebx, [eax + SOCKET.LocalIP]
726
;        mov     eax, [eax + SOCKET.RemoteIP]
727
;        call    ICMP_create_packet
728
 
729
	mov	[esp+32], eax
1159 hidnplayr 730
	ret
731
 
1257 hidnplayr 732
;-----------------------------------------------------------------
1256 clevermous 733
;
1257 hidnplayr 734
; SOCKET_get_options
1256 clevermous 735
;
736
;
737
;  IN:  socket number in ecx
738
;       edx points to the options:
1257 hidnplayr 739
;               dd      level, optname, optval, optlen
1256 clevermous 740
;  OUT: -1 on error
741
;
742
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
743
; TODO: find best way to notify that send()'ed data were acknowledged
1299 clevermous 744
; Also pseudo-optname -3 is valid and returns socket state, one of TCB_*.
1256 clevermous 745
;
1257 hidnplayr 746
;-----------------------------------------------------------------
747
align 4
1256 clevermous 748
socket_get_opt:
1257 hidnplayr 749
 
1256 clevermous 750
	cmp	dword [edx], IP_PROTO_TCP
751
	jnz	.unknown
752
	cmp	dword [edx+4], -2
1299 clevermous 753
	jz	@f
754
	cmp	dword [edx+4], -3
1256 clevermous 755
	jnz	.unknown
1299 clevermous 756
@@:
1256 clevermous 757
	mov	eax, [edx+12]
758
	test	eax, eax
759
	jz	.fail
760
	cmp	dword [eax], 4
761
	mov	dword [eax], 4
762
	jb	.fail
1257 hidnplayr 763
	stdcall net_socket_num_to_addr, ecx
1256 clevermous 764
	test	eax, eax
765
	jz	.fail
766
	; todo: check that eax is really TCP socket
767
	mov	ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number]
1299 clevermous 768
	cmp	dword [edx+4], -2
769
	jz	@f
770
	mov	ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
771
@@:
1256 clevermous 772
	mov	eax, [edx+8]
773
	test	eax, eax
774
	jz	@f
775
	mov	[eax], ecx
776
@@:
1257 hidnplayr 777
	mov	dword [esp+32], 0
1256 clevermous 778
	ret
779
.fail:
780
.unknown:
1257 hidnplayr 781
	mov	dword [esp+32], -1
1256 clevermous 782
	ret
1159 hidnplayr 783
 
784
 
1257 hidnplayr 785
;-----------------------------------------------------------------
1206 hidnplayr 786
;
787
; SOCKET_find_free_port (local port)
788
;
789
; works with INET byte order
790
;
791
;  IN:  type in ecx (TCP/UDP)
792
;  OUT: bx = 0 on error, portnumber otherwise
793
;
1257 hidnplayr 794
;-----------------------------------------------------------------
1206 hidnplayr 795
align 4
796
socket_find_port:
1159 hidnplayr 797
 
1208 hidnplayr 798
	DEBUGF	1,"Socket_find_free_port\n"
1159 hidnplayr 799
 
1206 hidnplayr 800
	cmp	ecx, IP_PROTO_UDP
801
	je	.udp
1159 hidnplayr 802
 
1206 hidnplayr 803
	cmp	ecx, IP_PROTO_TCP
804
	je	.tcp
1159 hidnplayr 805
 
1206 hidnplayr 806
  .udp:
807
	mov	bx, [last_UDP_port]
808
	je	.continue
809
 
810
  .tcp:
811
	mov	bx, [last_TCP_port]
812
 
813
 
814
  .continue:
815
	inc	bx
816
 
817
  .check_only:
818
	mov	esi, net_sockets
819
 
820
  .next_socket:
1249 hidnplayr 821
	mov	esi, [esi + SOCKET_head.NextPtr]
1206 hidnplayr 822
	or	esi, esi
823
	jz	.port_ok
824
 
1249 hidnplayr 825
	cmp	[esi + SOCKET_head.Type], ecx
1206 hidnplayr 826
	jne	.next_socket
827
 
828
	rol	bx, 8
1249 hidnplayr 829
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 830
	rol	bx, 8				; this doesnt change the zero flag, does it ?
831
	jne	.next_socket
832
 
833
	cmp	bx, MAX_EPHEMERAL_PORT
834
	jle	.continue
835
 
836
	; todo: WRAP!
837
;        mov     [last_UDP_port], MIN_EPHEMERAL_PORT
838
  .exit:
839
	xor	ebx, ebx
840
 
841
  .port_ok:
842
	rol	bx, 8
843
	ret
844
 
1257 hidnplayr 845
 
846
 
847
;-----------------------------------------------------------------
1206 hidnplayr 848
;
849
; SOCKET_check_port (local port)
850
;
851
; works with INET byte order
852
;
853
;  IN:  type in ecx (TCP/UDP)
854
;       port to check in bx
855
;  OUT: bx = 0 on error, unchanged otherwise
856
;
1257 hidnplayr 857
;-----------------------------------------------------------------
1206 hidnplayr 858
align 4
859
socket_check_port:
860
	mov	esi, net_sockets
861
 
862
  .next_socket:
1249 hidnplayr 863
	mov	esi, [esi + SOCKET_head.NextPtr]
1206 hidnplayr 864
	or	esi, esi
865
	jz	.port_ok
866
 
1249 hidnplayr 867
	cmp	[esi + SOCKET_head.Type], ecx
1206 hidnplayr 868
	jne	.next_socket
869
 
1249 hidnplayr 870
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 871
	jne	.next_socket
872
 
873
	xor	ebx, ebx
874
 
875
  .port_ok:
876
	ret
877
 
878
 
1257 hidnplayr 879
 
880
;-----------------------------------------------------------------
1206 hidnplayr 881
;
882
; SOCKET_internal_receiver
883
;
1249 hidnplayr 884
; Updates a socket with received data
1206 hidnplayr 885
;
1249 hidnplayr 886
; Note: the mutex must already be set !
1206 hidnplayr 887
;
1249 hidnplayr 888
;  IN:  eax = socket ptr
889
;       ecx = size
890
;       esi = pointer to buffer
891
;       edi = offset
892
;
1206 hidnplayr 893
;  OUT: xxx
894
;
1257 hidnplayr 895
;-----------------------------------------------------------------
1206 hidnplayr 896
align 4
897
socket_internal_receiver:
898
 
1255 hidnplayr 899
	DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x size=%u socket: %x\n", esi, edi, ecx, eax
1206 hidnplayr 900
 
1249 hidnplayr 901
	push	edi	; offset
902
	push	ecx	; size
903
	push	esi	; data_ptr
904
	mov	esi, esp
1257 hidnplayr 905
	add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, notify_network_event.full
1249 hidnplayr 906
	DEBUGF	1,"Queued packet successfully\n"
1257 hidnplayr 907
	add	esp, socket_queue_entry.size
1206 hidnplayr 908
 
1249 hidnplayr 909
	mov	[eax + SOCKET_head.lock], 0
1206 hidnplayr 910
 
1256 clevermous 911
notify_network_event:
1206 hidnplayr 912
	; flag an event to the application
1249 hidnplayr 913
	mov	edx, [eax + SOCKET_head.PID]				; get socket owner PID
1206 hidnplayr 914
	mov	ecx, 1
915
	mov	esi, TASK_DATA + TASKDATA.pid
916
 
917
       .next_pid:
918
	cmp	[esi], edx
919
	je	.found_pid
920
	inc	ecx
921
	add	esi, 0x20
922
	cmp	ecx, [TASK_COUNT]
923
	jbe	.next_pid
924
	ret
925
 
926
       .found_pid:
927
	shl	ecx, 8
1249 hidnplayr 928
	or	[ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK	; stack event
1206 hidnplayr 929
	mov	[check_idle_semaphore], 200
930
	ret
931
 
1249 hidnplayr 932
  .full:
933
	DEBUGF 1,"Socket %x is full!\n",eax
934
	mov	[eax + SOCKET_head.lock], 0
935
	call	kernel_free
936
	add	esp, 8
1206 hidnplayr 937
	ret
938
 
939
 
940
 
1159 hidnplayr 941
; Allocate memory for socket data and put new socket into the list
942
; Newly created socket is initialized with calling PID and number and
943
; put into beginning of list (which is a fastest way).
944
;
945
; @return socket structure address in EAX
946
;
947
proc net_socket_alloc stdcall uses ebx ecx edx edi
948
	stdcall kernel_alloc, SOCKETBUFFSIZE
949
	DEBUGF	1, "K : net_socket_alloc (0x%x)\n", eax
950
	; check if we can allocate needed amount of memory
951
	or	eax, eax
952
	jz	.exit
953
 
954
	; zero-initialize allocated memory
955
	push	eax
956
	mov	edi, eax
1249 hidnplayr 957
 
1159 hidnplayr 958
	mov	ecx, SOCKETBUFFSIZE / 4
959
;        cld
960
	xor	eax, eax
961
	rep	stosd
962
	pop	eax
963
 
1257 hidnplayr 964
	init_queue (eax + SOCKET_QUEUE_LOCATION)
1249 hidnplayr 965
 
1159 hidnplayr 966
	; add socket to the list by changing pointers
967
	mov	ebx, net_sockets
1249 hidnplayr 968
	push	[ebx + SOCKET_head.NextPtr]
969
	mov	[ebx + SOCKET_head.NextPtr], eax
970
	mov	[eax + SOCKET_head.PrevPtr], ebx
1159 hidnplayr 971
	pop	ebx
1249 hidnplayr 972
	mov	[eax + SOCKET_head.NextPtr], ebx
1159 hidnplayr 973
	or	ebx, ebx
974
	jz	@f
1249 hidnplayr 975
	mov	[ebx + SOCKET_head.PrevPtr], eax
1159 hidnplayr 976
 
977
    @@: ; set socket owner PID to the one of calling process
978
	mov	ebx, [TASK_BASE]
979
	mov	ebx, [ebx + TASKDATA.pid]
1249 hidnplayr 980
	mov	[eax + SOCKET_head.PID], ebx
1159 hidnplayr 981
 
982
	; find first free socket number and use it
983
	;mov     edx, ebx
984
	mov	ebx, net_sockets
985
	xor	ecx, ecx
986
  .next_socket_number:
987
	inc	ecx
988
  .next_socket:
1249 hidnplayr 989
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 990
	or	ebx, ebx
991
	jz	.last_socket_number
1249 hidnplayr 992
	cmp	[ebx + SOCKET_head.Number], ecx
1159 hidnplayr 993
	jne	.next_socket
994
	;cmp     [ebx + SOCKET.PID], edx
995
	;jne     .next_socket
996
	mov	ebx, net_sockets
997
	jmp	.next_socket_number
998
 
999
  .last_socket_number:
1249 hidnplayr 1000
	mov	[eax + SOCKET_head.Number], ecx
1159 hidnplayr 1001
 
1002
  .exit:
1003
	ret
1004
endp
1005
 
1006
; Free socket data memory and pop socket off the list
1007
;
1008
; @param sockAddr is a socket structure address
1009
;
1010
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
1011
	mov	eax, [sockAddr]
1012
	DEBUGF	1, "K : net_socket_free (0x%x)\n", eax
1013
	; check if we got something similar to socket structure address
1014
	or	eax, eax
1015
	jz	.error
1016
 
1017
	; make sure sockAddr is one of the socket addresses in the list
1018
	mov	ebx, net_sockets
1019
	;mov     ecx, [TASK_BASE]
1020
	;mov     ecx, [ecx + TASKDATA.pid]
1021
  .next_socket:
1249 hidnplayr 1022
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1023
	or	ebx, ebx
1024
	jz	.error
1025
	cmp	ebx, eax
1026
	jne	.next_socket
1027
	;cmp     [ebx + SOCKET.PID], ecx
1028
	;jne     .next_socket
1029
 
1030
	; okay, we found the correct one
1031
	; remove it from the list first, changing pointers
1249 hidnplayr 1032
	mov	ebx, [eax + SOCKET_head.NextPtr]
1033
	mov	eax, [eax + SOCKET_head.PrevPtr]
1034
	mov	[eax + SOCKET_head.NextPtr], ebx
1159 hidnplayr 1035
	or	ebx, ebx
1036
	jz	@f
1249 hidnplayr 1037
	mov	[ebx + SOCKET_head.PrevPtr], eax
1159 hidnplayr 1038
 
1249 hidnplayr 1039
	lea	ebx, [eax + SOCKET_head.lock]
1040
	call	wait_mutex
1041
 
1159 hidnplayr 1042
    @@: ; and finally free the memory structure used
1043
	stdcall kernel_free, [sockAddr]
1044
	ret
1045
 
1046
  .error:
1047
	DEBUGF	1, "K :   failed\n"
1048
	ret
1049
endp
1050
 
1051
; Get socket structure address by its number
1052
; Scan through sockets list to find the socket with specified number.
1053
; This proc uses SOCKET.PID indirectly to check if socket is owned by
1054
; calling process.
1055
;
1056
; @param sockNum is a socket number
1057
; @return socket structure address or 0 (not found) in EAX
1058
;
1059
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
1060
	mov	eax, [sockNum]
1061
	; check if we got something similar to socket number
1062
	or	eax, eax
1063
	jz	.error
1064
 
1065
	; scan through sockets list
1066
	mov	ebx, net_sockets
1067
	;mov     ecx, [TASK_BASE]
1068
	;mov     ecx, [ecx + TASKDATA.pid]
1069
  .next_socket:
1249 hidnplayr 1070
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1071
	or	ebx, ebx
1072
	jz	.error
1249 hidnplayr 1073
	cmp	[ebx + SOCKET_head.Number], eax
1159 hidnplayr 1074
	jne	.next_socket
1075
	;cmp     [ebx + SOCKET.PID], ecx
1076
	;jne     .next_socket
1077
 
1078
	; okay, we found the correct one
1079
	mov	eax, ebx
1080
	ret
1081
 
1082
  .error:
1083
	xor	eax, eax
1084
	ret
1085
endp
1086
 
1087
; Get socket number by its structure address
1088
; Scan through sockets list to find the socket with specified address.
1089
; This proc uses SOCKET.PID indirectly to check if socket is owned by
1090
; calling process.
1091
;
1092
; @param sockAddr is a socket structure address
1093
; @return socket number (SOCKET.Number) or 0 (not found) in EAX
1094
;
1095
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
1096
	mov	eax, [sockAddr]
1097
	; check if we got something similar to socket structure address
1098
	or	eax, eax
1099
	jz	.error
1100
 
1101
	; scan through sockets list
1102
	mov	ebx, net_sockets
1103
	;mov     ecx, [TASK_BASE]
1104
	;mov     ecx, [ecx + TASKDATA.pid]
1105
  .next_socket:
1249 hidnplayr 1106
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1107
	or	ebx, ebx
1108
	jz	.error
1109
	cmp	ebx, eax
1110
	jne	.next_socket
1111
	;cmp     [ebx + SOCKET.PID], ecx
1112
	;jne     .next_socket
1113
 
1114
	; okay, we found the correct one
1249 hidnplayr 1115
	mov	eax, [ebx + SOCKET_head.Number]
1159 hidnplayr 1116
	ret
1117
 
1118
  .error:
1119
	xor	eax, eax
1120
	ret
1121
endp