Subversion Repositories Kolibri OS

Rev

Rev 5594 | 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: 5984 $
  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. ;       edx = ptr to IPv4 header
  137. ;       esi = ptr to ICMP Packet data
  138. ;       edi = interface number*4
  139. ;
  140. ;  OUT: /
  141. ;
  142. ;-----------------------------------------------------------------
  143. align 4
  144. ICMP_input:
  145.  
  146.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
  147.  
  148. ; Dump all multicasts and broadcasts
  149.         mov     eax, [IP_LIST + edi]
  150.         cmp     eax, [edx + IPv4_header.DestinationAddress]
  151.         jne     .dump
  152.  
  153. ; Check the checksum
  154.         push    esi ecx edx
  155.         push    [esi + ICMP_header.Checksum]
  156.         mov     [esi + ICMP_header.Checksum], 0
  157.         xor     edx, edx
  158.         call    checksum_1
  159.         call    checksum_2
  160.         pop     si
  161.         cmp     dx, si
  162.         pop     edx ecx esi
  163.         jne     .checksum_mismatch
  164.  
  165.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
  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.         add     ecx, esi
  181.         sub     ecx, edx
  182.         mov     esi, edx
  183.         mov     eax, net_sockets
  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.         pusha
  196.         mov     ecx, socket_mutex
  197.         call    mutex_unlock
  198.         popa
  199.  
  200.         DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
  201.  
  202.         pusha
  203.         lea     ecx, [eax + SOCKET.mutex]
  204.         call    mutex_lock
  205.         popa
  206.  
  207.         jmp     SOCKET_input
  208.  
  209.  
  210.  
  211.   .echo_request:
  212.  
  213. ; We'll reuse the packet so we can create the response as fast as possible
  214.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP echo request\n"
  215.  
  216. ; Change Packet type to reply
  217.         mov     [esi + ICMP_header.Type], ICMP_ECHOREPLY
  218.  
  219.         mov     eax, [esp]
  220.         lea     esi, [eax + NET_BUFF.data]
  221.  
  222. ; Check frame type
  223.         cmp     [eax + NET_BUFF.type], NET_BUFF_ETH
  224.         jne     .not_ethernet
  225.  
  226. ; exchange dest and source MAC in ETH header
  227.         push    dword [esi + ETH_header.DstMAC]
  228.         push    dword [esi + ETH_header.SrcMAC]
  229.         pop     dword [esi + ETH_header.DstMAC]
  230.         pop     dword [esi + ETH_header.SrcMAC]
  231.         push    word [esi + ETH_header.DstMAC + 4]
  232.         push    word [esi + ETH_header.SrcMAC + 4]
  233.         pop     word [esi + ETH_header.DstMAC + 4]
  234.         pop     word [esi + ETH_header.SrcMAC + 4]
  235.         add     esi, sizeof.ETH_header
  236.  
  237.   .not_ethernet:
  238. ; Exchange dest and source address in IP header
  239.         push    [esi + IPv4_header.SourceAddress]
  240.         push    [esi + IPv4_header.DestinationAddress]
  241.         pop     [esi + IPv4_header.SourceAddress]
  242.         pop     [esi + IPv4_header.DestinationAddress]
  243.  
  244. ; Calculate IP header length
  245.         movzx   ecx, [esi + IPv4_header.VersionAndIHL]
  246.         and     ecx, 0x0f
  247.         shl     cx, 2
  248.         mov     edi, ecx                        ; put it in edi for later
  249.  
  250. ; Calculate IP checksum
  251.         mov     eax, esi
  252.         mov     [eax + IPv4_header.HeaderChecksum], 0
  253.         xor     edx, edx
  254.         call    checksum_1
  255.         call    checksum_2
  256.         mov     [eax + IPv4_header.HeaderChecksum], dx
  257.  
  258. ; Calculate ICMP packet length
  259.         movzx   ecx, [eax + IPv4_header.TotalLength]
  260.         xchg    ch, cl
  261.         sub     ecx, edi                        ; IP packet length - IP header length = ICMP packet length
  262.  
  263. ; Calculate ICMP checkSum
  264.         mov     eax, esi
  265.         mov     [esi + ICMP_header.Checksum], 0
  266.         xor     edx, edx
  267.         call    checksum_1
  268.         call    checksum_2
  269.         mov     [eax + ICMP_header.Checksum], dx
  270.  
  271. ; Transmit the frame
  272.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmitting reply\n"
  273.         call    [ebx + NET_DEVICE.transmit]
  274.         test    eax, eax
  275.         jnz     @f
  276.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmit failed\n"
  277.         call    NET_ptr_to_num4
  278.         inc     [ICMP_PACKETS_TX + edi]
  279.        @@:
  280.         ret
  281.  
  282.   .dump_:
  283.         pusha
  284.         mov     ecx, socket_mutex
  285.         call    mutex_unlock
  286.         popa
  287.  
  288.         DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
  289.         jmp     .dump
  290.  
  291.   .checksum_mismatch:
  292.         DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
  293.  
  294.   .dump:
  295.         DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
  296.         call    NET_BUFF_free
  297.         ret
  298.  
  299.  
  300. if 0
  301. ;-----------------------------------------------------------------
  302. ;
  303. ; ICMP_output
  304. ;
  305. ; IN:  eax = dest ip
  306. ;      bh  = type
  307. ;      bl  = code
  308. ;      ecx = data length
  309. ;      edx = source ip
  310. ;      esi = data offset
  311. ;      edi = identifier shl 16 + sequence number
  312. ;
  313. ;-----------------------------------------------------------------
  314. align 4
  315. ICMP_output:
  316.  
  317.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
  318.  
  319.         push    esi edi bx
  320.         add     ecx, sizeof.ICMP_header
  321.         mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
  322.         call    IPv4_output
  323.         jz      .exit
  324.  
  325.         DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
  326.  
  327.         pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
  328.         pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
  329.         mov     [edi + ICMP_header.Checksum], 0
  330.  
  331.         push    ebx ecx edx
  332.         mov     esi, edi
  333.         xor     edx, edx
  334.         call    checksum_1
  335.         call    checksum_2
  336.         mov     [edi + ICMP_header.Checksum], dx
  337.         pop     edx ecx ebx esi
  338.  
  339.         sub     ecx, sizeof.ICMP_header
  340.         add     edi, sizeof.ICMP_header
  341.         push    cx
  342.         shr     cx, 2
  343.         rep movsd
  344.         pop     cx
  345.         and     cx, 3
  346.         rep movsb
  347.  
  348.         sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
  349.         push    edx edi
  350.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  351.         call    [ebx + NET_DEVICE.transmit]
  352.         test    eax, eax
  353.         jnz     @f
  354.         call    NET_ptr_to_num4
  355.         inc     [ICMP_PACKETS_TX + edi]
  356.        @@:
  357.         ret
  358.   .exit:
  359.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  360.         add     esp, 2*4 + 2
  361.         ret
  362. end if
  363.  
  364.  
  365.  
  366.  
  367. ;-----------------------------------------------------------------
  368. ;
  369. ; ICMP_output_raw
  370. ;
  371. ; IN:  eax = socket ptr
  372. ;      ecx = data length
  373. ;      edx = data pointer
  374. ;
  375. ;-----------------------------------------------------------------
  376. align 4
  377. ICMP_output_raw:
  378.  
  379.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
  380.  
  381.         push    edx
  382.         mov     ebx, [eax + IP_SOCKET.device]
  383.         mov     edx, [eax + IP_SOCKET.LocalIP]
  384.         mov     edi, [eax + IP_SOCKET.RemoteIP]
  385.         mov     al, [eax + IP_SOCKET.ttl]
  386.         mov     ah, IP_PROTO_ICMP
  387.         call    IPv4_output
  388.         jz      .fail
  389.  
  390.         pop     esi
  391.         push    eax
  392.  
  393.         push    edi ecx
  394.         DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
  395.         rep movsb
  396.         pop     ecx edi
  397.  
  398.         mov     [edi + ICMP_header.Checksum], 0
  399.  
  400.         mov     esi, edi
  401.         xor     edx, edx
  402.         call    checksum_1
  403.         call    checksum_2
  404.         mov     [edi + ICMP_header.Checksum], dx
  405.  
  406.         DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
  407.         call    [ebx + NET_DEVICE.transmit]
  408.         test    eax, eax
  409.         jnz     @f
  410.         call    NET_ptr_to_num4
  411.         inc     [ICMP_PACKETS_TX + edi]
  412.   @@:
  413.         ret
  414.  
  415.   .fail:
  416.         pop     edx
  417.         DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
  418.         or      eax, -1
  419.         mov     ebx, EMSGSIZE           ;;; FIXME
  420.         ret
  421.  
  422.  
  423.  
  424.  
  425. ;-----------------------------------------------------------------
  426. ;
  427. ; ICMP_API
  428. ;
  429. ; This function is called by system function 75
  430. ;
  431. ; IN:  subfunction number in bl
  432. ;      device number in bh
  433. ;      ecx, edx, .. depends on subfunction
  434. ;
  435. ; OUT:
  436. ;
  437. ;-----------------------------------------------------------------
  438. align 4
  439. ICMP_api:
  440.  
  441.         movzx   eax, bh
  442.         shl     eax, 2
  443.  
  444.         test    bl, bl
  445.         jz      .packets_tx     ; 0
  446.         dec     bl
  447.         jz      .packets_rx     ; 1
  448.  
  449.   .error:
  450.         mov     eax, -1
  451.         ret
  452.  
  453.   .packets_tx:
  454.         mov     eax, [ICMP_PACKETS_TX + eax]
  455.         ret
  456.  
  457.   .packets_rx:
  458.         mov     eax, [ICMP_PACKETS_RX + eax]
  459.         ret
  460.