Subversion Repositories Kolibri OS

Rev

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