Subversion Repositories Kolibri OS

Rev

Rev 1263 | 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: 1274 $
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
 
337
 
1254 hidnplayr 338
	; fill in remote port and IP
1159 hidnplayr 339
 
1254 hidnplayr 340
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0	   ; Reset the window timer.
341
											   ; TODO: figure out WTF this is
342
	mov	bx , word [edx + 2]
343
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], bx
344
	DEBUGF	1,"remote port: %x ",bx
1159 hidnplayr 345
 
1254 hidnplayr 346
	mov	ebx, dword [edx + 4]
347
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
1159 hidnplayr 348
 
1254 hidnplayr 349
	; check if local port and IP is ok
1159 hidnplayr 350
 
1254 hidnplayr 351
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], 0
352
	jne	@f
353
	push	[IP_LIST]	    ; device zero = default
354
	pop	[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
355
       @@:
1159 hidnplayr 356
 
1254 hidnplayr 357
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], 0
358
	jne	@f
1159 hidnplayr 359
 
1254 hidnplayr 360
	mov	ecx, [eax + SOCKET_head.Type]
361
	call	socket_find_port
362
	test	bx, bx
363
	jz	s_error
1159 hidnplayr 364
 
1254 hidnplayr 365
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], bx
366
       @@:
1159 hidnplayr 367
 
368
 
1254 hidnplayr 369
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
370
	; now say hello to the remote tcp socket
1159 hidnplayr 371
 
1254 hidnplayr 372
	mov	bl, TH_SYN
1274 hidnplayr 373
	xor	ecx, ecx
374
	call	TCP_send
1159 hidnplayr 375
 
1254 hidnplayr 376
	mov	dword [esp+32],0
1159 hidnplayr 377
	ret
378
 
379
 
1257 hidnplayr 380
;-----------------------------------------------------------------
1159 hidnplayr 381
;
382
; SOCKET_listen
383
;
384
;
385
;  IN:  socket number in ecx
386
;       backlog in edx
387
;  OUT: eax is socket num, -1 on error
388
;
1257 hidnplayr 389
;-----------------------------------------------------------------
1206 hidnplayr 390
align 4
1159 hidnplayr 391
socket_listen:
392
 
393
	DEBUGF	1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx
394
 
395
	stdcall net_socket_num_to_addr, ecx
396
	cmp	eax, -1
1185 hidnplayr 397
	jz	s_error
1159 hidnplayr 398
 
1254 hidnplayr 399
	cmp	word [eax + SOCKET_head.Domain], AF_INET4
400
	jne	s_error
401
 
402
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
403
	jne	s_error
404
 
1159 hidnplayr 405
	cmp	edx, MAX_backlog
1256 clevermous 406
	jb	.ok
407
	mov	dx , MAX_backlog
1159 hidnplayr 408
  .ok:
409
 
1249 hidnplayr 410
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
1254 hidnplayr 411
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1159 hidnplayr 412
 
413
	mov	dword [esp+32], 0
414
	ret
415
 
416
 
1257 hidnplayr 417
;-----------------------------------------------------------------
1159 hidnplayr 418
;
419
; SOCKET_accept
420
;
421
;
422
;  IN:  socket number in ecx
423
;       addr in edx
424
;       addrlen in esi
425
;  OUT: eax is socket num, -1 on error
426
;
1257 hidnplayr 427
;-----------------------------------------------------------------
1206 hidnplayr 428
align 4
1159 hidnplayr 429
socket_accept:
430
 
431
	DEBUGF	1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi
432
 
433
	stdcall net_socket_num_to_addr, ecx
434
	or	eax, eax
1185 hidnplayr 435
	jz	s_error
1159 hidnplayr 436
	mov	esi, eax
437
 
1249 hidnplayr 438
	cmp	word [esi + SOCKET_head.Domain], AF_INET4
439
	je	.af_inet4
440
 
441
	jmp	s_error
442
 
443
  .af_inet4:
444
 
445
	cmp	[esi + SOCKET_head.Type], IP_PROTO_TCP
446
	je	.tcp
447
 
448
	jmp	s_error
449
 
450
  .tcp:
451
 
1256 clevermous 452
	lea	ebx, [esi + SOCKET_head.lock]
453
	call	wait_mutex
454
	movzx	eax, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
455
	test	eax, eax
456
	jz	.unlock_err
457
	dec	[esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog_cur]
458
	mov	eax, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end + (eax-1)*4]
459
	mov	[esi + SOCKET_head.lock], 0
1257 hidnplayr 460
	stdcall net_socket_addr_to_num, eax
1159 hidnplayr 461
	mov	[esp+32], eax
462
	ret
1256 clevermous 463
  .unlock_err:
464
	mov	[esi + SOCKET_head.lock], 0
465
	jmp	s_error
1159 hidnplayr 466
 
467
 
1257 hidnplayr 468
;-----------------------------------------------------------------
1159 hidnplayr 469
;
470
; SOCKET_close
471
;
472
;
473
;  IN:  socket number in ecx
474
;  OUT: eax is socket num, -1 on error
475
;
1257 hidnplayr 476
;-----------------------------------------------------------------
1206 hidnplayr 477
align 4
1159 hidnplayr 478
socket_close:
479
 
480
	DEBUGF	1,"Socket_close: socknum: %u\n",ecx
481
 
482
	stdcall net_socket_num_to_addr, ecx
483
	or	eax, eax
1185 hidnplayr 484
	jz	s_error
1159 hidnplayr 485
 
1249 hidnplayr 486
	cmp	[eax + SOCKET_head.Domain], AF_INET4
487
	jne	s_error
1159 hidnplayr 488
 
1249 hidnplayr 489
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 490
	je	.udp
491
 
1249 hidnplayr 492
	cmp	[eax + SOCKET_head.Type], IP_PROTO_ICMP
1159 hidnplayr 493
	je	.icmp
494
 
1249 hidnplayr 495
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
1206 hidnplayr 496
	je	.tcp
1159 hidnplayr 497
 
1185 hidnplayr 498
	jmp	s_error
1159 hidnplayr 499
 
500
  .udp:
501
 
502
	stdcall net_socket_free, eax
503
	mov	dword [esp+32],0
504
	ret
505
 
506
 
507
  .icmp:
508
 
509
 
510
 
511
	ret
512
 
513
  .tcp:
1254 hidnplayr 514
	; first, remove all resend entries for this socket
1159 hidnplayr 515
 
1254 hidnplayr 516
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
1159 hidnplayr 517
	je	.destroy_tcb
1254 hidnplayr 518
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
1159 hidnplayr 519
	je	.destroy_tcb
520
 
1254 hidnplayr 521
	; Now construct the response, and queue for sending by IP
1159 hidnplayr 522
 
523
	mov	bl, TH_FIN
1274 hidnplayr 524
	xor	ecx, ecx
525
	call	TCP_send
1159 hidnplayr 526
 
527
	; increament SND.NXT in socket
1254 hidnplayr 528
	lea	esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
529
	inc_INET esi
1159 hidnplayr 530
 
531
	; Get the socket state
1254 hidnplayr 532
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
1159 hidnplayr 533
	je	.fin_wait_1
1254 hidnplayr 534
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
1159 hidnplayr 535
	je	.fin_wait_1
536
 
537
	; assume CLOSE WAIT
538
	; Send a fin, then enter last-ack state
1254 hidnplayr 539
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LAST_ACK
1159 hidnplayr 540
	jmp	.send
541
 
542
  .fin_wait_1:
543
	; Send a fin, then enter finwait2 state
1254 hidnplayr 544
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_1
1159 hidnplayr 545
 
546
  .send:
547
 
1254 hidnplayr 548
	;;;;;
1159 hidnplayr 549
 
550
  .destroy_tcb:
551
 
552
	stdcall net_socket_free, eax
553
	mov	dword [esp+32],0
554
	ret
555
 
556
 
557
 
558
 
1257 hidnplayr 559
;-----------------------------------------------------------------
1159 hidnplayr 560
;
561
; SOCKET_receive
562
;
563
;
564
;  IN:  socket number in ecx
1249 hidnplayr 565
;       addr to buffer in edx
566
;       length of buffer in esi
1159 hidnplayr 567
;       flags in edi
568
;  OUT: eax is number of bytes copied, -1 on error
569
;
1257 hidnplayr 570
;-----------------------------------------------------------------
1206 hidnplayr 571
align 4
1159 hidnplayr 572
socket_recv:
573
 
1249 hidnplayr 574
	DEBUGF	1,"Socket_receive: socknum: %u bufferaddress: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
1159 hidnplayr 575
	stdcall net_socket_num_to_addr, ecx		   ; get real socket address
576
	or	eax, eax
1185 hidnplayr 577
	jz	s_error
1159 hidnplayr 578
 
1249 hidnplayr 579
	DEBUGF	1,"Socket pointer: %x\n", eax
1159 hidnplayr 580
 
1257 hidnplayr 581
	get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, s_error
1159 hidnplayr 582
 
583
	mov	edi, edx
1249 hidnplayr 584
	mov	ecx, [esi + socket_queue_entry.data_size]
1159 hidnplayr 585
 
1249 hidnplayr 586
	DEBUGF	1,"Got %u bytes of data\n", ecx
1159 hidnplayr 587
 
1249 hidnplayr 588
	cmp	ecx, edx
589
	jle	.large_enough
590
	DEBUGF	1,"Buffer too small...\n"
591
	jmp	s_error
592
  .large_enough:
1159 hidnplayr 593
 
1249 hidnplayr 594
	push	[esi + socket_queue_entry.data_ptr]
595
	mov	esi, [esi + socket_queue_entry.offset]
596
	add	esi, [esp]
597
	DEBUGF	1,"Source buffer: %x, real addr: %x\n", [esp], esi
1159 hidnplayr 598
 
1249 hidnplayr 599
	mov	dword[esp+32+4], ecx			     ; return number of bytes copied
1159 hidnplayr 600
 
1249 hidnplayr 601
	shr	ecx, 1
602
	jnc	.nb
603
	movsb
604
.nb:	shr	ecx, 1
605
	jnc	.nw
606
	movsw
1274 hidnplayr 607
.nw:	test	ecx, ecx
608
	jz	.nd
609
	rep	movsd
610
.nd:
1159 hidnplayr 611
 
1249 hidnplayr 612
	call	kernel_free
1159 hidnplayr 613
 
614
	ret
615
 
616
 
1257 hidnplayr 617
;-----------------------------------------------------------------
1159 hidnplayr 618
;
619
; SOCKET_send
620
;
621
;
622
;  IN:  socket number in ecx
1206 hidnplayr 623
;       pointer to data in edx
624
;       datalength in esi
1159 hidnplayr 625
;       flags in edi
626
;  OUT: -1 on error
627
;
1257 hidnplayr 628
;-----------------------------------------------------------------
1206 hidnplayr 629
align 4
1159 hidnplayr 630
socket_send:
631
 
632
	DEBUGF	1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi
633
 
634
	stdcall net_socket_num_to_addr, ecx		   ; get real socket address
635
	or	eax, eax
1185 hidnplayr 636
	jz	s_error
1159 hidnplayr 637
 
1249 hidnplayr 638
	cmp	word [eax + SOCKET_head.Domain], AF_INET4
1206 hidnplayr 639
	je	.af_inet4
640
 
641
	jmp	s_error
642
 
643
  .af_inet4:
1249 hidnplayr 644
	DEBUGF	1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
1206 hidnplayr 645
 
1249 hidnplayr 646
	cmp	[eax + SOCKET_head.Type], IP_PROTO_TCP
647
	je	.tcp
1159 hidnplayr 648
 
1249 hidnplayr 649
	cmp	[eax + SOCKET_head.Type], IP_PROTO_UDP
1159 hidnplayr 650
	je	.udp
651
 
1249 hidnplayr 652
	cmp	[eax + SOCKET_head.Type], SOCK_RAW
653
	je	.raw
1159 hidnplayr 654
 
1185 hidnplayr 655
	jmp	s_error
1159 hidnplayr 656
 
657
  .udp:
658
 
1206 hidnplayr 659
	DEBUGF	1,"type: UDP, "
1159 hidnplayr 660
 
1249 hidnplayr 661
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort],0
662
	jne	@f
1206 hidnplayr 663
 
1208 hidnplayr 664
	push	esi
1249 hidnplayr 665
	mov	ecx, [eax + SOCKET_head.Type]
1206 hidnplayr 666
	call	socket_find_port
667
	test	bx, bx
1208 hidnplayr 668
	pop	esi
1206 hidnplayr 669
	je	s_error
1249 hidnplayr 670
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 671
 
1249 hidnplayr 672
     @@:
1206 hidnplayr 673
 
1159 hidnplayr 674
	mov	ecx, esi
675
	mov	esi, edx
676
 
1249 hidnplayr 677
	call	UDP_socket_send
1159 hidnplayr 678
 
1263 clevermous 679
	and	dword [esp+32], 0
1159 hidnplayr 680
	ret
681
 
1249 hidnplayr 682
  .tcp:
1159 hidnplayr 683
 
1254 hidnplayr 684
	cmp	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort],0
685
	jne	@f
686
 
687
	push	esi
688
	mov	ecx, [eax + SOCKET_head.Type]
689
	call	socket_find_port
690
	test	bx, bx
691
	pop	esi
692
	je	s_error
693
	mov	[eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], bx
694
 
695
     @@:
696
 
697
	mov	ecx, esi
698
	mov	esi, edx
1274 hidnplayr 699
	xor	bl , bl
1254 hidnplayr 700
 
1274 hidnplayr 701
	call	TCP_send
1254 hidnplayr 702
 
1249 hidnplayr 703
	mov	[esp+32], eax
704
	ret
1159 hidnplayr 705
 
1249 hidnplayr 706
  .raw:
707
	cmp	[eax + SOCKET_head.Protocol], IP_PROTO_IP
708
	je	.raw_ip
709
 
710
	cmp	[eax + SOCKET_head.Protocol], IP_PROTO_ICMP
711
	je	.raw_icmp
712
 
713
	jmp	s_error
714
 
715
 
716
  .raw_ip:
717
 
1254 hidnplayr 718
	;;;;;;
719
 
1159 hidnplayr 720
	mov	[esp+32], eax
721
	ret
722
 
723
 
1249 hidnplayr 724
  .raw_icmp:
725
 
726
;        sub     ecx, ICMP_Packet.Data
727
;        mov     esi, edx
728
;        push    ax
729
;        call    IPv4_get_frgmnt_num
730
;        mov     dx, ax
731
;        pop     ax
732
;        shl     edx, 16
733
;        mov     dh , [esi + ICMP_Packet.Type]
734
;        mov     dl , [esi + ICMP_Packet.Code]
735
;        mov     di , [esi + ICMP_Packet.Identifier]
736
;        mov     [eax + SOCKET.LocalPort], di            ; Set localport to the identifier number, so we can receive reply's
737
;        shl     edi, 16
738
;        mov     di , [esi + ICMP_Packet.SequenceNumber]
739
;        add     esi, ICMP_Packet.Data
740
;        mov     ebx, [eax + SOCKET.LocalIP]
741
;        mov     eax, [eax + SOCKET.RemoteIP]
742
;        call    ICMP_create_packet
743
 
744
	mov	[esp+32], eax
1159 hidnplayr 745
	ret
746
 
1257 hidnplayr 747
;-----------------------------------------------------------------
1256 clevermous 748
;
1257 hidnplayr 749
; SOCKET_get_options
1256 clevermous 750
;
751
;
752
;  IN:  socket number in ecx
753
;       edx points to the options:
1257 hidnplayr 754
;               dd      level, optname, optval, optlen
1256 clevermous 755
;  OUT: -1 on error
756
;
757
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
758
; TODO: find best way to notify that send()'ed data were acknowledged
759
;
1257 hidnplayr 760
;-----------------------------------------------------------------
761
align 4
1256 clevermous 762
socket_get_opt:
1257 hidnplayr 763
 
1256 clevermous 764
	cmp	dword [edx], IP_PROTO_TCP
765
	jnz	.unknown
766
	cmp	dword [edx+4], -2
767
	jnz	.unknown
768
	mov	eax, [edx+12]
769
	test	eax, eax
770
	jz	.fail
771
	cmp	dword [eax], 4
772
	mov	dword [eax], 4
773
	jb	.fail
1257 hidnplayr 774
	stdcall net_socket_num_to_addr, ecx
1256 clevermous 775
	test	eax, eax
776
	jz	.fail
777
	; todo: check that eax is really TCP socket
778
	mov	ecx, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number]
779
	mov	eax, [edx+8]
780
	test	eax, eax
781
	jz	@f
782
	mov	[eax], ecx
783
@@:
1257 hidnplayr 784
	mov	dword [esp+32], 0
1256 clevermous 785
	ret
786
.fail:
787
.unknown:
1257 hidnplayr 788
	mov	dword [esp+32], -1
1256 clevermous 789
	ret
1159 hidnplayr 790
 
791
 
1257 hidnplayr 792
;-----------------------------------------------------------------
1206 hidnplayr 793
;
794
; SOCKET_find_free_port (local port)
795
;
796
; works with INET byte order
797
;
798
;  IN:  type in ecx (TCP/UDP)
799
;  OUT: bx = 0 on error, portnumber otherwise
800
;
1257 hidnplayr 801
;-----------------------------------------------------------------
1206 hidnplayr 802
align 4
803
socket_find_port:
1159 hidnplayr 804
 
1208 hidnplayr 805
	DEBUGF	1,"Socket_find_free_port\n"
1159 hidnplayr 806
 
1206 hidnplayr 807
	cmp	ecx, IP_PROTO_UDP
808
	je	.udp
1159 hidnplayr 809
 
1206 hidnplayr 810
	cmp	ecx, IP_PROTO_TCP
811
	je	.tcp
1159 hidnplayr 812
 
1206 hidnplayr 813
  .udp:
814
	mov	bx, [last_UDP_port]
815
	je	.continue
816
 
817
  .tcp:
818
	mov	bx, [last_TCP_port]
819
 
820
 
821
  .continue:
822
	inc	bx
823
 
824
  .check_only:
825
	mov	esi, net_sockets
826
 
827
  .next_socket:
1249 hidnplayr 828
	mov	esi, [esi + SOCKET_head.NextPtr]
1206 hidnplayr 829
	or	esi, esi
830
	jz	.port_ok
831
 
1249 hidnplayr 832
	cmp	[esi + SOCKET_head.Type], ecx
1206 hidnplayr 833
	jne	.next_socket
834
 
835
	rol	bx, 8
1249 hidnplayr 836
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 837
	rol	bx, 8				; this doesnt change the zero flag, does it ?
838
	jne	.next_socket
839
 
840
	cmp	bx, MAX_EPHEMERAL_PORT
841
	jle	.continue
842
 
843
	; todo: WRAP!
844
;        mov     [last_UDP_port], MIN_EPHEMERAL_PORT
845
  .exit:
846
	xor	ebx, ebx
847
 
848
  .port_ok:
849
	rol	bx, 8
850
	ret
851
 
1257 hidnplayr 852
 
853
 
854
;-----------------------------------------------------------------
1206 hidnplayr 855
;
856
; SOCKET_check_port (local port)
857
;
858
; works with INET byte order
859
;
860
;  IN:  type in ecx (TCP/UDP)
861
;       port to check in bx
862
;  OUT: bx = 0 on error, unchanged otherwise
863
;
1257 hidnplayr 864
;-----------------------------------------------------------------
1206 hidnplayr 865
align 4
866
socket_check_port:
867
	mov	esi, net_sockets
868
 
869
  .next_socket:
1249 hidnplayr 870
	mov	esi, [esi + SOCKET_head.NextPtr]
1206 hidnplayr 871
	or	esi, esi
872
	jz	.port_ok
873
 
1249 hidnplayr 874
	cmp	[esi + SOCKET_head.Type], ecx
1206 hidnplayr 875
	jne	.next_socket
876
 
1249 hidnplayr 877
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
1206 hidnplayr 878
	jne	.next_socket
879
 
880
	xor	ebx, ebx
881
 
882
  .port_ok:
883
	ret
884
 
885
 
1257 hidnplayr 886
 
887
;-----------------------------------------------------------------
1206 hidnplayr 888
;
889
; SOCKET_internal_receiver
890
;
1249 hidnplayr 891
; Updates a socket with received data
1206 hidnplayr 892
;
1249 hidnplayr 893
; Note: the mutex must already be set !
1206 hidnplayr 894
;
1249 hidnplayr 895
;  IN:  eax = socket ptr
896
;       ecx = size
897
;       esi = pointer to buffer
898
;       edi = offset
899
;
1206 hidnplayr 900
;  OUT: xxx
901
;
1257 hidnplayr 902
;-----------------------------------------------------------------
1206 hidnplayr 903
align 4
904
socket_internal_receiver:
905
 
1255 hidnplayr 906
	DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x size=%u socket: %x\n", esi, edi, ecx, eax
1206 hidnplayr 907
 
1249 hidnplayr 908
	push	edi	; offset
909
	push	ecx	; size
910
	push	esi	; data_ptr
911
	mov	esi, esp
1257 hidnplayr 912
	add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, socket_queue_entry.size, notify_network_event.full
1249 hidnplayr 913
	DEBUGF	1,"Queued packet successfully\n"
1257 hidnplayr 914
	add	esp, socket_queue_entry.size
1206 hidnplayr 915
 
1249 hidnplayr 916
	mov	[eax + SOCKET_head.lock], 0
1206 hidnplayr 917
 
1256 clevermous 918
notify_network_event:
1206 hidnplayr 919
	; flag an event to the application
1249 hidnplayr 920
	mov	edx, [eax + SOCKET_head.PID]				; get socket owner PID
1206 hidnplayr 921
	mov	ecx, 1
922
	mov	esi, TASK_DATA + TASKDATA.pid
923
 
924
       .next_pid:
925
	cmp	[esi], edx
926
	je	.found_pid
927
	inc	ecx
928
	add	esi, 0x20
929
	cmp	ecx, [TASK_COUNT]
930
	jbe	.next_pid
931
	ret
932
 
933
       .found_pid:
934
	shl	ecx, 8
1249 hidnplayr 935
	or	[ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK	; stack event
1206 hidnplayr 936
	mov	[check_idle_semaphore], 200
937
	ret
938
 
1249 hidnplayr 939
  .full:
940
	DEBUGF 1,"Socket %x is full!\n",eax
941
	mov	[eax + SOCKET_head.lock], 0
942
	call	kernel_free
943
	add	esp, 8
1206 hidnplayr 944
	ret
945
 
946
 
947
 
1159 hidnplayr 948
; Allocate memory for socket data and put new socket into the list
949
; Newly created socket is initialized with calling PID and number and
950
; put into beginning of list (which is a fastest way).
951
;
952
; @return socket structure address in EAX
953
;
954
proc net_socket_alloc stdcall uses ebx ecx edx edi
955
	stdcall kernel_alloc, SOCKETBUFFSIZE
956
	DEBUGF	1, "K : net_socket_alloc (0x%x)\n", eax
957
	; check if we can allocate needed amount of memory
958
	or	eax, eax
959
	jz	.exit
960
 
961
	; zero-initialize allocated memory
962
	push	eax
963
	mov	edi, eax
1249 hidnplayr 964
 
1159 hidnplayr 965
	mov	ecx, SOCKETBUFFSIZE / 4
966
;        cld
967
	xor	eax, eax
968
	rep	stosd
969
	pop	eax
970
 
1257 hidnplayr 971
	init_queue (eax + SOCKET_QUEUE_LOCATION)
1249 hidnplayr 972
 
1159 hidnplayr 973
	; add socket to the list by changing pointers
974
	mov	ebx, net_sockets
1249 hidnplayr 975
	push	[ebx + SOCKET_head.NextPtr]
976
	mov	[ebx + SOCKET_head.NextPtr], eax
977
	mov	[eax + SOCKET_head.PrevPtr], ebx
1159 hidnplayr 978
	pop	ebx
1249 hidnplayr 979
	mov	[eax + SOCKET_head.NextPtr], ebx
1159 hidnplayr 980
	or	ebx, ebx
981
	jz	@f
1249 hidnplayr 982
	mov	[ebx + SOCKET_head.PrevPtr], eax
1159 hidnplayr 983
 
984
    @@: ; set socket owner PID to the one of calling process
985
	mov	ebx, [TASK_BASE]
986
	mov	ebx, [ebx + TASKDATA.pid]
1249 hidnplayr 987
	mov	[eax + SOCKET_head.PID], ebx
1159 hidnplayr 988
 
989
	; find first free socket number and use it
990
	;mov     edx, ebx
991
	mov	ebx, net_sockets
992
	xor	ecx, ecx
993
  .next_socket_number:
994
	inc	ecx
995
  .next_socket:
1249 hidnplayr 996
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 997
	or	ebx, ebx
998
	jz	.last_socket_number
1249 hidnplayr 999
	cmp	[ebx + SOCKET_head.Number], ecx
1159 hidnplayr 1000
	jne	.next_socket
1001
	;cmp     [ebx + SOCKET.PID], edx
1002
	;jne     .next_socket
1003
	mov	ebx, net_sockets
1004
	jmp	.next_socket_number
1005
 
1006
  .last_socket_number:
1249 hidnplayr 1007
	mov	[eax + SOCKET_head.Number], ecx
1159 hidnplayr 1008
 
1009
  .exit:
1010
	ret
1011
endp
1012
 
1013
; Free socket data memory and pop socket off the list
1014
;
1015
; @param sockAddr is a socket structure address
1016
;
1017
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
1018
	mov	eax, [sockAddr]
1019
	DEBUGF	1, "K : net_socket_free (0x%x)\n", eax
1020
	; check if we got something similar to socket structure address
1021
	or	eax, eax
1022
	jz	.error
1023
 
1024
	; make sure sockAddr is one of the socket addresses in the list
1025
	mov	ebx, net_sockets
1026
	;mov     ecx, [TASK_BASE]
1027
	;mov     ecx, [ecx + TASKDATA.pid]
1028
  .next_socket:
1249 hidnplayr 1029
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1030
	or	ebx, ebx
1031
	jz	.error
1032
	cmp	ebx, eax
1033
	jne	.next_socket
1034
	;cmp     [ebx + SOCKET.PID], ecx
1035
	;jne     .next_socket
1036
 
1037
	; okay, we found the correct one
1038
	; remove it from the list first, changing pointers
1249 hidnplayr 1039
	mov	ebx, [eax + SOCKET_head.NextPtr]
1040
	mov	eax, [eax + SOCKET_head.PrevPtr]
1041
	mov	[eax + SOCKET_head.NextPtr], ebx
1159 hidnplayr 1042
	or	ebx, ebx
1043
	jz	@f
1249 hidnplayr 1044
	mov	[ebx + SOCKET_head.PrevPtr], eax
1159 hidnplayr 1045
 
1249 hidnplayr 1046
	lea	ebx, [eax + SOCKET_head.lock]
1047
	call	wait_mutex
1048
 
1159 hidnplayr 1049
    @@: ; and finally free the memory structure used
1050
	stdcall kernel_free, [sockAddr]
1051
	ret
1052
 
1053
  .error:
1054
	DEBUGF	1, "K :   failed\n"
1055
	ret
1056
endp
1057
 
1058
; Get socket structure address by its number
1059
; Scan through sockets list to find the socket with specified number.
1060
; This proc uses SOCKET.PID indirectly to check if socket is owned by
1061
; calling process.
1062
;
1063
; @param sockNum is a socket number
1064
; @return socket structure address or 0 (not found) in EAX
1065
;
1066
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
1067
	mov	eax, [sockNum]
1068
	; check if we got something similar to socket number
1069
	or	eax, eax
1070
	jz	.error
1071
 
1072
	; scan through sockets list
1073
	mov	ebx, net_sockets
1074
	;mov     ecx, [TASK_BASE]
1075
	;mov     ecx, [ecx + TASKDATA.pid]
1076
  .next_socket:
1249 hidnplayr 1077
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1078
	or	ebx, ebx
1079
	jz	.error
1249 hidnplayr 1080
	cmp	[ebx + SOCKET_head.Number], eax
1159 hidnplayr 1081
	jne	.next_socket
1082
	;cmp     [ebx + SOCKET.PID], ecx
1083
	;jne     .next_socket
1084
 
1085
	; okay, we found the correct one
1086
	mov	eax, ebx
1087
	ret
1088
 
1089
  .error:
1090
	xor	eax, eax
1091
	ret
1092
endp
1093
 
1094
; Get socket number by its structure address
1095
; Scan through sockets list to find the socket with specified address.
1096
; This proc uses SOCKET.PID indirectly to check if socket is owned by
1097
; calling process.
1098
;
1099
; @param sockAddr is a socket structure address
1100
; @return socket number (SOCKET.Number) or 0 (not found) in EAX
1101
;
1102
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
1103
	mov	eax, [sockAddr]
1104
	; check if we got something similar to socket structure address
1105
	or	eax, eax
1106
	jz	.error
1107
 
1108
	; scan through sockets list
1109
	mov	ebx, net_sockets
1110
	;mov     ecx, [TASK_BASE]
1111
	;mov     ecx, [ecx + TASKDATA.pid]
1112
  .next_socket:
1249 hidnplayr 1113
	mov	ebx, [ebx + SOCKET_head.NextPtr]
1159 hidnplayr 1114
	or	ebx, ebx
1115
	jz	.error
1116
	cmp	ebx, eax
1117
	jne	.next_socket
1118
	;cmp     [ebx + SOCKET.PID], ecx
1119
	;jne     .next_socket
1120
 
1121
	; okay, we found the correct one
1249 hidnplayr 1122
	mov	eax, [ebx + SOCKET_head.Number]
1159 hidnplayr 1123
	ret
1124
 
1125
  .error:
1126
	xor	eax, eax
1127
	ret
1128
endp