Subversion Repositories Kolibri OS

Rev

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