Subversion Repositories Kolibri OS

Rev

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