Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2016. 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: 6476 $
  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.  
  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.         bytes_tx        dq ?    ; Statistics, updated by the driver
  182.         bytes_rx        dq ?    ;
  183.         packets_tx      dd ?    ;
  184.         packets_rx      dd ?    ;
  185.  
  186.         link_state      dd ?    ; link state (0 = no link)
  187.         hwacc           dd ?    ; bitmask stating enabled HW accelerations (offload engines)
  188.  
  189. ends
  190.  
  191. struct  NET_BUFF
  192.  
  193.         NextPtr         dd ?    ; pointer to next frame in list
  194.         PrevPtr         dd ?    ; pointer to previous frame in list
  195.         device          dd ?    ; ptr to NET_DEVICE structure
  196.         type            dd ?    ; encapsulation type: e.g. Ethernet
  197.         length          dd ?    ; size of encapsulated data
  198.         offset          dd ?    ; offset to actual data (24 bytes for default frame)
  199.         data            rb 0
  200.  
  201. ends
  202.  
  203.  
  204. ; Exactly as it says..
  205. macro pseudo_random reg {
  206.         add     reg, [esp]
  207.         rol     reg, 5
  208.         xor     reg, [timer_ticks]
  209. ;        add     reg, [CPU_FREQ]
  210.         imul    reg, 214013
  211.         xor     reg, 0xdeadbeef
  212.         rol     reg, 9
  213. }
  214.  
  215. ; Network to Hardware byte order (dword)
  216. macro ntohd reg {
  217.  
  218.         rol     word reg, 8
  219.         rol     dword reg, 16
  220.         rol     word reg , 8
  221.  
  222. }
  223.  
  224. ; Network to Hardware byte order (word)
  225. macro ntohw reg {
  226.  
  227.         rol     word reg, 8
  228.  
  229. }
  230.  
  231.  
  232. include "queue.inc"
  233.  
  234. include "loopback.inc"
  235. include "ethernet.inc"
  236.  
  237. include "PPPoE.inc"
  238.  
  239. include "ARP.inc"
  240. include "IPv4.inc"
  241. include "IPv6.inc"
  242.  
  243. include "icmp.inc"
  244. include "udp.inc"
  245. include "tcp.inc"
  246.  
  247. include "socket.inc"
  248.  
  249.  
  250.  
  251. uglobal
  252. align 4
  253.  
  254.         NET_RUNNING     dd ?
  255.         NET_DRV_LIST    rd NET_DEVICES_MAX
  256.  
  257.         NET_BUFFS_FREE  rd NET_BUFFERS
  258.         .current        dd ?
  259.  
  260. endg
  261.  
  262.  
  263. ;-----------------------------------------------------------------;
  264. ;                                                                 ;
  265. ; stack_init: Initialize all network variables                    ;
  266. ;                                                                 ;
  267. ;  IN:  /                                                         ;
  268. ;  OUT: /                                                         ;
  269. ;                                                                 ;
  270. ;-----------------------------------------------------------------;
  271. align 4
  272. stack_init:
  273.  
  274. ; allocate network buffers
  275.         stdcall kernel_alloc, NET_BUFFER_SIZE*NET_BUFFERS
  276.         test    eax, eax
  277.         jz      .fail
  278.  
  279.         mov     edi, NET_BUFFS_FREE
  280.         mov     ecx, NET_BUFFERS
  281.         cld
  282.   .loop:
  283.         stosd
  284.         add     eax, NET_BUFFER_SIZE
  285.         dec     ecx
  286.         jnz     .loop
  287.  
  288.         mov     eax, NET_BUFFS_FREE
  289.         stosd
  290.  
  291. ; Init the network drivers list
  292.         xor     eax, eax
  293.         mov     edi, NET_RUNNING
  294.         mov     ecx, (NET_DEVICES_MAX + 1)
  295.         rep stosd
  296.  
  297.         eth_init
  298.  
  299.         pppoe_init
  300.  
  301.         ipv4_init
  302. ;        ipv6_init
  303.         icmp_init
  304.  
  305.         arp_init
  306.         udp_init
  307.         tcp_init
  308.  
  309.         socket_init
  310.  
  311.         loop_init
  312.  
  313.         mov     [net_tmr_count], 0
  314.         ret
  315.  
  316.   .fail:
  317.         DEBUGF  DEBUG_NETWORK_ERROR, "Stack init failed!\n"
  318.         ret
  319.  
  320.  
  321.  
  322. ; Wakeup every tick.
  323. proc stack_handler_has_work?
  324.  
  325.         mov     eax, [timer_ticks]
  326.         cmp     eax, [net_10ms]
  327.  
  328.         ret
  329. endp
  330.  
  331.  
  332. ;-----------------------------------------------------------------;
  333. ;                                                                 ;
  334. ; stack_handler: Network handlers called from os_loop.            ;
  335. ;                                                                 ;
  336. ;  IN:  /                                                         ;
  337. ;  OUT: /                                                         ;
  338. ;                                                                 ;
  339. ;-----------------------------------------------------------------;
  340. align 4
  341. stack_handler:
  342.  
  343.         ; Test for 10ms tick
  344.         mov     eax, [timer_ticks]
  345.         cmp     eax, [net_10ms]
  346.         je      .exit
  347.         mov     [net_10ms], eax
  348.  
  349.         cmp     [NET_RUNNING], 0
  350.         je      .exit
  351.  
  352.         test    [net_10ms], 0x0f        ; 160ms
  353.         jnz     .exit
  354.  
  355.         tcp_timer_160ms
  356.  
  357.         test    [net_10ms], 0x3f        ; 640ms
  358.         jnz     .exit
  359.  
  360.         arp_decrease_entry_ttls
  361.         ipv4_decrease_fragment_ttls
  362.  
  363.         xor     edx, edx
  364.         mov     eax, [TCP_timer1_event]
  365.         mov     ebx, [eax + EVENT.id]
  366.         xor     esi, esi
  367.         call    raise_event
  368.  
  369.   .exit:
  370.         ret
  371.  
  372.  
  373. align 4
  374. proc net_buff_alloc stdcall, buffersize
  375.  
  376.         cmp     [buffersize], NET_BUFFER_SIZE
  377.         ja      .too_large
  378.  
  379.         spin_lock_irqsave
  380.  
  381.         mov     eax, [NET_BUFFS_FREE.current]
  382.         cmp     eax, NET_BUFFS_FREE+NET_BUFFERS*4
  383.         jae     .out_of_mem
  384.         mov     eax, [eax]
  385.         add     [NET_BUFFS_FREE.current], 4
  386.  
  387.         spin_unlock_irqrestore
  388.  
  389.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_buff_alloc: 0x%x\n", eax
  390.         ret
  391.  
  392.   .out_of_mem:
  393.         spin_unlock_irqrestore
  394.  
  395.         xor     eax, eax
  396.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_alloc: out of mem!\n"
  397.         ret
  398.  
  399.   .too_large:
  400.         xor     eax, eax
  401.         DEBUGF  DEBUG_NETWORK_ERROR, "net_buff_alloc: too large!\n"
  402.         ret
  403. endp
  404.  
  405.  
  406. align 4
  407. proc net_buff_free stdcall, buffer
  408.  
  409.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_buff_free: 0x%x\n", [buffer]
  410.  
  411.         spin_lock_irqsave
  412.  
  413.         sub     [NET_BUFFS_FREE.current], 4
  414.         mov     eax, [NET_BUFFS_FREE.current]
  415.         push    [buffer]
  416.         pop     dword[eax]
  417.  
  418.         spin_unlock_irqrestore
  419.  
  420.         ret
  421. endp
  422.  
  423.  
  424. align 4
  425. net_link_changed:
  426.  
  427.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.link_state]
  428.  
  429. align 4
  430. net_send_event:
  431.  
  432.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_send_event\n"
  433.  
  434. ; Send event to all applications
  435.         push    edi ecx
  436.         mov     edi, SLOT_BASE
  437.         mov     ecx, [TASK_COUNT]
  438.   .loop:
  439.         add     edi, 256
  440.         or      [edi + APPDATA.event_mask], EVENT_NETWORK2
  441.         loop    .loop
  442.         pop     ecx edi
  443.  
  444.         ret
  445.  
  446.  
  447.  
  448. ;-----------------------------------------------------------------;
  449. ;                                                                 ;
  450. ; net_add_device: Called by network driver to register interface. ;
  451. ;                                                                 ;
  452. ;  IN:  ebx = ptr to device structure                             ;
  453. ;                                                                 ;
  454. ;  OUT: eax = device num on success                               ;
  455. ;       eax = -1 on error                                         ;
  456. ;                                                                 ;
  457. ;-----------------------------------------------------------------;
  458. align 4
  459. net_add_device:
  460.  
  461.         DEBUGF  DEBUG_NETWORK_VERBOSE, "net_add_device: %x\n", ebx   ;;; TODO: use mutex to lock net device list
  462.  
  463.         cmp     [NET_RUNNING], NET_DEVICES_MAX
  464.         jae     .error
  465.  
  466. ;----------------------------------
  467. ; Check if device is already listed
  468.         mov     eax, ebx
  469.         mov     ecx, NET_DEVICES_MAX    ; We need to check whole list because a device may be removed without re-organizing list
  470.         mov     edi, NET_DRV_LIST
  471.  
  472.         repne scasd                     ; See if device is already in the list
  473.         jz      .error
  474.  
  475. ;----------------------------
  476. ; Find empty slot in the list
  477.         xor     eax, eax
  478.         mov     ecx, NET_DEVICES_MAX
  479.         mov     edi, NET_DRV_LIST
  480.  
  481.         repne scasd
  482.         jnz     .error
  483.  
  484.         sub     edi, 4
  485.  
  486. ;-----------------------------
  487. ; Add device to the found slot
  488.         mov     [edi], ebx              ; add device to list
  489.  
  490.         mov     eax, edi                ; Calculate device number in eax
  491.         sub     eax, NET_DRV_LIST
  492.         shr     eax, 2
  493.  
  494.         inc     [NET_RUNNING]           ; Indicate that one more network device is up and running
  495.  
  496.         call    net_send_event
  497.  
  498.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Device number: %u\n", eax
  499.         ret
  500.  
  501.   .error:
  502.         or      eax, -1
  503.         DEBUGF  DEBUG_NETWORK_ERROR, "Adding network device failed\n"
  504.         ret
  505.  
  506.  
  507.  
  508. ;-----------------------------------------------------------------;
  509. ;                                                                 ;
  510. ; net_remove_device: Called by network driver to unregister dev.  ;
  511. ;                                                                 ;
  512. ;  IN:  ebx = ptr to device                                       ;
  513. ;                                                                 ;
  514. ;  OUT: eax: -1 on error                                          ;
  515. ;                                                                 ;
  516. ;-----------------------------------------------------------------;
  517. align 4
  518. net_remove_device:
  519.  
  520.         cmp     [NET_RUNNING], 0
  521.         je      .error
  522.  
  523. ;----------------------------
  524. ; Find the driver in the list
  525.  
  526.         mov     eax, ebx
  527.         mov     ecx, NET_DEVICES_MAX
  528.         mov     edi, NET_DRV_LIST
  529.  
  530.         repne scasd
  531.         jnz     .error
  532.  
  533. ;------------------------
  534. ; Remove it from the list
  535.  
  536.         xor     eax, eax
  537.         mov     dword [edi-4], eax
  538.         dec     [NET_RUNNING]
  539.  
  540.         call    net_send_event
  541.  
  542.         xor     eax, eax
  543.         ret
  544.  
  545.   .error:
  546.         or      eax, -1
  547.         ret
  548.  
  549.  
  550.  
  551. ;-----------------------------------------------------------------;
  552. ;                                                                 ;
  553. ; net_ptr_to_num                                                  ;
  554. ;                                                                 ;
  555. ;  IN:  ebx = ptr to device struct                                ;
  556. ;                                                                 ;
  557. ;  OUT: edi = device number                                       ;
  558. ;       edi = -1 on error                                         ;
  559. ;                                                                 ;
  560. ;-----------------------------------------------------------------;
  561. align 4
  562. net_ptr_to_num:
  563.  
  564.         call    net_ptr_to_num4
  565.         ror     edi, 2          ; If -1, stay -1
  566.                                 ; valid device numbers have last two bits 0, so do just shr
  567.  
  568.         ret
  569.  
  570. align 4
  571. net_ptr_to_num4:                ; Todo, place number in device structure so we only need to verify?
  572.  
  573.         test    ebx, ebx
  574.         jz      .fail
  575.  
  576.         push    ecx
  577.         mov     ecx, NET_DEVICES_MAX
  578.         mov     edi, NET_DRV_LIST
  579.   .loop:
  580.         cmp     ebx, [edi]
  581.         je      .found
  582.         add     edi, 4
  583.         dec     ecx
  584.         jnz     .loop
  585.  
  586.         pop     ecx
  587.   .fail:
  588.         or      edi, -1
  589.         ret
  590.  
  591.   .found:
  592.         sub     edi, NET_DRV_LIST
  593.         pop     ecx
  594.         ret
  595.  
  596. ;-----------------------------------------------------------------;
  597. ;                                                                 ;
  598. ; checksum_1: Calculate semi-checksum for network packets.        ;
  599. ;                                                                 ;
  600. ;  IN:  edx = start offset for semi-checksum                      ;
  601. ;       esi = pointer to data                                     ;
  602. ;       ecx = data size                                           ;
  603. ;                                                                 ;
  604. ;  OUT: edx = semi-checksum                                       ;
  605. ;                                                                 ;
  606. ;-----------------------------------------------------------------;
  607. align 4
  608. checksum_1:
  609.  
  610.         shr     ecx, 1
  611.         pushf
  612.         jz      .no_2
  613.  
  614.         shr     ecx, 1
  615.         pushf
  616.         jz      .no_4
  617.  
  618.         shr     ecx, 1
  619.         pushf
  620.         jz      .no_8
  621.  
  622.   .loop:
  623.         add     dl, [esi+1]
  624.         adc     dh, [esi+0]
  625.  
  626.         adc     dl, [esi+3]
  627.         adc     dh, [esi+2]
  628.  
  629.         adc     dl, [esi+5]
  630.         adc     dh, [esi+4]
  631.  
  632.         adc     dl, [esi+7]
  633.         adc     dh, [esi+6]
  634.  
  635.         adc     edx, 0
  636.         add     esi, 8
  637.  
  638.         dec     ecx
  639.         jnz     .loop
  640.  
  641.         adc     edx, 0
  642.  
  643.   .no_8:
  644.         popf
  645.         jnc     .no_4
  646.  
  647.         add     dl, [esi+1]
  648.         adc     dh, [esi+0]
  649.  
  650.         adc     dl, [esi+3]
  651.         adc     dh, [esi+2]
  652.  
  653.         adc     edx, 0
  654.         add     esi, 4
  655.  
  656.   .no_4:
  657.         popf
  658.         jnc     .no_2
  659.  
  660.         add     dl, [esi+1]
  661.         adc     dh, [esi+0]
  662.  
  663.         adc     edx, 0
  664.         inc     esi
  665.         inc     esi
  666.  
  667.   .no_2:
  668.         popf
  669.         jnc     .end
  670.  
  671.         add     dh, [esi+0]
  672.         adc     edx, 0
  673.   .end:
  674.         ret
  675.  
  676. ;-----------------------------------------------------------------;
  677. ;                                                                 ;
  678. ; checksum_2: Calculate the final ip/tcp/udp checksum.            ;
  679. ;                                                                 ;
  680. ;   IN: edx = semi-checksum                                       ;
  681. ;                                                                 ;
  682. ;  OUT: dx = checksum (in INET byte order)                        ;
  683. ;                                                                 ;
  684. ;-----------------------------------------------------------------;
  685. align 4
  686. checksum_2:
  687.  
  688.         mov     ecx, edx
  689.         shr     ecx, 16
  690.         and     edx, 0xffff
  691.         add     edx, ecx
  692.  
  693.         mov     ecx, edx
  694.         shr     ecx, 16
  695.         add     dx, cx
  696.         test    dx, dx          ; it seems that ZF is not set when CF is set :(
  697.         not     dx
  698.         jnz     .not_zero
  699.         dec     dx
  700.   .not_zero:
  701.         xchg    dl, dh
  702.  
  703.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Checksum: %x\n", dx
  704.  
  705.         ret
  706.  
  707.  
  708.  
  709. ;-----------------------------------------------------------------;
  710. ;                                                                 ;
  711. ;  System function 74: Low level access to network devices.       ;
  712. ;                                                                 ;
  713. ;-----------------------------------------------------------------;
  714. align 4
  715. sys_network:
  716.  
  717.         cmp     bl, 255
  718.         jne     @f
  719.  
  720.         mov     eax, [NET_RUNNING]
  721.         mov     [esp+32], eax
  722.         ret
  723.  
  724.    @@:
  725.         cmp     bh, NET_DEVICES_MAX             ; Check if device number exists
  726.         jae     .doesnt_exist
  727.  
  728.         mov     esi, ebx
  729.         and     esi, 0x0000ff00
  730.         shr     esi, 6
  731.  
  732.         cmp     dword[esi + NET_DRV_LIST], 0    ; check if driver is running
  733.         je      .doesnt_exist
  734.  
  735.         mov     eax, [esi + NET_DRV_LIST]
  736.  
  737.         and     ebx, 0x000000ff
  738.         cmp     ebx, .number
  739.         ja      .doesnt_exist
  740.         jmp     dword [.table + 4*ebx]
  741.  
  742.   .table:
  743.         dd      .get_type               ; 0
  744.         dd      .get_dev_name           ; 1
  745.         dd      .reset                  ; 2
  746.         dd      .stop                   ; 3
  747.         dd      .get_ptr                ; 4
  748.         dd      .get_drv_name           ; 5
  749.  
  750.         dd      .packets_tx             ; 6
  751.         dd      .packets_rx             ; 7
  752.         dd      .bytes_tx               ; 8
  753.         dd      .bytes_rx               ; 9
  754.         dd      .state                  ; 10
  755.   .number = ($ - .table) / 4 - 1
  756.  
  757.   .get_type:
  758.         mov     eax, [eax + NET_DEVICE.device_type]
  759.         mov     [esp+32], eax
  760.         ret
  761.  
  762.   .get_dev_name:
  763.         mov     esi, [eax + NET_DEVICE.name]
  764.         mov     edi, ecx
  765.  
  766.         mov     ecx, 64/4 ; max length
  767.         rep movsd
  768.  
  769.         xor     eax, eax
  770.         mov     [esp+32], eax
  771.         ret
  772.  
  773.   .reset:
  774.         call    [eax + NET_DEVICE.reset]
  775.         mov     [esp+32], eax
  776.         ret
  777.  
  778.   .stop:
  779.         call    [eax + NET_DEVICE.unload]
  780.         mov     [esp+32], eax
  781.         ret
  782.  
  783.  
  784.   .get_ptr:
  785.         mov     [esp+32], eax
  786.         ret
  787.  
  788.  
  789.   .get_drv_name:
  790.         xor     eax, eax
  791.         mov     [esp+32], eax
  792.         ret
  793.  
  794.   .packets_tx:
  795.         mov     eax, [eax + NET_DEVICE.packets_tx]
  796.         mov     [esp+32], eax
  797.         ret
  798.  
  799.   .packets_rx:
  800.         mov     eax, [eax + NET_DEVICE.packets_rx]
  801.         mov     [esp+32], eax
  802.         ret
  803.  
  804.   .bytes_tx:
  805.         mov     ebx, dword[eax + NET_DEVICE.bytes_tx + 4]
  806.         mov     [esp+20], ebx
  807.         mov     eax, dword[eax + NET_DEVICE.bytes_tx]
  808.         mov     [esp+32], eax
  809.         ret
  810.  
  811.   .bytes_rx:
  812.         mov     ebx, dword[eax + NET_DEVICE.bytes_rx + 4]
  813.         mov     [esp+20], ebx
  814.         mov     eax, dword[eax + NET_DEVICE.bytes_rx]
  815.         mov     [esp+32], eax
  816.         ret
  817.  
  818.   .state:
  819.         mov     eax, [eax + NET_DEVICE.link_state]
  820.         mov     [esp+32], eax
  821.         ret
  822.  
  823.  
  824.   .doesnt_exist:
  825.         mov     dword[esp+32], -1
  826.         ret
  827.  
  828.  
  829.  
  830. ;-----------------------------------------------------------------;
  831. ;                                                                 ;
  832. ;  System function 76: Low level access to protocol handlers.     ;
  833. ;                                                                 ;
  834. ;-----------------------------------------------------------------;
  835. align 4
  836. sys_protocols:
  837.         cmp     bh, NET_DEVICES_MAX             ; Check if device number exists
  838.         jae     .doesnt_exist
  839.  
  840.         mov     esi, ebx
  841.         and     esi, 0x0000ff00
  842.         shr     esi, 6                          ; now we have the device num * 4 in esi
  843.         cmp     [esi + NET_DRV_LIST], 0         ; check if driver is running
  844.         je      .doesnt_exist
  845.  
  846.         push    .return                         ; return address (we will be using jumps instead of calls)
  847.  
  848.         mov     eax, ebx                        ; set ax to protocol number
  849.         shr     eax, 16                         ;
  850.  
  851.         cmp     ax, API_ETH
  852.         je      eth_api
  853.  
  854.         cmp     ax, API_IPv4
  855.         je      ipv4_api
  856.  
  857.         cmp     ax, API_ICMP
  858.         je      icmp_api
  859.  
  860.         cmp     ax, API_UDP
  861.         je      udp_api
  862.  
  863.         cmp     ax, API_TCP
  864.         je      tcp_api
  865.  
  866.         cmp     ax, API_ARP
  867.         je      arp_api
  868.  
  869.         cmp     ax, API_PPPOE
  870.         je      pppoe_api
  871.  
  872.         cmp     ax, API_IPv6
  873.         je      ipv6_api
  874.  
  875.         add     esp, 4                           ; if we reached here, no function was called, so we need to balance stack
  876.  
  877.   .doesnt_exist:
  878.         mov     eax, -1
  879.  
  880.   .return:
  881.         mov     [esp+28+4], eax                 ; return eax value to the program
  882.         ret
  883.