Subversion Repositories Kolibri OS

Rev

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

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