Subversion Repositories Kolibri OS

Rev

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