Subversion Repositories Kolibri OS

Rev

Rev 5565 | Rev 5984 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  ICMP.INC                                                       ;;
  7. ;;                                                                 ;;
  8. ;;  Part of the tcp/ip network stack for KolibriOS                 ;;
  9. ;;                                                                 ;;
  10. ;;  Based on the work of [Johnny_B] and [smb]                      ;;
  11. ;;                                                                 ;;
  12. ;;    Written by hidnplayr@kolibrios.org                           ;;
  13. ;;                                                                 ;;
  14. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  15. ;;             Version 2, June 1991                                ;;
  16. ;;                                                                 ;;
  17. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  18.  
  19. $Revision: 5594 $
  20.  
  21. ; ICMP types & codes
  22.  
  23. ICMP_ECHOREPLY                  = 0               ; echo reply message
  24.  
  25. ICMP_UNREACH                    = 3
  26. ICMP_UNREACH_NET                = 0               ; bad net
  27. ICMP_UNREACH_HOST               = 1               ; bad host
  28. ICMP_UNREACH_PROTOCOL           = 2               ; bad protocol
  29. ICMP_UNREACH_PORT               = 3               ; bad port
  30. ICMP_UNREACH_NEEDFRAG           = 4               ; IP_DF caused drop
  31. ICMP_UNREACH_SRCFAIL            = 5               ; src route failed
  32. ICMP_UNREACH_NET_UNKNOWN        = 6               ; unknown net
  33. ICMP_UNREACH_HOST_UNKNOWN       = 7               ; unknown host
  34. ICMP_UNREACH_ISOLATED           = 8               ; src host isolated
  35. ICMP_UNREACH_NET_PROHIB         = 9               ; prohibited access
  36. ICMP_UNREACH_HOST_PROHIB        = 10              ; ditto
  37. ICMP_UNREACH_TOSNET             = 11              ; bad tos for net
  38. ICMP_UNREACH_TOSHOST            = 12              ; bad tos for host
  39. ICMP_UNREACH_FILTER_PROHIB      = 13              ; admin prohib
  40. ICMP_UNREACH_HOST_PRECEDENCE    = 14              ; host prec vio.
  41. ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15              ; prec cutoff
  42.  
  43. ICMP_SOURCEQUENCH               = 4               ; Packet lost, slow down
  44.  
  45. ICMP_REDIRECT                   = 5               ; shorter route, codes:
  46. ICMP_REDIRECT_NET               = 0               ; for network
  47. ICMP_REDIRECT_HOST              = 1               ; for host
  48. ICMP_REDIRECT_TOSNET            = 2               ; for tos and net
  49. ICMP_REDIRECT_TOSHOST           = 3               ; for tos and host
  50.  
  51. ICMP_ALTHOSTADDR                = 6               ; alternate host address
  52. ICMP_ECHO                       = 8               ; echo service
  53. ICMP_ROUTERADVERT               = 9               ; router advertisement
  54. ICMP_ROUTERADVERT_NORMAL        = 0                  ; normal advertisement
  55. ICMP_ROUTERADVERT_NOROUTE_COMMON= 16         ; selective routing
  56.  
  57. ICMP_ROUTERSOLICIT              = 10              ; router solicitation
  58. ICMP_TIMXCEED                   = 11              ; time exceeded, code:
  59. ICMP_TIMXCEED_INTRANS           = 0               ; ttl==0 in transit
  60. ICMP_TIMXCEED_REASS             = 1               ; ttl==0 in reass
  61.  
  62. ICMP_PARAMPROB                  = 12               ; ip header bad
  63. ICMP_PARAMPROB_ERRATPTR         = 0            ; error at param ptr
  64. ICMP_PARAMPROB_OPTABSENT        = 1            ; req. opt. absent
  65. ICMP_PARAMPROB_LENGTH           = 2            ; bad length
  66.  
  67. ICMP_TSTAMP                     = 13              ; timestamp request
  68. ICMP_TSTAMPREPLY                = 14              ; timestamp reply
  69. ICMP_IREQ                       = 15              ; information request
  70. ICMP_IREQREPLY                  = 16              ; information reply
  71. ICMP_MASKREQ                    = 17              ; address mask request
  72. ICMP_MASKREPLY                  = 18              ; address mask reply
  73. ICMP_TRACEROUTE                 = 30              ; traceroute
  74. ICMP_DATACONVERR                = 31              ; data conversion error
  75. ICMP_MOBILE_REDIRECT            = 32              ; mobile host redirect
  76. ICMP_IPV6_WHEREAREYOU           = 33              ; IPv6 where-are-you
  77. ICMP_IPV6_IAMHERE               = 34              ; IPv6 i-am-here
  78. ICMP_MOBILE_REGREQUEST          = 35              ; mobile registration req
  79. ICMP_MOBILE_REGREPLY            = 36              ; mobile registreation reply
  80. ICMP_SKIP                       = 39              ; SKIP
  81.  
  82. ICMP_PHOTURIS                   = 40              ; Photuris
  83. ICMP_PHOTURIS_UNKNOWN_INDEX     = 1                ; unknown sec index
  84. ICMP_PHOTURIS_AUTH_FAILED       = 2                ; auth failed
  85. ICMP_PHOTURIS_DECRYPT_FAILED    = 3                ; decrypt failed
  86.  
  87.  
  88.  
  89. struct  ICMP_header
  90.  
  91.         Type                    db ?
  92.         Code                    db ?
  93.         Checksum                dw ?
  94.         Identifier              dw ?
  95.         SequenceNumber          dw ?
  96.  
  97. ends
  98.  
  99.  
  100. uglobal
  101. align 4
  102.  
  103.         ICMP_PACKETS_TX         rd NET_DEVICES_MAX
  104.         ICMP_PACKETS_RX         rd NET_DEVICES_MAX
  105.  
  106. endg
  107.  
  108.  
  109.  
  110. ;-----------------------------------------------------------------
  111. ;
  112. ; ICMP_init
  113. ;
  114. ;-----------------------------------------------------------------
  115.  
  116. macro ICMP_init {
  117.  
  118.         xor     eax, eax
  119.         mov     edi, ICMP_PACKETS_TX
  120.         mov     ecx, 2*NET_DEVICES_MAX
  121.         rep stosd
  122.  
  123. }
  124.  
  125.  
  126. ;-----------------------------------------------------------------
  127. ;
  128. ; ICMP_input:
  129. ;
  130. ;  This procedure will send reply's to ICMP echo's
  131. ;   and insert packets into sockets when needed
  132. ;
  133. ;  IN:  Pointer to buffer in [esp]
  134. ;       ebx = pointer to device struct
  135. ;       ecx = ICMP Packet size
  136. ;       esi = ptr to ICMP Packet data
  137. ;       edi = ptr to ipv4 source and dest address
  138. ;
  139. ;  OUT: /
  140. ;
  141. ;-----------------------------------------------------------------
  142. align 4
  143. ICMP_input:
  144.  
  145.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
  146.  
  147. ; Check the checksum
  148.         push    esi ecx
  149.         push    [esi + ICMP_header.Checksum]
  150.         mov     [esi + ICMP_header.Checksum], 0
  151.         xor     edx, edx
  152.         call    checksum_1
  153.         call    checksum_2
  154.         pop     si
  155.         cmp     dx, si
  156.         pop     ecx esi
  157.         jne     .checksum_mismatch
  158.  
  159.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
  160.  
  161. ; Ualidate device ptr
  162.         mov     eax, edi
  163.         call    NET_ptr_to_num4
  164.         cmp     edi, -1
  165.         je      .dump
  166.  
  167. ; Update stats
  168.         inc     [ICMP_PACKETS_RX + edi]
  169.  
  170. ; Is this an echo request?
  171.         cmp     [esi + ICMP_header.Type], ICMP_ECHO
  172.         je      .echo_request
  173.  
  174. ; Look for an open ICMP socket
  175.         pusha
  176.         mov     ecx, socket_mutex
  177.         call    mutex_lock
  178.         popa
  179.  
  180.         mov     edx, [eax]              ; ipv4 source address
  181.         mov     eax, net_sockets
  182.   .try_more:
  183. ;        mov      , [esi + ICMP_header.Identifier]
  184.   .next_socket:
  185.         mov     eax, [eax + SOCKET.NextPtr]
  186.         or      eax, eax
  187.         jz      .dump_
  188.  
  189.         cmp     [eax + SOCKET.Domain], AF_INET4
  190.         jne     .next_socket
  191.  
  192.         cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
  193.         jne     .next_socket
  194.  
  195.         cmp     [eax + IP_SOCKET.RemoteIP], edx
  196.         jne     .next_socket
  197.  
  198. ;        cmp     [eax + ICMP_SOCKET.Identifier],
  199. ;        jne     .next_socket
  200.  
  201.         pusha
  202.         mov     ecx, socket_mutex
  203.         call    mutex_unlock
  204.         popa
  205.  
  206.         DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
  207.  
  208.         pusha
  209.         lea     ecx, [eax + SOCKET.mutex]
  210.         call    mutex_lock
  211.         popa
  212.  
  213.         jmp     SOCKET_input
  214.  
  215.  
  216.  
  217.   .echo_request:
  218.  
  219. ; We'll reuse the packet so we can create the response as fast as possible
  220.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP echo request\n"
  221.  
  222. ; Change Packet type to reply
  223.         mov     [esi + ICMP_header.Type], ICMP_ECHOREPLY
  224.  
  225.         mov     eax, [esp]
  226.         lea     esi, [eax + NET_BUFF.data]
  227.  
  228. ; Check frame type
  229.         cmp     [eax + NET_BUFF.type], NET_BUFF_ETH
  230.         jne     .not_ethernet
  231.  
  232. ; exchange dest and source MAC in ETH header
  233.         push    dword [esi + ETH_header.DstMAC]
  234.         push    dword [esi + ETH_header.SrcMAC]
  235.         pop     dword [esi + ETH_header.DstMAC]
  236.         pop     dword [esi + ETH_header.SrcMAC]
  237.         push    word [esi + ETH_header.DstMAC + 4]
  238.         push    word [esi + ETH_header.SrcMAC + 4]
  239.         pop     word [esi + ETH_header.DstMAC + 4]
  240.         pop     word [esi + ETH_header.SrcMAC + 4]
  241.         add     esi, sizeof.ETH_header
  242.  
  243.   .not_ethernet:
  244. ; Exchange dest and source address in IP header
  245.         push    [esi + IPv4_header.SourceAddress]
  246.         push    [esi + IPv4_header.DestinationAddress]
  247.         pop     [esi + IPv4_header.SourceAddress]
  248.         pop     [esi + IPv4_header.DestinationAddress]
  249.  
  250. ; Calculate IP header length
  251.         movzx   ecx, [esi + IPv4_header.VersionAndIHL]
  252.         and     ecx, 0x0f
  253.         shl     cx, 2
  254.         mov     edi, ecx                        ; put it in edi for later
  255.  
  256. ; Calculate IP checksum
  257.         mov     eax, esi
  258.         mov     [eax + IPv4_header.HeaderChecksum], 0
  259.         xor     edx, edx
  260.         call    checksum_1
  261.         call    checksum_2
  262.         mov     [eax + IPv4_header.HeaderChecksum], dx
  263.  
  264. ; Calculate ICMP packet length
  265.         movzx   ecx, [eax + IPv4_header.TotalLength]
  266.         xchg    ch, cl
  267.         sub     ecx, edi                        ; IP packet length - IP header length = ICMP packet length
  268.  
  269. ; Calculate ICMP checkSum
  270.         mov     eax, esi
  271.         mov     [esi + ICMP_header.Checksum], 0
  272.         xor     edx, edx
  273.         call    checksum_1
  274.         call    checksum_2
  275.         mov     [eax + ICMP_header.Checksum], dx
  276.  
  277. ; Transmit the frame
  278.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmitting reply\n"
  279.         call    [ebx + NET_DEVICE.transmit]
  280.         test    eax, eax
  281.         jnz     @f
  282.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmit failed\n"
  283.         call    NET_ptr_to_num4
  284.         inc     [ICMP_PACKETS_TX + edi]
  285.        @@:
  286.         ret
  287.  
  288.   .dump_:
  289.         pusha
  290.         mov     ecx, socket_mutex
  291.         call    mutex_unlock
  292.         popa
  293.  
  294.         DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
  295.         jmp     .dump
  296.  
  297.   .checksum_mismatch:
  298.         DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
  299.  
  300.   .dump:
  301.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
  302.         call    NET_BUFF_free
  303.         ret
  304.  
  305.  
  306. if 0
  307. ;-----------------------------------------------------------------
  308. ;
  309. ; ICMP_output
  310. ;
  311. ; IN:  eax = dest ip
  312. ;      bh  = type
  313. ;      bl  = code
  314. ;      ecx = data length
  315. ;      edx = source ip
  316. ;      esi = data offset
  317. ;      edi = identifier shl 16 + sequence number
  318. ;
  319. ;-----------------------------------------------------------------
  320. align 4
  321. ICMP_output:
  322.  
  323.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
  324.  
  325.         push    esi edi bx
  326.         add     ecx, sizeof.ICMP_header
  327.         mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
  328.         call    IPv4_output
  329.         jz      .exit
  330.  
  331.         DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
  332.  
  333.         pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
  334.         pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
  335.         mov     [edi + ICMP_header.Checksum], 0
  336.  
  337.         push    ebx ecx edx
  338.         mov     esi, edi
  339.         xor     edx, edx
  340.         call    checksum_1
  341.         call    checksum_2
  342.         mov     [edi + ICMP_header.Checksum], dx
  343.         pop     edx ecx ebx esi
  344.  
  345.         sub     ecx, sizeof.ICMP_header
  346.         add     edi, sizeof.ICMP_header
  347.         push    cx
  348.         shr     cx, 2
  349.         rep movsd
  350.         pop     cx
  351.         and     cx, 3
  352.         rep movsb
  353.  
  354.         sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
  355.         push    edx edi
  356.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  357.         call    [ebx + NET_DEVICE.transmit]
  358.         test    eax, eax
  359.         jnz     @f
  360.         call    NET_ptr_to_num4
  361.         inc     [ICMP_PACKETS_TX + edi]
  362.        @@:
  363.         ret
  364.   .exit:
  365.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  366.         add     esp, 2*4 + 2
  367.         ret
  368. end if
  369.  
  370.  
  371.  
  372.  
  373. ;-----------------------------------------------------------------
  374. ;
  375. ; ICMP_output_raw
  376. ;
  377. ; IN:  eax = socket ptr
  378. ;      ecx = data length
  379. ;      esi = data offset
  380. ;
  381. ;-----------------------------------------------------------------
  382. align 4
  383. ICMP_output_raw:
  384.  
  385.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
  386.  
  387.         push    edx
  388.  
  389.         mov     di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
  390.         mov     edx, [eax + IP_SOCKET.LocalIP]
  391.         mov     ebx, [eax + IP_SOCKET.device]
  392.         mov     eax, [eax + IP_SOCKET.RemoteIP]
  393.         call    IPv4_output
  394.         jz      .exit
  395.  
  396.         pop     esi
  397.         push    eax
  398.  
  399.         push    edi ecx
  400.         DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
  401.         rep movsb
  402.         pop     ecx edi
  403.  
  404.         mov     [edi + ICMP_header.Checksum], 0
  405.  
  406.         mov     esi, edi
  407.         xor     edx, edx
  408.         call    checksum_1
  409.         call    checksum_2
  410.         mov     [edi + ICMP_header.Checksum], dx
  411.  
  412.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  413.         call    [ebx + NET_DEVICE.transmit]
  414.         test    eax, eax
  415.         jnz     @f
  416.         call    NET_ptr_to_num4
  417.         inc     [ICMP_PACKETS_TX + edi]
  418.        @@:
  419.         ret
  420.   .exit:
  421.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  422.         ret
  423.  
  424.  
  425.  
  426.  
  427. ;-----------------------------------------------------------------
  428. ;
  429. ; ICMP_API
  430. ;
  431. ; This function is called by system function 75
  432. ;
  433. ; IN:  subfunction number in bl
  434. ;      device number in bh
  435. ;      ecx, edx, .. depends on subfunction
  436. ;
  437. ; OUT:
  438. ;
  439. ;-----------------------------------------------------------------
  440. align 4
  441. ICMP_api:
  442.  
  443.         movzx   eax, bh
  444.         shl     eax, 2
  445.  
  446.         test    bl, bl
  447.         jz      .packets_tx     ; 0
  448.         dec     bl
  449.         jz      .packets_rx     ; 1
  450.  
  451.   .error:
  452.         mov     eax, -1
  453.         ret
  454.  
  455.   .packets_tx:
  456.         mov     eax, [ICMP_PACKETS_TX + eax]
  457.         ret
  458.  
  459.   .packets_rx:
  460.         mov     eax, [ICMP_PACKETS_RX + eax]
  461.         ret
  462.