Subversion Repositories Kolibri OS

Rev

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