Subversion Repositories Kolibri OS

Rev

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