Subversion Repositories Kolibri OS

Rev

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