Subversion Repositories Kolibri OS

Rev

Rev 3146 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2362 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
1159 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
3143 hidnplayr 6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
2888 hidnplayr 7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
1529 hidnplayr 9
;;     and Clevermouse.                                            ;;
1159 hidnplayr 10
;;                                                                 ;;
1529 hidnplayr 11
;;       Based on code by mike.dld                                 ;;
1159 hidnplayr 12
;;                                                                 ;;
1529 hidnplayr 13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
1159 hidnplayr 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
1206 hidnplayr 18
$Revision: 3147 $
1159 hidnplayr 19
 
1773 hidnplayr 20
 
2402 hidnplayr 21
struct  SOCKET
1249 hidnplayr 22
 
2402 hidnplayr 23
        NextPtr                 dd ? ; pointer to next socket in list
24
        PrevPtr                 dd ? ; pointer to previous socket in list
25
        Number                  dd ? ; socket number
1249 hidnplayr 26
 
2402 hidnplayr 27
        mutex                   MUTEX
1249 hidnplayr 28
 
2402 hidnplayr 29
        PID                     dd ? ; application process id
30
        Domain                  dd ? ; INET/UNIX/..
31
        Type                    dd ? ; RAW/STREAM/DGRAP
32
        Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
33
        errorcode               dd ?
2877 hidnplayr 34
        device                  dd ?
1249 hidnplayr 35
 
2402 hidnplayr 36
        options                 dd ?
37
        state                   dd ?
38
        backlog                 dw ? ; how many incomming connections that can be queued
1249 hidnplayr 39
 
2402 hidnplayr 40
        snd_proc                dd ?
41
        rcv_proc                dd ?
1536 hidnplayr 42
 
2305 hidnplayr 43
ends
1249 hidnplayr 44
 
2402 hidnplayr 45
struct  IP_SOCKET               SOCKET
1254 hidnplayr 46
 
2995 hidnplayr 47
        LocalIP                 rd 4 ; network byte order
48
        RemoteIP                rd 4 ; network byte order
1318 hidnplayr 49
 
2305 hidnplayr 50
ends
1159 hidnplayr 51
 
2402 hidnplayr 52
struct  TCP_SOCKET              IP_SOCKET
1249 hidnplayr 53
 
2995 hidnplayr 54
        LocalPort               dw ? ; network byte order
55
        RemotePort              dw ? ; network byte order
1514 hidnplayr 56
 
2402 hidnplayr 57
        t_state                 dd ? ; TCB state
2955 hidnplayr 58
        t_rxtshift              db ?
59
                                rb 3 ; align
2402 hidnplayr 60
        t_rxtcur                dd ?
61
        t_dupacks               dd ?
62
        t_maxseg                dd ?
63
        t_force                 dd ?
64
        t_flags                 dd ?
1514 hidnplayr 65
 
66
;---------------
67
; RFC783 page 21
68
 
69
; send sequence
2402 hidnplayr 70
        SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
71
        SND_NXT                 dd ? ; next send sequence number to use
2890 hidnplayr 72
        SND_UP                  dd ? ; urgent pointer
2402 hidnplayr 73
        SND_WL1                 dd ? ; window minus one
74
        SND_WL2                 dd ? ;
75
        ISS                     dd ? ; initial send sequence number
76
        SND_WND                 dd ? ; send window
1514 hidnplayr 77
 
78
; receive sequence
2957 hidnplayr 79
        RCV_WND                 dd ? ; receive window
2402 hidnplayr 80
        RCV_NXT                 dd ? ; next receive sequence number to use
2890 hidnplayr 81
        RCV_UP                  dd ? ; urgent pointer
2402 hidnplayr 82
        IRS                     dd ? ; initial receive sequence number
1514 hidnplayr 83
 
84
;---------------------
85
; Additional variables
86
 
87
; receive variables
2402 hidnplayr 88
        RCV_ADV                 dd ?
1514 hidnplayr 89
 
90
; retransmit variables
2402 hidnplayr 91
        SND_MAX                 dd ?
1514 hidnplayr 92
 
93
; congestion control
2402 hidnplayr 94
        SND_CWND                dd ?
95
        SND_SSTHRESH            dd ?
1514 hidnplayr 96
 
97
;----------------------
98
; Transmit timing stuff
2402 hidnplayr 99
        t_idle                  dd ?
100
        t_rtt                   dd ?
101
        t_rtseq                 dd ?
102
        t_srtt                  dd ?
103
        t_rttvar                dd ?
104
        t_rttmin                dd ?
105
        max_sndwnd              dd ?
1514 hidnplayr 106
 
107
;-----------------
108
; Out-of-band data
2402 hidnplayr 109
        t_oobflags              dd ?
110
        t_iobc                  dd ?
111
        t_softerror             dd ?
1514 hidnplayr 112
 
113
 
114
;---------
2924 hidnplayr 115
; RFC 1323                              ; the order of next 4 elements may not change
1514 hidnplayr 116
 
2402 hidnplayr 117
        SND_SCALE               db ?
118
        RCV_SCALE               db ?
119
        requested_s_scale       db ?
120
        request_r_scale         db ?
1514 hidnplayr 121
 
2924 hidnplayr 122
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
2402 hidnplayr 123
        ts_recent_age           dd ?
124
        last_ack_sent           dd ?
1519 hidnplayr 125
 
2310 hidnplayr 126
 
1519 hidnplayr 127
;-------
128
; Timers
2955 hidnplayr 129
        timer_retransmission    dd ? ; rexmt
130
        timer_persist           dd ?
131
        timer_keepalive         dd ? ; keepalive/syn timeout
132
        timer_timed_wait        dd ? ; also used as 2msl timer
1519 hidnplayr 133
 
2890 hidnplayr 134
; extra
135
 
2924 hidnplayr 136
        ts_ecr                  dd ? ; timestamp echo reply
2937 hidnplayr 137
        ts_val                  dd ?
138
        temp_bits               db ?
2890 hidnplayr 139
 
2305 hidnplayr 140
ends
1249 hidnplayr 141
 
2402 hidnplayr 142
struct  UDP_SOCKET              IP_SOCKET
1249 hidnplayr 143
 
2995 hidnplayr 144
        LocalPort               dw ? ; network byte order
145
        RemotePort              dw ? ; network byte order
2402 hidnplayr 146
        firstpacket             db ?
1249 hidnplayr 147
 
2305 hidnplayr 148
ends
1249 hidnplayr 149
 
150
 
2402 hidnplayr 151
struct  ICMP_SOCKET             IP_SOCKET
1249 hidnplayr 152
 
2402 hidnplayr 153
        Identifier              dw ?
1514 hidnplayr 154
 
2305 hidnplayr 155
ends
1514 hidnplayr 156
 
157
 
2402 hidnplayr 158
struct  RING_BUFFER
2311 hidnplayr 159
 
2402 hidnplayr 160
        start_ptr               dd ? ; Pointer to start of buffer
161
        end_ptr                 dd ? ; pointer to end of buffer
162
        read_ptr                dd ? ; Read pointer
163
        write_ptr               dd ? ; Write pointer
164
        size                    dd ? ; Number of bytes buffered
2311 hidnplayr 165
 
2305 hidnplayr 166
ends
1514 hidnplayr 167
 
2402 hidnplayr 168
struct  STREAM_SOCKET           TCP_SOCKET
1529 hidnplayr 169
 
2402 hidnplayr 170
        rcv                     RING_BUFFER
171
        snd                     RING_BUFFER
1529 hidnplayr 172
 
2305 hidnplayr 173
ends
1529 hidnplayr 174
 
2402 hidnplayr 175
struct  socket_queue_entry
1529 hidnplayr 176
 
2402 hidnplayr 177
        data_ptr                dd ?
178
        buf_ptr                 dd ?
179
        data_size               dd ?
1529 hidnplayr 180
 
1274 hidnplayr 181
ends
182
 
1514 hidnplayr 183
 
2614 hidnplayr 184
SOCKETBUFFSIZE          = 4096     ; in bytes
1514 hidnplayr 185
 
2614 hidnplayr 186
SOCKET_QUEUE_SIZE       = 10       ; maximum number ofincoming packets queued for 1 socket
1514 hidnplayr 187
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
2614 hidnplayr 188
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
1249 hidnplayr 189
 
1159 hidnplayr 190
uglobal
2402 hidnplayr 191
        net_sockets     rd 4
192
        last_socket_num dd ?
193
        last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
194
        last_TCP_port   dw ? ;
1159 hidnplayr 195
endg
196
 
197
 
1257 hidnplayr 198
;-----------------------------------------------------------------
1159 hidnplayr 199
;
200
; SOCKET_init
201
;
1257 hidnplayr 202
;-----------------------------------------------------------------
2402 hidnplayr 203
macro   SOCKET_init {
1159 hidnplayr 204
 
2402 hidnplayr 205
        xor     eax, eax
206
        mov     edi, net_sockets
207
        mov     ecx, 5
208
        rep     stosd
1159 hidnplayr 209
 
1529 hidnplayr 210
       @@:
2402 hidnplayr 211
        pseudo_random eax
212
        cmp     ax, MIN_EPHEMERAL_PORT
213
        jb      @r
214
        cmp     ax, MAX_EPHEMERAL_PORT
215
        ja      @r
2995 hidnplayr 216
        xchg    al, ah
2402 hidnplayr 217
        mov     [last_UDP_port], ax
1529 hidnplayr 218
 
219
       @@:
2402 hidnplayr 220
        pseudo_random eax
221
        cmp     ax, MIN_EPHEMERAL_PORT
222
        jb      @r
223
        cmp     ax, MAX_EPHEMERAL_PORT
224
        ja      @r
2995 hidnplayr 225
        xchg    al, ah
2402 hidnplayr 226
        mov     [last_TCP_port], ax
1529 hidnplayr 227
 
228
}
229
 
230
 
1257 hidnplayr 231
;-----------------------------------------------------------------
1159 hidnplayr 232
;
2994 hidnplayr 233
; SOCKET_block
234
;
235
;-----------------------------------------------------------------
236
macro   SOCKET_block socket, loop, done {
237
 
238
        test    [socket + SOCKET.options], SO_BLOCK     ; Is this a blocking socket?
239
        jz      done                                    ; No, return immediately
240
 
3143 hidnplayr 241
        pusha
242
        mov     eax, EVENT_NETWORK
243
        mov     ebx, 1337                   ; UID: ????
244
        call    wait_event
245
        popa
2994 hidnplayr 246
 
247
        jmp     loop
248
 
249
}
250
 
251
 
252
;-----------------------------------------------------------------
253
;
1159 hidnplayr 254
; Socket API (function 74)
255
;
1257 hidnplayr 256
;-----------------------------------------------------------------
2614 hidnplayr 257
align 4
258
sys_socket:
259
 
260
        cmp     ebx, 255
261
        jz      SOCKET_debug
262
 
263
        cmp     ebx, .number
264
        ja      s_error
265
        jmp     dword [.table + 4*ebx]
266
 
267
  .table:
2402 hidnplayr 268
        dd      SOCKET_open     ; 0
269
        dd      SOCKET_close    ; 1
270
        dd      SOCKET_bind     ; 2
271
        dd      SOCKET_listen   ; 3
272
        dd      SOCKET_connect  ; 4
273
        dd      SOCKET_accept   ; 5
274
        dd      SOCKET_send     ; 6
275
        dd      SOCKET_receive  ; 7
276
        dd      SOCKET_set_opt  ; 8
277
        dd      SOCKET_get_opt  ; 9
2614 hidnplayr 278
  .number = ($ - .table) / 4 - 1
2301 hidnplayr 279
 
1529 hidnplayr 280
s_error:
2402 hidnplayr 281
        DEBUGF  1,"socket error\n"
282
        mov     dword [esp+32], -1
1529 hidnplayr 283
 
2402 hidnplayr 284
        ret
1529 hidnplayr 285
 
1159 hidnplayr 286
 
2301 hidnplayr 287
 
1257 hidnplayr 288
;-----------------------------------------------------------------
1159 hidnplayr 289
;
290
; SOCKET_open
291
;
292
;  IN:  domain in ecx
293
;       type in edx
1196 hidnplayr 294
;       protocol in esi
1159 hidnplayr 295
;  OUT: eax is socket num, -1 on error
296
;
1257 hidnplayr 297
;-----------------------------------------------------------------
1206 hidnplayr 298
align 4
1514 hidnplayr 299
SOCKET_open:
1159 hidnplayr 300
 
2891 hidnplayr 301
        DEBUGF  1,"SOCKET_open: domain=%u type=%u protocol=%x\n", ecx, edx, esi
1159 hidnplayr 302
 
2402 hidnplayr 303
        push    ecx edx esi
304
        call    SOCKET_alloc
305
        pop     esi edx ecx
306
        jz      s_error
1159 hidnplayr 307
 
2402 hidnplayr 308
        mov     [esp+32], edi                   ; return socketnumber
1542 hidnplayr 309
 
2402 hidnplayr 310
        mov     [eax + SOCKET.Domain], ecx
311
        mov     [eax + SOCKET.Type], edx
312
        mov     [eax + SOCKET.Protocol], esi
1159 hidnplayr 313
 
2402 hidnplayr 314
        cmp     ecx, AF_INET4
315
        jne     .no_inet4
1529 hidnplayr 316
 
2402 hidnplayr 317
        cmp     edx, SOCK_DGRAM
318
        je      .udp
1536 hidnplayr 319
 
2402 hidnplayr 320
        cmp     edx, SOCK_STREAM
321
        je      .tcp
1529 hidnplayr 322
 
2402 hidnplayr 323
        cmp     edx, SOCK_RAW
324
        je      .raw
1541 hidnplayr 325
 
1536 hidnplayr 326
  .no_inet4:
2931 hidnplayr 327
        cmp     ecx, AF_PPP
328
        jne     .no_ppp
329
 
330
        cmp     esi, PPP_PROTO_ETHERNET
331
        je      .pppoe
332
 
333
  .no_ppp:
2402 hidnplayr 334
        ret
1536 hidnplayr 335
 
1542 hidnplayr 336
align 4
337
  .raw:
2402 hidnplayr 338
        test    esi, esi       ; IP_PROTO_IP
339
        jz      .ip
1529 hidnplayr 340
 
2402 hidnplayr 341
        cmp     esi, IP_PROTO_ICMP
342
        je      .icmp
1529 hidnplayr 343
 
2402 hidnplayr 344
        cmp     esi, IP_PROTO_UDP
345
        je      .udp
1533 hidnplayr 346
 
2402 hidnplayr 347
        cmp     esi, IP_PROTO_TCP
348
        je      .tcp
1536 hidnplayr 349
 
2402 hidnplayr 350
        ret
1159 hidnplayr 351
 
1542 hidnplayr 352
align 4
1536 hidnplayr 353
  .udp:
2402 hidnplayr 354
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
355
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
356
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
357
        ret
1529 hidnplayr 358
 
1542 hidnplayr 359
align 4
360
  .tcp:
2402 hidnplayr 361
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
362
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
363
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_tcp
1838 hidnplayr 364
 
2612 hidnplayr 365
        TCP_init_socket eax
2402 hidnplayr 366
        ret
1529 hidnplayr 367
 
368
 
1543 hidnplayr 369
align 4
370
  .ip:
2402 hidnplayr 371
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
372
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
373
        ret
1541 hidnplayr 374
 
1542 hidnplayr 375
 
376
align 4
1541 hidnplayr 377
  .icmp:
2402 hidnplayr 378
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
379
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
380
        ret
1541 hidnplayr 381
 
2931 hidnplayr 382
align 4
383
  .pppoe:
384
        push    eax
385
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
386
        pop     eax
1541 hidnplayr 387
 
2931 hidnplayr 388
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
389
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
390
        ret
1541 hidnplayr 391
 
2931 hidnplayr 392
 
1257 hidnplayr 393
;-----------------------------------------------------------------
1159 hidnplayr 394
;
395
; SOCKET_bind
396
;
397
;  IN:  socket number in ecx
398
;       pointer to sockaddr struct in edx
399
;       length of that struct in esi
400
;  OUT: 0 on success
401
;
1257 hidnplayr 402
;-----------------------------------------------------------------
1206 hidnplayr 403
align 4
1514 hidnplayr 404
SOCKET_bind:
1159 hidnplayr 405
 
2891 hidnplayr 406
        DEBUGF  1,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
1159 hidnplayr 407
 
2402 hidnplayr 408
        call    SOCKET_num_to_ptr
409
        jz      s_error
1159 hidnplayr 410
 
2402 hidnplayr 411
        cmp     esi, 2
412
        jb      s_error
1159 hidnplayr 413
 
2402 hidnplayr 414
        cmp     word [edx], AF_INET4
415
        je      .af_inet4
1159 hidnplayr 416
 
2402 hidnplayr 417
        cmp     word [edx], AF_UNIX
418
        je      .af_unix
1249 hidnplayr 419
 
2402 hidnplayr 420
        jmp     s_error
1249 hidnplayr 421
 
422
  .af_unix:
2402 hidnplayr 423
        ; TODO: write code here
1249 hidnplayr 424
 
2402 hidnplayr 425
        mov     dword [esp+32], 0
426
        ret
1249 hidnplayr 427
 
1159 hidnplayr 428
  .af_inet4:
429
 
2402 hidnplayr 430
        cmp     esi, 6
431
        jb      s_error
1159 hidnplayr 432
 
2622 hidnplayr 433
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
434
        je      .udp
1159 hidnplayr 435
 
2622 hidnplayr 436
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
437
        je      .tcp
1159 hidnplayr 438
 
2622 hidnplayr 439
        jmp     s_error
440
 
441
  .tcp:
442
  .udp:
443
 
444
        mov     ebx, [edx + 4]                  ; First, fill in the IP
445
        test    ebx, ebx                        ; If IP is 0, use default
446
        jnz     @f
447
        mov     ebx, [NET_DEFAULT]
448
        mov     ebx, [IP_LIST + 4*ebx]
449
       @@:
450
        mov     [eax + IP_SOCKET.LocalIP], ebx
451
 
2995 hidnplayr 452
        mov     bx, [edx + 2]                   ; Now fill in the local port if it's still available
2622 hidnplayr 453
        call    SOCKET_check_port
454
        jz      s_error                         ; ZF is set by socket_check_port, on error
455
 
2891 hidnplayr 456
        DEBUGF  1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\
2402 hidnplayr 457
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
458
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
1159 hidnplayr 459
 
2402 hidnplayr 460
        mov     dword [esp+32], 0
461
        ret
1159 hidnplayr 462
 
463
 
464
 
465
 
1257 hidnplayr 466
;-----------------------------------------------------------------
1159 hidnplayr 467
;
468
; SOCKET_connect
469
;
470
;  IN:  socket number in ecx
471
;       pointer to sockaddr struct in edx
472
;       length of that struct in esi
473
;  OUT: 0 on success
474
;
1257 hidnplayr 475
;-----------------------------------------------------------------
1159 hidnplayr 476
align 4
1514 hidnplayr 477
SOCKET_connect:
1159 hidnplayr 478
 
2891 hidnplayr 479
        DEBUGF  1,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
1159 hidnplayr 480
 
2402 hidnplayr 481
        call    SOCKET_num_to_ptr
482
        jz      s_error
1159 hidnplayr 483
 
2402 hidnplayr 484
        cmp     esi, 8
485
        jb      s_error
1159 hidnplayr 486
 
2402 hidnplayr 487
        cmp     word [edx], AF_INET4
488
        je      .af_inet4
1159 hidnplayr 489
 
2402 hidnplayr 490
        jmp     s_error
1159 hidnplayr 491
 
492
  .af_inet4:
2402 hidnplayr 493
        cmp     [eax + IP_SOCKET.LocalIP], 0
494
        jne     @f
495
        push    [IP_LIST]
496
        pop     [eax + IP_SOCKET.LocalIP]
1543 hidnplayr 497
       @@:
1159 hidnplayr 498
 
2402 hidnplayr 499
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
500
        je      .udp
1159 hidnplayr 501
 
2402 hidnplayr 502
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
503
        je      .tcp
1159 hidnplayr 504
 
2402 hidnplayr 505
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
506
        je      .ip
1541 hidnplayr 507
 
2402 hidnplayr 508
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
509
        je      .ip
1542 hidnplayr 510
 
2402 hidnplayr 511
        jmp     s_error
1159 hidnplayr 512
 
1542 hidnplayr 513
align 4
1254 hidnplayr 514
  .udp:
2402 hidnplayr 515
        pusha
516
        lea     ecx, [eax + SOCKET.mutex]
517
        call    mutex_lock
518
        popa
1543 hidnplayr 519
 
2402 hidnplayr 520
        pushw   [edx + 2]
521
        pop     [eax + UDP_SOCKET.RemotePort]
1543 hidnplayr 522
 
2402 hidnplayr 523
        pushd   [edx + 4]
524
        pop     [eax + IP_SOCKET.RemoteIP]
1543 hidnplayr 525
 
2402 hidnplayr 526
        cmp     [eax + UDP_SOCKET.LocalPort], 0
527
        jne     @f
528
        call    SOCKET_find_port
1543 hidnplayr 529
       @@:
530
 
2402 hidnplayr 531
        mov     [eax + UDP_SOCKET.firstpacket], 0
1159 hidnplayr 532
 
2402 hidnplayr 533
        push    eax
534
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
535
        pop     eax
1159 hidnplayr 536
 
2402 hidnplayr 537
        lea     ecx, [eax + SOCKET.mutex]
538
        call    mutex_unlock
1159 hidnplayr 539
 
2402 hidnplayr 540
        mov     dword [esp+32], 0
541
        ret
542
 
1542 hidnplayr 543
align 4
1254 hidnplayr 544
  .tcp:
2402 hidnplayr 545
        pusha
546
        lea     ecx, [eax + SOCKET.mutex]
547
        call    mutex_lock
548
        popa
1159 hidnplayr 549
 
2402 hidnplayr 550
        pushw   [edx + 2]
551
        pop     [eax + TCP_SOCKET.RemotePort]
1159 hidnplayr 552
 
2402 hidnplayr 553
        pushd   [edx + 4]
554
        pop     [eax + IP_SOCKET.RemoteIP]
1159 hidnplayr 555
 
2402 hidnplayr 556
        cmp     [eax + TCP_SOCKET.LocalPort], 0
557
        jne     @f
558
        call    SOCKET_find_port
1543 hidnplayr 559
       @@:
1159 hidnplayr 560
 
2402 hidnplayr 561
        mov     [eax + TCP_SOCKET.timer_persist], 0
562
        mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
2612 hidnplayr 563
 
2402 hidnplayr 564
        push    [TCP_sequence_num]
565
        add     [TCP_sequence_num], 6400
566
        pop     [eax + TCP_SOCKET.ISS]
567
        mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
1519 hidnplayr 568
 
2612 hidnplayr 569
 
2402 hidnplayr 570
        TCP_sendseqinit eax
1529 hidnplayr 571
 
1543 hidnplayr 572
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
1533 hidnplayr 573
 
2402 hidnplayr 574
        mov     ebx, eax
1159 hidnplayr 575
 
2402 hidnplayr 576
        lea     eax, [ebx + STREAM_SOCKET.snd]
577
        call    SOCKET_ring_create
1543 hidnplayr 578
 
2402 hidnplayr 579
        lea     eax, [ebx + STREAM_SOCKET.rcv]
580
        call    SOCKET_ring_create
1543 hidnplayr 581
 
2402 hidnplayr 582
        pusha
2939 hidnplayr 583
        lea     ecx, [ebx + SOCKET.mutex]
2402 hidnplayr 584
        call    mutex_unlock
585
        popa
1733 hidnplayr 586
 
2402 hidnplayr 587
        mov     eax, ebx
588
        call    TCP_output
1733 hidnplayr 589
 
2994 hidnplayr 590
;;; TODO: wait for successfull connection if blocking socket
591
 
2402 hidnplayr 592
        mov     dword [esp+32], 0
593
        ret
1159 hidnplayr 594
 
1542 hidnplayr 595
align 4
596
  .ip:
2402 hidnplayr 597
        pusha
598
        lea     ecx, [eax + SOCKET.mutex]
599
        call    mutex_lock
600
        popa
1543 hidnplayr 601
 
2402 hidnplayr 602
        pushd   [edx + 4]
603
        pop     [eax + IP_SOCKET.RemoteIP]
1159 hidnplayr 604
 
2402 hidnplayr 605
        push    eax
606
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
607
        pop     eax
1543 hidnplayr 608
 
2402 hidnplayr 609
        lea     ecx, [eax + SOCKET.mutex]
610
        call    mutex_unlock
1541 hidnplayr 611
 
2402 hidnplayr 612
        mov     dword [esp+32], 0
613
        ret
1541 hidnplayr 614
 
2402 hidnplayr 615
 
1257 hidnplayr 616
;-----------------------------------------------------------------
1159 hidnplayr 617
;
618
; SOCKET_listen
619
;
620
;  IN:  socket number in ecx
621
;       backlog in edx
622
;  OUT: eax is socket num, -1 on error
623
;
1257 hidnplayr 624
;-----------------------------------------------------------------
1206 hidnplayr 625
align 4
1514 hidnplayr 626
SOCKET_listen:
1159 hidnplayr 627
 
2891 hidnplayr 628
        DEBUGF  1,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
1159 hidnplayr 629
 
2402 hidnplayr 630
        call    SOCKET_num_to_ptr
631
        jz      s_error
1159 hidnplayr 632
 
2402 hidnplayr 633
        cmp     [eax + SOCKET.Domain], AF_INET4
634
        jne     s_error
1254 hidnplayr 635
 
2402 hidnplayr 636
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
637
        jne     s_error
1254 hidnplayr 638
 
2402 hidnplayr 639
        cmp     [eax + TCP_SOCKET.LocalPort], 0
640
        je      s_error
1514 hidnplayr 641
 
2402 hidnplayr 642
        cmp     [eax + IP_SOCKET.LocalIP], 0
643
        jne     @f
644
        push    [IP_LIST]
645
        pop     [eax + IP_SOCKET.LocalIP]
1543 hidnplayr 646
       @@:
647
 
2402 hidnplayr 648
        cmp     edx, MAX_backlog
649
        jbe     @f
650
        mov     edx, MAX_backlog
1543 hidnplayr 651
       @@:
1159 hidnplayr 652
 
2402 hidnplayr 653
        mov     [eax + SOCKET.backlog], dx
654
        or      [eax + SOCKET.options], SO_ACCEPTCON
655
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
2880 hidnplayr 656
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
1159 hidnplayr 657
 
2402 hidnplayr 658
        push    eax
659
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
660
        pop     eax
1543 hidnplayr 661
 
2402 hidnplayr 662
        mov     dword [esp+32], 0
1514 hidnplayr 663
 
2402 hidnplayr 664
        ret
1159 hidnplayr 665
 
666
 
1257 hidnplayr 667
;-----------------------------------------------------------------
1159 hidnplayr 668
;
669
; SOCKET_accept
670
;
671
;  IN:  socket number in ecx
672
;       addr in edx
673
;       addrlen in esi
674
;  OUT: eax is socket num, -1 on error
675
;
1257 hidnplayr 676
;-----------------------------------------------------------------
1206 hidnplayr 677
align 4
1514 hidnplayr 678
SOCKET_accept:
1159 hidnplayr 679
 
2891 hidnplayr 680
        DEBUGF  1,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
1159 hidnplayr 681
 
2402 hidnplayr 682
        call    SOCKET_num_to_ptr
683
        jz      s_error
1159 hidnplayr 684
 
2402 hidnplayr 685
        test    [eax + SOCKET.options], SO_ACCEPTCON
686
        jz      s_error
1543 hidnplayr 687
 
2402 hidnplayr 688
        cmp     [eax + SOCKET.Domain], AF_INET4
689
        jne     s_error
1249 hidnplayr 690
 
2402 hidnplayr 691
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
692
        jne     s_error
1249 hidnplayr 693
 
2994 hidnplayr 694
  .loop:
695
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
696
 
697
; Ok, we got a socket ptr
2572 hidnplayr 698
        mov     eax, [esi]
1249 hidnplayr 699
 
2572 hidnplayr 700
; Change PID to that of the current process
701
        mov     ebx, [TASK_BASE]
702
        mov     ebx, [ebx + TASKDATA.pid]
703
        mov     [eax + SOCKET.PID], ebx
704
 
2994 hidnplayr 705
; Convert it to a socket number
2402 hidnplayr 706
        call    SOCKET_ptr_to_num
707
        jz      s_error
2994 hidnplayr 708
; and return it to caller
2402 hidnplayr 709
        mov     [esp+32], eax
710
        ret
1514 hidnplayr 711
 
2994 hidnplayr 712
  .block:
713
        SOCKET_block    eax, .loop, s_error
1159 hidnplayr 714
 
1257 hidnplayr 715
;-----------------------------------------------------------------
1159 hidnplayr 716
;
717
; SOCKET_close
718
;
719
;  IN:  socket number in ecx
720
;  OUT: eax is socket num, -1 on error
721
;
1257 hidnplayr 722
;-----------------------------------------------------------------
1206 hidnplayr 723
align 4
1514 hidnplayr 724
SOCKET_close:
1159 hidnplayr 725
 
2891 hidnplayr 726
        DEBUGF  1,"SOCKET_close: %u\n", ecx
1159 hidnplayr 727
 
2402 hidnplayr 728
        call    SOCKET_num_to_ptr
729
        jz      s_error
1159 hidnplayr 730
 
2402 hidnplayr 731
        cmp     [eax + SOCKET.Domain], AF_INET4
732
        jne     s_error
1159 hidnplayr 733
 
2402 hidnplayr 734
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
735
        je      .free
1159 hidnplayr 736
 
2402 hidnplayr 737
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
738
        je      .free
1159 hidnplayr 739
 
2402 hidnplayr 740
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
741
        je      .free
1542 hidnplayr 742
 
2402 hidnplayr 743
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
744
        je      .tcp
1159 hidnplayr 745
 
2402 hidnplayr 746
        jmp     s_error
1159 hidnplayr 747
 
748
  .tcp:
2402 hidnplayr 749
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
750
        jb      .free
1318 hidnplayr 751
 
2890 hidnplayr 752
        call    TCP_usrclosed
2891 hidnplayr 753
        call    TCP_output      ;;;; Fixme: is this nescessary??
2994 hidnplayr 754
 
755
;;; TODO: wait for successfull termination if blocking socket
2402 hidnplayr 756
        mov     dword [esp+32], 0
1159 hidnplayr 757
 
2402 hidnplayr 758
        ret
1159 hidnplayr 759
 
1514 hidnplayr 760
  .free:
2402 hidnplayr 761
        call    SOCKET_free
762
        mov     dword [esp+32], 0
1159 hidnplayr 763
 
2402 hidnplayr 764
        ret
1159 hidnplayr 765
 
766
 
1257 hidnplayr 767
;-----------------------------------------------------------------
1159 hidnplayr 768
;
769
; SOCKET_receive
770
;
771
;  IN:  socket number in ecx
1249 hidnplayr 772
;       addr to buffer in edx
773
;       length of buffer in esi
1159 hidnplayr 774
;       flags in edi
775
;  OUT: eax is number of bytes copied, -1 on error
776
;
1257 hidnplayr 777
;-----------------------------------------------------------------
1206 hidnplayr 778
align 4
1514 hidnplayr 779
SOCKET_receive:
1159 hidnplayr 780
 
2891 hidnplayr 781
        DEBUGF  1,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
1514 hidnplayr 782
 
2402 hidnplayr 783
        call    SOCKET_num_to_ptr
784
        jz      s_error
1159 hidnplayr 785
 
2402 hidnplayr 786
        jmp     [eax + SOCKET.rcv_proc]
1533 hidnplayr 787
 
1536 hidnplayr 788
 
789
align 4
1541 hidnplayr 790
SOCKET_receive_dgram:
1536 hidnplayr 791
 
2402 hidnplayr 792
        DEBUGF  1,"SOCKET_receive: DGRAM\n"
1536 hidnplayr 793
 
2402 hidnplayr 794
        mov     ebx, esi
795
        mov     edi, edx                                        ; addr to buffer
1159 hidnplayr 796
 
2994 hidnplayr 797
  .loop:
798
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block      ; destroys esi and ecx
1536 hidnplayr 799
 
2402 hidnplayr 800
        mov     ecx, [esi + socket_queue_entry.data_size]
2891 hidnplayr 801
        DEBUGF  1,"SOCKET_receive: %u bytes data\n", ecx
1159 hidnplayr 802
 
2402 hidnplayr 803
        cmp     ecx, ebx
804
        ja      .too_small
1514 hidnplayr 805
 
2402 hidnplayr 806
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
807
        mov     esi, [esi + socket_queue_entry.data_ptr]
2891 hidnplayr 808
        DEBUGF  1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
2402 hidnplayr 809
        mov     [esp+32+4], ecx                                 ; return number of bytes copied
1159 hidnplayr 810
 
1514 hidnplayr 811
; copy the data
2402 hidnplayr 812
        shr     ecx, 1
813
        jnc     .nb
814
        movsb
1536 hidnplayr 815
  .nb:
2402 hidnplayr 816
        shr     ecx, 1
817
        jnc     .nw
818
        movsw
1536 hidnplayr 819
  .nw:
2402 hidnplayr 820
        test    ecx, ecx
821
        jz      .nd
822
        rep     movsd
1536 hidnplayr 823
  .nd:
1159 hidnplayr 824
 
2402 hidnplayr 825
        call    kernel_free                                     ; remove the packet
826
        ret
1514 hidnplayr 827
 
1536 hidnplayr 828
  .too_small:
1533 hidnplayr 829
 
2891 hidnplayr 830
        DEBUGF  1,"SOCKET_receive: Buffer too small\n"
2402 hidnplayr 831
        jmp     s_error
1536 hidnplayr 832
 
2994 hidnplayr 833
  .block:
834
        SOCKET_block    eax, .loop, s_error
835
 
836
 
1536 hidnplayr 837
align 4
838
SOCKET_receive_tcp:
839
 
2402 hidnplayr 840
        DEBUGF  1,"SOCKET_receive: TCP\n"
1536 hidnplayr 841
 
2402 hidnplayr 842
        mov     ecx, esi
843
        mov     edi, edx
2994 hidnplayr 844
        xor     edx, edx
2402 hidnplayr 845
        add     eax, STREAM_SOCKET.rcv
2998 hidnplayr 846
  .loop:
847
        cmp     [eax + RING_BUFFER.size], 0
848
        je      .block
2402 hidnplayr 849
        call    SOCKET_ring_read
850
        call    SOCKET_ring_free
1533 hidnplayr 851
 
2402 hidnplayr 852
        mov     [esp+32], ecx                                   ; return number of bytes copied
853
        ret
1159 hidnplayr 854
 
2994 hidnplayr 855
  .block:
856
        SOCKET_block    (eax - STREAM_SOCKET.rcv), .loop, s_error
1159 hidnplayr 857
 
2994 hidnplayr 858
 
1257 hidnplayr 859
;-----------------------------------------------------------------
1159 hidnplayr 860
;
861
; SOCKET_send
862
;
863
;
864
;  IN:  socket number in ecx
1206 hidnplayr 865
;       pointer to data in edx
866
;       datalength in esi
1159 hidnplayr 867
;       flags in edi
868
;  OUT: -1 on error
869
;
1257 hidnplayr 870
;-----------------------------------------------------------------
1206 hidnplayr 871
align 4
1514 hidnplayr 872
SOCKET_send:
1159 hidnplayr 873
 
2891 hidnplayr 874
        DEBUGF  1,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
1159 hidnplayr 875
 
2402 hidnplayr 876
        call    SOCKET_num_to_ptr
877
        jz      s_error
1159 hidnplayr 878
 
2402 hidnplayr 879
        mov     ecx, esi
880
        mov     esi, edx
1763 hidnplayr 881
 
2402 hidnplayr 882
        jmp     [eax + SOCKET.snd_proc]
1206 hidnplayr 883
 
884
 
1536 hidnplayr 885
align 4
886
SOCKET_send_udp:
1529 hidnplayr 887
 
2402 hidnplayr 888
        DEBUGF  1,"SOCKET_send: UDP\n"
1159 hidnplayr 889
 
2573 hidnplayr 890
        mov     [esp+32], ecx
2402 hidnplayr 891
        call    UDP_output
2573 hidnplayr 892
        cmp     eax, -1
893
        je      s_error
2402 hidnplayr 894
        ret
1159 hidnplayr 895
 
896
 
1536 hidnplayr 897
align 4
898
SOCKET_send_tcp:
1254 hidnplayr 899
 
2402 hidnplayr 900
        DEBUGF  1,"SOCKET_send: TCP\n"
1254 hidnplayr 901
 
2402 hidnplayr 902
        push    eax
903
        add     eax, STREAM_SOCKET.snd
904
        call    SOCKET_ring_write
905
        pop     eax
1536 hidnplayr 906
 
2621 hidnplayr 907
        mov     [esp+32], ecx
908
 
2402 hidnplayr 909
        call    TCP_output
910
        ret
1159 hidnplayr 911
 
1249 hidnplayr 912
 
1543 hidnplayr 913
align 4
914
SOCKET_send_ip:
1249 hidnplayr 915
 
2891 hidnplayr 916
        DEBUGF  1,"SOCKET_send: IPv4\n"
1543 hidnplayr 917
 
2573 hidnplayr 918
        mov     [esp+32], ecx
2402 hidnplayr 919
        call    IPv4_output_raw
2573 hidnplayr 920
        cmp     eax, -1
921
        je      s_error
2402 hidnplayr 922
        ret
1543 hidnplayr 923
 
2573 hidnplayr 924
 
1541 hidnplayr 925
align 4
926
SOCKET_send_icmp:
1249 hidnplayr 927
 
2402 hidnplayr 928
        DEBUGF  1,"SOCKET_send: ICMP\n"
1541 hidnplayr 929
 
2573 hidnplayr 930
        mov     [esp+32], ecx
2402 hidnplayr 931
        call    ICMP_output_raw
2573 hidnplayr 932
        cmp     eax, -1
933
        je      s_error
2402 hidnplayr 934
        ret
1541 hidnplayr 935
 
936
 
2931 hidnplayr 937
align 4
938
SOCKET_send_pppoe:
1541 hidnplayr 939
 
2931 hidnplayr 940
        DEBUGF  1,"SOCKET_send: PPPoE\n"
1541 hidnplayr 941
 
2931 hidnplayr 942
        mov     [esp+32], ecx
943
        mov     ebx, [eax + SOCKET.device]
944
 
945
        call    PPPoE_discovery_output
946
        cmp     eax, -1
947
        je      s_error
948
        ret
949
 
950
 
951
 
952
 
1257 hidnplayr 953
;-----------------------------------------------------------------
1256 clevermous 954
;
1257 hidnplayr 955
; SOCKET_get_options
1256 clevermous 956
;
1514 hidnplayr 957
;  IN:  ecx = socket number
958
;       edx = pointer to the options:
1257 hidnplayr 959
;               dd      level, optname, optval, optlen
1256 clevermous 960
;  OUT: -1 on error
961
;
962
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
963
; TODO: find best way to notify that send()'ed data were acknowledged
1831 hidnplayr 964
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
1256 clevermous 965
;
1257 hidnplayr 966
;-----------------------------------------------------------------
967
align 4
1514 hidnplayr 968
SOCKET_get_opt:
1257 hidnplayr 969
 
2402 hidnplayr 970
        DEBUGF  1,"SOCKET_get_opt\n"
1514 hidnplayr 971
 
2402 hidnplayr 972
        call    SOCKET_num_to_ptr
973
        jz      s_error
1514 hidnplayr 974
 
2402 hidnplayr 975
        cmp     dword [edx], IP_PROTO_TCP
976
        jne     s_error
977
        cmp     dword [edx+4], -2
978
        je      @f
979
        cmp     dword [edx+4], -3
980
        jne     s_error
1299 clevermous 981
@@:
1514 hidnplayr 982
;        mov     eax, [edx+12]
983
;        test    eax, eax
984
;        jz      .fail
985
;        cmp     dword [eax], 4
986
;        mov     dword [eax], 4
987
;        jb      .fail
988
;        stdcall net_socket_num_to_addr, ecx
989
;        test    eax, eax
990
;        jz      .fail
991
;        ; todo: check that eax is really TCP socket
992
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
993
;        cmp     dword [edx+4], -2
994
;        jz      @f
995
;        mov     ecx, [eax + TCP_SOCKET.state]
1299 clevermous 996
@@:
2402 hidnplayr 997
        mov     eax, [edx+8]
998
        test    eax, eax
999
        jz      @f
1000
        mov     [eax], ecx
1256 clevermous 1001
@@:
2402 hidnplayr 1002
        mov     dword [esp+32], 0
1003
        ret
1159 hidnplayr 1004
 
1005
 
1529 hidnplayr 1006
 
2731 hidnplayr 1007
;-----------------------------------------------------------------
1008
;
1009
; SOCKET_set_options
1010
;
1011
;  IN:  ecx = socket number
1012
;       edx = pointer to the options:
2877 hidnplayr 1013
;               dd      level, optname, optlen, optval
2731 hidnplayr 1014
;  OUT: -1 on error
1015
;
1016
;-----------------------------------------------------------------
1542 hidnplayr 1017
align 4
1018
SOCKET_set_opt:
1019
 
2731 hidnplayr 1020
        DEBUGF  1,"SOCKET_set_opt\n"
1021
 
1022
        call    SOCKET_num_to_ptr
1023
        jz      s_error
1024
 
2877 hidnplayr 1025
        cmp     dword [edx], SOL_SOCKET
1026
        jne     s_error
2731 hidnplayr 1027
 
2877 hidnplayr 1028
        cmp     dword [edx+4], SO_BINDTODEVICE
1029
        je      .bind
2731 hidnplayr 1030
 
2996 hidnplayr 1031
        cmp     dword [edx+4], SO_BLOCK
1032
        je      .block
1033
 
2877 hidnplayr 1034
        jmp     s_error
1035
 
1036
  .bind:
1037
        cmp     dword [edx+8], 0
1038
        je      .unbind
1039
 
1040
        movzx   edx, byte [edx + 9]
1041
        cmp     edx, MAX_NET_DEVICES
1042
        ja      s_error
1043
 
1044
        mov     edx, [NET_DRV_LIST + 4*edx]
1045
        test    edx, edx
1046
        jz      s_error
1047
        mov     [eax + SOCKET.device], edx
1048
 
2891 hidnplayr 1049
        DEBUGF  1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
2877 hidnplayr 1050
 
1051
        mov     dword [esp+32], 0       ; success!
2402 hidnplayr 1052
        ret
1542 hidnplayr 1053
 
2877 hidnplayr 1054
  .unbind:
1055
        mov     [eax + SOCKET.device], 0
1542 hidnplayr 1056
 
2877 hidnplayr 1057
        mov     dword [esp+32], 0       ; success!
1058
        ret
1542 hidnplayr 1059
 
2996 hidnplayr 1060
  .block:
1061
        cmp     dword [edx+8], 0
1062
        je      .unblock
2877 hidnplayr 1063
 
2996 hidnplayr 1064
        or      [eax + SOCKET.options], SO_BLOCK
2877 hidnplayr 1065
 
2996 hidnplayr 1066
        mov     dword [esp+32], 0       ; success!
1067
        ret
1068
 
1069
  .unblock:
1070
        and     [eax + SOCKET.options], not SO_BLOCK
1071
 
1072
        mov     dword [esp+32], 0       ; success!
1073
        ret
1074
 
1075
 
1076
 
1077
 
1078
 
1257 hidnplayr 1079
;-----------------------------------------------------------------
1206 hidnplayr 1080
;
1529 hidnplayr 1081
; SOCKET_debug
1082
;
1083
;  Copies socket variables to application buffer
1084
;
1085
;  IN:  ecx = socket number
1086
;       edx = pointer to buffer
1087
;
1088
;  OUT: -1 on error
1089
;-----------------------------------------------------------------
1090
align 4
1091
SOCKET_debug:
1092
 
3147 hidnplayr 1093
;        DEBUGF  1,"SOCKET_debug\n"
1529 hidnplayr 1094
 
3146 hidnplayr 1095
        mov     edi, edx
1096
 
1097
        test    ecx, ecx
1098
        jz      .returnall
1099
 
2402 hidnplayr 1100
        call    SOCKET_num_to_ptr
1101
        jz      s_error
1529 hidnplayr 1102
 
2402 hidnplayr 1103
        mov     esi, eax
1104
        mov     ecx, SOCKETBUFFSIZE/4
1105
        rep     movsd
1529 hidnplayr 1106
 
2402 hidnplayr 1107
        mov     dword [esp+32], 0
1108
        ret
1529 hidnplayr 1109
 
3146 hidnplayr 1110
  .returnall:
1111
        mov     ebx, net_sockets
1112
  .next_socket:
1113
        mov     ebx, [ebx + SOCKET.NextPtr]
1114
        test    ebx, ebx
1115
        jz      .done
1116
        mov     eax, [ebx + SOCKET.Number]
1117
        stosd
1118
        jmp     .next_socket
1119
  .done:
1120
        xor     eax, eax
1121
        stosd
1529 hidnplayr 1122
 
3146 hidnplayr 1123
        mov     dword [esp+32], 0
1124
        ret
1125
 
1126
 
1529 hidnplayr 1127
;-----------------------------------------------------------------
1128
;
1514 hidnplayr 1129
; SOCKET_find_port
1206 hidnplayr 1130
;
1514 hidnplayr 1131
; Fills in the local port number for TCP and UDP sockets
1132
; This procedure always works because the number of sockets is
1133
; limited to a smaller number then the number of possible ports
1206 hidnplayr 1134
;
1514 hidnplayr 1135
;  IN:  eax = socket pointer
1136
;  OUT: /
1206 hidnplayr 1137
;
1257 hidnplayr 1138
;-----------------------------------------------------------------
1206 hidnplayr 1139
align 4
1514 hidnplayr 1140
SOCKET_find_port:
1159 hidnplayr 1141
 
2402 hidnplayr 1142
        DEBUGF  1,"SOCKET_find_port\n"
1159 hidnplayr 1143
 
2402 hidnplayr 1144
        push    ebx esi ecx
1514 hidnplayr 1145
 
2402 hidnplayr 1146
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1147
        je      .udp
1159 hidnplayr 1148
 
2402 hidnplayr 1149
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1150
        je      .tcp
1159 hidnplayr 1151
 
2402 hidnplayr 1152
        pop     ecx esi ebx
1153
        ret
1514 hidnplayr 1154
 
1206 hidnplayr 1155
  .udp:
2402 hidnplayr 1156
        mov     bx, [last_UDP_port]
1157
        call    .findit
1158
        mov     [last_UDP_port], bx
1206 hidnplayr 1159
 
2995 hidnplayr 1160
        pop     ecx esi ebx
1161
        ret
1162
 
1206 hidnplayr 1163
  .tcp:
2402 hidnplayr 1164
        mov     bx, [last_TCP_port]
1165
        call    .findit
1166
        mov     [last_TCP_port], bx
1206 hidnplayr 1167
 
2995 hidnplayr 1168
        pop     ecx esi ebx
1169
        ret
1206 hidnplayr 1170
 
2995 hidnplayr 1171
 
1514 hidnplayr 1172
  .restart:
2995 hidnplayr 1173
        mov     bx, MIN_EPHEMERAL_PORT_N
1514 hidnplayr 1174
  .findit:
2995 hidnplayr 1175
        cmp     bx, MAX_EPHEMERAL_PORT_N
1176
        je      .restart
1206 hidnplayr 1177
 
2995 hidnplayr 1178
        add     bh, 1
1179
        adc     bl, 0
1206 hidnplayr 1180
 
2402 hidnplayr 1181
        call    SOCKET_check_port
1182
        jz      .findit
1183
        ret
1206 hidnplayr 1184
 
1257 hidnplayr 1185
 
1186
 
1187
;-----------------------------------------------------------------
1206 hidnplayr 1188
;
1542 hidnplayr 1189
; SOCKET_check_port (to be used with AF_INET only!)
1206 hidnplayr 1190
;
1514 hidnplayr 1191
; Checks if a local port number is unused
1192
; If the proposed port number is unused, it is filled in in the socket structure
1206 hidnplayr 1193
;
1514 hidnplayr 1194
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
2995 hidnplayr 1195
;        bx = proposed socket number (network byte order)
1206 hidnplayr 1196
;
2995 hidnplayr 1197
;  OUT:  ZF = set on error
1514 hidnplayr 1198
;
1257 hidnplayr 1199
;-----------------------------------------------------------------
1206 hidnplayr 1200
align 4
1514 hidnplayr 1201
SOCKET_check_port:
1202
 
2891 hidnplayr 1203
        DEBUGF  1,"SOCKET_check_port: "
1514 hidnplayr 1204
 
2402 hidnplayr 1205
        mov     ecx, [eax + SOCKET.Protocol]
2622 hidnplayr 1206
        mov     edx, [eax + IP_SOCKET.LocalIP]
2402 hidnplayr 1207
        mov     esi, net_sockets
1206 hidnplayr 1208
 
1209
  .next_socket:
2402 hidnplayr 1210
        mov     esi, [esi + SOCKET.NextPtr]
1211
        or      esi, esi
1212
        jz      .port_ok
1206 hidnplayr 1213
 
2402 hidnplayr 1214
        cmp     [esi + SOCKET.Protocol], ecx
1215
        jne     .next_socket
1206 hidnplayr 1216
 
2622 hidnplayr 1217
        cmp     [esi + IP_SOCKET.LocalIP], edx
1218
        jne     .next_socket
1219
 
2402 hidnplayr 1220
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1221
        jne     .next_socket
1206 hidnplayr 1222
 
3143 hidnplayr 1223
        DEBUGF  1,"local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
2402 hidnplayr 1224
        ret
1206 hidnplayr 1225
 
1226
  .port_ok:
2995 hidnplayr 1227
        DEBUGF  1,"local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
2402 hidnplayr 1228
        mov     [eax + UDP_SOCKET.LocalPort], bx
2995 hidnplayr 1229
        or      bx, bx                                  ; clear the zero-flag
2402 hidnplayr 1230
        ret
1206 hidnplayr 1231
 
1232
 
1257 hidnplayr 1233
 
1234
;-----------------------------------------------------------------
1206 hidnplayr 1235
;
1514 hidnplayr 1236
; SOCKET_input
1206 hidnplayr 1237
;
1536 hidnplayr 1238
; Updates a (stateless) socket with received data
1206 hidnplayr 1239
;
1514 hidnplayr 1240
; Note: the mutex should already be set !
1206 hidnplayr 1241
;
1249 hidnplayr 1242
;  IN:  eax = socket ptr
1514 hidnplayr 1243
;       ecx = data size
1244
;       esi = ptr to data
1245
;       [esp] = ptr to buf
1246
;       [esp + 4] = buf size
1249 hidnplayr 1247
;
1514 hidnplayr 1248
;  OUT: /
1206 hidnplayr 1249
;
1257 hidnplayr 1250
;-----------------------------------------------------------------
1206 hidnplayr 1251
align 4
1514 hidnplayr 1252
SOCKET_input:
1206 hidnplayr 1253
 
2402 hidnplayr 1254
        DEBUGF  1,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
1206 hidnplayr 1255
 
2402 hidnplayr 1256
        mov     [esp+4], ecx
1257
        push    esi
1258
        mov     esi, esp
1514 hidnplayr 1259
 
2402 hidnplayr 1260
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1514 hidnplayr 1261
 
2402 hidnplayr 1262
        DEBUGF  1,"SOCKET_input: queued packet successfully\n"
1263
        add     esp, sizeof.socket_queue_entry
1206 hidnplayr 1264
 
2402 hidnplayr 1265
        pusha
1266
        lea     ecx, [eax + SOCKET.mutex]
1267
        call    mutex_unlock
1268
        popa
1269
 
1270
        jmp     SOCKET_notify_owner
1271
 
1514 hidnplayr 1272
  .full:
2402 hidnplayr 1273
        DEBUGF  2,"SOCKET_input: socket %x is full!\n", eax
1206 hidnplayr 1274
 
2402 hidnplayr 1275
        pusha
1276
        lea     ecx, [eax + SOCKET.mutex]
1277
        call    mutex_unlock
1278
        popa
1514 hidnplayr 1279
 
2402 hidnplayr 1280
        call    kernel_free
1281
        add     esp, 8
1533 hidnplayr 1282
 
2402 hidnplayr 1283
        ret
1284
 
1285
 
1533 hidnplayr 1286
;--------------------------
1287
;
1288
; eax = ptr to ring struct (just a buffer of the right size)
1289
;
1290
align 4
1291
SOCKET_ring_create:
1292
 
2402 hidnplayr 1293
        push    esi
1294
        mov     esi, eax
1543 hidnplayr 1295
 
2402 hidnplayr 1296
        push    edx
1297
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
1298
        pop     edx
1533 hidnplayr 1299
 
2402 hidnplayr 1300
        DEBUGF  1,"SOCKET_ring_created: %x\n", eax
1301
        mov     [esi + RING_BUFFER.start_ptr], eax
1302
        mov     [esi + RING_BUFFER.write_ptr], eax
1303
        mov     [esi + RING_BUFFER.read_ptr], eax
1304
        mov     [esi + RING_BUFFER.size], 0
2888 hidnplayr 1305
        add     eax, SOCKET_MAXDATA
2402 hidnplayr 1306
        mov     [esi + RING_BUFFER.end_ptr], eax
1307
        mov     eax, esi
1308
        pop     esi
1533 hidnplayr 1309
 
2402 hidnplayr 1310
        ret
1533 hidnplayr 1311
 
1514 hidnplayr 1312
;-----------------------------------------------------------------
1313
;
1533 hidnplayr 1314
; SOCKET_ring_write
1529 hidnplayr 1315
;
1533 hidnplayr 1316
; Adds data to a stream socket, and updates write pointer and size
1529 hidnplayr 1317
;
1318
;  IN:  eax = ptr to ring struct
1319
;       ecx = data size
1320
;       esi = ptr to data
1321
;
1533 hidnplayr 1322
;  OUT: ecx = number of bytes stored
1529 hidnplayr 1323
;
1324
;-----------------------------------------------------------------
1325
align 4
1533 hidnplayr 1326
SOCKET_ring_write:
1529 hidnplayr 1327
 
2402 hidnplayr 1328
        DEBUGF  1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
1529 hidnplayr 1329
 
2402 hidnplayr 1330
        add     [eax + RING_BUFFER.size], ecx
2573 hidnplayr 1331
        jc      .way_too_large
2402 hidnplayr 1332
        cmp     [eax + RING_BUFFER.size], SOCKET_MAXDATA
1333
        ja      .too_large
1529 hidnplayr 1334
 
1335
  .copy:
2402 hidnplayr 1336
        mov     edi, [eax + RING_BUFFER.write_ptr]
1337
        DEBUGF  2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
1529 hidnplayr 1338
 
2402 hidnplayr 1339
        push    ecx
1340
        shr     ecx, 1
1341
        jnc     .nb
1342
        movsb
1536 hidnplayr 1343
  .nb:
2402 hidnplayr 1344
        shr     ecx, 1
1345
        jnc     .nw
1346
        movsw
1536 hidnplayr 1347
  .nw:
2402 hidnplayr 1348
        test    ecx, ecx
1349
        jz      .nd
1350
        rep     movsd
1536 hidnplayr 1351
  .nd:
2402 hidnplayr 1352
        pop     ecx
1529 hidnplayr 1353
 
2402 hidnplayr 1354
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1355
        jae     .wrap
1356
        mov     [eax + RING_BUFFER.write_ptr], edi
1533 hidnplayr 1357
 
2402 hidnplayr 1358
        ret
1529 hidnplayr 1359
 
1533 hidnplayr 1360
  .wrap:
2402 hidnplayr 1361
        sub     edi, SOCKET_MAXDATA
1362
        mov     [eax + RING_BUFFER.write_ptr], edi
1533 hidnplayr 1363
 
2402 hidnplayr 1364
        ret
1533 hidnplayr 1365
 
2404 hidnplayr 1366
  .too_large:                                                           ; update size, we will fill buffer completely
1367
        sub     [eax + RING_BUFFER.size], SOCKET_MAXDATA
2402 hidnplayr 1368
        sub     ecx, [eax + RING_BUFFER.size]
2404 hidnplayr 1369
        mov     [eax + RING_BUFFER.size], SOCKET_MAXDATA
2573 hidnplayr 1370
        ja      .copy
1529 hidnplayr 1371
 
2573 hidnplayr 1372
  .full:
2402 hidnplayr 1373
        DEBUGF  2,"SOCKET_ring_write: ring buffer is full!\n"
1374
        xor     ecx, ecx
1375
        ret
1529 hidnplayr 1376
 
2573 hidnplayr 1377
  .way_too_large:
1378
        sub     [eax + RING_BUFFER.size], ecx
1379
        mov     ecx, SOCKET_MAXDATA
1380
        sub     ecx, [eax + RING_BUFFER.size]
1381
        ja      .copy
1382
        jmp     .full
1529 hidnplayr 1383
 
2573 hidnplayr 1384
 
1385
 
1529 hidnplayr 1386
;-----------------------------------------------------------------
1387
;
1388
; SOCKET_ring_read
1389
;
2893 hidnplayr 1390
;  IN:  eax = ring struct ptr
1391
;       ecx = bytes to read
1392
;       edx = offset
2994 hidnplayr 1393
;       edi = ptr to buffer start
1529 hidnplayr 1394
;
2994 hidnplayr 1395
;  OUT: eax = unchanged
1396
;       ecx = number of bytes read (0 on error)
1397
;       edx = destroyed
1398
;       esi = destroyed
1399
;       edi = ptr to buffer end
1529 hidnplayr 1400
;
1401
;-----------------------------------------------------------------
1402
align 4
1403
SOCKET_ring_read:
1404
 
2893 hidnplayr 1405
        DEBUGF  1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
1529 hidnplayr 1406
 
2893 hidnplayr 1407
        mov     esi, [eax + RING_BUFFER.read_ptr]
1408
        add     esi, edx                                        ; esi = start_ptr + offset
1409
 
1410
        neg     edx
1411
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1412
        jle     .no_data_at_all
1413
 
1414
        cmp     ecx, edx
2402 hidnplayr 1415
        ja      .less_data
1529 hidnplayr 1416
 
1417
  .copy:
2402 hidnplayr 1418
        DEBUGF  2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
1419
        push    ecx
1420
        shr     ecx, 1
1421
        jnc     .nb
1422
        movsb
1536 hidnplayr 1423
  .nb:
2402 hidnplayr 1424
        shr     ecx, 1
1425
        jnc     .nw
1426
        movsw
1536 hidnplayr 1427
  .nw:
2402 hidnplayr 1428
        test    ecx, ecx
1429
        jz      .nd
1430
        rep     movsd
1536 hidnplayr 1431
  .nd:
2402 hidnplayr 1432
        pop     ecx
2893 hidnplayr 1433
        ret
1529 hidnplayr 1434
 
1830 hidnplayr 1435
  .no_data_at_all:
2894 hidnplayr 1436
        DEBUGF  1,"SOCKET_ring_read: no data at all!\n"
2993 hidnplayr 1437
        xor     ecx, ecx
2402 hidnplayr 1438
        ret
1529 hidnplayr 1439
 
1533 hidnplayr 1440
  .less_data:
2893 hidnplayr 1441
        mov     ecx, edx
2402 hidnplayr 1442
        jmp     .copy
1529 hidnplayr 1443
 
1444
 
1445
;-----------------------------------------------------------------
1446
;
1447
; SOCKET_ring_free
1448
;
1449
; Free's some bytes from the ringbuffer
1450
;
1451
;  IN:  eax = ptr to ring struct
1452
;       ecx = data size
1453
;
1454
;  OUT: ecx = number of bytes free-ed
1455
;
1456
;-----------------------------------------------------------------
1457
align 4
1458
SOCKET_ring_free:
1459
 
2402 hidnplayr 1460
        DEBUGF  1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
1529 hidnplayr 1461
 
2402 hidnplayr 1462
        sub     [eax + RING_BUFFER.size], ecx
2888 hidnplayr 1463
        jb      .error
2402 hidnplayr 1464
        add     [eax + RING_BUFFER.read_ptr], ecx
1529 hidnplayr 1465
 
2402 hidnplayr 1466
        mov     edx, [eax + RING_BUFFER.end_ptr]
1467
        cmp     [eax + RING_BUFFER.read_ptr], edx
1468
        jb      @f
1469
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1529 hidnplayr 1470
       @@:
2402 hidnplayr 1471
        ret
1529 hidnplayr 1472
 
2888 hidnplayr 1473
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
1474
        DEBUGF  1,"SOCKET_ring_free: buffer=%x error!\n", eax
2402 hidnplayr 1475
        add     [eax + RING_BUFFER.size], ecx
1476
        xor     ecx, ecx
1477
        ret
1529 hidnplayr 1478
 
1479
 
1480
;-----------------------------------------------------------------
1481
;
1514 hidnplayr 1482
; SOCKET_notify_owner
1483
;
1484
; notify's the owner of a socket that something happened
1485
;
1486
;  IN:  eax = socket ptr
1487
;  OUT: /
1488
;
1489
;-----------------------------------------------------------------
1490
align 4
1491
SOCKET_notify_owner:
1492
 
2402 hidnplayr 1493
        DEBUGF  1,"SOCKET_notify_owner: %x\n", eax
1514 hidnplayr 1494
 
2402 hidnplayr 1495
        call    SOCKET_check
1496
        jz      .error
1514 hidnplayr 1497
 
2402 hidnplayr 1498
        push    eax ecx esi
1514 hidnplayr 1499
 
1500
; socket exists, now try to flag an event to the application
1501
 
2402 hidnplayr 1502
        mov     eax, [eax + SOCKET.PID]
2629 hidnplayr 1503
        test    eax, eax
1504
        jz      .error2
2402 hidnplayr 1505
        mov     ecx, 1
1506
        mov     esi, TASK_DATA + TASKDATA.pid
1206 hidnplayr 1507
 
1508
       .next_pid:
2402 hidnplayr 1509
        cmp     [esi], eax
1510
        je      .found_pid
1511
        inc     ecx
1512
        add     esi, 0x20
1513
        cmp     ecx, [TASK_COUNT]
1514
        jbe     .next_pid
1206 hidnplayr 1515
 
1514 hidnplayr 1516
; PID not found, TODO: close socket!
1517
 
2402 hidnplayr 1518
        jmp     .error2
1514 hidnplayr 1519
 
1206 hidnplayr 1520
       .found_pid:
2402 hidnplayr 1521
        shl     ecx, 8
1522
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1523
        mov     [check_idle_semaphore], 200
1206 hidnplayr 1524
 
2402 hidnplayr 1525
        DEBUGF  1,"SOCKET_notify_owner: succes!\n"
1514 hidnplayr 1526
 
1527
  .error2:
2402 hidnplayr 1528
        pop     esi ecx eax
1536 hidnplayr 1529
 
1514 hidnplayr 1530
  .error:
1531
 
2402 hidnplayr 1532
        ret
1206 hidnplayr 1533
 
1534
 
1514 hidnplayr 1535
;--------------------------------------------------------------------
1536
;
1537
; SOCKET_alloc
1538
;
1159 hidnplayr 1539
; Allocate memory for socket data and put new socket into the list
1540
; Newly created socket is initialized with calling PID and number and
1541
; put into beginning of list (which is a fastest way).
1542
;
1514 hidnplayr 1543
; IN:  /
1544
; OUT: eax = 0 on error, socket ptr otherwise
1545
;      edi = socket number
1546
;       ZF = cleared on error
1159 hidnplayr 1547
;
1514 hidnplayr 1548
;--------------------------------------------------------------------
1549
align 4
1550
SOCKET_alloc:
1551
 
2402 hidnplayr 1552
        push    ebx
1514 hidnplayr 1553
 
2402 hidnplayr 1554
        stdcall kernel_alloc, SOCKETBUFFSIZE
1555
        DEBUGF  1, "SOCKET_alloc: ptr=%x\n", eax
1556
        or      eax, eax
1557
        jz      .exit
1159 hidnplayr 1558
 
1514 hidnplayr 1559
; zero-initialize allocated memory
2402 hidnplayr 1560
        push    eax
1561
        mov     edi, eax
1562
        mov     ecx, SOCKETBUFFSIZE / 4
1563
        xor     eax, eax
1564
        rep     stosd
1565
        pop     eax
1159 hidnplayr 1566
 
1536 hidnplayr 1567
; set send-and receive procedures to return -1
2402 hidnplayr 1568
        mov     [eax + SOCKET.snd_proc], s_error
1569
        mov     [eax + SOCKET.rcv_proc], s_error
1536 hidnplayr 1570
 
1514 hidnplayr 1571
; find first free socket number and use it
2402 hidnplayr 1572
        mov     edi, [last_socket_num]
1159 hidnplayr 1573
  .next_socket_number:
2402 hidnplayr 1574
        inc     edi
1575
        jz      .next_socket_number     ; avoid socket nr 0
1576
        cmp     edi, -1
1577
        je      .next_socket_number     ; avoid socket nr -1
1578
        mov     ebx, net_sockets
1159 hidnplayr 1579
  .next_socket:
2402 hidnplayr 1580
        mov     ebx, [ebx + SOCKET.NextPtr]
1581
        test    ebx, ebx
1582
        jz      .last_socket
1536 hidnplayr 1583
 
2402 hidnplayr 1584
        cmp     [ebx + SOCKET.Number], edi
1585
        jne     .next_socket
1586
        jmp     .next_socket_number
1159 hidnplayr 1587
 
1514 hidnplayr 1588
  .last_socket:
2402 hidnplayr 1589
        mov     [last_socket_num], edi
1590
        mov     [eax + SOCKET.Number], edi
1591
        DEBUGF  1, "SOCKET_alloc: number=%u\n", edi
1159 hidnplayr 1592
 
1514 hidnplayr 1593
; Fill in PID
2402 hidnplayr 1594
        mov     ebx, [TASK_BASE]
1595
        mov     ebx, [ebx + TASKDATA.pid]
1596
        mov     [eax + SOCKET.PID], ebx
1514 hidnplayr 1597
 
2403 hidnplayr 1598
; init mutex
1599
        pusha
1600
        lea     ecx, [eax + SOCKET.mutex]
1601
        call    mutex_init
1602
        popa
1603
 
1529 hidnplayr 1604
; add socket to the list by re-arranging some pointers
2402 hidnplayr 1605
        mov     ebx, [net_sockets + SOCKET.NextPtr]
1514 hidnplayr 1606
 
2402 hidnplayr 1607
        mov     [eax + SOCKET.PrevPtr], net_sockets
1608
        mov     [eax + SOCKET.NextPtr], ebx
1514 hidnplayr 1609
 
2402 hidnplayr 1610
        test    ebx, ebx
1611
        jz      @f
1612
 
1613
        pusha
1614
        lea     ecx, [ebx + SOCKET.mutex]
1615
        call    mutex_lock
1616
        popa
1617
 
1618
        mov     [ebx + SOCKET.PrevPtr], eax
1619
 
1620
        pusha
1621
        lea     ecx, [ebx + SOCKET.mutex]
1622
        call    mutex_unlock
1623
        popa
1514 hidnplayr 1624
       @@:
1625
 
2402 hidnplayr 1626
        mov     [net_sockets + SOCKET.NextPtr], eax
1627
        or      eax, eax                ; used to clear zero flag
1159 hidnplayr 1628
  .exit:
2402 hidnplayr 1629
        pop     ebx
1514 hidnplayr 1630
 
2402 hidnplayr 1631
        ret
1159 hidnplayr 1632
 
1514 hidnplayr 1633
 
1634
;----------------------------------------------------
1159 hidnplayr 1635
;
1514 hidnplayr 1636
; SOCKET_free
1159 hidnplayr 1637
;
1514 hidnplayr 1638
; Free socket data memory and remove socket from the list
1639
;
1640
; IN:  eax = socket ptr
1641
; OUT: /
1642
;
1643
;----------------------------------------------------
1644
align 4
1645
SOCKET_free:
1159 hidnplayr 1646
 
2402 hidnplayr 1647
        DEBUGF  1, "SOCKET_free: %x\n", eax
1514 hidnplayr 1648
 
2402 hidnplayr 1649
        call    SOCKET_check
1650
        jz      .error
1159 hidnplayr 1651
 
2402 hidnplayr 1652
        push    ebx
1514 hidnplayr 1653
 
2402 hidnplayr 1654
        pusha
1655
        lea     ecx, [eax + SOCKET.mutex]
1656
        call    mutex_lock
1657
        popa
1514 hidnplayr 1658
 
2402 hidnplayr 1659
        cmp     [eax + SOCKET.Domain], AF_INET4
1660
        jnz     .no_tcp
1529 hidnplayr 1661
 
2402 hidnplayr 1662
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1663
        jnz     .no_tcp
1664
 
1665
        mov     ebx, eax
1666
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
1667
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
1668
        mov     eax, ebx
1536 hidnplayr 1669
  .no_tcp:
1529 hidnplayr 1670
 
2402 hidnplayr 1671
        push    eax                             ; this will be passed to kernel_free
1672
        mov     ebx, [eax + SOCKET.NextPtr]
1673
        mov     eax, [eax + SOCKET.PrevPtr]
1514 hidnplayr 1674
 
2402 hidnplayr 1675
        DEBUGF  1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
1514 hidnplayr 1676
 
2402 hidnplayr 1677
        test    eax, eax
1678
        jz      @f
1679
        mov     [eax + SOCKET.NextPtr], ebx
1514 hidnplayr 1680
       @@:
1159 hidnplayr 1681
 
2402 hidnplayr 1682
        test    ebx, ebx
1683
        jz      @f
1684
        mov     [ebx + SOCKET.PrevPtr], eax
1514 hidnplayr 1685
       @@:
1249 hidnplayr 1686
 
2402 hidnplayr 1687
        call    kernel_free
1688
        pop     ebx
1159 hidnplayr 1689
 
2402 hidnplayr 1690
        DEBUGF  1, "SOCKET_free: success!\n"
1514 hidnplayr 1691
 
1159 hidnplayr 1692
  .error:
2402 hidnplayr 1693
        ret
1159 hidnplayr 1694
 
1543 hidnplayr 1695
;------------------------------------
1696
;
1697
; SOCKET_fork
1698
;
1699
; Create a child socket
1700
;
1533 hidnplayr 1701
; IN:  socket nr in ebx
1543 hidnplayr 1702
; OUT: child socket nr in eax
1703
;
1704
;-----------------------------------
1529 hidnplayr 1705
align 4
1706
SOCKET_fork:
1707
 
2402 hidnplayr 1708
        DEBUGF  1,"SOCKET_fork: %x\n", ebx
1529 hidnplayr 1709
 
1543 hidnplayr 1710
; Exit if backlog queue is full
2402 hidnplayr 1711
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
1712
        cmp     ax, [ebx + SOCKET.backlog]
1713
        jae     .fail
1543 hidnplayr 1714
 
1529 hidnplayr 1715
; Allocate new socket
2402 hidnplayr 1716
        push    ebx
1717
        call    SOCKET_alloc
1718
        pop     ebx
1719
        jz      .fail
1529 hidnplayr 1720
 
2402 hidnplayr 1721
        push    eax
1722
        mov     esi, esp
1723
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
1724
        pop     eax
1543 hidnplayr 1725
 
1726
; Copy structure from current socket to new
1727
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
2402 hidnplayr 1728
        lea     esi, [ebx + SOCKET.PID]
1729
        lea     edi, [eax + SOCKET.PID]
1730
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
1731
        rep     movsd
1529 hidnplayr 1732
 
2402 hidnplayr 1733
        and     [eax + SOCKET.options], not SO_ACCEPTCON
1529 hidnplayr 1734
 
2402 hidnplayr 1735
        ret
1529 hidnplayr 1736
 
1543 hidnplayr 1737
  .fail2:
2402 hidnplayr 1738
        add     esp, 4+4+4
1543 hidnplayr 1739
  .fail:
2402 hidnplayr 1740
        DEBUGF  1,"SOCKET_fork: failed\n"
1741
        xor     eax, eax
1742
        ret
1529 hidnplayr 1743
 
1543 hidnplayr 1744
 
1514 hidnplayr 1745
;---------------------------------------------------
1746
;
1747
; SOCKET_num_to_ptr
1748
;
1159 hidnplayr 1749
; Get socket structure address by its number
1750
;
1514 hidnplayr 1751
; IN:  ecx = socket number
1533 hidnplayr 1752
; OUT: eax = 0 on error, socket ptr otherwise
1514 hidnplayr 1753
;       ZF = set on error
1159 hidnplayr 1754
;
1514 hidnplayr 1755
;---------------------------------------------------
1756
align 4
1757
SOCKET_num_to_ptr:
1159 hidnplayr 1758
 
2891 hidnplayr 1759
        DEBUGF  1,"SOCKET_num_to_ptr: num=%u ", ecx
1514 hidnplayr 1760
 
2402 hidnplayr 1761
        mov     eax, net_sockets
1514 hidnplayr 1762
 
1159 hidnplayr 1763
  .next_socket:
2402 hidnplayr 1764
        mov     eax, [eax + SOCKET.NextPtr]
1765
        or      eax, eax
1766
        jz      .error
1767
        cmp     [eax + SOCKET.Number], ecx
1768
        jne     .next_socket
1159 hidnplayr 1769
 
2402 hidnplayr 1770
        test    eax, eax
1159 hidnplayr 1771
 
2891 hidnplayr 1772
        DEBUGF  1,"ptr=%x\n", eax
1773
        ret
1774
 
1159 hidnplayr 1775
  .error:
2891 hidnplayr 1776
        DEBUGF  1,"not found\n", eax
2402 hidnplayr 1777
        ret
1159 hidnplayr 1778
 
1514 hidnplayr 1779
 
1780
;---------------------------------------------------
1159 hidnplayr 1781
;
1514 hidnplayr 1782
; SOCKET_ptr_to_num
1159 hidnplayr 1783
;
1514 hidnplayr 1784
; Get socket number by its address
1785
;
1786
; IN:  eax = socket ptr
1787
; OUT: eax = 0 on error, socket num otherwise
1788
;       ZF = set on error
1789
;
1790
;---------------------------------------------------
1791
align 4
1792
SOCKET_ptr_to_num:
1793
 
2891 hidnplayr 1794
        DEBUGF  1,"SOCKET_ptr_to_num: ptr=%x ", eax
1514 hidnplayr 1795
 
2402 hidnplayr 1796
        call    SOCKET_check
1797
        jz      .error
1159 hidnplayr 1798
 
2402 hidnplayr 1799
        mov     eax, [eax + SOCKET.Number]
1514 hidnplayr 1800
 
2891 hidnplayr 1801
        DEBUGF  1,"num=%u\n", eax
1802
        ret
1514 hidnplayr 1803
 
1804
  .error:
2891 hidnplayr 1805
        DEBUGF  1,"not found\n", eax
2402 hidnplayr 1806
        ret
1514 hidnplayr 1807
 
1808
 
1809
;---------------------------------------------------
1810
;
1811
; SOCKET_check
1812
;
1813
; checks if the given value is really a socket ptr
1814
;
1815
; IN:  eax = socket ptr
1816
; OUT: eax = 0 on error, unchanged otherwise
1817
;       ZF = set on error
1818
;
1819
;---------------------------------------------------
1820
align 4
1821
SOCKET_check:
1822
 
2402 hidnplayr 1823
        DEBUGF  1,"SOCKET_check: %x\n", eax
1514 hidnplayr 1824
 
2402 hidnplayr 1825
        push    ebx
1826
        mov     ebx, net_sockets
1514 hidnplayr 1827
 
1159 hidnplayr 1828
  .next_socket:
2402 hidnplayr 1829
        mov     ebx, [ebx + SOCKET.NextPtr]
1830
        or      ebx, ebx
1831
        jz      .done
1832
        cmp     ebx, eax
1833
        jnz     .next_socket
1159 hidnplayr 1834
 
1514 hidnplayr 1835
  .done:
2402 hidnplayr 1836
        mov     eax, ebx
1837
        test    eax, eax
1838
        pop     ebx
1514 hidnplayr 1839
 
2402 hidnplayr 1840
        ret
1159 hidnplayr 1841
 
1514 hidnplayr 1842
 
1843
 
1844
;---------------------------------------------------
1845
;
1846
; SOCKET_check_owner
1847
;
1848
; checks if the caller application owns the socket
1849
;
1850
; IN:  eax = socket ptr
1851
; OUT:  ZF = true/false
1852
;
1853
;---------------------------------------------------
1854
align 4
1855
SOCKET_check_owner:
1856
 
2402 hidnplayr 1857
        DEBUGF  1,"SOCKET_check_owner: %x\n", eax
1514 hidnplayr 1858
 
2402 hidnplayr 1859
        push    ebx
1860
        mov     ebx, [TASK_BASE]
1861
        mov     ebx, [ecx + TASKDATA.pid]
1862
        cmp     [eax + SOCKET.PID], ebx
1863
        pop      ebx
1514 hidnplayr 1864
 
2402 hidnplayr 1865
        ret
1514 hidnplayr 1866
 
1867
 
1868
 
1869
 
1885 hidnplayr 1870
;------------------------------------------------------
1514 hidnplayr 1871
;
1872
; SOCKET_process_end
1873
;
1874
; Kernel calls this function when a certain process ends
1875
; This function will check if the process had any open sockets
1876
; And update them accordingly
1877
;
2867 hidnplayr 1878
; IN:  edx = pid
1514 hidnplayr 1879
; OUT: /
1880
;
1881
;------------------------------------------------------
1882
align 4
1883
SOCKET_process_end:
1884
 
2867 hidnplayr 1885
        DEBUGF  1,"SOCKET_process_end: %x\n", edx
1514 hidnplayr 1886
 
2402 hidnplayr 1887
        push    ebx
1888
        mov     ebx, net_sockets
1514 hidnplayr 1889
 
1890
  .next_socket:
2402 hidnplayr 1891
        mov     ebx, [ebx + SOCKET.NextPtr]
1514 hidnplayr 1892
  .test_socket:
2402 hidnplayr 1893
        test    ebx, ebx
1894
        jz      .done
1514 hidnplayr 1895
 
2867 hidnplayr 1896
        cmp     [ebx + SOCKET.PID], edx
2402 hidnplayr 1897
        jne     .next_socket
1514 hidnplayr 1898
 
2891 hidnplayr 1899
        DEBUGF  1,"SOCKET_process_end: killing socket %x\n", ebx
1514 hidnplayr 1900
 
2402 hidnplayr 1901
        mov     [ebx + SOCKET.PID], 0
1514 hidnplayr 1902
 
2402 hidnplayr 1903
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
1904
        je      .tcp
1514 hidnplayr 1905
 
2629 hidnplayr 1906
; The socket is stateless, just kill it right away!
1514 hidnplayr 1907
 
2402 hidnplayr 1908
        mov     eax, ebx
1909
        mov     ebx, [ebx + SOCKET.NextPtr]
1910
        call    SOCKET_free
1911
        jmp     .test_socket
1514 hidnplayr 1912
 
1913
  .tcp:
2629 hidnplayr 1914
        push    [ebx + SOCKET.NextPtr]
1915
        mov     eax, ebx
2869 hidnplayr 1916
        call    TCP_disconnect
2629 hidnplayr 1917
        pop     ebx
1918
        jmp     .test_socket
1885 hidnplayr 1919
 
1514 hidnplayr 1920
  .done:
2402 hidnplayr 1921
        pop     ebx
1514 hidnplayr 1922
 
2402 hidnplayr 1923
        ret
1773 hidnplayr 1924
 
1925
 
1926
 
1927
 
1885 hidnplayr 1928
;-----------------------------------------------------------------
1929
;
1930
; SOCKET_is_connecting
1931
;
1932
;  IN:  eax = socket ptr
1933
;  OUT: /
1934
;
1935
;-----------------------------------------------------------------
1773 hidnplayr 1936
 
1885 hidnplayr 1937
align 4
1938
SOCKET_is_connecting:
1773 hidnplayr 1939
 
2891 hidnplayr 1940
        DEBUGF  1,"SOCKET_is_connecting: %x\n", eax
1773 hidnplayr 1941
 
2402 hidnplayr 1942
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
1943
        or      [eax + SOCKET.options], SS_ISCONNECTING
1773 hidnplayr 1944
 
2402 hidnplayr 1945
        jmp     SOCKET_notify_owner
1885 hidnplayr 1946
 
1947
 
1948
 
1773 hidnplayr 1949
;-----------------------------------------------------------------
1950
;
1885 hidnplayr 1951
; SOCKET_is_connected
1952
;
1953
;  IN:  eax = socket ptr
1954
;  OUT: /
1955
;
1956
;-----------------------------------------------------------------
1957
 
1958
align 4
1959
SOCKET_is_connected:
1960
 
2891 hidnplayr 1961
        DEBUGF  1,"SOCKET_is_connected: %x\n", eax
1885 hidnplayr 1962
 
2402 hidnplayr 1963
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
1964
        or      [eax + SOCKET.options], SS_ISCONNECTED
1885 hidnplayr 1965
 
2402 hidnplayr 1966
        jmp     SOCKET_notify_owner
1885 hidnplayr 1967
 
1968
 
1969
 
1970
 
1971
;-----------------------------------------------------------------
1972
;
1773 hidnplayr 1973
; SOCKET_is_disconnecting
1974
;
1975
;  IN:  eax = socket ptr
1976
;  OUT: /
1977
;
1978
;-----------------------------------------------------------------
1979
 
1980
align 4
1981
SOCKET_is_disconnecting:
1982
 
2891 hidnplayr 1983
        DEBUGF  1,"SOCKET_is_disconnecting: %x\n", eax
1984
 
2402 hidnplayr 1985
        and     [eax + SOCKET.options], not (SS_ISCONNECTING)
1986
        or      [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
1773 hidnplayr 1987
 
2402 hidnplayr 1988
        jmp     SOCKET_notify_owner
1773 hidnplayr 1989
 
1990
 
1991
 
1992
;-----------------------------------------------------------------
1993
;
1994
; SOCKET_is_disconnected
1995
;
1996
;  IN:  eax = socket ptr
1997
;  OUT: /
1998
;
1999
;-----------------------------------------------------------------
2000
 
2001
align 4
2002
SOCKET_is_disconnected:
2003
 
2891 hidnplayr 2004
        DEBUGF  1,"SOCKET_is_disconnected: %x\n", eax
2005
 
2402 hidnplayr 2006
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2007
        or      [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
1773 hidnplayr 2008
 
2402 hidnplayr 2009
        jmp     SOCKET_notify_owner
1774 hidnplayr 2010
 
2011
 
2012
;-----------------------------------------------------------------
2013
;
2014
; SOCKET_cant_recv_more
2015
;
2016
;  IN:  eax = socket ptr
2017
;  OUT: /
2018
;
2019
;-----------------------------------------------------------------
2020
 
2021
align 4
2022
SOCKET_cant_recv_more:
2023
 
2891 hidnplayr 2024
        DEBUGF  1,"SOCKET_cant_recv_more: %x\n", eax
2025
 
2402 hidnplayr 2026
        or      [eax + SOCKET.options], SS_CANTRCVMORE
1885 hidnplayr 2027
 
2402 hidnplayr 2028
        ret
1831 hidnplayr 2029
 
2030
 
2031
 
2032
;-----------------------------------------------------------------
2033
;
1885 hidnplayr 2034
; SOCKET_cant_send_more
1831 hidnplayr 2035
;
2036
;  IN:  eax = socket ptr
2037
;  OUT: /
2038
;
2039
;-----------------------------------------------------------------
2040
 
2041
align 4
1885 hidnplayr 2042
SOCKET_cant_send_more:
1831 hidnplayr 2043
 
2891 hidnplayr 2044
        DEBUGF  1,"SOCKET_cant_send_more: %x\n", eax
2045
 
2402 hidnplayr 2046
        or      [eax + SOCKET.options], SS_CANTSENDMORE
1831 hidnplayr 2047
 
2402 hidnplayr 2048
        ret