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