Subversion Repositories Kolibri OS

Rev

Rev 3698 | Rev 3861 | Go to most recent revision | Details | Compare with Previous | 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
$Revision: 2924 $
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
3556 hidnplayr 40
ICMP_UNREACH_HOST_PRECEDENCE    = 14              ; host prec vio.
41
ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15              ; prec cutoff
3545 hidnplayr 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
 
3698 hidnplayr 100
uglobal
3545 hidnplayr 101
align 4
3698 hidnplayr 102
 
3600 hidnplayr 103
        ICMP_PACKETS_TX         rd NET_DEVICES_MAX
104
        ICMP_PACKETS_RX         rd NET_DEVICES_MAX
3698 hidnplayr 105
 
3545 hidnplayr 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
3600 hidnplayr 120
        mov     ecx, 2*NET_DEVICES_MAX
3711 clevermous 121
        rep stosd
3545 hidnplayr 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
;       size of buffer in [esp+4]
135
;       ebx = pointer to device struct
136
;       ecx = ICMP Packet size
137
;       esi = ptr to ICMP Packet data
138
;       edi = ptr to ipv4 source and dest address
139
;
140
;  OUT: /
141
;
142
;-----------------------------------------------------------------
143
align 4
144
ICMP_input:
145
 
3556 hidnplayr 146
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input:\n"
3545 hidnplayr 147
 
148
; First, check the checksum (altough some implementations ignore it)
149
 
150
        push    esi ecx
151
        push    [esi + ICMP_header.Checksum]
152
        mov     [esi + ICMP_header.Checksum], 0
153
        xor     edx, edx
154
        call    checksum_1
155
        call    checksum_2
156
        pop     si
157
        cmp     dx, si
158
        pop     ecx edx
159
        jne     .checksum_mismatch
160
 
3643 hidnplayr 161
; Check packet type
162
 
3545 hidnplayr 163
        cmp     [edx + ICMP_header.Type], ICMP_ECHO             ; Is this an echo request?
164
        jne     .check_sockets
165
 
3643 hidnplayr 166
; Update stats (and validate device ptr)
167
        call    NET_ptr_to_num4
168
        cmp     edi, -1
169
        je      .dump
170
        inc     [ICMP_PACKETS_RX + edi]
171
 
3545 hidnplayr 172
; We well re-use the packet so we can create the response as fast as possible
173
; Notice: this only works on pure ethernet
174
 
3556 hidnplayr 175
        DEBUGF  DEBUG_NETWORK_VERBOSE, "got echo request\n"
3545 hidnplayr 176
        mov     [edx + ICMP_header.Type], ICMP_ECHOREPLY        ; Change Packet type to reply
177
 
178
        mov     esi, [esp]                                      ; Start of buffer
3601 hidnplayr 179
        cmp     ebx, LOOPBACK_DEVICE
180
        je      .loopback
181
 
182
; FIXME: dont assume device is an ethernet device!
183
 
3545 hidnplayr 184
; exchange dest and source address in IP header
185
; exchange dest and source MAC in ETH header
186
        push    dword [esi + ETH_header.DstMAC]
187
        push    dword [esi + ETH_header.SrcMAC]
188
        pop     dword [esi + ETH_header.DstMAC]
189
        pop     dword [esi + ETH_header.SrcMAC]
190
        push    word [esi + ETH_header.DstMAC + 4]
191
        push    word [esi + ETH_header.SrcMAC + 4]
192
        pop     word [esi + ETH_header.DstMAC + 4]
193
        pop     word [esi + ETH_header.SrcMAC + 4]
3601 hidnplayr 194
        add     esi, sizeof.ETH_header-4
3545 hidnplayr 195
 
196
  .loopback:
3601 hidnplayr 197
        add     esi, 4
3545 hidnplayr 198
        push    [esi + IPv4_header.SourceAddress]
199
        push    [esi + IPv4_header.DestinationAddress]
200
        pop     [esi + IPv4_header.SourceAddress]
201
        pop     [esi + IPv4_header.DestinationAddress]
202
 
203
; Recalculate ip header checksum
204
        movzx   ecx, [esi + IPv4_header.VersionAndIHL]          ; Calculate IP Header length by using IHL field
205
        and     ecx, 0x0f
206
        shl     cx, 2
207
        mov     edi, ecx                                        ; IP header length
208
        mov     eax, edx                                        ; ICMP packet start addr
209
 
210
        push    esi                                             ; Calculate the IP checksum
211
        xor     edx, edx                                        ;
212
        call    checksum_1                                      ;
213
        call    checksum_2                                      ;
214
        pop     esi                                             ;
215
        mov     [esi + IPv4_header.HeaderChecksum], dx          ;
216
 
217
; Recalculate ICMP CheckSum
218
        movzx   ecx, [esi + IPv4_header.TotalLength]            ; Find length of IP Packet
219
        xchg    ch, cl                                          ;
220
        sub     ecx, edi                                        ; IP packet length - IP header length = ICMP packet length
221
 
222
        mov     esi, eax                                        ; Calculate ICMP checksum
223
        xor     edx, edx                                        ;
224
        call    checksum_1                                      ;
225
        call    checksum_2                                      ;
226
        mov     [eax + ICMP_header.Checksum], dx                ;
227
 
228
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
229
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 230
        test    eax, eax
231
        jnz     @f
232
        call    NET_ptr_to_num4
233
        inc     [UDP_PACKETS_TX + edi]
234
       @@:
3545 hidnplayr 235
        ret
236
 
237
 
238
 
239
 
240
       .check_sockets:
241
        ; Look for an open ICMP socket
242
 
3647 hidnplayr 243
        pusha
244
        mov     ecx, socket_mutex
245
        call    mutex_lock
246
        popa
247
 
3545 hidnplayr 248
        mov     esi, [edi]              ; ipv4 source address
249
        mov     eax, net_sockets
250
  .try_more:
251
;        mov      , [edx + ICMP_header.Identifier]
252
  .next_socket:
253
        mov     eax, [eax + SOCKET.NextPtr]
254
        or      eax, eax
3647 hidnplayr 255
        jz      .dump_
3545 hidnplayr 256
 
257
        cmp     [eax + SOCKET.Domain], AF_INET4
258
        jne     .next_socket
259
 
260
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
261
        jne     .next_socket
262
 
263
        cmp     [eax + IP_SOCKET.RemoteIP], esi
264
        jne     .next_socket
265
 
266
;        cmp     [eax + ICMP_SOCKET.Identifier],
267
;        jne     .next_socket
268
 
3643 hidnplayr 269
; Update stats (and validate device ptr)
270
        call    NET_ptr_to_num4
271
        cmp     edi, -1
3647 hidnplayr 272
        je      .dump_
3643 hidnplayr 273
        inc     [ICMP_PACKETS_RX + edi]
3545 hidnplayr 274
 
3647 hidnplayr 275
        pusha
276
        mov     ecx, socket_mutex
277
        call    mutex_unlock
278
        popa
279
 
3556 hidnplayr 280
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3545 hidnplayr 281
 
282
        pusha
283
        lea     ecx, [eax + SOCKET.mutex]
284
        call    mutex_lock
285
        popa
286
 
287
        mov     esi, edx
288
        jmp     SOCKET_input
289
 
3647 hidnplayr 290
  .dump_:
3545 hidnplayr 291
 
3647 hidnplayr 292
        pusha
293
        mov     ecx, socket_mutex
294
        call    mutex_unlock
295
        popa
296
 
297
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: no socket found\n"
298
        jmp     .dump
299
 
300
 
3545 hidnplayr 301
  .checksum_mismatch:
3556 hidnplayr 302
        DEBUGF  DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
3545 hidnplayr 303
 
304
  .dump:
3556 hidnplayr 305
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
3545 hidnplayr 306
 
307
        call    kernel_free
308
        add     esp, 4 ; pop (balance stack)
309
 
310
        ret
311
 
312
 
313
;-----------------------------------------------------------------
314
;
315
; ICMP_output
316
;
317
; IN:  eax = dest ip
318
;      ebx = source ip
319
;      ecx = data length
320
;      dh  = type
321
;      dl  = code
322
;      esi = data offset
323
;      edi = identifier shl 16 + sequence number
324
;
325
;-----------------------------------------------------------------
326
align 4
327
ICMP_output:
328
 
3556 hidnplayr 329
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3545 hidnplayr 330
 
331
        push    esi edi dx
332
 
333
        mov     edx, [eax + IP_SOCKET.LocalIP]
334
        mov     eax, [eax + IP_SOCKET.RemoteIP]
335
        add     ecx, sizeof.ICMP_header
336
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
337
        call    IPv4_output
338
        jz      .exit
339
 
3556 hidnplayr 340
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3545 hidnplayr 341
 
342
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
343
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
344
        mov     [edi + ICMP_header.Checksum], 0
345
 
346
        push    ebx ecx edx
347
        mov     esi, edi
348
        xor     edx, edx
349
        call    checksum_1
350
        call    checksum_2
351
        mov     [edi + ICMP_header.Checksum], dx
352
        pop     edx ecx ebx esi
353
 
354
        sub     ecx, sizeof.ICMP_header
355
        add     edi, sizeof.ICMP_header
356
        push    cx
357
        shr     cx, 2
3711 clevermous 358
        rep movsd
3545 hidnplayr 359
        pop     cx
360
        and     cx, 3
3711 clevermous 361
        rep movsb
3545 hidnplayr 362
 
363
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
364
        push    edx edi
3556 hidnplayr 365
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 366
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 367
        test    eax, eax
368
        jnz     @f
369
        call    NET_ptr_to_num4
370
        inc     [ICMP_PACKETS_TX + edi]
371
       @@:
3545 hidnplayr 372
        ret
373
  .exit:
3556 hidnplayr 374
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3545 hidnplayr 375
        add     esp, 2*4 + 2
376
        ret
377
 
378
 
379
 
380
 
381
;-----------------------------------------------------------------
382
;
383
; ICMP_output
384
;
385
; IN:  eax = socket ptr
386
;      ecx = data length
387
;      esi = data offset
388
;
389
;-----------------------------------------------------------------
390
align 4
391
ICMP_output_raw:
392
 
3556 hidnplayr 393
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
3545 hidnplayr 394
 
395
        push    edx
396
 
397
        mov     di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
398
        mov     edx, [eax + IP_SOCKET.LocalIP]
399
        mov     eax, [eax + IP_SOCKET.RemoteIP]
400
        call    IPv4_output
401
        jz      .exit
402
 
403
        pop     esi
404
        push    edx
405
        push    eax
406
 
407
        push    edi ecx
3556 hidnplayr 408
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3711 clevermous 409
        rep movsb
3545 hidnplayr 410
        pop     ecx edi
411
 
412
        mov     [edi + ICMP_header.Checksum], 0
413
 
414
        mov     esi, edi
415
        xor     edx, edx
416
        call    checksum_1
417
        call    checksum_2
418
        mov     [edi + ICMP_header.Checksum], dx
419
 
3556 hidnplayr 420
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 421
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 422
        test    eax, eax
423
        jnz     @f
424
        call    NET_ptr_to_num4
425
        inc     [ICMP_PACKETS_TX + edi]
426
       @@:
3545 hidnplayr 427
        ret
428
  .exit:
3556 hidnplayr 429
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3545 hidnplayr 430
        add     esp, 4
431
        ret
432
 
433
 
434
 
435
 
436
;-----------------------------------------------------------------
437
;
438
; ICMP_API
439
;
440
; This function is called by system function 75
441
;
442
; IN:  subfunction number in bl
443
;      device number in bh
444
;      ecx, edx, .. depends on subfunction
445
;
446
; OUT:
447
;
448
;-----------------------------------------------------------------
449
align 4
450
ICMP_api:
451
 
452
        movzx   eax, bh
453
        shl     eax, 2
454
 
455
        test    bl, bl
456
        jz      .packets_tx     ; 0
457
        dec     bl
458
        jz      .packets_rx     ; 1
459
 
460
  .error:
461
        mov     eax, -1
462
        ret
463
 
464
  .packets_tx:
465
        mov     eax, [ICMP_PACKETS_TX + eax]
466
        ret
467
 
468
  .packets_rx:
469
        mov     eax, [ICMP_PACKETS_RX + eax]
470
        ret