Subversion Repositories Kolibri OS

Rev

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

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