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