Subversion Repositories Kolibri OS

Rev

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