Subversion Repositories Kolibri OS

Rev

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