Subversion Repositories Kolibri OS

Rev

Rev 3589 | Rev 3725 | 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
 
593 mikedld 19
$Revision: 3626 $
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
 
100
align 4
101
uglobal
3626 Serge 102
        ICMP_PACKETS_TX         rd NET_DEVICES_MAX
103
        ICMP_PACKETS_RX         rd NET_DEVICES_MAX
3555 Serge 104
endg
105
 
106
 
107
 
108
;-----------------------------------------------------------------
261 hidnplayr 109
;
3555 Serge 110
; ICMP_init
261 hidnplayr 111
;
3555 Serge 112
;-----------------------------------------------------------------
261 hidnplayr 113
 
3555 Serge 114
macro ICMP_init {
115
 
116
        xor     eax, eax
117
        mov     edi, ICMP_PACKETS_TX
3626 Serge 118
        mov     ecx, 2*NET_DEVICES_MAX
3555 Serge 119
        rep     stosd
120
 
121
}
122
 
123
 
124
;-----------------------------------------------------------------
261 hidnplayr 125
;
3555 Serge 126
; ICMP_input:
261 hidnplayr 127
;
3555 Serge 128
;  This procedure will send reply's to ICMP echo's
129
;   and insert packets into sockets when needed
130
;
131
;  IN:  Pointer to buffer in [esp]
132
;       size of buffer in [esp+4]
133
;       ebx = pointer to device struct
134
;       ecx = ICMP Packet size
135
;       esi = ptr to ICMP Packet data
136
;       edi = ptr to ipv4 source and dest address
137
;
138
;  OUT: /
139
;
140
;-----------------------------------------------------------------
141
align 4
142
ICMP_input:
261 hidnplayr 143
 
3589 Serge 144
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input:\n"
261 hidnplayr 145
 
3555 Serge 146
; First, check the checksum (altough some implementations ignore it)
261 hidnplayr 147
 
3555 Serge 148
        push    esi ecx
149
        push    [esi + ICMP_header.Checksum]
150
        mov     [esi + ICMP_header.Checksum], 0
151
        xor     edx, edx
152
        call    checksum_1
153
        call    checksum_2
154
        pop     si
155
        cmp     dx, si
156
        pop     ecx edx
157
        jne     .checksum_mismatch
261 hidnplayr 158
 
3555 Serge 159
        cmp     [edx + ICMP_header.Type], ICMP_ECHO             ; Is this an echo request?
160
        jne     .check_sockets
261 hidnplayr 161
 
3555 Serge 162
; We well re-use the packet so we can create the response as fast as possible
163
; Notice: this only works on pure ethernet
261 hidnplayr 164
 
3589 Serge 165
        DEBUGF  DEBUG_NETWORK_VERBOSE, "got echo request\n"
3555 Serge 166
        mov     [edx + ICMP_header.Type], ICMP_ECHOREPLY        ; Change Packet type to reply
261 hidnplayr 167
 
3555 Serge 168
        mov     esi, [esp]                                      ; Start of buffer
261 hidnplayr 169
 
3555 Serge 170
; Update stats (and validate device ptr)
171
        call    NET_ptr_to_num
3626 Serge 172
        cmp     edi, -1
3555 Serge 173
        je      .dump
174
        inc     [ICMP_PACKETS_RX + 4*edi]
175
        inc     [ICMP_PACKETS_TX + 4*edi]
431 serge 176
 
3626 Serge 177
        cmp     ebx, LOOPBACK_DEVICE
178
        je      .loopback
179
 
180
; FIXME: dont assume device is an ethernet device!
181
 
3555 Serge 182
; exchange dest and source address in IP header
183
; exchange dest and source MAC in ETH header
184
        push    dword [esi + ETH_header.DstMAC]
185
        push    dword [esi + ETH_header.SrcMAC]
186
        pop     dword [esi + ETH_header.DstMAC]
187
        pop     dword [esi + ETH_header.SrcMAC]
188
        push    word [esi + ETH_header.DstMAC + 4]
189
        push    word [esi + ETH_header.SrcMAC + 4]
190
        pop     word [esi + ETH_header.DstMAC + 4]
191
        pop     word [esi + ETH_header.SrcMAC + 4]
3626 Serge 192
        add     esi, sizeof.ETH_header-4
431 serge 193
 
3555 Serge 194
  .loopback:
3626 Serge 195
        add     esi, 4
3555 Serge 196
        push    [esi + IPv4_header.SourceAddress]
197
        push    [esi + IPv4_header.DestinationAddress]
198
        pop     [esi + IPv4_header.SourceAddress]
199
        pop     [esi + IPv4_header.DestinationAddress]
200
 
201
; Recalculate ip header checksum
202
        movzx   ecx, [esi + IPv4_header.VersionAndIHL]          ; Calculate IP Header length by using IHL field
203
        and     ecx, 0x0f
204
        shl     cx, 2
205
        mov     edi, ecx                                        ; IP header length
206
        mov     eax, edx                                        ; ICMP packet start addr
207
 
208
        push    esi                                             ; Calculate the IP checksum
209
        xor     edx, edx                                        ;
210
        call    checksum_1                                      ;
211
        call    checksum_2                                      ;
212
        pop     esi                                             ;
213
        mov     [esi + IPv4_header.HeaderChecksum], dx          ;
214
 
215
; Recalculate ICMP CheckSum
216
        movzx   ecx, [esi + IPv4_header.TotalLength]            ; Find length of IP Packet
217
        xchg    ch, cl                                          ;
218
        sub     ecx, edi                                        ; IP packet length - IP header length = ICMP packet length
219
 
220
        mov     esi, eax                                        ; Calculate ICMP checksum
221
        xor     edx, edx                                        ;
222
        call    checksum_1                                      ;
223
        call    checksum_2                                      ;
224
        mov     [eax + ICMP_header.Checksum], dx                ;
225
 
226
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
227
        call    [ebx + NET_DEVICE.transmit]
228
        ret
229
 
230
 
231
 
232
 
233
       .check_sockets:
234
        ; Look for an open ICMP socket
235
 
236
        mov     esi, [edi]              ; ipv4 source address
237
        mov     eax, net_sockets
238
  .try_more:
239
;        mov      , [edx + ICMP_header.Identifier]
240
  .next_socket:
241
        mov     eax, [eax + SOCKET.NextPtr]
242
        or      eax, eax
243
        jz      .dump
244
 
245
        cmp     [eax + SOCKET.Domain], AF_INET4
246
        jne     .next_socket
247
 
248
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
249
        jne     .next_socket
250
 
251
        cmp     [eax + IP_SOCKET.RemoteIP], esi
252
        jne     .next_socket
253
 
254
;        cmp     [eax + ICMP_SOCKET.Identifier],
255
;        jne     .next_socket
256
 
257
;        call    IPv4_dest_to_dev
258
;        cmp     edi,-1
259
;        je      .dump
260
;        inc     [ICMP_PACKETS_RX+edi]
261
 
3589 Serge 262
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3555 Serge 263
 
264
        pusha
265
        lea     ecx, [eax + SOCKET.mutex]
266
        call    mutex_lock
267
        popa
268
 
269
        mov     esi, edx
270
        jmp     SOCKET_input
271
 
272
 
273
  .checksum_mismatch:
3589 Serge 274
        DEBUGF  DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
3555 Serge 275
 
276
  .dump:
3589 Serge 277
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
3555 Serge 278
 
279
        call    kernel_free
280
        add     esp, 4 ; pop (balance stack)
281
 
282
        ret
283
 
284
 
285
;-----------------------------------------------------------------
261 hidnplayr 286
;
3555 Serge 287
; ICMP_output
261 hidnplayr 288
;
3555 Serge 289
; IN:  eax = dest ip
290
;      ebx = source ip
291
;      ecx = data length
292
;      dh  = type
293
;      dl  = code
294
;      esi = data offset
295
;      edi = identifier shl 16 + sequence number
261 hidnplayr 296
;
3555 Serge 297
;-----------------------------------------------------------------
298
align 4
299
ICMP_output:
300
 
3589 Serge 301
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3555 Serge 302
 
303
        push    esi edi dx
304
 
305
        mov     edx, [eax + IP_SOCKET.LocalIP]
306
        mov     eax, [eax + IP_SOCKET.RemoteIP]
307
        add     ecx, sizeof.ICMP_header
308
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
309
        call    IPv4_output
310
        jz      .exit
311
 
3589 Serge 312
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3555 Serge 313
 
314
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
315
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
316
        mov     [edi + ICMP_header.Checksum], 0
317
 
318
        push    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 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
3589 Serge 337
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 338
        call    [ebx + NET_DEVICE.transmit]
339
        ret
340
  .exit:
3589 Serge 341
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 342
        add     esp, 2*4 + 2
343
        ret
344
 
345
 
346
 
347
 
348
;-----------------------------------------------------------------
261 hidnplayr 349
;
3555 Serge 350
; ICMP_output
261 hidnplayr 351
;
3555 Serge 352
; IN:  eax = socket ptr
353
;      ecx = data length
354
;      esi = data offset
355
;
356
;-----------------------------------------------------------------
357
align 4
358
ICMP_output_raw:
261 hidnplayr 359
 
3589 Serge 360
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
261 hidnplayr 361
 
3555 Serge 362
        push    edx
261 hidnplayr 363
 
3555 Serge 364
        mov     di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
365
        mov     edx, [eax + IP_SOCKET.LocalIP]
366
        mov     eax, [eax + IP_SOCKET.RemoteIP]
367
        call    IPv4_output
368
        jz      .exit
261 hidnplayr 369
 
3555 Serge 370
        pop     esi
371
        push    edx
372
        push    eax
261 hidnplayr 373
 
3555 Serge 374
        push    edi ecx
3589 Serge 375
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3555 Serge 376
        rep     movsb
377
        pop     ecx edi
261 hidnplayr 378
 
3555 Serge 379
        mov     [edi + ICMP_header.Checksum], 0
261 hidnplayr 380
 
3555 Serge 381
        mov     esi, edi
382
        xor     edx, edx
383
        call    checksum_1
384
        call    checksum_2
385
        mov     [edi + ICMP_header.Checksum], dx
261 hidnplayr 386
 
3589 Serge 387
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3555 Serge 388
        call    [ebx + NET_DEVICE.transmit]
389
        ret
390
  .exit:
3589 Serge 391
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3555 Serge 392
        add     esp, 4
393
        ret
261 hidnplayr 394
 
395
 
396
 
397
 
3555 Serge 398
;-----------------------------------------------------------------
399
;
400
; ICMP_API
401
;
402
; This function is called by system function 75
403
;
404
; IN:  subfunction number in bl
405
;      device number in bh
406
;      ecx, edx, .. depends on subfunction
407
;
408
; OUT:
409
;
410
;-----------------------------------------------------------------
411
align 4
412
ICMP_api:
261 hidnplayr 413
 
3555 Serge 414
        movzx   eax, bh
415
        shl     eax, 2
416
 
417
        test    bl, bl
418
        jz      .packets_tx     ; 0
419
        dec     bl
420
        jz      .packets_rx     ; 1
421
 
422
  .error:
423
        mov     eax, -1
2434 Serge 424
        ret
3555 Serge 425
 
426
  .packets_tx:
427
        mov     eax, [ICMP_PACKETS_TX + eax]
428
        ret
429
 
430
  .packets_rx:
431
        mov     eax, [ICMP_PACKETS_RX + eax]
432
        ret