Subversion Repositories Kolibri OS

Rev

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

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