Subversion Repositories Kolibri OS

Rev

Rev 3908 | Rev 4423 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3555 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3908 Serge 3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
3555 Serge 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261 hidnplayr 18
 
593 mikedld 19
$Revision: 4265 $
261 hidnplayr 20
 
3555 Serge 21
; ICMP types & codes
593 mikedld 22
 
3555 Serge 23
ICMP_ECHOREPLY                  = 0               ; echo reply message
261 hidnplayr 24
 
3555 Serge 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
3589 Serge 40
ICMP_UNREACH_HOST_PRECEDENCE    = 14              ; host prec vio.
41
ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15              ; prec cutoff
261 hidnplayr 42
 
3555 Serge 43
ICMP_SOURCEQUENCH               = 4               ; Packet lost, slow down
261 hidnplayr 44
 
3555 Serge 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
 
3725 Serge 100
uglobal
3555 Serge 101
align 4
3725 Serge 102
 
3626 Serge 103
        ICMP_PACKETS_TX         rd NET_DEVICES_MAX
104
        ICMP_PACKETS_RX         rd NET_DEVICES_MAX
3725 Serge 105
 
3555 Serge 106
endg
107
 
108
 
109
 
110
;-----------------------------------------------------------------
261 hidnplayr 111
;
3555 Serge 112
; ICMP_init
261 hidnplayr 113
;
3555 Serge 114
;-----------------------------------------------------------------
261 hidnplayr 115
 
3555 Serge 116
macro ICMP_init {
117
 
118
        xor     eax, eax
119
        mov     edi, ICMP_PACKETS_TX
3626 Serge 120
        mov     ecx, 2*NET_DEVICES_MAX
3725 Serge 121
        rep stosd
3555 Serge 122
 
123
}
124
 
125
 
126
;-----------------------------------------------------------------
261 hidnplayr 127
;
3555 Serge 128
; ICMP_input:
261 hidnplayr 129
;
3555 Serge 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:
261 hidnplayr 145
 
3589 Serge 146
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input:\n"
261 hidnplayr 147
 
3555 Serge 148
; First, check the checksum (altough some implementations ignore it)
261 hidnplayr 149
 
3555 Serge 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
261 hidnplayr 160
 
3725 Serge 161
; Check packet type
162
 
3555 Serge 163
        cmp     [edx + ICMP_header.Type], ICMP_ECHO             ; Is this an echo request?
164
        jne     .check_sockets
261 hidnplayr 165
 
3725 Serge 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
 
3555 Serge 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
261 hidnplayr 174
 
3589 Serge 175
        DEBUGF  DEBUG_NETWORK_VERBOSE, "got echo request\n"
3555 Serge 176
        mov     [edx + ICMP_header.Type], ICMP_ECHOREPLY        ; Change Packet type to reply
261 hidnplayr 177
 
3555 Serge 178
        mov     esi, [esp]                                      ; Start of buffer
3626 Serge 179
        cmp     ebx, LOOPBACK_DEVICE
180
        je      .loopback
181
 
182
; FIXME: dont assume device is an ethernet device!
183
 
3555 Serge 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]
3626 Serge 194
        add     esi, sizeof.ETH_header-4
431 serge 195
 
3555 Serge 196
  .loopback:
3626 Serge 197
        add     esi, 4
3555 Serge 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]
3725 Serge 230
        test    eax, eax
231
        jnz     @f
232
        call    NET_ptr_to_num4
233
        inc     [UDP_PACKETS_TX + edi]
234
       @@:
3555 Serge 235
        ret
236
 
237
 
238
 
239
 
240
       .check_sockets:
241
        ; Look for an open ICMP socket
242
 
3725 Serge 243
        pusha
244
        mov     ecx, socket_mutex
245
        call    mutex_lock
246
        popa
247
 
3555 Serge 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
3725 Serge 255
        jz      .dump_
3555 Serge 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
 
3725 Serge 269
; Update stats (and validate device ptr)
270
        call    NET_ptr_to_num4
271
        cmp     edi, -1
272
        je      .dump_
273
        inc     [ICMP_PACKETS_RX + edi]
3555 Serge 274
 
3725 Serge 275
        pusha
276
        mov     ecx, socket_mutex
277
        call    mutex_unlock
278
        popa
279
 
3589 Serge 280
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3555 Serge 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
 
3725 Serge 290
  .dump_:
3555 Serge 291
 
3725 Serge 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
 
3555 Serge 301
  .checksum_mismatch:
3589 Serge 302
        DEBUGF  DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
3555 Serge 303
 
304
  .dump:
3589 Serge 305
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
3555 Serge 306
 
3908 Serge 307
        call    NET_packet_free
3555 Serge 308
        add     esp, 4 ; pop (balance stack)
309
 
310
        ret
311
 
312
 
4265 Serge 313
if 0
3555 Serge 314
;-----------------------------------------------------------------
261 hidnplayr 315
;
3555 Serge 316
; ICMP_output
261 hidnplayr 317
;
3555 Serge 318
; IN:  eax = dest ip
4265 Serge 319
;      bh  = type
320
;      bl  = code
3555 Serge 321
;      ecx = data length
4265 Serge 322
;      edx = source ip
3555 Serge 323
;      esi = data offset
324
;      edi = identifier shl 16 + sequence number
261 hidnplayr 325
;
3555 Serge 326
;-----------------------------------------------------------------
327
align 4
328
ICMP_output:
329
 
3589 Serge 330
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3555 Serge 331
 
4265 Serge 332
        push    esi edi bx
3555 Serge 333
        add     ecx, sizeof.ICMP_header
334
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
335
        call    IPv4_output
336
        jz      .exit
337
 
3589 Serge 338
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3555 Serge 339
 
340
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
341
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
342
        mov     [edi + ICMP_header.Checksum], 0
343
 
344
        push    ebx ecx edx
345
        mov     esi, edi
346
        xor     edx, edx
347
        call    checksum_1
348
        call    checksum_2
349
        mov     [edi + ICMP_header.Checksum], dx
350
        pop     edx ecx ebx esi
351
 
352
        sub     ecx, sizeof.ICMP_header
353
        add     edi, sizeof.ICMP_header
354
        push    cx
355
        shr     cx, 2
3725 Serge 356
        rep movsd
3555 Serge 357
        pop     cx
358
        and     cx, 3
3725 Serge 359
        rep movsb
3555 Serge 360
 
361
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
362
        push    edx edi
3589 Serge 363
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 364
        call    [ebx + NET_DEVICE.transmit]
3725 Serge 365
        test    eax, eax
366
        jnz     @f
367
        call    NET_ptr_to_num4
368
        inc     [ICMP_PACKETS_TX + edi]
369
       @@:
3555 Serge 370
        ret
371
  .exit:
3589 Serge 372
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 373
        add     esp, 2*4 + 2
374
        ret
4265 Serge 375
end if
3555 Serge 376
 
377
 
378
 
379
 
380
;-----------------------------------------------------------------
261 hidnplayr 381
;
4265 Serge 382
; ICMP_output_raw
261 hidnplayr 383
;
3555 Serge 384
; IN:  eax = socket ptr
385
;      ecx = data length
386
;      esi = data offset
387
;
388
;-----------------------------------------------------------------
389
align 4
390
ICMP_output_raw:
261 hidnplayr 391
 
3589 Serge 392
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
261 hidnplayr 393
 
3555 Serge 394
        push    edx
261 hidnplayr 395
 
3555 Serge 396
        mov     di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
397
        mov     edx, [eax + IP_SOCKET.LocalIP]
398
        mov     eax, [eax + IP_SOCKET.RemoteIP]
399
        call    IPv4_output
400
        jz      .exit
261 hidnplayr 401
 
3555 Serge 402
        pop     esi
403
        push    edx
404
        push    eax
261 hidnplayr 405
 
3555 Serge 406
        push    edi ecx
3589 Serge 407
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3725 Serge 408
        rep movsb
3555 Serge 409
        pop     ecx edi
261 hidnplayr 410
 
3555 Serge 411
        mov     [edi + ICMP_header.Checksum], 0
261 hidnplayr 412
 
3555 Serge 413
        mov     esi, edi
414
        xor     edx, edx
415
        call    checksum_1
416
        call    checksum_2
417
        mov     [edi + ICMP_header.Checksum], dx
261 hidnplayr 418
 
3589 Serge 419
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 420
        call    [ebx + NET_DEVICE.transmit]
3725 Serge 421
        test    eax, eax
422
        jnz     @f
423
        call    NET_ptr_to_num4
424
        inc     [ICMP_PACKETS_TX + edi]
425
       @@:
3555 Serge 426
        ret
427
  .exit:
3589 Serge 428
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 429
        add     esp, 4
430
        ret
261 hidnplayr 431
 
432
 
433
 
434
 
3555 Serge 435
;-----------------------------------------------------------------
436
;
437
; ICMP_API
438
;
439
; This function is called by system function 75
440
;
441
; IN:  subfunction number in bl
442
;      device number in bh
443
;      ecx, edx, .. depends on subfunction
444
;
445
; OUT:
446
;
447
;-----------------------------------------------------------------
448
align 4
449
ICMP_api:
261 hidnplayr 450
 
3555 Serge 451
        movzx   eax, bh
452
        shl     eax, 2
453
 
454
        test    bl, bl
455
        jz      .packets_tx     ; 0
456
        dec     bl
457
        jz      .packets_rx     ; 1
458
 
459
  .error:
460
        mov     eax, -1
2434 Serge 461
        ret
3555 Serge 462
 
463
  .packets_tx:
464
        mov     eax, [ICMP_PACKETS_TX + eax]
465
        ret
466
 
467
  .packets_rx:
468
        mov     eax, [ICMP_PACKETS_RX + eax]
469
        ret