Subversion Repositories Kolibri OS

Rev

Rev 2553 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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