Subversion Repositories Kolibri OS

Rev

Rev 3556 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 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: 2924 $
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_NET_DEVICES
104
        ICMP_PACKETS_RX         rd MAX_NET_DEVICES
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_NET_DEVICES
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:\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,"got echo request\n"
167
        mov     [edx + ICMP_header.Type], ICMP_ECHOREPLY        ; Change Packet type to reply
168
 
169
        mov     esi, [esp]                                      ; Start of buffer
170
 
171
        cmp     dword[edi + 4], 1 shl 24 + 127
172
        je      .loopback
173
 
174
; Update stats (and validate device ptr)
175
        call    NET_ptr_to_num
176
        cmp     edi,-1
177
        je      .dump
178
        inc     [ICMP_PACKETS_RX + 4*edi]
179
        inc     [ICMP_PACKETS_TX + 4*edi]
180
 
181
; exchange dest and source address in IP header
182
; exchange dest and source MAC in ETH header
183
        push    dword [esi + ETH_header.DstMAC]
184
        push    dword [esi + ETH_header.SrcMAC]
185
        pop     dword [esi + ETH_header.DstMAC]
186
        pop     dword [esi + ETH_header.SrcMAC]
187
        push    word [esi + ETH_header.DstMAC + 4]
188
        push    word [esi + ETH_header.SrcMAC + 4]
189
        pop     word [esi + ETH_header.DstMAC + 4]
190
        pop     word [esi + ETH_header.SrcMAC + 4]
191
        add     esi, sizeof.ETH_header-2
192
 
193
  .loopback:
194
        add     esi, 2
195
        push    [esi + IPv4_header.SourceAddress]
196
        push    [esi + IPv4_header.DestinationAddress]
197
        pop     [esi + IPv4_header.SourceAddress]
198
        pop     [esi + IPv4_header.DestinationAddress]
199
 
200
; Recalculate ip header checksum
201
        movzx   ecx, [esi + IPv4_header.VersionAndIHL]          ; Calculate IP Header length by using IHL field
202
        and     ecx, 0x0f
203
        shl     cx, 2
204
        mov     edi, ecx                                        ; IP header length
205
        mov     eax, edx                                        ; ICMP packet start addr
206
 
207
        push    esi                                             ; Calculate the IP checksum
208
        xor     edx, edx                                        ;
209
        call    checksum_1                                      ;
210
        call    checksum_2                                      ;
211
        pop     esi                                             ;
212
        mov     [esi + IPv4_header.HeaderChecksum], dx          ;
213
 
214
; Recalculate ICMP CheckSum
215
        movzx   ecx, [esi + IPv4_header.TotalLength]            ; Find length of IP Packet
216
        xchg    ch, cl                                          ;
217
        sub     ecx, edi                                        ; IP packet length - IP header length = ICMP packet length
218
 
219
        mov     esi, eax                                        ; Calculate ICMP checksum
220
        xor     edx, edx                                        ;
221
        call    checksum_1                                      ;
222
        call    checksum_2                                      ;
223
        mov     [eax + ICMP_header.Checksum], dx                ;
224
 
225
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
226
        call    [ebx + NET_DEVICE.transmit]
227
        ret
228
 
229
 
230
 
231
 
232
       .check_sockets:
233
        ; Look for an open ICMP socket
234
 
235
        mov     esi, [edi]              ; ipv4 source address
236
        mov     eax, net_sockets
237
  .try_more:
238
;        mov      , [edx + ICMP_header.Identifier]
239
  .next_socket:
240
        mov     eax, [eax + SOCKET.NextPtr]
241
        or      eax, eax
242
        jz      .dump
243
 
244
        cmp     [eax + SOCKET.Domain], AF_INET4
245
        jne     .next_socket
246
 
247
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
248
        jne     .next_socket
249
 
250
        cmp     [eax + IP_SOCKET.RemoteIP], esi
251
        jne     .next_socket
252
 
253
;        cmp     [eax + ICMP_SOCKET.Identifier],
254
;        jne     .next_socket
255
 
256
;        call    IPv4_dest_to_dev
257
;        cmp     edi,-1
258
;        je      .dump
259
;        inc     [ICMP_PACKETS_RX+edi]
260
 
261
        DEBUGF 1,"socket=%x\n", eax
262
 
263
        pusha
264
        lea     ecx, [eax + SOCKET.mutex]
265
        call    mutex_lock
266
        popa
267
 
268
        mov     esi, edx
269
        jmp     SOCKET_input
270
 
271
 
272
  .checksum_mismatch:
273
        DEBUGF  1,"checksum mismatch\n"
274
 
275
  .dump:
276
        DEBUGF  1,"ICMP_input: dumping\n"
277
 
278
        call    kernel_free
279
        add     esp, 4 ; pop (balance stack)
280
 
281
        ret
282
 
283
 
284
;-----------------------------------------------------------------
285
;
286
; ICMP_output
287
;
288
; IN:  eax = dest ip
289
;      ebx = source ip
290
;      ecx = data length
291
;      dh  = type
292
;      dl  = code
293
;      esi = data offset
294
;      edi = identifier shl 16 + sequence number
295
;
296
;-----------------------------------------------------------------
297
align 4
298
ICMP_output:
299
 
300
        DEBUGF  1,"Creating ICMP Packet\n"
301
 
302
        push    esi edi dx
303
 
304
        mov     edx, [eax + IP_SOCKET.LocalIP]
305
        mov     eax, [eax + IP_SOCKET.RemoteIP]
306
        add     ecx, sizeof.ICMP_header
307
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
308
        call    IPv4_output
309
        jz      .exit
310
 
311
        DEBUGF  1,"full icmp packet size: %u\n", edx
312
 
313
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
314
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
315
        mov     [edi + ICMP_header.Checksum], 0
316
 
317
        push    ebx ecx edx
318
        mov     esi, edi
319
        xor     edx, edx
320
        call    checksum_1
321
        call    checksum_2
322
        mov     [edi + ICMP_header.Checksum], dx
323
        pop     edx ecx ebx esi
324
 
325
        sub     ecx, sizeof.ICMP_header
326
        add     edi, sizeof.ICMP_header
327
        push    cx
328
        shr     cx, 2
329
        rep     movsd
330
        pop     cx
331
        and     cx, 3
332
        rep     movsb
333
 
334
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
335
        push    edx edi
336
        DEBUGF  1,"Sending ICMP Packet\n"
337
        call    [ebx + NET_DEVICE.transmit]
338
        ret
339
  .exit:
340
        DEBUGF  1,"Creating ICMP Packet failed\n"
341
        add     esp, 2*4 + 2
342
        ret
343
 
344
 
345
 
346
 
347
;-----------------------------------------------------------------
348
;
349
; ICMP_output
350
;
351
; IN:  eax = socket ptr
352
;      ecx = data length
353
;      esi = data offset
354
;
355
;-----------------------------------------------------------------
356
align 4
357
ICMP_output_raw:
358
 
359
        DEBUGF  1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
360
 
361
        push    edx
362
 
363
        mov     di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
364
        mov     edx, [eax + IP_SOCKET.LocalIP]
365
        mov     eax, [eax + IP_SOCKET.RemoteIP]
366
        call    IPv4_output
367
        jz      .exit
368
 
369
        pop     esi
370
        push    edx
371
        push    eax
372
 
373
        push    edi ecx
374
        DEBUGF  1,"copying %u bytes from %x to %x\n", ecx, esi, edi
375
        rep     movsb
376
        pop     ecx edi
377
 
378
        mov     [edi + ICMP_header.Checksum], 0
379
 
380
        mov     esi, edi
381
        xor     edx, edx
382
        call    checksum_1
383
        call    checksum_2
384
        mov     [edi + ICMP_header.Checksum], dx
385
 
386
        DEBUGF  1,"Sending ICMP Packet\n"
387
        call    [ebx + NET_DEVICE.transmit]
388
        ret
389
  .exit:
390
        DEBUGF  1,"Creating ICMP Packet failed\n"
391
        add     esp, 4
392
        ret
393
 
394
 
395
 
396
 
397
;-----------------------------------------------------------------
398
;
399
; ICMP_API
400
;
401
; This function is called by system function 75
402
;
403
; IN:  subfunction number in bl
404
;      device number in bh
405
;      ecx, edx, .. depends on subfunction
406
;
407
; OUT:
408
;
409
;-----------------------------------------------------------------
410
align 4
411
ICMP_api:
412
 
413
        movzx   eax, bh
414
        shl     eax, 2
415
 
416
        test    bl, bl
417
        jz      .packets_tx     ; 0
418
        dec     bl
419
        jz      .packets_rx     ; 1
420
 
421
  .error:
422
        mov     eax, -1
423
        ret
424
 
425
  .packets_tx:
426
        mov     eax, [ICMP_PACKETS_TX + eax]
427
        ret
428
 
429
  .packets_rx:
430
        mov     eax, [ICMP_PACKETS_RX + eax]
431
        ret