Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3555 Serge 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261 hidnplayr 18
 
3555 Serge 19
 
593 mikedld 20
$Revision: 3589 $
261 hidnplayr 21
 
3555 Serge 22
; ICMP types & codes
593 mikedld 23
 
3555 Serge 24
ICMP_ECHOREPLY                  = 0               ; echo reply message
261 hidnplayr 25
 
3555 Serge 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
3589 Serge 41
ICMP_UNREACH_HOST_PRECEDENCE    = 14              ; host prec vio.
42
ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15              ; prec cutoff
261 hidnplayr 43
 
3555 Serge 44
ICMP_SOURCEQUENCH               = 4               ; Packet lost, slow down
261 hidnplayr 45
 
3555 Serge 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
;-----------------------------------------------------------------
261 hidnplayr 110
;
3555 Serge 111
; ICMP_init
261 hidnplayr 112
;
3555 Serge 113
;-----------------------------------------------------------------
261 hidnplayr 114
 
3555 Serge 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
;-----------------------------------------------------------------
261 hidnplayr 126
;
3555 Serge 127
; ICMP_input:
261 hidnplayr 128
;
3555 Serge 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:
261 hidnplayr 144
 
3589 Serge 145
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input:\n"
261 hidnplayr 146
 
3555 Serge 147
; First, check the checksum (altough some implementations ignore it)
261 hidnplayr 148
 
3555 Serge 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
261 hidnplayr 159
 
3555 Serge 160
        cmp     [edx + ICMP_header.Type], ICMP_ECHO             ; Is this an echo request?
161
        jne     .check_sockets
261 hidnplayr 162
 
3555 Serge 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
261 hidnplayr 165
 
3589 Serge 166
        DEBUGF  DEBUG_NETWORK_VERBOSE, "got echo request\n"
3555 Serge 167
        mov     [edx + ICMP_header.Type], ICMP_ECHOREPLY        ; Change Packet type to reply
261 hidnplayr 168
 
3555 Serge 169
        mov     esi, [esp]                                      ; Start of buffer
261 hidnplayr 170
 
3555 Serge 171
        cmp     dword[edi + 4], 1 shl 24 + 127
172
        je      .loopback
261 hidnplayr 173
 
3555 Serge 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]
431 serge 180
 
3555 Serge 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
431 serge 192
 
3555 Serge 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
 
3589 Serge 261
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3555 Serge 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:
3589 Serge 273
        DEBUGF  DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
3555 Serge 274
 
275
  .dump:
3589 Serge 276
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
3555 Serge 277
 
278
        call    kernel_free
279
        add     esp, 4 ; pop (balance stack)
280
 
281
        ret
282
 
283
 
284
;-----------------------------------------------------------------
261 hidnplayr 285
;
3555 Serge 286
; ICMP_output
261 hidnplayr 287
;
3555 Serge 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
261 hidnplayr 295
;
3555 Serge 296
;-----------------------------------------------------------------
297
align 4
298
ICMP_output:
299
 
3589 Serge 300
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3555 Serge 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
 
3589 Serge 311
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3555 Serge 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
3589 Serge 336
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 337
        call    [ebx + NET_DEVICE.transmit]
338
        ret
339
  .exit:
3589 Serge 340
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 341
        add     esp, 2*4 + 2
342
        ret
343
 
344
 
345
 
346
 
347
;-----------------------------------------------------------------
261 hidnplayr 348
;
3555 Serge 349
; ICMP_output
261 hidnplayr 350
;
3555 Serge 351
; IN:  eax = socket ptr
352
;      ecx = data length
353
;      esi = data offset
354
;
355
;-----------------------------------------------------------------
356
align 4
357
ICMP_output_raw:
261 hidnplayr 358
 
3589 Serge 359
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
261 hidnplayr 360
 
3555 Serge 361
        push    edx
261 hidnplayr 362
 
3555 Serge 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
261 hidnplayr 368
 
3555 Serge 369
        pop     esi
370
        push    edx
371
        push    eax
261 hidnplayr 372
 
3555 Serge 373
        push    edi ecx
3589 Serge 374
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3555 Serge 375
        rep     movsb
376
        pop     ecx edi
261 hidnplayr 377
 
3555 Serge 378
        mov     [edi + ICMP_header.Checksum], 0
261 hidnplayr 379
 
3555 Serge 380
        mov     esi, edi
381
        xor     edx, edx
382
        call    checksum_1
383
        call    checksum_2
384
        mov     [edi + ICMP_header.Checksum], dx
261 hidnplayr 385
 
3589 Serge 386
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 387
        call    [ebx + NET_DEVICE.transmit]
388
        ret
389
  .exit:
3589 Serge 390
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 391
        add     esp, 4
392
        ret
261 hidnplayr 393
 
394
 
395
 
396
 
3555 Serge 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:
261 hidnplayr 412
 
3555 Serge 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
2434 Serge 423
        ret
3555 Serge 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