Subversion Repositories Kolibri OS

Rev

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