Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1514 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved.    ;;
1159 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
 
19
 
1206 hidnplayr 20
$Revision: 2305 $
1159 hidnplayr 21
 
22
; ICMP types & codes
23
 
1514 hidnplayr 24
ICMP_ECHOREPLY			equ 0		    ; echo reply message
1159 hidnplayr 25
 
1514 hidnplayr 26
ICMP_UNREACH			equ 3
27
ICMP_UNREACH_NET		equ  0		     ; bad net
28
ICMP_UNREACH_HOST		equ  1		     ; bad host
29
ICMP_UNREACH_PROTOCOL		equ  2		     ; bad protocol
30
ICMP_UNREACH_PORT		equ  3		     ; bad port
31
ICMP_UNREACH_NEEDFRAG		equ  4		     ; IP_DF caused drop
32
ICMP_UNREACH_SRCFAIL		equ  5		     ; src route failed
33
ICMP_UNREACH_NET_UNKNOWN	equ  6		     ; unknown net
34
ICMP_UNREACH_HOST_UNKNOWN	equ  7		     ; unknown host
35
ICMP_UNREACH_ISOLATED		equ  8		     ; src host isolated
36
ICMP_UNREACH_NET_PROHIB 	equ  9		     ; prohibited access
37
ICMP_UNREACH_HOST_PROHIB	equ 10		    ; ditto
38
ICMP_UNREACH_TOSNET		equ 11		    ; bad tos for net
39
ICMP_UNREACH_TOSHOST		equ 12		    ; bad tos for host
40
ICMP_UNREACH_FILTER_PROHIB	equ 13		    ; admin prohib
41
ICMP_UNREACH_HOST_PRECEDENCE	equ 14		   ; host prec vio.
42
ICMP_UNREACH_PRECEDENCE_CUTOFF	equ 15		 ; prec cutoff
1159 hidnplayr 43
 
1514 hidnplayr 44
ICMP_SOURCEQUENCH		equ 4		    ; Packet lost, slow down
1159 hidnplayr 45
 
1514 hidnplayr 46
ICMP_REDIRECT			equ 5		    ; shorter route, codes:
47
ICMP_REDIRECT_NET		equ  0		     ; for network
48
ICMP_REDIRECT_HOST		equ  1		     ; for host
49
ICMP_REDIRECT_TOSNET		equ  2		     ; for tos and net
50
ICMP_REDIRECT_TOSHOST		equ  3		     ; for tos and host
1159 hidnplayr 51
 
1514 hidnplayr 52
ICMP_ALTHOSTADDR		equ 6		    ; alternate host address
53
ICMP_ECHO			equ  8		     ; echo service
54
ICMP_ROUTERADVERT		equ  9		     ; router advertisement
55
ICMP_ROUTERADVERT_NORMAL	equ  0			; normal advertisement
56
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 	; selective routing
1159 hidnplayr 57
 
1514 hidnplayr 58
ICMP_ROUTERSOLICIT		equ 10		    ; router solicitation
59
ICMP_TIMXCEED			equ 11		    ; time exceeded, code:
60
ICMP_TIMXCEED_INTRANS		equ 0		    ; ttl==0 in transit
61
ICMP_TIMXCEED_REASS		equ 1		    ; ttl==0 in reass
1159 hidnplayr 62
 
1514 hidnplayr 63
ICMP_PARAMPROB			equ 12		     ; ip header bad
64
ICMP_PARAMPROB_ERRATPTR 	equ 0		 ; error at param ptr
65
ICMP_PARAMPROB_OPTABSENT	equ 1		 ; req. opt. absent
66
ICMP_PARAMPROB_LENGTH		equ 2		 ; bad length
1159 hidnplayr 67
 
1514 hidnplayr 68
ICMP_TSTAMP			equ 13		    ; timestamp request
69
ICMP_TSTAMPREPLY		equ 14		    ; timestamp reply
70
ICMP_IREQ			equ 15		    ; information request
71
ICMP_IREQREPLY			equ 16		    ; information reply
72
ICMP_MASKREQ			equ 17		    ; address mask request
73
ICMP_MASKREPLY			equ 18		    ; address mask reply
74
ICMP_TRACEROUTE 		equ 30		    ; traceroute
75
ICMP_DATACONVERR		equ 31		    ; data conversion error
76
ICMP_MOBILE_REDIRECT		equ 32		    ; mobile host redirect
77
ICMP_IPV6_WHEREAREYOU		equ 33		    ; IPv6 where-are-you
78
ICMP_IPV6_IAMHERE		equ 34		    ; IPv6 i-am-here
79
ICMP_MOBILE_REGREQUEST		equ 35		    ; mobile registration req
80
ICMP_MOBILE_REGREPLY		equ 36		    ; mobile registreation reply
81
ICMP_SKIP			equ 39		    ; SKIP
1159 hidnplayr 82
 
1514 hidnplayr 83
ICMP_PHOTURIS			equ 40		    ; Photuris
84
ICMP_PHOTURIS_UNKNOWN_INDEX	equ 1		     ; unknown sec index
85
ICMP_PHOTURIS_AUTH_FAILED	equ 2		     ; auth failed
86
ICMP_PHOTURIS_DECRYPT_FAILED	equ 3		     ; decrypt failed
1159 hidnplayr 87
 
88
 
89
 
2305 hidnplayr 90
struct	ICMP_header
91
 
92
	Type			db   ?
93
	Code			db   ?
94
	Checksum		dw   ?
95
	Identifier		dw   ?
96
	SequenceNumber		dw   ?
97
 
1159 hidnplayr 98
ends
99
 
100
 
101
align 4
102
uglobal
103
	ICMP_PACKETS_TX 	rd  MAX_IP
104
	ICMP_PACKETS_RX 	rd  MAX_IP
105
endg
106
 
1185 hidnplayr 107
 
108
 
1159 hidnplayr 109
;-----------------------------------------------------------------
110
;
111
; ICMP_init
112
;
113
;-----------------------------------------------------------------
114
 
1529 hidnplayr 115
macro ICMP_init {
116
 
1159 hidnplayr 117
	xor	eax, eax
118
	mov	edi, ICMP_PACKETS_TX
119
	mov	ecx, 2*MAX_IP
120
	rep	stosd
121
 
1529 hidnplayr 122
}
1171 hidnplayr 123
 
124
 
1257 hidnplayr 125
;-----------------------------------------------------------------
1159 hidnplayr 126
;
1514 hidnplayr 127
; ICMP_input:
1159 hidnplayr 128
;
1514 hidnplayr 129
;  This procedure will send reply's to ICMP echo's
130
;   and insert packets into sockets when needed
1159 hidnplayr 131
;
132
;  IN:  Pointer to buffer in [esp]
133
;       size of buffer in [esp+4]
1541 hidnplayr 134
;       ebx = pointer to device struct
135
;       ecx = ICMP Packet size
136
;       edx = ptr to ICMP Packet data
137
;       esi = ipv4 source address
138
;       edi = ipv4 dest   address
1159 hidnplayr 139
;  OUT: /
140
;
1257 hidnplayr 141
;-----------------------------------------------------------------
1159 hidnplayr 142
align 4
1514 hidnplayr 143
ICMP_input:
1159 hidnplayr 144
 
1544 hidnplayr 145
	DEBUGF	1,"ICMP_input - start\n"
1514 hidnplayr 146
 
1544 hidnplayr 147
; First, check the checksum (altough some implementations ignore it)
148
 
149
	push	edx esi ecx
2305 hidnplayr 150
	push	[edx + ICMP_header.Checksum]
151
	mov	[edx + ICMP_header.Checksum], 0
1544 hidnplayr 152
	mov	esi, edx
153
	xor	edx, edx
154
	call	checksum_1
155
	call	checksum_2
156
	pop	si
157
	cmp	dx, si
158
	pop	ecx esi edx
159
	jne	.checksum_mismatch
160
 
2305 hidnplayr 161
	cmp	[edx + ICMP_header.Type], ICMP_ECHO		; Is this an echo request?
1159 hidnplayr 162
	jne	.check_sockets
163
 
1544 hidnplayr 164
; We well re-use the packet sow e can create the response as fast as possible
165
; Notice: this only works on pure ethernet (however, IP packet options are not a problem this time :)
166
 
1541 hidnplayr 167
	DEBUGF	1,"ICMP_input - echo request\n"
2305 hidnplayr 168
	mov	[edx + ICMP_header.Type], ICMP_ECHOREPLY	; Change Packet type to reply
1159 hidnplayr 169
 
1544 hidnplayr 170
; Update stats (and validate device ptr)
1514 hidnplayr 171
	call	NET_ptr_to_num
1171 hidnplayr 172
	cmp	edi,-1
173
	je	.dump
174
	inc	[ICMP_PACKETS_RX+4*edi]
1185 hidnplayr 175
	inc	[ICMP_PACKETS_TX+4*edi]
1171 hidnplayr 176
 
1159 hidnplayr 177
; exchange dest and source address in IP header
178
; exchange dest and source MAC in ETH header
2305 hidnplayr 179
	mov	esi, [esp]					; Start of buffer
180
	push	dword [esi + ETH_header.DstMAC]
181
	push	dword [esi + ETH_header.SrcMAC]
182
	pop	dword [esi + ETH_header.DstMAC]
183
	pop	dword [esi + ETH_header.SrcMAC]
184
	push	word [esi + ETH_header.DstMAC + 4]
185
	push	word [esi + ETH_header.SrcMAC + 4]
186
	pop	word [esi + ETH_header.DstMAC + 4]
187
	pop	word [esi + ETH_header.SrcMAC + 4]
1159 hidnplayr 188
 
2305 hidnplayr 189
	add	esi, sizeof.ETH_header
190
	push	[esi + IPv4_header.SourceAddress]
191
	push	[esi + IPv4_header.DestinationAddress]
192
	pop	[esi + IPv4_header.SourceAddress]
193
	pop	[esi + IPv4_header.DestinationAddress]
1159 hidnplayr 194
 
195
; Recalculate ip header checksum
2305 hidnplayr 196
	movzx	ecx, [esi + IPv4_header.VersionAndIHL]		; Calculate IP Header length by using IHL field
1544 hidnplayr 197
	and	ecx, 0x0f
198
	shl	cx, 2
2302 hidnplayr 199
	mov	edi, ecx					; IP header length
200
	mov	eax, edx					; ICMP packet start addr
1159 hidnplayr 201
 
2302 hidnplayr 202
	push	esi						; Calculate the IP checksum
203
	xor	edx, edx					;
204
	call	checksum_1					;
205
	call	checksum_2					;
206
	pop	esi						;
2305 hidnplayr 207
	mov	[esi + IPv4_header.HeaderChecksum], dx		;
1544 hidnplayr 208
 
1159 hidnplayr 209
; Recalculate ICMP CheckSum
2305 hidnplayr 210
	movzx	ecx, [esi + IPv4_header.TotalLength]		; Find length of IP Packet
2302 hidnplayr 211
	xchg	ch, cl						;
212
	sub	ecx, edi					; IP packet length - IP header length = ICMP packet length
1159 hidnplayr 213
 
2302 hidnplayr 214
	mov	esi, eax					; Calculate ICMP checksum
215
	xor	edx, edx					;
216
	call	checksum_1					;
217
	call	checksum_2					;
2305 hidnplayr 218
	mov	[eax + ICMP_header.Checksum], dx		;
1544 hidnplayr 219
 
220
; Transmit the packet (notice that packet ptr and packet size have been on stack since start of the procedure!)
1519 hidnplayr 221
	call	[ebx + NET_DEVICE.transmit]
222
	ret
1159 hidnplayr 223
 
1171 hidnplayr 224
 
225
 
226
 
1159 hidnplayr 227
       .check_sockets:
228
	; Look for an open ICMP socket
1541 hidnplayr 229
	; esi = sender ip
1159 hidnplayr 230
 
1541 hidnplayr 231
	mov	ebx, net_sockets
1159 hidnplayr 232
  .try_more:
2305 hidnplayr 233
;        mov     ax , [edx + ICMP_header.Identifier]
1159 hidnplayr 234
  .next_socket:
1541 hidnplayr 235
	mov	ebx, [ebx + SOCKET.NextPtr]
236
	or	ebx, ebx
1159 hidnplayr 237
	jz	.dump
1541 hidnplayr 238
 
239
	cmp	[ebx + SOCKET.Domain], AF_INET4
1159 hidnplayr 240
	jne	.next_socket
1541 hidnplayr 241
 
242
	cmp	[ebx + SOCKET.Protocol], IP_PROTO_ICMP
243
	jne	.next_socket
1171 hidnplayr 244
 
1541 hidnplayr 245
	cmp	[ebx + IP_SOCKET.RemoteIP], esi
246
	jne	.next_socket
1159 hidnplayr 247
 
1541 hidnplayr 248
;        cmp     [esi + ICMP_SOCKET.Identifier], ax
249
;        jne     .next_socket
250
 
251
;        call    IPv4_dest_to_dev
252
;        cmp     edi,-1
253
;        je      .dump
254
;        inc     [ICMP_PACKETS_RX+edi]
255
 
256
	DEBUGF 1,"Found valid ICMP packet for socket %x\n", ebx
257
 
258
	mov	eax, ebx
259
	add	ebx, SOCKET.lock
1159 hidnplayr 260
	call	wait_mutex
261
 
1541 hidnplayr 262
	mov	esi, edx
1519 hidnplayr 263
	jmp	SOCKET_input
1159 hidnplayr 264
 
1541 hidnplayr 265
 
1544 hidnplayr 266
  .checksum_mismatch:
267
	DEBUGF	1,"ICMP_Handler - checksum mismatch\n"
268
 
269
  .dump:
1159 hidnplayr 270
	DEBUGF	1,"ICMP_Handler - dumping\n"
271
 
272
	call	kernel_free
1249 hidnplayr 273
	add	esp, 4 ; pop (balance stack)
1159 hidnplayr 274
 
275
	ret
276
 
277
 
1257 hidnplayr 278
;-----------------------------------------------------------------
1159 hidnplayr 279
;
1519 hidnplayr 280
; ICMP_output
1159 hidnplayr 281
;
1519 hidnplayr 282
; IN:  eax = dest ip
283
;      ebx = source ip
284
;      ecx = data length
285
;      dh  = type
286
;      dl  = code
287
;      high 16 bits of edx = fragment id (for IP header)
288
;      esi = data offset
289
;      edi = identifier shl 16 + sequence number
1159 hidnplayr 290
;
291
;-----------------------------------------------------------------
292
align 4
1514 hidnplayr 293
ICMP_output:
1159 hidnplayr 294
 
1519 hidnplayr 295
	DEBUGF	1,"Creating ICMP Packet\n"
1159 hidnplayr 296
 
297
	push	esi edi edx
298
 
1541 hidnplayr 299
	mov	ebx, [eax + IP_SOCKET.LocalIP]
300
	mov	eax, [eax + IP_SOCKET.RemoteIP]
2305 hidnplayr 301
	add	ecx, sizeof.ICMP_header
1529 hidnplayr 302
	mov	di , IP_PROTO_ICMP SHL 8 + 128	; TTL
1159 hidnplayr 303
	shr	edx, 16
304
 
1529 hidnplayr 305
	call	IPv4_output
1514 hidnplayr 306
	jz	.exit
1159 hidnplayr 307
 
1519 hidnplayr 308
	DEBUGF	1,"full icmp packet size: %u\n", edx
1165 hidnplayr 309
 
1159 hidnplayr 310
	pop	eax
2305 hidnplayr 311
	mov	word [edi + ICMP_header.Type], ax	; Write both type and code bytes at once
1159 hidnplayr 312
	pop	eax
2305 hidnplayr 313
	mov	[edi + ICMP_header.SequenceNumber], ax
1159 hidnplayr 314
	shr	eax, 16
2305 hidnplayr 315
	mov	[edi + ICMP_header.Identifier], ax
316
	mov	[edi + ICMP_header.Checksum], 0
1159 hidnplayr 317
 
1249 hidnplayr 318
	push	eax ebx ecx edx
319
	mov	esi, edi
320
	xor	edx, edx
321
	call	checksum_1
322
	call	checksum_2
2305 hidnplayr 323
	mov	[edi + ICMP_header.Checksum], dx
1249 hidnplayr 324
	pop	edx ecx ebx eax esi
1159 hidnplayr 325
 
2305 hidnplayr 326
	sub	ecx, sizeof.ICMP_header
327
	add	edi, sizeof.ICMP_header
1159 hidnplayr 328
	push	cx
329
	shr	cx , 2
330
	rep	movsd
331
	pop	cx
332
	and	cx , 3
333
	rep	movsb
334
 
1514 hidnplayr 335
	sub	edi, edx				;;; TODO: find a better way to remember start of packet
1519 hidnplayr 336
	push	edx edi
337
	DEBUGF	1,"Sending ICMP Packet\n"
338
	call	[ebx + NET_DEVICE.transmit]
339
	ret
1159 hidnplayr 340
  .exit:
1519 hidnplayr 341
	DEBUGF	1,"Creating ICMP Packet failed\n"
1165 hidnplayr 342
	add	esp, 3*4
1159 hidnplayr 343
	ret
344
 
345
 
346
 
347
 
1257 hidnplayr 348
;-----------------------------------------------------------------
1159 hidnplayr 349
;
1541 hidnplayr 350
; ICMP_output
351
;
352
; IN:  eax = socket ptr
353
;      ecx = data length
354
;      esi = data offset
355
;
356
;-----------------------------------------------------------------
357
align 4
358
ICMP_output_raw:
359
 
360
	DEBUGF	1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
361
 
362
	push	edx
363
 
364
	mov	di, IP_PROTO_ICMP SHL 8 + 128  ; TTL
365
	shr	edx, 16
366
	mov	ebx, [eax + IP_SOCKET.LocalIP]
367
	mov	eax, [eax + IP_SOCKET.RemoteIP]
368
	call	IPv4_output
369
	jz	.exit
370
 
371
	pop	esi
372
	push	edx
373
	push	eax
374
 
375
	push	edi ecx
376
	DEBUGF	1,"copying %u bytes from %x to %x\n", ecx, esi, edi
377
	rep	movsb
378
	pop	ecx edi
379
 
2305 hidnplayr 380
	mov	[edi + ICMP_header.Checksum], 0
1541 hidnplayr 381
 
382
	mov	esi, edi
383
	xor	edx, edx
384
	call	checksum_1
385
	call	checksum_2
2305 hidnplayr 386
	mov	[edi + ICMP_header.Checksum], dx
1541 hidnplayr 387
 
388
	DEBUGF	1,"Sending ICMP Packet\n"
389
	call	[ebx + NET_DEVICE.transmit]
390
	ret
391
  .exit:
392
	DEBUGF	1,"Creating ICMP Packet failed\n"
393
	add	esp, 4
394
	ret
395
 
396
 
397
 
398
 
399
;-----------------------------------------------------------------
400
;
1159 hidnplayr 401
; ICMP_API
402
;
403
; This function is called by system function 75
404
;
405
; IN:  subfunction number in bl
406
;      device number in bh
407
;      ecx, edx, .. depends on subfunction
408
;
409
; OUT:
410
;
1257 hidnplayr 411
;-----------------------------------------------------------------
1159 hidnplayr 412
align 4
413
ICMP_API:
414
 
415
	movzx	eax, bh
416
	shl	eax, 2
417
 
418
	test	bl, bl
419
	jz	.packets_tx	; 0
420
	dec	bl
421
	jz	.packets_rx	; 1
422
 
423
.error:
424
	mov	eax, -1
425
	ret
426
 
427
.packets_tx:
428
	add	eax, ICMP_PACKETS_TX
429
	mov	eax, [eax]
430
	ret
431
 
432
.packets_rx:
433
	add	eax, ICMP_PACKETS_RX
434
	mov	eax, [eax]
435
	ret