Subversion Repositories Kolibri OS

Rev

Rev 9045 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2021. 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: 9049 $
  25.  
  26. uglobal
  27.         net_10ms        dd ?
  28.         net_tmr_count   dw ?
  29. endg
  30.  
  31. DEBUG_NETWORK_ERROR     = 1
  32. DEBUG_NETWORK_VERBOSE   = 0
  33. NETWORK_SANITY_CHECKS   = 1
  34.  
  35. NET_DEVICES_MAX         = 16
  36. NET_BUFFERS             = 512
  37. NET_BUFFER_SIZE         = 2048
  38. ARP_BLOCK               = 1             ; true or false
  39.  
  40. EPHEMERAL_PORT_MIN      = 49152
  41. EPHEMERAL_PORT_MAX      = 61000
  42. MIN_EPHEMERAL_PORT_N    = 0x00C0        ; same in Network byte order (FIXME)
  43. MAX_EPHEMERAL_PORT_N    = 0x48EE        ; same in Network byte order (FIXME)
  44.  
  45. ; Ethernet protocol numbers
  46. ETHER_PROTO_ARP                 = 0x0608
  47. ETHER_PROTO_IPv4                = 0x0008
  48. ETHER_PROTO_IPv6                = 0xDD86
  49. ETHER_PROTO_PPP_DISCOVERY       = 0x6388
  50. ETHER_PROTO_PPP_SESSION         = 0x6488
  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. IP_PROTO_RAW            = 255
  58.  
  59. ; IP options
  60. IP_TOS                  = 1
  61. IP_TTL                  = 2
  62. IP_HDRINCL              = 3
  63.  
  64. ; PPP protocol numbers
  65. PPP_PROTO_IPv4          = 0x2100
  66. PPP_PROTO_IPV6          = 0x5780
  67. PPP_PROTO_ETHERNET      = 666           ; FIXME
  68.  
  69. ;Protocol family
  70. AF_UNSPEC               = 0
  71. AF_LOCAL                = 1
  72. AF_INET4                = 2
  73. AF_INET6                = 10
  74. AF_PPP                  = 777           ; FIXME
  75.  
  76. ; Socket types
  77. SOCK_STREAM             = 1
  78. SOCK_DGRAM              = 2
  79. SOCK_RAW                = 3
  80.  
  81. ; Socket level
  82. SOL_SOCKET              = 0xffff
  83.  
  84. ; Socket options
  85. SO_ACCEPTCON            = 1 shl 0
  86. SO_BROADCAST            = 1 shl 1
  87. SO_DEBUG                = 1 shl 2
  88. SO_DONTROUTE            = 1 shl 3
  89. SO_KEEPALIVE            = 1 shl 4
  90. SO_OOBINLINE            = 1 shl 5
  91. SO_REUSEADDR            = 1 shl 6
  92. SO_REUSEPORT            = 1 shl 7
  93. SO_USELOOPBACK          = 1 shl 8
  94. SO_BINDTODEVICE         = 1 shl 9
  95. SO_LINGER               = 1 shl 10
  96.  
  97. SO_NONBLOCK             = 1 shl 31
  98.  
  99. ; Socket flags for user calls
  100. MSG_PEEK                = 0x02
  101. MSG_DONTWAIT            = 0x40
  102.  
  103. ; Socket States
  104. SS_NOFDREF              = 0x0001        ; no file table ref any more
  105. SS_ISCONNECTED          = 0x0002        ; socket connected to a peer
  106. SS_ISCONNECTING         = 0x0004        ; in process of connecting to peer
  107. SS_ISDISCONNECTING      = 0x0008        ; in process of disconnecting
  108. SS_CANTSENDMORE         = 0x0010        ; can't send more data to peer
  109. SS_CANTRCVMORE          = 0x0020        ; can't receive more data from peer
  110. SS_RCVATMARK            = 0x0040        ; at mark on input
  111. SS_ISABORTING           = 0x0080        ; aborting fd references - close()
  112. SS_RESTARTSYS           = 0x0100        ; restart blocked system calls
  113. SS_ISDISCONNECTED       = 0x0800        ; socket disconnected from peer
  114.  
  115. SS_ASYNC                = 0x1000        ; async i/o notify
  116. SS_ISCONFIRMING         = 0x2000        ; deciding to accept connection req
  117. SS_MORETOCOME           = 0x4000
  118.  
  119. SS_BLOCKED              = 0x8000
  120.  
  121.  
  122. SOCKET_BUFFER_SIZE      = 4096*8        ; must be 4096*(power of 2) where 'power of 2' is at least 8
  123. MAX_backlog             = 20            ; maximum backlog for stream sockets
  124.  
  125. ; Error Codes
  126. ENOBUFS                 = 1
  127. EINPROGRESS             = 2
  128. EOPNOTSUPP              = 4
  129. EWOULDBLOCK             = 6
  130. ENOTCONN                = 9
  131. EALREADY                = 10
  132. EINVAL                  = 11
  133. EMSGSIZE                = 12
  134. ENOMEM                  = 18
  135. EADDRINUSE              = 20
  136. EADDRNOTAVAIL           = 21
  137. ECONNRESET              = 52
  138. ECONNABORTED            = 53
  139. EISCONN                 = 56
  140. ETIMEDOUT               = 60
  141. ECONNREFUSED            = 61
  142.  
  143. ; Api protocol numbers
  144. API_ETH                 = 0
  145. API_IPv4                = 1
  146. API_ICMP                = 2
  147. API_UDP                 = 3
  148. API_TCP                 = 4
  149. API_ARP                 = 5
  150. API_PPPOE               = 6
  151. API_IPv6                = 7
  152.  
  153. ; Network device types
  154. NET_DEVICE_LOOPBACK     = 0
  155. NET_DEVICE_ETH          = 1
  156. NET_DEVICE_SLIP         = 2
  157.  
  158. ; Network link types (link protocols)
  159. NET_LINK_LOOPBACK       = 0
  160. NET_LINK_MAC            = 1     ; Media access control (ethernet, isdn, ...)
  161. NET_LINK_PPP            = 2     ; Point to Point Protocol (PPPoE, ...)
  162. NET_LINK_IEEE802.11     = 3     ; IEEE 802.11 (WiFi)
  163.  
  164. ; Hardware acceleration bits
  165. NET_HWACC_TCP_IPv4_IN   = 1 shl 0
  166. NET_HWACC_TCP_IPv4_OUT  = 1 shl 1
  167.  
  168. ; Network frame types
  169. NET_BUFF_LOOPBACK       = 0
  170. NET_BUFF_ETH            = 1
  171.  
  172. struct  NET_DEVICE
  173.  
  174.         device_type     dd ?    ; Type field
  175.         mtu             dd ?    ; Maximal Transmission Unit
  176.         name            dd ?    ; Ptr to 0 terminated string
  177.  
  178.         unload          dd ?    ; Ptrs to driver functions
  179.         reset           dd ?    ;
  180.         transmit        dd ?    ;
  181.  
  182.         link_state      dd ?    ; link state (0 = no link)
  183.         hwacc           dd ?    ; bitmask stating enabled HW accelerations (offload engines)
  184.  
  185.         bytes_tx        dq ?    ; Statistics, updated by the driver
  186.         bytes_rx        dq ?    ;
  187.  
  188.         packets_tx      dd ?    ;
  189.         packets_tx_err  dd ?    ; CRC errors, too long or too short frames
  190.         packets_tx_drop dd ?    ;
  191.         packets_tx_ovr  dd ?    ; FIFO overrun
  192.  
  193.         packets_rx      dd ?    ;
  194.         packets_rx_err  dd ?    ; CRC errors, too long or too short frames
  195.         packets_rx_drop dd ?    ;
  196.         packets_rx_ovr  dd ?    ; FIFO overrun
  197.  
  198. ends
  199.  
  200. struct  NET_BUFF
  201.  
  202.         NextPtr         dd ?    ; pointer to next frame in list
  203.         PrevPtr         dd ?    ; pointer to previous frame in list
  204.         device          dd ?    ; ptr to NET_DEVICE structure
  205.         type            dd ?    ; encapsulation type: e.g. Ethernet
  206.         length          dd ?    ; size of encapsulated data
  207.         offset          dd ?    ; offset to actual data (24 bytes for default frame)
  208.         data            rb 0
  209.  
  210. ends
  211.  
  212.  
  213. ; Exactly as it says..
  214. macro pseudo_random reg {
  215.         add     reg, [esp]
  216.         rol     reg, 5
  217.         xor     reg, [timer_ticks]
  218. ;        add     reg, [CPU_FREQ]
  219.         imul    reg, 214013
  220.         xor     reg, 0xdeadbeef
  221.         rol     reg, 9
  222. }
  223.  
  224. ; Network to Hardware byte order (dword)
  225. macro ntohd reg {
  226.  
  227.         rol     word reg, 8
  228.         rol     dword reg, 16
  229.         rol     word reg , 8
  230.  
  231. }
  232.  
  233. ; Network to Hardware byte order (word)
  234. macro ntohw reg {
  235.  
  236.         rol     word reg, 8
  237.  
  238. }
  239.  
  240.  
  241. include "queue.inc"
  242.  
  243. include "loopback.inc"
  244. include "ethernet.inc"
  245.  
  246. ;include "PPPoE.inc"
  247.  
  248. include "ARP.inc"
  249. include "IPv4.inc"
  250. ;include "IPv6.inc"
  251.  
  252. include "icmp.inc"
  253. include "udp.inc"
  254. include "tcp.inc"
  255.  
  256. include "socket.inc"
  257.  
  258.  
  259.  
  260. uglobal
  261. align 4
  262.  
  263.         net_device_count        dd ?
  264.         net_device_list         rd NET_DEVICES_MAX
  265.  
  266.         net_buffs_free          rd NET_BUFFERS  ; list of pointers to actual net buffs
  267.         .current                dd ?            ; pointer to current element in net_buffs_free list
  268.  
  269. if defined NETWORK_SANITY_CHECKS
  270.         net_buffs_low           dd ?            ; actual net buff mem region start
  271.         net_buffs_high          dd ?            ; actual net buff mem region stop
  272. end if
  273.  
  274. endg
  275.  
  276.  
  277. ;-----------------------------------------------------------------;
  278. ;                                                                 ;
  279. ; stack_init: Initialize all network variables                    ;
  280. ;                                                                 ;
  281. ;  IN:  /                                                         ;
  282. ;  OUT: /                                                         ;
  283. ;                                                                 ;
  284. ;-----------------------------------------------------------------;
  285. align 4
  286. stack_init:
  287.  
  288. ; allocate network buffers
  289.         stdcall kernel_alloc, NET_BUFFER_SIZE*NET_BUFFERS
  290.         test    eax, eax
  291.         jz      .fail
  292.  
  293. if defined NETWORK_SANITY_CHECKS
  294.         mov     [net_buffs_low], eax
  295. end if
  296.  
  297.         mov     edi, net_buffs_free
  298.         mov     ecx, NET_BUFFERS
  299.         cld
  300.   .loop:
  301.         stosd
  302.         add     eax, NET_BUFFER_SIZE
  303.         dec     ecx
  304.         jnz     .loop
  305.  
  306. if defined NETWORK_SANITY_CHECKS
  307.         sub     eax, NET_BUFFER_SIZE
  308.         mov     [net_buffs_high], eax
  309. end if
  310.  
  311.         mov     eax, net_buffs_free
  312.         stosd
  313.  
  314. ; Init the network drivers list
  315.         xor     eax, eax
  316.         mov     edi, net_device_count
  317.         mov     ecx, (NET_DEVICES_MAX + 1)
  318.         rep stosd
  319.  
  320.         eth_init
  321.  
  322. ;        pppoe_init
  323.  
  324.         ipv4_init
  325. ;        ipv6_init
  326.         icmp_init
  327.  
  328.         arp_init
  329.         udp_init
  330.         tcp_init
  331.  
  332.         socket_init
  333.  
  334.         loop_init
  335.  
  336.         mov     [net_tmr_count], 0
  337.         ret
  338.  
  339.   .fail:
  340.         DEBUGF  DEBUG_NETWORK_ERROR, "Stack init failed!\n"
  341.         ret
  342.  
  343.  
  344.  
  345. ; Wakeup every tick.
  346. proc stack_handler_has_work?
  347.  
  348.         mov     eax, [timer_ticks]
  349.         cmp     eax, [net_10ms]
  350.  
  351.         ret
  352. endp
  353.  
  354.  
  355. ;-----------------------------------------------------------------;
  356. ;                                                                 ;
  357. ; stack_handler: Network handlers called from os_loop.            ;
  358. ;                                                                 ;
  359. ;  IN:  /                                                         ;
  360. ;  OUT: /                                                         ;
  361. ;                                                                 ;
  362. ;-----------------------------------------------------------------;
  363. align 4
  364. stack_handler:
  365.  
  366.         ; Test for 10ms tick
  367.         mov     eax, [timer_ticks]
  368.         cmp     eax, [net_10ms]
  369.         je      .exit
  370.         mov     [net_10ms], eax
  371.  
  372.         cmp     [net_device_count], 0
  373.         je      .exit
  374.  
  375.         test    [net_10ms], 0x0f        ; 160ms
  376.         jnz     .exit
  377.  
  378.         tcp_timer_160ms
  379.  
  380.         test    [net_10ms], 0x3f        ; 640ms
  381.         jnz     .exit
  382.  
  383.         arp_decrease_entry_ttls
  384.         ipv4_decrease_fragment_ttls
  385.  
  386.         xor     edx, edx
  387.         mov     eax, [TCP_timer1_event]
  388.         mov     ebx, [eax + EVENT.id]
  389.         xor     esi, esi
  390.         call    raise_event
  391.  
  392.   .exit:
  393.         ret
  394.  
  395.  
  396. align 4
  397. proc net_buff_alloc stdcall, buffersize
  398.  
  399.         cmp     [buffersize], NET_BUFFER_SIZE
  400.         ja      .too_large
  401.  
  402.         spin_lock_irqsave
  403.  
  404.         mov     eax, [net_buffs_free.current]
  405.         cmp     eax, net_buffs_free+NET_BUFFERS*4
  406.         jae     .out_of_mem
  407.         mov     eax, [eax]
  408.         add     [net_buffs_free.current], 4
  409.  
  410.         spin_unlock_irqrestore
  411.  
  412. if defined NETWORK_SANITY_CHECKS
  413.         cmp     eax, [net_buffs_low]
  414.         cmp     eax, [net_buffs_low]
  415.         jb      .assert_mbuff
  416.         cmp     eax, [net_buffs_high]
  417.         ja      .assert_mbuff
  418.         test    eax, 0x7ff
  419.         jnz     .assert_mbuff
  420. end if
  421.  
  422.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_buff_alloc: 0x%x\n", eax
  423.         ret
  424.  
  425.   .out_of_mem:
  426.         spin_unlock_irqrestore
  427.  
  428.         xor     eax, eax
  429.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_alloc: out of mem!\n"
  430.         ret
  431.  
  432.   .too_large:
  433.         xor     eax, eax
  434.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_alloc: too large!\n"
  435.         ret
  436.  
  437. if defined NETWORK_SANITY_CHECKS
  438.   .assert_mbuff:
  439.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_alloc: invalid buffer 0x%x\n", eax
  440.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_alloc: caller=0x%x\n", [esp+4]
  441.         xor     eax, eax
  442.         ret
  443. end if
  444.  
  445. endp
  446.  
  447.  
  448. align 4
  449. proc net_buff_free stdcall, buffer
  450.  
  451.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_buff_free: 0x%x\n", [buffer]
  452.  
  453. if defined NETWORK_SANITY_CHECKS
  454.         mov     eax, [buffer]
  455.         cmp     eax, [net_buffs_low]
  456.         jb      .assert_mbuff
  457.         cmp     eax, [net_buffs_high]
  458.         ja      .assert_mbuff
  459.         test    eax, 0x7ff
  460.         jnz     .assert_mbuff
  461. end if
  462.  
  463.         spin_lock_irqsave
  464.  
  465.         sub     [net_buffs_free.current], 4             ; move pointer backwards
  466.         mov     eax, [net_buffs_free.current]           ; place free'd buffer pointer on the list
  467.         push    [buffer]
  468.         pop     dword[eax]
  469.  
  470.         spin_unlock_irqrestore
  471.  
  472.         ret
  473.  
  474. if defined NETWORK_SANITY_CHECKS
  475.   .assert_mbuff:
  476.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_free: invalid buffer 0x%x\n", eax
  477.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_free: caller=0x%x\n", [esp+4]
  478.         xor     eax, eax
  479.         ret
  480. end if
  481.  
  482. endp
  483.  
  484.  
  485. align 4
  486. net_link_changed:
  487.  
  488.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.link_state]
  489.  
  490. align 4
  491. net_send_event:
  492.  
  493.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_send_event\n"
  494.  
  495. ; Send event to all applications
  496.         push    edi ecx
  497.         mov     edi, SLOT_BASE
  498.         mov     ecx, [thread_count]
  499.   .loop:
  500.         add     edi, sizeof.APPDATA
  501.         or      [edi + APPDATA.occurred_events], EVENT_NETWORK2
  502.         loop    .loop
  503.         pop     ecx edi
  504.  
  505.         ret
  506.  
  507.  
  508.  
  509. ;-----------------------------------------------------------------;
  510. ;                                                                 ;
  511. ; net_add_device: Called by network driver to register interface. ;
  512. ;                                                                 ;
  513. ;  IN:  ebx = ptr to device structure                             ;
  514. ;                                                                 ;
  515. ;  OUT: eax = device num on success                               ;
  516. ;       eax = -1 on error                                         ;
  517. ;                                                                 ;
  518. ;-----------------------------------------------------------------;
  519. align 4
  520. net_add_device:
  521.  
  522.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_add_device: %x\n", ebx   ;;; TODO: use mutex to lock net device list
  523.  
  524.         cmp     [net_device_count], NET_DEVICES_MAX
  525.         jae     .error
  526.  
  527. ;----------------------------------
  528. ; Check if device is already listed
  529.         mov     eax, ebx
  530.         mov     ecx, NET_DEVICES_MAX    ; We need to check whole list because a device may be removed without re-organizing list
  531.         mov     edi, net_device_list
  532.  
  533.         repne scasd                     ; See if device is already in the list
  534.         jz      .error
  535.  
  536. ;----------------------------
  537. ; Find empty slot in the list
  538.         xor     eax, eax
  539.         mov     ecx, NET_DEVICES_MAX
  540.         mov     edi, net_device_list
  541.  
  542.         repne scasd
  543.         jnz     .error
  544.  
  545.         sub     edi, 4
  546.  
  547. ;-----------------------------
  548. ; Add device to the found slot
  549.         mov     [edi], ebx              ; add device to list
  550.  
  551.         mov     eax, edi                ; Calculate device number in eax
  552.         sub     eax, net_device_list
  553.         shr     eax, 2
  554.  
  555.         inc     [net_device_count]      ; Indicate that one more network device is up and running
  556.  
  557.         call    net_send_event
  558.  
  559.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Device number: %u\n", eax
  560.         ret
  561.  
  562.   .error:
  563.         or      eax, -1
  564.         DEBUGF  DEBUG_NETWORK_ERROR, "Adding network device failed\n"
  565.         ret
  566.  
  567.  
  568.  
  569. ;-----------------------------------------------------------------;
  570. ;                                                                 ;
  571. ; net_remove_device: Called by network driver to unregister dev.  ;
  572. ;                                                                 ;
  573. ;  IN:  ebx = ptr to device                                       ;
  574. ;                                                                 ;
  575. ;  OUT: eax: -1 on error                                          ;
  576. ;                                                                 ;
  577. ;-----------------------------------------------------------------;
  578. align 4
  579. net_remove_device:
  580.  
  581.         cmp     [net_device_count], 0
  582.         je      .error
  583.  
  584. ;----------------------------
  585. ; Find the driver in the list
  586.  
  587.         mov     eax, ebx
  588.         mov     ecx, NET_DEVICES_MAX
  589.         mov     edi, net_device_list
  590.  
  591.         repne scasd
  592.         jnz     .error
  593.  
  594. ;------------------------
  595. ; Remove it from the list
  596.  
  597.         xor     eax, eax
  598.         mov     dword [edi-4], eax
  599.         dec     [net_device_count]
  600.  
  601.         call    net_send_event
  602.  
  603.         xor     eax, eax
  604.         ret
  605.  
  606.   .error:
  607.         or      eax, -1
  608.         ret
  609.  
  610.  
  611.  
  612. ;-----------------------------------------------------------------;
  613. ;                                                                 ;
  614. ; net_ptr_to_num                                                  ;
  615. ;                                                                 ;
  616. ;  IN:  ebx = ptr to device struct                                ;
  617. ;                                                                 ;
  618. ;  OUT: edi = device number                                       ;
  619. ;       edi = -1 on error                                         ;
  620. ;                                                                 ;
  621. ;-----------------------------------------------------------------;
  622. align 4
  623. net_ptr_to_num:
  624.  
  625.         call    net_ptr_to_num4
  626.         ror     edi, 2          ; If -1, stay -1
  627.                                 ; valid device numbers have last two bits 0, so do just shr
  628.  
  629.         ret
  630.  
  631. align 4
  632. net_ptr_to_num4:                ; Todo, place number in device structure so we only need to verify?
  633.  
  634.         test    ebx, ebx
  635.         jz      .fail
  636.  
  637.         push    ecx
  638.         mov     ecx, NET_DEVICES_MAX
  639.         mov     edi, net_device_list
  640.   .loop:
  641.         cmp     ebx, [edi]
  642.         je      .found
  643.         add     edi, 4
  644.         dec     ecx
  645.         jnz     .loop
  646.  
  647.         pop     ecx
  648.   .fail:
  649.         or      edi, -1
  650.         ret
  651.  
  652.   .found:
  653.         sub     edi, net_device_list
  654.         pop     ecx
  655.         ret
  656.  
  657. ;-----------------------------------------------------------------;
  658. ;                                                                 ;
  659. ; checksum_1: Calculate semi-checksum for network packets.        ;
  660. ;                                                                 ;
  661. ;  IN:  edx = start offset for semi-checksum                      ;
  662. ;       esi = pointer to data                                     ;
  663. ;       ecx = data size                                           ;
  664. ;                                                                 ;
  665. ;  OUT: edx = semi-checksum                                       ;
  666. ;                                                                 ;
  667. ;-----------------------------------------------------------------;
  668. align 4
  669. checksum_1:
  670.  
  671.         shr     ecx, 1
  672.         pushf
  673.         jz      .no_2
  674.  
  675.         shr     ecx, 1
  676.         pushf
  677.         jz      .no_4
  678.  
  679.         shr     ecx, 1
  680.         pushf
  681.         jz      .no_8
  682.  
  683.   .loop:
  684.         add     dl, [esi+1]
  685.         adc     dh, [esi+0]
  686.  
  687.         adc     dl, [esi+3]
  688.         adc     dh, [esi+2]
  689.  
  690.         adc     dl, [esi+5]
  691.         adc     dh, [esi+4]
  692.  
  693.         adc     dl, [esi+7]
  694.         adc     dh, [esi+6]
  695.  
  696.         adc     edx, 0
  697.         add     esi, 8
  698.  
  699.         dec     ecx
  700.         jnz     .loop
  701.  
  702.         adc     edx, 0
  703.  
  704.   .no_8:
  705.         popf
  706.         jnc     .no_4
  707.  
  708.         add     dl, [esi+1]
  709.         adc     dh, [esi+0]
  710.  
  711.         adc     dl, [esi+3]
  712.         adc     dh, [esi+2]
  713.  
  714.         adc     edx, 0
  715.         add     esi, 4
  716.  
  717.   .no_4:
  718.         popf
  719.         jnc     .no_2
  720.  
  721.         add     dl, [esi+1]
  722.         adc     dh, [esi+0]
  723.  
  724.         adc     edx, 0
  725.         inc     esi
  726.         inc     esi
  727.  
  728.   .no_2:
  729.         popf
  730.         jnc     .end
  731.  
  732.         add     dh, [esi+0]
  733.         adc     edx, 0
  734.   .end:
  735.         ret
  736.  
  737. ;-----------------------------------------------------------------;
  738. ;                                                                 ;
  739. ; checksum_2: Calculate the final ip/tcp/udp checksum.            ;
  740. ;                                                                 ;
  741. ;   IN: edx = semi-checksum                                       ;
  742. ;                                                                 ;
  743. ;  OUT: dx = checksum (in INET byte order)                        ;
  744. ;                                                                 ;
  745. ;-----------------------------------------------------------------;
  746. align 4
  747. checksum_2:
  748.  
  749.         mov     ecx, edx
  750.         shr     ecx, 16
  751.         and     edx, 0xffff
  752.         add     edx, ecx
  753.  
  754.         mov     ecx, edx
  755.         shr     ecx, 16
  756.         add     dx, cx
  757.         test    dx, dx          ; it seems that ZF is not set when CF is set :(
  758.         not     dx
  759.         jnz     .not_zero
  760.         dec     dx
  761.   .not_zero:
  762.         xchg    dl, dh
  763.  
  764.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Checksum: %x\n", dx
  765.  
  766.         ret
  767.  
  768.  
  769.  
  770. ;-----------------------------------------------------------------;
  771. ;                                                                 ;
  772. ;  System function 74: Low level access to network devices.       ;
  773. ;                                                                 ;
  774. ;-----------------------------------------------------------------;
  775. align 4
  776. sys_network:
  777.  
  778.         cmp     bl, 255
  779.         jne     @f
  780.  
  781.         mov     eax, [net_device_count]
  782.         mov     [esp+32], eax
  783.         ret
  784.  
  785.    @@:
  786.         cmp     bh, NET_DEVICES_MAX                     ; Check if device number exists
  787.         jae     .doesnt_exist
  788.  
  789.         mov     esi, ebx
  790.         and     esi, 0x0000ff00
  791.         shr     esi, 6
  792.  
  793.         cmp     dword[esi + net_device_list], 0         ; check if device is running
  794.         je      .doesnt_exist
  795.  
  796.         mov     eax, [esi + net_device_list]
  797.  
  798.         and     ebx, 0x000000ff
  799.         cmp     ebx, .number
  800.         ja      .doesnt_exist
  801.         jmp     dword [.table + 4*ebx]
  802.  
  803.   .table:
  804.         dd      .get_type               ;  0
  805.         dd      .get_dev_name           ;  1
  806.         dd      .reset                  ;  2
  807.         dd      .stop                   ;  3
  808.         dd      .get_ptr                ;  4
  809.         dd      .get_drv_name           ;  5
  810.  
  811.         dd      .packets_tx             ;  6
  812.         dd      .packets_rx             ;  7
  813.         dd      .bytes_tx               ;  8
  814.         dd      .bytes_rx               ;  9
  815.         dd      .state                  ; 10
  816.         dd      .packets_tx_err         ; 11
  817.         dd      .packets_tx_drop        ; 12
  818.         dd      .packets_tx_ovr         ; 13
  819.         dd      .packets_rx_err         ; 14
  820.         dd      .packets_rx_drop        ; 15
  821.         dd      .packets_rx_ovr         ; 16
  822.  
  823.   .number = ($ - .table) / 4 - 1
  824.  
  825.   .get_type:
  826.         mov     eax, [eax + NET_DEVICE.device_type]
  827.         mov     [esp+32], eax
  828.         ret
  829.  
  830.   .get_dev_name:
  831.         stdcall is_region_userspace, ecx, 64
  832.         jnz     .bad_buffer
  833.         mov     esi, [eax + NET_DEVICE.name]
  834.         mov     edi, ecx
  835.  
  836.         mov     ecx, 64/4 ; max length
  837.         rep movsd
  838.  
  839.         xor     eax, eax
  840.         mov     [esp+32], eax
  841.         ret
  842.  
  843.   .reset:
  844.         call    [eax + NET_DEVICE.reset]
  845.         mov     [esp+32], eax
  846.         ret
  847.  
  848.   .stop:
  849.         call    [eax + NET_DEVICE.unload]
  850.         mov     [esp+32], eax
  851.         ret
  852.  
  853.  
  854.   .get_ptr:
  855.         mov     [esp+32], eax
  856.         ret
  857.  
  858.  
  859.   .get_drv_name:
  860.         xor     eax, eax
  861.         mov     [esp+32], eax
  862.         ret
  863.  
  864.   .packets_tx:
  865.         mov     eax, [eax + NET_DEVICE.packets_tx]
  866.         mov     [esp+32], eax
  867.         ret
  868.  
  869.   .packets_rx:
  870.         mov     eax, [eax + NET_DEVICE.packets_rx]
  871.         mov     [esp+32], eax
  872.         ret
  873.  
  874.   .bytes_tx:
  875.         mov     ebx, dword[eax + NET_DEVICE.bytes_tx + 4]
  876.         mov     [esp+20], ebx
  877.         mov     eax, dword[eax + NET_DEVICE.bytes_tx]
  878.         mov     [esp+32], eax
  879.         ret
  880.  
  881.   .bytes_rx:
  882.         mov     ebx, dword[eax + NET_DEVICE.bytes_rx + 4]
  883.         mov     [esp+20], ebx
  884.         mov     eax, dword[eax + NET_DEVICE.bytes_rx]
  885.         mov     [esp+32], eax
  886.         ret
  887.  
  888.   .packets_tx_err:
  889.         mov     eax, [eax + NET_DEVICE.packets_tx_err]
  890.         mov     [esp+32], eax
  891.         ret
  892.  
  893.   .packets_tx_drop:
  894.         mov     eax, [eax + NET_DEVICE.packets_tx_drop]
  895.         mov     [esp+32], eax
  896.         ret
  897.  
  898.   .packets_tx_ovr:
  899.         mov     eax, [eax + NET_DEVICE.packets_tx_ovr]
  900.         mov     [esp+32], eax
  901.         ret
  902.  
  903.   .packets_rx_err:
  904.         mov     eax, [eax + NET_DEVICE.packets_rx_err]
  905.         mov     [esp+32], eax
  906.         ret
  907.  
  908.   .packets_rx_drop:
  909.         mov     eax, [eax + NET_DEVICE.packets_rx_drop]
  910.         mov     [esp+32], eax
  911.         ret
  912.  
  913.   .packets_rx_ovr:
  914.         mov     eax, [eax + NET_DEVICE.packets_rx_ovr]
  915.         mov     [esp+32], eax
  916.         ret
  917.  
  918.   .state:
  919.         mov     eax, [eax + NET_DEVICE.link_state]
  920.         mov     [esp+32], eax
  921.         ret
  922.  
  923.  
  924.   .doesnt_exist:
  925.   .bad_buffer: ; Sanity check failed, exit
  926.         mov     dword[esp+32], -1
  927.         ret
  928.  
  929.  
  930.  
  931. ;-----------------------------------------------------------------;
  932. ;                                                                 ;
  933. ;  System function 76: Low level access to protocol handlers.     ;
  934. ;                                                                 ;
  935. ;-----------------------------------------------------------------;
  936. align 4
  937. sys_protocols:
  938.         cmp     bh, NET_DEVICES_MAX             ; Check if device number exists
  939.         jae     .doesnt_exist
  940.  
  941.         mov     eax, ebx
  942.         and     eax, 0x0000ff00
  943.         shr     eax, 6                          ; now we have the device num * 4 in eax
  944.         cmp     [eax + net_device_list], 0      ; check if device is running
  945.         je      .doesnt_exist
  946.  
  947.         push    .return                         ; return address (we will be using jumps instead of calls)
  948.  
  949.         mov     eax, ebx                        ; set ax to protocol number
  950.         shr     eax, 16                         ;
  951.  
  952.         cmp     ax, API_ETH
  953.         je      eth_api
  954.  
  955.         cmp     ax, API_IPv4
  956.         je      ipv4_api
  957.  
  958.         cmp     ax, API_ICMP
  959.         je      icmp_api
  960.  
  961.         cmp     ax, API_UDP
  962.         je      udp_api
  963.  
  964.         cmp     ax, API_TCP
  965.         je      tcp_api
  966.  
  967.         cmp     ax, API_ARP
  968.         je      arp_api
  969.  
  970. ;        cmp     ax, API_PPPOE
  971. ;        je      pppoe_api
  972.  
  973. ;        cmp     ax, API_IPv6
  974. ;        je      ipv6_api
  975.  
  976.         add     esp, 4                           ; if we reached here, no function was called, so we need to balance stack
  977.  
  978.   .doesnt_exist:
  979.         mov     eax, -1
  980.  
  981.   .return:
  982.         mov     [esp+28+4], eax                 ; return eax value to the program
  983.         ret
  984.