Rev 1185 | 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 | |||
17 | $Revision: 1019 $ |
||
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 |
||
30 | .LocalPort dw ? ; local port |
||
31 | .RemotePort dw ? ; remote port |
||
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 | ;----------------------------------------------- |
||
133 | socket_open: |
||
134 | |||
135 | DEBUGF 1,"socket_open: domain: %u, type: %u",ecx, edx |
||
136 | |||
137 | call net_socket_alloc |
||
138 | or eax, eax |
||
1185 | hidnplayr | 139 | jz s_error |
1159 | hidnplayr | 140 | |
141 | mov [eax + SOCKET.Domain], ecx |
||
142 | mov [eax + SOCKET.Type], edx |
||
1196 | hidnplayr | 143 | mov [eax + SOCKET.Protocol], esi |
1159 | hidnplayr | 144 | |
145 | stdcall net_socket_addr_to_num, eax |
||
146 | DEBUGF 1,", socketnumber: %u\n", eax |
||
147 | |||
148 | mov [esp+32], eax |
||
149 | |||
150 | ret |
||
151 | |||
152 | |||
153 | |||
154 | |||
155 | ;----------------------------------------------- |
||
156 | ; |
||
157 | ; SOCKET_bind |
||
158 | ; |
||
159 | ; IN: socket number in ecx |
||
160 | ; pointer to sockaddr struct in edx |
||
161 | ; length of that struct in esi |
||
162 | ; OUT: 0 on success |
||
163 | ; |
||
164 | ;----------------------------------------------- |
||
165 | |||
166 | socket_bind: |
||
167 | |||
168 | DEBUGF 1,"Socket_bind: socknum: %u sockaddr: %x, length: %u, ",ecx,edx,esi |
||
169 | |||
170 | stdcall net_socket_num_to_addr, ecx |
||
171 | cmp eax, -1 |
||
1185 | hidnplayr | 172 | jz s_error |
1159 | hidnplayr | 173 | |
174 | cmp esi, 2 |
||
1185 | hidnplayr | 175 | jl s_error |
1159 | hidnplayr | 176 | |
177 | cmp word [edx], AF_INET4 |
||
178 | je .af_inet4 |
||
179 | |||
1185 | hidnplayr | 180 | jmp s_error |
1159 | hidnplayr | 181 | |
182 | .af_inet4: |
||
183 | |||
184 | cmp esi, 6 |
||
1185 | hidnplayr | 185 | jl s_error |
1159 | hidnplayr | 186 | |
187 | mov bx, word [edx + 2] |
||
1196 | hidnplayr | 188 | rol bx,8 ;;; |
1159 | hidnplayr | 189 | DEBUGF 1,"local port: %u ",bx |
190 | test bx, bx |
||
191 | jnz .check_only |
||
192 | |||
193 | mov bx , [last_UDP_port] |
||
194 | |||
195 | .find_port_loop: |
||
196 | inc bx |
||
197 | inc [last_UDP_port] |
||
198 | |||
199 | .check_only: |
||
200 | mov esi, net_sockets |
||
201 | |||
202 | .next_udp_socket: |
||
203 | mov esi, [esi + SOCKET.NextPtr] |
||
204 | or esi, esi |
||
205 | jz .udp_port_ok |
||
206 | |||
207 | cmp [esi + SOCKET.Type], IP_PROTO_UDP |
||
208 | jne .next_udp_socket |
||
209 | |||
210 | cmp [esi + SOCKET.LocalPort], bx |
||
211 | jne .next_udp_socket |
||
212 | |||
213 | cmp word [edx + 2], 0 |
||
1185 | hidnplayr | 214 | jne s_error |
1159 | hidnplayr | 215 | |
216 | cmp bx, MAX_EPHEMERAL_PORT |
||
217 | jle .find_port_loop |
||
218 | |||
219 | mov [last_UDP_port], MIN_EPHEMERAL_PORT |
||
1185 | hidnplayr | 220 | jmp s_error |
1159 | hidnplayr | 221 | |
222 | .udp_port_ok: |
||
223 | mov word [eax + SOCKET.LocalPort], bx |
||
224 | |||
225 | mov ebx, dword [edx + 4] |
||
226 | mov dword [eax + SOCKET.LocalIP], ebx |
||
227 | |||
228 | DEBUGF 1,"local ip: %u.%u.%u.%u\n",\ |
||
229 | [eax + SOCKET.LocalIP]:1,[eax + SOCKET.LocalIP + 1]:1,[eax + SOCKET.LocalIP + 2]:1,[eax + SOCKET.LocalIP + 3]:1 |
||
230 | |||
231 | mov dword [esp+32],0 |
||
232 | ret |
||
233 | |||
234 | |||
235 | |||
236 | |||
237 | ;----------------------------------------------- |
||
238 | ; |
||
239 | ; SOCKET_connect |
||
240 | ; |
||
241 | ; |
||
242 | ; IN: socket number in ecx |
||
243 | ; pointer to sockaddr struct in edx |
||
244 | ; length of that struct in esi |
||
245 | ; OUT: 0 on success |
||
246 | ; |
||
247 | ;----------------------------------------------- |
||
248 | align 4 |
||
249 | |||
250 | socket_connect: |
||
251 | |||
252 | DEBUGF 1,"Socket_connect: socknum: %u sockaddr: %x, length: %u,",ecx,edx,esi |
||
253 | |||
254 | stdcall net_socket_num_to_addr, ecx |
||
255 | cmp eax, -1 |
||
1185 | hidnplayr | 256 | jz s_error |
1159 | hidnplayr | 257 | |
258 | cmp esi, 2 |
||
1185 | hidnplayr | 259 | jl s_error |
1159 | hidnplayr | 260 | |
261 | cmp word [edx], AF_INET4 |
||
262 | je .af_inet4 |
||
263 | |||
1185 | hidnplayr | 264 | jmp s_error |
1159 | hidnplayr | 265 | |
266 | .af_inet4: |
||
267 | |||
268 | cmp esi, 8 |
||
1185 | hidnplayr | 269 | jl s_error |
1159 | hidnplayr | 270 | |
271 | cmp [eax + SOCKET.Type], IP_PROTO_UDP |
||
272 | je .udp |
||
273 | |||
274 | cmp [eax + SOCKET.Type], IP_PROTO_ICMP |
||
275 | je .icmp |
||
276 | |||
277 | ; cmp [eax + SOCKET.Type], IP_PROTO_TCP |
||
278 | ; je .tcp |
||
279 | |||
1185 | hidnplayr | 280 | jmp s_error |
1159 | hidnplayr | 281 | |
282 | .udp: |
||
283 | |||
284 | mov bx , word [edx + 2] |
||
1196 | hidnplayr | 285 | rol bx, 8 |
1159 | hidnplayr | 286 | mov word [eax + SOCKET.RemotePort], bx |
287 | |||
288 | DEBUGF 1,"remote port: %u ",bx |
||
289 | |||
290 | mov ebx, dword [edx + 4] |
||
291 | mov dword [eax + SOCKET.RemoteIP], ebx |
||
292 | |||
293 | DEBUGF 1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1 |
||
294 | |||
295 | mov dword [esp+32],0 |
||
296 | ret |
||
297 | |||
298 | .icmp: |
||
299 | |||
300 | |||
301 | ret |
||
302 | |||
303 | |||
304 | |||
305 | .tcp: |
||
306 | |||
307 | ;local sockAddr dd ? |
||
308 | |||
309 | ; cmp esi, SOCKET_PASSIVE |
||
310 | ; jne .skip_port_check |
||
311 | ; |
||
312 | ; push ebx |
||
313 | ; mov eax, ebx |
||
314 | ; xchg al, ah |
||
315 | ; mov ebx, net_sockets |
||
316 | ; |
||
317 | ; .next_socket: |
||
318 | ; mov ebx, [ebx + SOCKET.NextPtr] |
||
319 | ; or ebx, ebx |
||
320 | ; jz .last_socket |
||
321 | ; cmp [ebx + SOCKET.TCBState], TCB_LISTEN |
||
322 | ; jne .next_socket |
||
323 | ; cmp [ebx + SOCKET.LocalPort], ax |
||
324 | ; jne .next_socket |
||
325 | ; |
||
326 | ; xchg al, ah |
||
327 | ; DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx |
||
328 | ; pop ebx |
||
329 | ; jmp .error |
||
330 | ; |
||
331 | ; .last_socket: |
||
332 | ; pop ebx |
||
333 | ; |
||
334 | ; .skip_port_check: |
||
335 | |||
336 | ; mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. |
||
337 | ; |
||
338 | ; xchg bh, bl |
||
339 | ; mov [eax + SOCKET.LocalPort], bx |
||
340 | ; xchg ch, cl |
||
341 | ; mov [eax + SOCKET.RemotePort], cx |
||
342 | ; mov [eax + SOCKET.OrigRemotePort], cx |
||
343 | ; mov ebx, [IP_LIST] |
||
344 | ; mov [eax + SOCKET.LocalIP], ebx |
||
345 | ; mov [eax + SOCKET.RemoteIP], edx |
||
346 | ; mov [eax + SOCKET.OrigRemoteIP], edx |
||
347 | |||
348 | ; mov ebx, TCB_LISTEN |
||
349 | ; cmp esi, SOCKET_PASSIVE |
||
350 | ; je @f |
||
351 | ; mov ebx, TCB_SYN_SENT |
||
352 | ; @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB |
||
353 | |||
354 | ; cmp ebx, TCB_LISTEN |
||
355 | ; je .exit |
||
356 | |||
357 | ; Now, if we are in active mode, then we have to send a SYN to the specified remote port |
||
358 | ; mov eax, EMPTY_QUEUE |
||
359 | ; call dequeue |
||
360 | ; cmp ax, NO_BUFFER |
||
361 | ; je .exit |
||
362 | |||
363 | ; push eax |
||
364 | |||
365 | ; mov bl, TH_SYN |
||
366 | ; xor ecx, ecx |
||
367 | ; stdcall build_tcp_Packet, [sockAddr] |
||
368 | |||
369 | ; mov eax, NET1OUT_QUEUE |
||
370 | ; mov edx, [IP_LIST] |
||
371 | ; mov ecx, [sockAddr] |
||
372 | ; cmp edx, [ecx + SOCKET.RemoteIP] |
||
373 | ; jne .not_local |
||
374 | ; mov eax, IPIN_QUEUE |
||
375 | |||
376 | ; .not_local: |
||
377 | ; Send it. |
||
378 | ; pop ebx |
||
379 | ; call queue |
||
380 | |||
381 | .exit: |
||
382 | xor eax, eax |
||
383 | ret |
||
384 | |||
385 | |||
386 | |||
387 | |||
388 | ;----------------------------------------------- |
||
389 | ; |
||
390 | ; SOCKET_listen |
||
391 | ; |
||
392 | ; |
||
393 | ; IN: socket number in ecx |
||
394 | ; backlog in edx |
||
395 | ; OUT: eax is socket num, -1 on error |
||
396 | ; |
||
397 | ;----------------------------------------------- |
||
398 | |||
399 | socket_listen: |
||
400 | |||
401 | DEBUGF 1,"Socket_listen: socknum: %u backlog: %u\n",ecx,edx |
||
402 | |||
403 | stdcall net_socket_num_to_addr, ecx |
||
404 | cmp eax, -1 |
||
1185 | hidnplayr | 405 | jz s_error |
1159 | hidnplayr | 406 | |
407 | cmp edx, MAX_backlog |
||
408 | jl .ok |
||
409 | mov dx , 20 |
||
410 | .ok: |
||
411 | |||
412 | mov [eax + SOCKET.backlog], dx |
||
413 | |||
414 | ; TODO: insert code for active connections like TCP |
||
415 | |||
416 | mov dword [esp+32], 0 |
||
417 | ret |
||
418 | |||
419 | |||
420 | |||
421 | |||
422 | |||
423 | |||
424 | ;----------------------------------------------- |
||
425 | ; |
||
426 | ; SOCKET_accept |
||
427 | ; |
||
428 | ; |
||
429 | ; IN: socket number in ecx |
||
430 | ; addr in edx |
||
431 | ; addrlen in esi |
||
432 | ; OUT: eax is socket num, -1 on error |
||
433 | ; |
||
434 | ;----------------------------------------------- |
||
435 | |||
436 | |||
437 | socket_accept: |
||
438 | |||
439 | DEBUGF 1,"Socket_accept: socknum: %u sockaddr: %x, length: %u\n",ecx,edx,esi |
||
440 | |||
441 | stdcall net_socket_num_to_addr, ecx |
||
442 | or eax, eax |
||
1185 | hidnplayr | 443 | jz s_error |
1159 | hidnplayr | 444 | mov esi, eax |
445 | |||
446 | cmp [esi + SOCKET.backlog], 0 |
||
1185 | hidnplayr | 447 | jz s_error |
1159 | hidnplayr | 448 | |
449 | call net_socket_alloc |
||
450 | or eax, eax |
||
1185 | hidnplayr | 451 | jz s_error |
1159 | hidnplayr | 452 | mov edi, eax |
453 | |||
454 | dec [esi + SOCKET.backlog] |
||
455 | |||
456 | mov ecx, (SOCKET.rxData+3)/4 |
||
457 | rep movsd |
||
458 | |||
459 | mov [edi + SOCKET.backlog], 0 |
||
460 | |||
461 | ; TODO: fill in structure in ecx |
||
462 | |||
463 | mov [esi + SOCKET.RemoteIP], 0 |
||
464 | mov [esi + SOCKET.RemotePort], 0 |
||
465 | |||
466 | stdcall net_socket_addr_to_num, eax |
||
467 | mov [esp+32], eax |
||
468 | |||
469 | ret |
||
470 | |||
471 | |||
472 | |||
473 | ;----------------------------------------------- |
||
474 | ; |
||
475 | ; SOCKET_close |
||
476 | ; |
||
477 | ; |
||
478 | ; IN: socket number in ecx |
||
479 | ; OUT: eax is socket num, -1 on error |
||
480 | ; |
||
481 | ;----------------------------------------------- |
||
482 | |||
483 | socket_close: |
||
484 | |||
485 | DEBUGF 1,"Socket_close: socknum: %u\n",ecx |
||
486 | |||
487 | stdcall net_socket_num_to_addr, ecx |
||
488 | or eax, eax |
||
1185 | hidnplayr | 489 | jz s_error |
1159 | hidnplayr | 490 | |
491 | |||
492 | cmp [eax + SOCKET.Type], IP_PROTO_UDP |
||
493 | je .udp |
||
494 | |||
495 | cmp [eax + SOCKET.Type], IP_PROTO_ICMP |
||
496 | je .icmp |
||
497 | |||
498 | ; cmp [eax + SOCKET.Type], IP_PROTO_TCP |
||
499 | ; je .tcp |
||
500 | |||
1185 | hidnplayr | 501 | jmp s_error |
1159 | hidnplayr | 502 | |
503 | .udp: |
||
504 | |||
505 | lea ebx, [eax + SOCKET.lock] |
||
506 | call wait_mutex |
||
507 | ; TODO: mark the socket for deletion, using the mutex |
||
508 | |||
509 | stdcall net_socket_free, eax |
||
510 | |||
511 | mov dword [esp+32],0 |
||
512 | ret |
||
513 | |||
514 | |||
515 | .icmp: |
||
516 | |||
517 | |||
518 | |||
519 | ret |
||
520 | |||
521 | .tcp: |
||
522 | |||
523 | if 1 = 0 |
||
524 | ;local sockAddr dd ? |
||
525 | |||
526 | ; DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx |
||
527 | ; first, remove any resend entries |
||
528 | pusha |
||
529 | |||
530 | mov esi, resendQ |
||
531 | mov ecx, 0 |
||
532 | |||
533 | .next_resendq: |
||
534 | cmp ecx, NUMRESENDENTRIES |
||
535 | je .last_resendq ; None left |
||
536 | cmp [esi + 4], ebx |
||
537 | je @f ; found one |
||
538 | inc ecx |
||
539 | add esi, 8 |
||
540 | jmp .next_resendq |
||
541 | |||
542 | @@: mov dword[esi + 4], 0 |
||
543 | inc ecx |
||
544 | add esi, 8 |
||
545 | jmp .next_resendq |
||
546 | |||
547 | .last_resendq: |
||
548 | popa |
||
549 | |||
550 | mov ebx, eax |
||
551 | ; mov [sockAddr], eax |
||
552 | |||
553 | cmp [eax + SOCKET.TCBState], TCB_LISTEN |
||
554 | je .destroy_tcb |
||
555 | cmp [eax + SOCKET.TCBState], TCB_SYN_SENT |
||
556 | je .destroy_tcb |
||
557 | |||
558 | ; Now construct the response, and queue for sending by IP |
||
559 | mov eax, EMPTY_QUEUE |
||
560 | call dequeue |
||
561 | cmp ax, NO_BUFFER |
||
562 | je .error |
||
563 | |||
564 | push eax |
||
565 | |||
566 | mov bl, TH_FIN |
||
567 | xor ecx, ecx |
||
568 | xor esi, esi |
||
569 | stdcall build_tcp_Packet, [sockAddr] |
||
570 | |||
571 | mov ebx, [sockAddr] |
||
572 | ; increament SND.NXT in socket |
||
573 | lea esi, [ebx + SOCKET.SND_NXT] |
||
574 | call inc_inet_esi |
||
575 | |||
576 | ; Get the socket state |
||
577 | mov eax, [ebx + SOCKET.TCBState] |
||
578 | cmp eax, TCB_SYN_RECEIVED |
||
579 | je .fin_wait_1 |
||
580 | cmp eax, TCB_ESTABLISHED |
||
581 | je .fin_wait_1 |
||
582 | |||
583 | ; assume CLOSE WAIT |
||
584 | ; Send a fin, then enter last-ack state |
||
585 | mov [ebx + SOCKET.TCBState], TCB_LAST_ACK |
||
586 | jmp .send |
||
587 | |||
588 | .fin_wait_1: |
||
589 | ; Send a fin, then enter finwait2 state |
||
590 | mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 |
||
591 | |||
592 | .send: |
||
593 | mov eax, NET1OUT_QUEUE |
||
594 | mov edx, [IP_LIST] |
||
595 | ; mov ecx, [sockAddr] |
||
596 | cmp edx, [ecx + SOCKET.RemoteIP] |
||
597 | jne .not_local |
||
598 | mov eax, IPIN_QUEUE |
||
599 | |||
600 | .not_local: |
||
601 | ; Send it. |
||
602 | pop ebx |
||
603 | call queue |
||
604 | jmp .exit |
||
605 | |||
606 | |||
607 | .destroy_tcb: |
||
608 | |||
609 | stdcall net_socket_free, eax |
||
610 | |||
611 | end if |
||
612 | |||
613 | .exit: |
||
614 | mov dword [esp+32],0 |
||
615 | ret |
||
616 | |||
617 | |||
618 | |||
619 | |||
620 | ;----------------------------------------------- |
||
621 | ; |
||
622 | ; SOCKET_receive |
||
623 | ; |
||
624 | ; |
||
625 | ; IN: socket number in ecx |
||
626 | ; addr in edx |
||
627 | ; addrlen in esi |
||
628 | ; flags in edi |
||
629 | ; OUT: eax is number of bytes copied, -1 on error |
||
630 | ; |
||
631 | ;----------------------------------------------- |
||
632 | |||
633 | socket_recv: |
||
634 | |||
635 | DEBUGF 1,"Socket_receive: socknum: %u sockaddr: %x, length: %u, flags: %x\n",ecx,edx,esi,edi |
||
636 | |||
637 | stdcall net_socket_num_to_addr, ecx ; get real socket address |
||
638 | or eax, eax |
||
1185 | hidnplayr | 639 | jz s_error |
1159 | hidnplayr | 640 | |
641 | DEBUGF 1,"real socket address:%x\n", eax |
||
642 | |||
643 | mov dword[esp+32], -1 |
||
644 | |||
645 | mov edi, edx |
||
646 | |||
647 | lea ebx, [eax + SOCKET.lock] |
||
648 | call wait_mutex |
||
649 | |||
650 | mov ecx, [eax + SOCKET.rxDataCount] ; get count of bytes |
||
651 | DEBUGF 1,"bytes in socket:%u\n", ecx |
||
652 | test ecx, ecx ; if count of bytes is zero.. |
||
653 | jz .exit ; exit function (eax will be zero) |
||
654 | |||
655 | cmp ecx, esi ; if buffer size is larger then the bytes of data, copy all data |
||
656 | jle .copy_all_bytes |
||
657 | |||
658 | sub ecx, esi ; store new count (data bytes in buffer - bytes we're about to copy) |
||
659 | mov [eax + SOCKET.rxDataCount], ecx ; |
||
660 | push ecx |
||
661 | mov edx, esi |
||
662 | |||
663 | call .start_copy ; copy to the application |
||
664 | |||
665 | mov dword[esp+32], edx |
||
666 | |||
667 | lea edi, [eax + SOCKET.rxData] ; Now shift the remaining bytes to start of buffer |
||
668 | lea esi, [edi + edx] |
||
669 | mov ecx, [esp] |
||
670 | shr ecx, 2 ; divide eax by 4 |
||
671 | rep movsd ; copy all full dwords |
||
672 | pop ecx |
||
673 | and ecx, 3 |
||
674 | rep movsb ; copy remaining bytes |
||
675 | |||
676 | .exit: |
||
677 | mov [eax + SOCKET.lock], 0 |
||
678 | ret |
||
679 | |||
680 | .copy_all_bytes: |
||
681 | mov dword[esp+32], ecx |
||
682 | mov [eax + SOCKET.rxDataCount], 0 ; store new count (zero) |
||
683 | push dword .exit ; this code results in same as commented out code |
||
684 | |||
685 | .start_copy: |
||
686 | DEBUGF 1,"copying %u bytes\n",ecx |
||
687 | |||
688 | lea esi, [eax + SOCKET.rxData] |
||
689 | push ecx |
||
690 | shr ecx, 2 ; divide eax by 4 |
||
691 | rep movsd |
||
692 | pop ecx |
||
693 | and ecx, 3 |
||
694 | rep movsb ; copy the rest bytes |
||
695 | |||
696 | ret ; exit, or go back to shift remaining bytes if any |
||
697 | |||
698 | |||
699 | |||
700 | ;----------------------------------------------- |
||
701 | ; |
||
702 | ; SOCKET_send |
||
703 | ; |
||
704 | ; |
||
705 | ; IN: socket number in ecx |
||
706 | ; addr in edx |
||
707 | ; addrlen in esi |
||
708 | ; flags in edi |
||
709 | ; OUT: -1 on error |
||
710 | ; |
||
711 | ;----------------------------------------------- |
||
712 | |||
713 | socket_send: |
||
714 | |||
715 | DEBUGF 1,"Socket_send: socknum: %u sockaddr: %x, length: %u, flags: %x, ",ecx,edx,esi,edi |
||
716 | |||
717 | stdcall net_socket_num_to_addr, ecx ; get real socket address |
||
718 | or eax, eax |
||
1185 | hidnplayr | 719 | jz s_error |
1159 | hidnplayr | 720 | |
721 | DEBUGF 1,"Socket type:%u\n", [eax + SOCKET.Type]:4 |
||
722 | |||
723 | cmp [eax + SOCKET.Type], IP_PROTO_UDP |
||
724 | je .udp |
||
725 | |||
726 | cmp [eax + SOCKET.Type], IP_PROTO_ICMP |
||
727 | je .icmp |
||
728 | |||
729 | ; cmp [eax + SOCKET.Type], IP_PROTO_TCP |
||
730 | ; je .tcp |
||
731 | |||
1185 | hidnplayr | 732 | jmp s_error |
1159 | hidnplayr | 733 | |
734 | .udp: |
||
735 | |||
736 | DEBUGF 1,"type: UDP\n" |
||
737 | |||
738 | mov ecx, esi |
||
739 | mov esi, edx |
||
740 | mov edx, dword [eax + SOCKET.LocalPort] ; load local port and remote port at once |
||
741 | DEBUGF 1,"local port: %u, remote port:%u\n",[eax + SOCKET.LocalPort]:2, [eax + SOCKET.RemotePort]:2 |
||
1196 | hidnplayr | 742 | bswap edx ;;; |
743 | rol edx, 16 ;;; |
||
1159 | hidnplayr | 744 | mov ebx, [eax + SOCKET.LocalIP] |
745 | mov eax, [eax + SOCKET.RemoteIP] |
||
746 | |||
1196 | hidnplayr | 747 | call UDP_create_packet |
1159 | hidnplayr | 748 | |
749 | mov [esp+32], eax |
||
750 | ret |
||
751 | |||
752 | .icmp: |
||
753 | ; note: for ICMP sockets the SOCKET.LocalPort is used as the 'Identifier' value for ICMP packets |
||
754 | ; the application must add the header to the data, the kernel will fill in 'identifier' and 'checksum' |
||
755 | |||
756 | sub ecx, ICMP_Packet.Data |
||
757 | mov esi, edx |
||
758 | push ax |
||
759 | call IPv4_get_frgmnt_num |
||
760 | mov dx, ax |
||
761 | pop ax |
||
762 | shl edx, 16 |
||
763 | mov dh , [esi + ICMP_Packet.Type] |
||
764 | mov dl , [esi + ICMP_Packet.Code] |
||
765 | mov di , [esi + ICMP_Packet.Identifier] |
||
766 | ; mov [eax + SOCKET.LocalPort], di ; Set localport to the identifier number, so we can receive reply's |
||
767 | shl edi, 16 |
||
768 | mov di , [esi + ICMP_Packet.SequenceNumber] |
||
769 | add esi, ICMP_Packet.Data |
||
770 | mov ebx, [eax + SOCKET.LocalIP] |
||
771 | mov eax, [eax + SOCKET.RemoteIP] |
||
1196 | hidnplayr | 772 | call ICMP_create_packet |
1159 | hidnplayr | 773 | |
774 | mov [esp+32], eax |
||
775 | ret |
||
776 | |||
777 | .tcp: |
||
778 | |||
779 | ret |
||
780 | |||
781 | |||
782 | |||
783 | |||
784 | |||
785 | |||
786 | |||
787 | |||
788 | ; Allocate memory for socket data and put new socket into the list |
||
789 | ; Newly created socket is initialized with calling PID and number and |
||
790 | ; put into beginning of list (which is a fastest way). |
||
791 | ; |
||
792 | ; @return socket structure address in EAX |
||
793 | ; |
||
794 | proc net_socket_alloc stdcall uses ebx ecx edx edi |
||
795 | stdcall kernel_alloc, SOCKETBUFFSIZE |
||
796 | DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax |
||
797 | ; check if we can allocate needed amount of memory |
||
798 | or eax, eax |
||
799 | jz .exit |
||
800 | |||
801 | ; zero-initialize allocated memory |
||
802 | push eax |
||
803 | mov edi, eax |
||
804 | mov ecx, SOCKETBUFFSIZE / 4 |
||
805 | ; cld |
||
806 | xor eax, eax |
||
807 | rep stosd |
||
808 | pop eax |
||
809 | |||
810 | ; add socket to the list by changing pointers |
||
811 | mov ebx, net_sockets |
||
812 | push [ebx + SOCKET.NextPtr] |
||
813 | mov [ebx + SOCKET.NextPtr], eax |
||
814 | mov [eax + SOCKET.PrevPtr], ebx |
||
815 | pop ebx |
||
816 | mov [eax + SOCKET.NextPtr], ebx |
||
817 | or ebx, ebx |
||
818 | jz @f |
||
819 | mov [ebx + SOCKET.PrevPtr], eax |
||
820 | |||
821 | @@: ; set socket owner PID to the one of calling process |
||
822 | mov ebx, [TASK_BASE] |
||
823 | mov ebx, [ebx + TASKDATA.pid] |
||
824 | mov [eax + SOCKET.PID], ebx |
||
825 | |||
826 | ; find first free socket number and use it |
||
827 | ;mov edx, ebx |
||
828 | mov ebx, net_sockets |
||
829 | xor ecx, ecx |
||
830 | .next_socket_number: |
||
831 | inc ecx |
||
832 | .next_socket: |
||
833 | mov ebx, [ebx + SOCKET.NextPtr] |
||
834 | or ebx, ebx |
||
835 | jz .last_socket_number |
||
836 | cmp [ebx + SOCKET.Number], ecx |
||
837 | jne .next_socket |
||
838 | ;cmp [ebx + SOCKET.PID], edx |
||
839 | ;jne .next_socket |
||
840 | mov ebx, net_sockets |
||
841 | jmp .next_socket_number |
||
842 | |||
843 | .last_socket_number: |
||
844 | mov [eax + SOCKET.Number], ecx |
||
845 | |||
846 | .exit: |
||
847 | ret |
||
848 | endp |
||
849 | |||
850 | ; Free socket data memory and pop socket off the list |
||
851 | ; |
||
852 | ; @param sockAddr is a socket structure address |
||
853 | ; |
||
854 | proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD |
||
855 | mov eax, [sockAddr] |
||
856 | DEBUGF 1, "K : net_socket_free (0x%x)\n", eax |
||
857 | ; check if we got something similar to socket structure address |
||
858 | or eax, eax |
||
859 | jz .error |
||
860 | |||
861 | ; make sure sockAddr is one of the socket addresses in the list |
||
862 | mov ebx, net_sockets |
||
863 | ;mov ecx, [TASK_BASE] |
||
864 | ;mov ecx, [ecx + TASKDATA.pid] |
||
865 | .next_socket: |
||
866 | mov ebx, [ebx + SOCKET.NextPtr] |
||
867 | or ebx, ebx |
||
868 | jz .error |
||
869 | cmp ebx, eax |
||
870 | jne .next_socket |
||
871 | ;cmp [ebx + SOCKET.PID], ecx |
||
872 | ;jne .next_socket |
||
873 | |||
874 | ; okay, we found the correct one |
||
875 | ; remove it from the list first, changing pointers |
||
876 | mov ebx, [eax + SOCKET.NextPtr] |
||
877 | mov eax, [eax + SOCKET.PrevPtr] |
||
878 | mov [eax + SOCKET.NextPtr], ebx |
||
879 | or ebx, ebx |
||
880 | jz @f |
||
881 | mov [ebx + SOCKET.PrevPtr], eax |
||
882 | |||
883 | @@: ; and finally free the memory structure used |
||
884 | stdcall kernel_free, [sockAddr] |
||
885 | ret |
||
886 | |||
887 | .error: |
||
888 | DEBUGF 1, "K : failed\n" |
||
889 | ret |
||
890 | endp |
||
891 | |||
892 | ; Get socket structure address by its number |
||
893 | ; Scan through sockets list to find the socket with specified number. |
||
894 | ; This proc uses SOCKET.PID indirectly to check if socket is owned by |
||
895 | ; calling process. |
||
896 | ; |
||
897 | ; @param sockNum is a socket number |
||
898 | ; @return socket structure address or 0 (not found) in EAX |
||
899 | ; |
||
900 | proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD |
||
901 | mov eax, [sockNum] |
||
902 | ; check if we got something similar to socket number |
||
903 | or eax, eax |
||
904 | jz .error |
||
905 | |||
906 | ; scan through sockets list |
||
907 | mov ebx, net_sockets |
||
908 | ;mov ecx, [TASK_BASE] |
||
909 | ;mov ecx, [ecx + TASKDATA.pid] |
||
910 | .next_socket: |
||
911 | mov ebx, [ebx + SOCKET.NextPtr] |
||
912 | or ebx, ebx |
||
913 | jz .error |
||
914 | cmp [ebx + SOCKET.Number], eax |
||
915 | jne .next_socket |
||
916 | ;cmp [ebx + SOCKET.PID], ecx |
||
917 | ;jne .next_socket |
||
918 | |||
919 | ; okay, we found the correct one |
||
920 | mov eax, ebx |
||
921 | ret |
||
922 | |||
923 | .error: |
||
924 | xor eax, eax |
||
925 | ret |
||
926 | endp |
||
927 | |||
928 | ; Get socket number by its structure address |
||
929 | ; Scan through sockets list to find the socket with specified address. |
||
930 | ; This proc uses SOCKET.PID indirectly to check if socket is owned by |
||
931 | ; calling process. |
||
932 | ; |
||
933 | ; @param sockAddr is a socket structure address |
||
934 | ; @return socket number (SOCKET.Number) or 0 (not found) in EAX |
||
935 | ; |
||
936 | proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD |
||
937 | mov eax, [sockAddr] |
||
938 | ; check if we got something similar to socket structure address |
||
939 | or eax, eax |
||
940 | jz .error |
||
941 | |||
942 | ; scan through sockets list |
||
943 | mov ebx, net_sockets |
||
944 | ;mov ecx, [TASK_BASE] |
||
945 | ;mov ecx, [ecx + TASKDATA.pid] |
||
946 | .next_socket: |
||
947 | mov ebx, [ebx + SOCKET.NextPtr] |
||
948 | or ebx, ebx |
||
949 | jz .error |
||
950 | cmp ebx, eax |
||
951 | jne .next_socket |
||
952 | ;cmp [ebx + SOCKET.PID], ecx |
||
953 | ;jne .next_socket |
||
954 | |||
955 | ; okay, we found the correct one |
||
956 | mov eax, [ebx + SOCKET.Number] |
||
957 | ret |
||
958 | |||
959 | .error: |
||
960 | xor eax, eax |
||
961 | ret |
||
962 | endp |