Subversion Repositories Kolibri OS

Rev

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