Subversion Repositories Kolibri OS

Rev

Rev 9917 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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