Subversion Repositories Kolibri OS

Rev

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