Subversion Repositories Kolibri OS

Rev

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

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