Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3545 hidnplayr 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
 
4850 mario79 19
$Revision: 6011 $
3545 hidnplayr 20
 
21
; ICMP types & codes
22
 
6011 hidnplayr 23
ICMP_ECHOREPLY                  = 0             ; echo reply message
3545 hidnplayr 24
 
25
ICMP_UNREACH                    = 3
6011 hidnplayr 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
40
ICMP_UNREACH_HOST_PRECEDENCE    = 14            ; host prec vio.
41
ICMP_UNREACH_PRECEDENCE_CUTOFF  = 15            ; prec cutoff
3545 hidnplayr 42
 
6011 hidnplayr 43
ICMP_SOURCEQUENCH               = 4             ; Packet lost, slow down
3545 hidnplayr 44
 
6011 hidnplayr 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
3545 hidnplayr 50
 
6011 hidnplayr 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
3545 hidnplayr 56
 
6011 hidnplayr 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
3545 hidnplayr 61
 
6011 hidnplayr 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
3545 hidnplayr 66
 
6011 hidnplayr 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
3545 hidnplayr 81
 
6011 hidnplayr 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
3545 hidnplayr 86
 
87
 
88
struct  ICMP_header
89
 
90
        Type                    db ?
91
        Code                    db ?
92
        Checksum                dw ?
93
        Identifier              dw ?
94
        SequenceNumber          dw ?
95
 
96
ends
97
 
98
 
3698 hidnplayr 99
uglobal
3545 hidnplayr 100
align 4
3698 hidnplayr 101
 
3600 hidnplayr 102
        ICMP_PACKETS_TX         rd NET_DEVICES_MAX
103
        ICMP_PACKETS_RX         rd NET_DEVICES_MAX
3698 hidnplayr 104
 
3545 hidnplayr 105
endg
106
 
107
 
108
 
6011 hidnplayr 109
;-----------------------------------------------------------------;
110
;                                                                 ;
111
; ICMP_init                                                       ;
112
;                                                                 ;
113
;-----------------------------------------------------------------;
3545 hidnplayr 114
 
6011 hidnplayr 115
macro icmp_init {
3545 hidnplayr 116
 
117
        xor     eax, eax
118
        mov     edi, ICMP_PACKETS_TX
3600 hidnplayr 119
        mov     ecx, 2*NET_DEVICES_MAX
3711 clevermous 120
        rep stosd
3545 hidnplayr 121
 
122
}
123
 
124
 
6011 hidnplayr 125
;-----------------------------------------------------------------;
126
;                                                                 ;
127
; icmp_input: Send a reply's to an ICMP echo or insert packets    ;
128
; into socket.                                                    ;
129
;                                                                 ;
130
;  IN:  [esp] = ptr to buffer                                     ;
131
;       ebx = ptr to device struct                                ;
132
;       ecx = ICMP Packet size                                    ;
133
;       edx = ptr to IPv4 header                                  ;
134
;       esi = ptr to ICMP Packet data                             ;
135
;       edi = interface number*4                                  ;
136
;                                                                 ;
137
;  OUT: /                                                         ;
138
;                                                                 ;
139
;-----------------------------------------------------------------;
3545 hidnplayr 140
align 4
6011 hidnplayr 141
icmp_input:
3545 hidnplayr 142
 
5522 hidnplayr 143
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input\n"
3545 hidnplayr 144
 
5842 hidnplayr 145
; Dump all multicasts and broadcasts
146
        mov     eax, [IP_LIST + edi]
147
        cmp     eax, [edx + IPv4_header.DestinationAddress]
148
        jne     .dump
149
 
5522 hidnplayr 150
; Check the checksum
5842 hidnplayr 151
        push    esi ecx edx
3545 hidnplayr 152
        push    [esi + ICMP_header.Checksum]
153
        mov     [esi + ICMP_header.Checksum], 0
154
        xor     edx, edx
155
        call    checksum_1
156
        call    checksum_2
157
        pop     si
158
        cmp     dx, si
5842 hidnplayr 159
        pop     edx ecx esi
3545 hidnplayr 160
        jne     .checksum_mismatch
161
 
5522 hidnplayr 162
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: Checksum OK\n"
3643 hidnplayr 163
 
5522 hidnplayr 164
; Update stats
3643 hidnplayr 165
        inc     [ICMP_PACKETS_RX + edi]
166
 
5522 hidnplayr 167
; Is this an echo request?
168
        cmp     [esi + ICMP_header.Type], ICMP_ECHO
169
        je      .echo_request
3545 hidnplayr 170
 
5522 hidnplayr 171
; Look for an open ICMP socket
3647 hidnplayr 172
        pusha
173
        mov     ecx, socket_mutex
174
        call    mutex_lock
175
        popa
176
 
5842 hidnplayr 177
        add     ecx, esi
178
        sub     ecx, edx
179
        mov     esi, edx
3545 hidnplayr 180
        mov     eax, net_sockets
181
  .next_socket:
182
        mov     eax, [eax + SOCKET.NextPtr]
183
        or      eax, eax
3647 hidnplayr 184
        jz      .dump_
3545 hidnplayr 185
 
186
        cmp     [eax + SOCKET.Domain], AF_INET4
187
        jne     .next_socket
188
 
189
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
190
        jne     .next_socket
191
 
3647 hidnplayr 192
        pusha
193
        mov     ecx, socket_mutex
194
        call    mutex_unlock
195
        popa
196
 
3556 hidnplayr 197
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
3545 hidnplayr 198
 
199
        pusha
200
        lea     ecx, [eax + SOCKET.mutex]
201
        call    mutex_lock
202
        popa
203
 
6011 hidnplayr 204
        jmp     socket_input
3545 hidnplayr 205
 
5522 hidnplayr 206
 
207
 
208
  .echo_request:
209
 
210
; We'll reuse the packet so we can create the response as fast as possible
211
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP echo request\n"
212
 
213
; Change Packet type to reply
214
        mov     [esi + ICMP_header.Type], ICMP_ECHOREPLY
215
 
216
        mov     eax, [esp]
217
        lea     esi, [eax + NET_BUFF.data]
218
 
219
; Check frame type
220
        cmp     [eax + NET_BUFF.type], NET_BUFF_ETH
221
        jne     .not_ethernet
222
 
223
; exchange dest and source MAC in ETH header
224
        push    dword [esi + ETH_header.DstMAC]
225
        push    dword [esi + ETH_header.SrcMAC]
226
        pop     dword [esi + ETH_header.DstMAC]
227
        pop     dword [esi + ETH_header.SrcMAC]
228
        push    word [esi + ETH_header.DstMAC + 4]
229
        push    word [esi + ETH_header.SrcMAC + 4]
230
        pop     word [esi + ETH_header.DstMAC + 4]
231
        pop     word [esi + ETH_header.SrcMAC + 4]
232
        add     esi, sizeof.ETH_header
233
 
234
  .not_ethernet:
235
; Exchange dest and source address in IP header
236
        push    [esi + IPv4_header.SourceAddress]
237
        push    [esi + IPv4_header.DestinationAddress]
238
        pop     [esi + IPv4_header.SourceAddress]
239
        pop     [esi + IPv4_header.DestinationAddress]
240
 
241
; Calculate IP header length
242
        movzx   ecx, [esi + IPv4_header.VersionAndIHL]
243
        and     ecx, 0x0f
244
        shl     cx, 2
245
        mov     edi, ecx                        ; put it in edi for later
246
 
247
; Calculate IP checksum
248
        mov     eax, esi
249
        mov     [eax + IPv4_header.HeaderChecksum], 0
250
        xor     edx, edx
251
        call    checksum_1
252
        call    checksum_2
253
        mov     [eax + IPv4_header.HeaderChecksum], dx
254
 
255
; Calculate ICMP packet length
256
        movzx   ecx, [eax + IPv4_header.TotalLength]
257
        xchg    ch, cl
258
        sub     ecx, edi                        ; IP packet length - IP header length = ICMP packet length
259
 
260
; Calculate ICMP checkSum
261
        mov     eax, esi
262
        mov     [esi + ICMP_header.Checksum], 0
263
        xor     edx, edx
264
        call    checksum_1
265
        call    checksum_2
266
        mov     [eax + ICMP_header.Checksum], dx
267
 
268
; Transmit the frame
269
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmitting reply\n"
270
        call    [ebx + NET_DEVICE.transmit]
271
        test    eax, eax
272
        jnz     @f
273
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP transmit failed\n"
6011 hidnplayr 274
        call    net_ptr_to_num4
5522 hidnplayr 275
        inc     [ICMP_PACKETS_TX + edi]
276
       @@:
277
        ret
278
 
3647 hidnplayr 279
  .dump_:
280
        pusha
281
        mov     ecx, socket_mutex
282
        call    mutex_unlock
283
        popa
284
 
4892 hidnplayr 285
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: no socket found\n"
3647 hidnplayr 286
        jmp     .dump
287
 
3545 hidnplayr 288
  .checksum_mismatch:
4892 hidnplayr 289
        DEBUGF  DEBUG_NETWORK_ERROR, "ICMP_input: checksum mismatch\n"
3545 hidnplayr 290
 
291
  .dump:
3556 hidnplayr 292
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
6011 hidnplayr 293
        call    net_buff_free
3545 hidnplayr 294
        ret
295
 
296
 
4052 hidnplayr 297
if 0
6011 hidnplayr 298
;-----------------------------------------------------------------;
299
;                                                                 ;
300
; icmp_output                                                     ;
301
;                                                                 ;
302
; IN:   eax = dest ip                                             ;
303
;       bh  = type                                                ;
304
;       bl  = code                                                ;
305
;       ecx = data length                                         ;
306
;       edx = source ip                                           ;
307
;       esi = data offset                                         ;
308
;       edi = identifier shl 16 + sequence number                 ;
309
;                                                                 ;
310
;-----------------------------------------------------------------;
3545 hidnplayr 311
align 4
6011 hidnplayr 312
icmp_output:
3545 hidnplayr 313
 
3556 hidnplayr 314
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
3545 hidnplayr 315
 
4052 hidnplayr 316
        push    esi edi bx
3545 hidnplayr 317
        add     ecx, sizeof.ICMP_header
318
        mov     di, IP_PROTO_ICMP SHL 8 + 128           ; TTL
319
        call    IPv4_output
320
        jz      .exit
321
 
3556 hidnplayr 322
        DEBUGF  DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
3545 hidnplayr 323
 
324
        pop     word [edi + ICMP_header.Type]           ; Write both type and code bytes at once
325
        pop     dword [edi + ICMP_header.Identifier]    ; identifier and sequence number
326
        mov     [edi + ICMP_header.Checksum], 0
327
 
328
        push    ebx ecx edx
329
        mov     esi, edi
330
        xor     edx, edx
331
        call    checksum_1
332
        call    checksum_2
333
        mov     [edi + ICMP_header.Checksum], dx
334
        pop     edx ecx ebx esi
335
 
336
        sub     ecx, sizeof.ICMP_header
337
        add     edi, sizeof.ICMP_header
338
        push    cx
339
        shr     cx, 2
3711 clevermous 340
        rep movsd
3545 hidnplayr 341
        pop     cx
342
        and     cx, 3
3711 clevermous 343
        rep movsb
3545 hidnplayr 344
 
345
        sub     edi, edx                                ;;; TODO: find a better way to remember start of packet
346
        push    edx edi
3556 hidnplayr 347
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 348
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 349
        test    eax, eax
350
        jnz     @f
351
        call    NET_ptr_to_num4
352
        inc     [ICMP_PACKETS_TX + edi]
353
       @@:
3545 hidnplayr 354
        ret
355
  .exit:
3556 hidnplayr 356
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
3545 hidnplayr 357
        add     esp, 2*4 + 2
358
        ret
4052 hidnplayr 359
end if
3545 hidnplayr 360
 
361
 
362
 
363
 
6011 hidnplayr 364
;-----------------------------------------------------------------;
365
;                                                                 ;
366
; icmp_output_raw                                                 ;
367
;                                                                 ;
368
;  IN:  eax = socket ptr                                          ;
369
;       ecx = data length                                         ;
370
;       edx = data pointer                                        ;
371
;                                                                 ;
372
;-----------------------------------------------------------------;
3545 hidnplayr 373
align 4
6011 hidnplayr 374
icmp_output_raw:
3545 hidnplayr 375
 
3556 hidnplayr 376
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
3545 hidnplayr 377
 
378
        push    edx
5842 hidnplayr 379
        mov     ebx, [eax + IP_SOCKET.device]
3545 hidnplayr 380
        mov     edx, [eax + IP_SOCKET.LocalIP]
5842 hidnplayr 381
        mov     edi, [eax + IP_SOCKET.RemoteIP]
382
        mov     al, [eax + IP_SOCKET.ttl]
383
        mov     ah, IP_PROTO_ICMP
6011 hidnplayr 384
        call    ipv4_output
5842 hidnplayr 385
        jz      .fail
3545 hidnplayr 386
 
387
        pop     esi
388
        push    eax
389
 
390
        push    edi ecx
3556 hidnplayr 391
        DEBUGF  DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
3711 clevermous 392
        rep movsb
3545 hidnplayr 393
        pop     ecx edi
394
 
395
        mov     [edi + ICMP_header.Checksum], 0
396
 
397
        mov     esi, edi
398
        xor     edx, edx
399
        call    checksum_1
400
        call    checksum_2
401
        mov     [edi + ICMP_header.Checksum], dx
402
 
3556 hidnplayr 403
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
3545 hidnplayr 404
        call    [ebx + NET_DEVICE.transmit]
3643 hidnplayr 405
        test    eax, eax
406
        jnz     @f
6011 hidnplayr 407
        call    net_ptr_to_num4
3643 hidnplayr 408
        inc     [ICMP_PACKETS_TX + edi]
5842 hidnplayr 409
  @@:
3545 hidnplayr 410
        ret
5842 hidnplayr 411
 
412
  .fail:
413
        pop     edx
3556 hidnplayr 414
        DEBUGF  DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
5842 hidnplayr 415
        or      eax, -1
416
        mov     ebx, EMSGSIZE           ;;; FIXME
3545 hidnplayr 417
        ret
418
 
419
 
420
 
421
 
6011 hidnplayr 422
;-----------------------------------------------------------------;
423
;                                                                 ;
424
; icmp_api: Part of system function 76.                           ;
425
;                                                                 ;
426
;  IN:  bl = subfunction number                                   ;
427
;       bh = device number                                        ;
428
;       ecx, edx, .. depends on subfunction                       ;
429
;                                                                 ;
430
; OUT:  depends on subfunction                                    ;
431
;                                                                 ;
432
;-----------------------------------------------------------------;
3545 hidnplayr 433
align 4
6011 hidnplayr 434
icmp_api:
3545 hidnplayr 435
 
436
        movzx   eax, bh
437
        shl     eax, 2
438
 
439
        test    bl, bl
440
        jz      .packets_tx     ; 0
441
        dec     bl
442
        jz      .packets_rx     ; 1
443
 
444
  .error:
445
        mov     eax, -1
446
        ret
447
 
448
  .packets_tx:
449
        mov     eax, [ICMP_PACKETS_TX + eax]
450
        ret
451
 
452
  .packets_rx:
453
        mov     eax, [ICMP_PACKETS_RX + eax]
454
        ret