Subversion Repositories Kolibri OS

Rev

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