Subversion Repositories Kolibri OS

Rev

Rev 1185 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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