Subversion Repositories Kolibri OS

Rev

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