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