Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  STACK.INC                                                      ;;
  7. ;;                                                                 ;;
  8. ;;  TCP/IP stack for KolibriOS                                     ;;
  9. ;;                                                                 ;;
  10. ;;    Written by hidnplayr@kolibrios.org                           ;;
  11. ;;                                                                 ;;
  12. ;;     Some parts of code are based on the work of:                ;;
  13. ;;      Mike Hibbett (menuetos network stack)                      ;;
  14. ;;      Eugen Brasoveanu (solar os network stack and drivers)      ;;
  15. ;;      mike.dld (kolibrios socket code)                           ;;
  16. ;;                                                                 ;;
  17. ;;     TCP part is based on 4.4BSD                                 ;;
  18. ;;                                                                 ;;
  19. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  20. ;;             Version 2, June 1991                                ;;
  21. ;;                                                                 ;;
  22. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  23.  
  24. $Revision: 3257 $
  25.  
  26. uglobal
  27.         net_10ms        dd ?
  28.         net_tmr_count   dw ?
  29. endg
  30.  
  31. MAX_NET_DEVICES         = 16
  32.  
  33. MIN_EPHEMERAL_PORT      = 49152
  34. MIN_EPHEMERAL_PORT_N    = 0x00C0        ; same in Network byte order (FIXME)
  35. MAX_EPHEMERAL_PORT      = 61000
  36. MAX_EPHEMERAL_PORT_N    = 0x48EE        ; same in Network byte order (FIXME)
  37.  
  38. ; Ethernet protocol numbers
  39. ETHER_ARP               = 0x0608
  40. ETHER_IPv4              = 0x0008
  41. ETHER_IPv6              = 0xDD86
  42. ETHER_PPP_DISCOVERY     = 0x6388
  43. ETHER_PPP_SESSION       = 0x6488
  44.  
  45. ; PPP protocol numbers
  46. PPP_IPv4                = 0x2100
  47. PPP_IPV6                = 0x5780
  48.  
  49. ;Protocol family
  50. AF_UNSPEC               = 0
  51. AF_LOCAL                = 1
  52. AF_INET4                = 2
  53. AF_INET6                = 10
  54. AF_PPP                  = 777
  55.  
  56. ; Internet protocol numbers
  57. IP_PROTO_IP             = 0
  58. IP_PROTO_ICMP           = 1
  59. IP_PROTO_TCP            = 6
  60. IP_PROTO_UDP            = 17
  61.  
  62. ; PPP protocol number
  63. PPP_PROTO_ETHERNET      = 666
  64.  
  65. ; Socket types
  66. SOCK_STREAM             = 1
  67. SOCK_DGRAM              = 2
  68. SOCK_RAW                = 3
  69.  
  70. ; Socket options
  71. SO_ACCEPTCON            = 1 shl 0
  72. SO_BROADCAST            = 1 shl 1
  73. SO_DEBUG                = 1 shl 2
  74. SO_DONTROUTE            = 1 shl 3
  75. SO_KEEPALIVE            = 1 shl 4
  76. SO_OOBINLINE            = 1 shl 5
  77. SO_REUSEADDR            = 1 shl 6
  78. SO_REUSEPORT            = 1 shl 7
  79. SO_USELOOPBACK          = 1 shl 8
  80. SO_BINDTODEVICE         = 1 shl 9
  81.  
  82. SO_BLOCK                = 1 shl 10    ; TO BE REMOVED
  83. SO_NONBLOCK             = 1 shl 31
  84.  
  85. ; Socket level
  86. SOL_SOCKET              = 0
  87.  
  88.  
  89. ; Socket States
  90. SS_NOFDREF              = 0x0001      ; no file table ref any more
  91. SS_ISCONNECTED          = 0x0002      ; socket connected to a peer
  92. SS_ISCONNECTING         = 0x0004      ; in process of connecting to peer
  93. SS_ISDISCONNECTING      = 0x0008      ; in process of disconnecting
  94. SS_CANTSENDMORE         = 0x0010      ; can't send more data to peer
  95. SS_CANTRCVMORE          = 0x0020      ; can't receive more data from peer
  96. SS_RCVATMARK            = 0x0040      ; at mark on input
  97. SS_ISABORTING           = 0x0080      ; aborting fd references - close()
  98. SS_RESTARTSYS           = 0x0100      ; restart blocked system calls
  99. SS_ISDISCONNECTED       = 0x0800      ; socket disconnected from peer
  100.  
  101. SS_ASYNC                = 0x0100      ; async i/o notify
  102. SS_ISCONFIRMING         = 0x0200      ; deciding to accept connection req
  103. SS_MORETOCOME           = 0x0400
  104.  
  105. SS_BLOCKED              = 0x8000
  106.  
  107.  
  108. SOCKET_MAXDATA          = 4096*32     ; must be 4096*(power of 2) where 'power of 2' is at least 8
  109.  
  110. ; Network driver types
  111. NET_TYPE_LOOPBACK       = 0
  112. NET_TYPE_ETH            = 1
  113. NET_TYPE_SLIP           = 2
  114.  
  115. MAX_backlog             = 20          ; maximum backlog for stream sockets
  116.  
  117. ; Error Codes
  118. ENOBUFS                 = 55
  119. ECONNREFUSED            = 61
  120. ECONNRESET              = 52
  121. ETIMEDOUT               = 60
  122. ECONNABORTED            = 53
  123.  
  124. ; Api protocol numbers
  125. API_ETH                 = 0
  126. API_IPv4                = 1
  127. API_ICMP                = 2
  128. API_UDP                 = 3
  129. API_TCP                 = 4
  130. API_ARP                 = 5
  131. API_PPPOE               = 6
  132. API_IPv6                = 7
  133.  
  134. HWACC_TCP_IPv4          = 1 shl 0
  135.  
  136. struct  NET_DEVICE
  137.  
  138.         type            dd ?    ; Type field
  139.         mtu             dd ?    ; Maximal Transmission Unit
  140.         name            dd ?    ; Ptr to 0 terminated string
  141.  
  142.         unload          dd ?    ; Ptrs to driver functions
  143.         reset           dd ?    ;
  144.         transmit        dd ?    ;
  145.  
  146.         bytes_tx        dq ?    ; Statistics, updated by the driver
  147.         bytes_rx        dq ?    ;
  148.         packets_tx      dd ?    ;
  149.         packets_rx      dd ?    ;
  150.  
  151. ;       hwacc           dd ?    ; bitmask stating available hardware accelerations (offload engines)
  152.  
  153. ends
  154.  
  155.  
  156. ; Exactly as it says..
  157. macro pseudo_random reg {
  158.         add     reg, [esp]
  159.         rol     reg, 5
  160.         xor     reg, [timer_ticks]
  161.         add     reg, [CPU_FREQ]
  162.         imul    reg, 214013
  163.         xor     reg, 0xdeadbeef
  164.         rol     reg, 9
  165. }
  166.  
  167. ; Network to Hardware byte order (dword)
  168. macro ntohd reg {
  169.  
  170.         rol     word reg, 8
  171.         rol     dword reg, 16
  172.         rol     word reg , 8
  173.  
  174. }
  175.  
  176. ; Network to Hardware byte order (word)
  177. macro ntohw reg {
  178.  
  179.         rol     word reg, 8
  180.  
  181. }
  182.  
  183.  
  184. include "queue.inc"
  185.  
  186. include "loopback.inc"
  187. include "ethernet.inc"
  188.  
  189. include "PPPoE.inc"
  190.  
  191. include "ARP.inc"
  192. include "IPv4.inc"
  193. include "IPv6.inc"
  194.  
  195. include "icmp.inc"
  196. include "udp.inc"
  197. include "tcp.inc"
  198.  
  199. include "socket.inc"
  200.  
  201.  
  202.  
  203. align 4
  204. uglobal
  205.  
  206.         NET_RUNNING     dd  ?
  207.         NET_DEFAULT     dd  ?
  208.         NET_DRV_LIST    rd  MAX_NET_DEVICES
  209.  
  210. endg
  211.  
  212.  
  213. ;-----------------------------------------------------------------
  214. ;
  215. ; stack_init
  216. ;
  217. ;  This function calls all network init procedures
  218. ;
  219. ;  IN:  /
  220. ;  OUT: /
  221. ;
  222. ;-----------------------------------------------------------------
  223. align 4
  224. stack_init:
  225.  
  226. ; Init the network drivers list
  227.         xor     eax, eax
  228.         mov     edi, NET_RUNNING
  229.         mov     ecx, (MAX_NET_DEVICES + 2)
  230.         rep     stosd
  231.  
  232.         PPPoE_init
  233.  
  234.         IPv4_init
  235. ;        IPv6_init
  236.         ICMP_init
  237.  
  238.         ARP_init
  239.         UDP_init
  240.         TCP_init
  241.  
  242.         SOCKET_init
  243.  
  244.         mov     [net_tmr_count], 0
  245.  
  246.         ret
  247.  
  248.  
  249. ;-----------------------------------------------------------------
  250. ;
  251. ; stack_handler
  252. ;
  253. ;  This function is called in kernel loop
  254. ;
  255. ;  IN:  /
  256. ;  OUT: /
  257. ;
  258. ;-----------------------------------------------------------------
  259. align 4
  260. stack_handler:
  261.  
  262.         cmp     [NET_RUNNING], 0
  263.         je      .exit
  264.  
  265.         call    TCP_process_input       ; de-queue TCP ragments and process them
  266.  
  267.         ; Test for 10ms tick
  268.         mov     eax, [timer_ticks]
  269.         cmp     eax, [net_10ms]
  270.         je      .exit
  271.         mov     [net_10ms], eax
  272.  
  273.         test    [net_10ms], 0x0f        ; 160ms
  274.         jnz     .exit
  275.  
  276.         TCP_timer_160ms
  277.  
  278.         test    [net_10ms], 0x3f        ; 640ms
  279.         jnz     .exit
  280.  
  281.         TCP_timer_640ms
  282.         ARP_decrease_entry_ttls
  283.         IPv4_decrease_fragment_ttls
  284.  
  285.   .exit:
  286.         ret
  287.  
  288.  
  289.  
  290. ;-----------------------------------------------------------------
  291. ;
  292. ; NET_add_device:
  293. ;
  294. ;  This function is called by the network drivers,
  295. ;  to register each running NIC to the kernel
  296. ;
  297. ;  IN:  Pointer to device structure in ebx
  298. ;  OUT: Device num in eax, -1 on error
  299. ;
  300. ;-----------------------------------------------------------------
  301. align 4
  302. NET_add_device:
  303.  
  304.         DEBUGF  1,"NET_Add_Device: %x\n", ebx   ;;; TODO: use mutex to lock net device list
  305.  
  306.         mov     eax, [NET_RUNNING]
  307.         cmp     eax, MAX_NET_DEVICES
  308.         jae     .error
  309.  
  310. ;----------------------------------
  311. ; Check if device is already listed
  312.         mov     eax, ebx
  313.         mov     ecx, MAX_NET_DEVICES    ; We need to check whole list because a device may be removed without re-organizing list
  314.         mov     edi, NET_DRV_LIST
  315.  
  316.         repne   scasd                   ; See if device is already in the list
  317.         jz      .error
  318.  
  319. ;----------------------------
  320. ; Find empty slot in the list
  321.         xor     eax, eax
  322.         mov     ecx, MAX_NET_DEVICES
  323.         mov     edi, NET_DRV_LIST
  324.  
  325.         repne   scasd
  326.         jnz     .error
  327.  
  328.         sub     edi, 4
  329.  
  330. ;-----------------------------
  331. ; Add device to the found slot
  332.         mov     [edi], ebx              ; add device to list
  333.  
  334.         mov     eax, edi                ; Calculate device number in eax
  335.         sub     eax, NET_DRV_LIST
  336.         shr     eax, 2
  337.  
  338.         inc     [NET_RUNNING]           ; Indicate that one more network device is up and running
  339.  
  340.         cmp     eax, 1                  ; If it's the first network device, try to set it as default
  341.         jne     @f
  342.         push    eax
  343.         call    NET_set_default
  344.         pop     eax
  345.        @@:
  346.  
  347.         DEBUGF  1,"Device number: %u\n", eax
  348.         ret
  349.  
  350.   .error:
  351.         or      eax, -1
  352.         DEBUGF  2,"Adding network device failed\n"
  353.         ret
  354.  
  355.  
  356.  
  357. ;-----------------------------------------------------------------
  358. ;
  359. ; NET_set_default
  360. ;
  361. ;  API to set the default interface
  362. ;
  363. ;  IN:  Device num in eax
  364. ;  OUT: Device num in eax, -1 on error
  365. ;
  366. ;-----------------------------------------------------------------
  367. align 4
  368. NET_set_default:
  369.  
  370.         DEBUGF  1,"NET_set_default: device=%x\n", eax
  371.  
  372.         cmp     eax, MAX_NET_DEVICES
  373.         jae     .error
  374.  
  375.         cmp     [NET_DRV_LIST+eax*4], 0
  376.         je      .error
  377.  
  378.         mov     [NET_DEFAULT], eax
  379.  
  380.         DEBUGF  1,"NET_set_default: succes\n"
  381.         ret
  382.  
  383.   .error:
  384.         or      eax, -1
  385.         DEBUGF  1,"NET_set_default: failed\n"
  386.         ret
  387.  
  388.  
  389. ;-----------------------------------------------------------------
  390. ;
  391. ; NET_Remove_Device:
  392. ;
  393. ;  This function is called by etwork drivers,
  394. ;  to unregister network devices from the kernel
  395. ;
  396. ;  IN:  Pointer to device structure in ebx
  397. ;  OUT: eax: -1 on error
  398. ;
  399. ;-----------------------------------------------------------------
  400. align 4
  401. NET_remove_device:
  402.  
  403.         cmp     [NET_RUNNING], 0
  404.         je      .error
  405.  
  406.         cmp     [NET_DRV_LIST], ebx
  407.         jne     @f
  408.         mov     [NET_DRV_LIST], 0
  409.         cmp     [NET_RUNNING], 1
  410.         je      @f
  411.         ; there are still active devices, find one and make it default
  412.         xor     eax, eax
  413.         mov     ecx, MAX_NET_DEVICES
  414.         mov     edi, NET_DRV_LIST
  415.         repe    scasd
  416.         je      @f
  417.         shr     edi, 2
  418.         dec     edi
  419.         mov     [NET_DEFAULT], edi
  420.        @@:
  421.  
  422. ;----------------------------
  423. ; Find the driver in the list
  424.  
  425.         mov     eax, ebx
  426.         mov     ecx, MAX_NET_DEVICES
  427.         mov     edi, NET_DRV_LIST+4
  428.  
  429.         repne   scasd
  430.         jnz     .error
  431.  
  432. ;------------------------
  433. ; Remove it from the list
  434.  
  435.         xor     eax, eax
  436.         mov     dword [edi-4], eax
  437.  
  438.         dec     [NET_RUNNING]
  439.         ret
  440.  
  441.   .error:
  442.         or      eax, -1
  443.         ret
  444.  
  445.  
  446.  
  447. ;-----------------------------------------------------------------
  448. ;
  449. ; NET_ptr_to_num
  450. ;
  451. ; IN:  ebx = ptr to device struct
  452. ; OUT: edi = -1 on error, device number otherwise
  453. ;
  454. ;-----------------------------------------------------------------
  455. align 4
  456. NET_ptr_to_num:
  457.         push    ecx
  458.  
  459.         mov     ecx, MAX_NET_DEVICES
  460.         mov     edi, NET_DRV_LIST
  461.  
  462.   .loop:
  463.         cmp     ebx, [edi]
  464.         jz      .found
  465.         add     edi, 4
  466.         dec     ecx
  467.         jnz     .loop
  468.  
  469.         ; repnz  scasd could work too if eax is used instead of ebx!
  470.  
  471.         or      edi, -1
  472.  
  473.         pop     ecx
  474.         ret
  475.  
  476.   .found:
  477.         sub     edi, NET_DRV_LIST
  478.         shr     edi, 2
  479.  
  480.         pop     ecx
  481.         ret
  482.  
  483. ;-----------------------------------------------------------------
  484. ;
  485. ; checksum_1
  486. ;
  487. ;  This is the first of two functions needed to calculate a checksum.
  488. ;
  489. ;  IN:  edx = start offset for semi-checksum
  490. ;       esi = pointer to data
  491. ;       ecx = data size
  492. ;  OUT: edx = semi-checksum
  493. ;
  494. ;
  495. ; Code was optimized by diamond
  496. ;
  497. ;-----------------------------------------------------------------
  498. align 4
  499. checksum_1:
  500.  
  501.         shr     ecx, 1
  502.         pushf
  503.         jz      .no_2
  504.  
  505.         shr     ecx, 1
  506.         pushf
  507.         jz      .no_4
  508.  
  509.         shr     ecx, 1
  510.         pushf
  511.         jz      .no_8
  512.  
  513.   .loop:
  514.         add     dl, [esi+1]
  515.         adc     dh, [esi+0]
  516.  
  517.         adc     dl, [esi+3]
  518.         adc     dh, [esi+2]
  519.  
  520.         adc     dl, [esi+5]
  521.         adc     dh, [esi+4]
  522.  
  523.         adc     dl, [esi+7]
  524.         adc     dh, [esi+6]
  525.  
  526.         adc     edx, 0
  527.         add     esi, 8
  528.  
  529.         dec     ecx
  530.         jnz     .loop
  531.  
  532.         adc     edx, 0
  533.  
  534.   .no_8:
  535.         popf
  536.         jnc     .no_4
  537.  
  538.         add     dl, [esi+1]
  539.         adc     dh, [esi+0]
  540.  
  541.         adc     dl, [esi+3]
  542.         adc     dh, [esi+2]
  543.  
  544.         adc     edx, 0
  545.         add     esi, 4
  546.  
  547.   .no_4:
  548.         popf
  549.         jnc     .no_2
  550.  
  551.         add     dl, [esi+1]
  552.         adc     dh, [esi+0]
  553.  
  554.         adc     edx, 0
  555.         inc     esi
  556.         inc     esi
  557.  
  558.   .no_2:
  559.         popf
  560.         jnc     .end
  561.  
  562.         add     dh, [esi+0]
  563.         adc     edx, 0
  564.   .end:
  565.         ret
  566.  
  567. ;-----------------------------------------------------------------
  568. ;
  569. ; checksum_2
  570. ;
  571. ;  This function calculates the final ip/tcp/udp checksum for you
  572. ;
  573. ;  IN:  edx = semi-checksum
  574. ;  OUT: dx = checksum (in INET byte order)
  575. ;
  576. ;-----------------------------------------------------------------
  577. align 4
  578. checksum_2:
  579.  
  580.         mov     ecx, edx
  581.         shr     ecx, 16
  582.         and     edx, 0xffff
  583.         add     edx, ecx
  584.  
  585.         mov     ecx, edx
  586.         shr     ecx, 16
  587.         add     dx, cx
  588.         test    dx, dx          ; it seems that ZF is not set when CF is set :(
  589.         not     dx
  590.         jnz     .not_zero
  591.         dec     dx
  592.   .not_zero:
  593.         xchg    dl, dh
  594.  
  595.         DEBUGF  1,"Checksum: %x\n", dx
  596.  
  597.         ret
  598.  
  599.  
  600.  
  601. ;----------------------------------------------------------------
  602. ;
  603. ;  System function to work with network devices (75)
  604. ;
  605. ;----------------------------------------------------------------
  606. align 4
  607. sys_network:                    ; FIXME: make default device easily accessible
  608.  
  609.         cmp     ebx, -1
  610.         jne     @f
  611.  
  612.         mov     eax, [NET_RUNNING]
  613.         jmp     .return
  614.  
  615.    @@:
  616.         cmp     bh, MAX_NET_DEVICES             ; Check if device number exists
  617.         jae     .doesnt_exist
  618.  
  619.         mov     esi, ebx
  620.         and     esi, 0x0000ff00
  621.         shr     esi, 6
  622.  
  623.         cmp     dword [esi + NET_DRV_LIST], 0   ; check if driver is running
  624.         je      .doesnt_exist
  625.  
  626.         mov     eax, [esi + NET_DRV_LIST]
  627.  
  628.         and     ebx, 0x000000ff
  629.         cmp     ebx, .number
  630.         ja      .doesnt_exist
  631.         jmp     dword [.table + 4*ebx]
  632.  
  633.   .table:
  634.         dd      .get_type               ; 0
  635.         dd      .get_dev_name           ; 1
  636.         dd      .reset                  ; 2
  637.         dd      .stop                   ; 3
  638.         dd      .get_ptr                ; 4
  639.         dd      .get_drv_name           ; 5
  640.         dd      .set_default            ; 6
  641.   .number = ($ - .table) / 4 - 1
  642.  
  643.   .get_type:                            ; 0 = Get device type (ethernet/token ring/...)
  644.  
  645.         mov     eax, [eax + NET_DEVICE.type]
  646.         jmp     .return
  647.  
  648.  
  649.   .get_dev_name:                        ; 1 = Get device name
  650.  
  651.         mov     esi, [eax + NET_DEVICE.name]
  652.         mov     edi, ecx
  653.  
  654.         mov     ecx, 64/4 ; max length
  655.         rep     movsd
  656.  
  657.         xor     eax, eax
  658.         jmp     .return
  659.  
  660.   .reset:                               ; 2 = Reset the device
  661.  
  662.         call    [eax + NET_DEVICE.reset]
  663.         jmp     .return
  664.  
  665.   .stop:                                ; 3 = Stop driver for this device
  666.  
  667.         call    [eax + NET_DEVICE.unload]
  668.         jmp     .return
  669.  
  670.  
  671.   .get_ptr:                             ; 4 = Get driver pointer
  672.  
  673.         jmp     .return
  674.  
  675.  
  676.   .get_drv_name:                        ; 5 = Get driver name
  677.  
  678.         xor     eax, eax
  679.         jmp     .return
  680.  
  681.  
  682.   .set_default:                         ; 6 = Set default device
  683.  
  684.         call    NET_set_default
  685.         jmp     .return
  686.  
  687.   .doesnt_exist:
  688.         mov     eax, -1
  689.  
  690.   .return:
  691.         mov     [esp+32], eax
  692.         ret
  693.  
  694.  
  695. ;----------------------------------------------------------------
  696. ;
  697. ;  System function to work with protocols  (76)
  698. ;
  699. ;----------------------------------------------------------------
  700. align 4
  701. sys_protocols:
  702.         cmp     bh, MAX_NET_DEVICES             ; Check if device number exists
  703.         jae     .doesnt_exist
  704.  
  705.         mov     esi, ebx
  706.         and     esi, 0x0000ff00
  707.         shr     esi, 6                          ; now we have the device num * 4 in esi
  708.         cmp     [esi + NET_DRV_LIST], 0         ; check if driver is running
  709.         je      .doesnt_exist
  710.  
  711.         push    .return                         ; return address (we will be using jumps instead of calls)
  712.  
  713.         mov     eax, ebx                        ; set ax to protocol number
  714.         shr     eax, 16                         ;
  715.  
  716.         cmp     ax, API_ETH
  717.         je      ETH_api
  718.  
  719.         cmp     ax, API_IPv4
  720.         je      IPv4_api
  721.  
  722.         cmp     ax, API_ICMP
  723.         je      ICMP_api
  724.  
  725.         cmp     ax, API_UDP
  726.         je      UDP_api
  727.  
  728.         cmp     ax, API_TCP
  729.         je      TCP_api
  730.  
  731.         cmp     ax, API_ARP
  732.         je      ARP_api
  733.  
  734.         cmp     ax, API_PPPOE
  735.         je      PPPoE_api
  736.  
  737.         cmp     ax, API_IPv6
  738.         je      IPv6_api
  739.  
  740.         add     esp, 4                           ; if we reached here, no function was called, so we need to balance stack
  741.  
  742.   .doesnt_exist:
  743.         mov     eax, -1
  744.  
  745.   .return:
  746.         mov     [esp+28+4], eax                 ; return eax value to the program
  747.         ret
  748.