Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
1196 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2009. 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: 1473 $
1159 hidnplayr 21
 
22
; ICMP types & codes
23
 
24
ICMP_ECHOREPLY		equ	0		; echo reply message
25
 
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
43
 
44
ICMP_SOURCEQUENCH	equ	4		; Packet lost, slow down
45
 
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
51
 
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
57
 
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
62
 
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
67
 
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
82
 
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
87
 
88
 
89
 
90
struct	ICMP_Packet
91
	.Type		db   ?
92
	.Code		db   ?
93
	.Checksum	dw   ?
94
	.Identifier	dw   ?
95
	.SequenceNumber dw   ?
96
	.Data:
97
ends
98
 
99
 
100
align 4
101
uglobal
102
	ICMP_PACKETS_TX 	rd  MAX_IP
103
	ICMP_PACKETS_RX 	rd  MAX_IP
104
endg
105
 
1185 hidnplayr 106
 
107
 
1159 hidnplayr 108
;-----------------------------------------------------------------
109
;
110
; ICMP_init
111
;
112
;  This function resets all ICMP variables
113
;
114
;  IN:  /
115
;  OUT: /
116
;
117
;-----------------------------------------------------------------
118
align 4
119
ICMP_init:
120
 
121
	xor	eax, eax
122
	mov	edi, ICMP_PACKETS_TX
123
	mov	ecx, 2*MAX_IP
124
	rep	stosd
125
 
126
	ret
1171 hidnplayr 127
 
128
 
129
 
130
 
1257 hidnplayr 131
;-----------------------------------------------------------------
1159 hidnplayr 132
;
133
; ICMP_Handler:
134
;
1249 hidnplayr 135
;  this procedure will send reply's to ICMP echo's
136
;  and insert packets into sockets when needed                         ;;; TODO: update this to work with fragmented packets too!
1159 hidnplayr 137
;
138
;  IN:  Pointer to buffer in [esp]
139
;       size of buffer in [esp+4]
140
;       pointer to device struct in ebx
141
;       ICMP Packet size in ecx
142
;       pointer to ICMP Packet data in edx
143
;  OUT: /
144
;
1257 hidnplayr 145
;-----------------------------------------------------------------
1159 hidnplayr 146
align 4
1196 hidnplayr 147
ICMP_handler:	;TODO: works only on pure ethernet right now !
1159 hidnplayr 148
 
1473 hidnplayr 149
	DEBUGF	1,"ICMP_Handler - buf:%x size:%x dev:%x, size:%x, buf:%x\n", [esp], [esp+4], ebx, ecx, edx
1185 hidnplayr 150
	cmp	byte [edx + ICMP_Packet.Type], ICMP_ECHO		    ; Is this an echo request?
1159 hidnplayr 151
	jne	.check_sockets
152
 
1473 hidnplayr 153
;;; TODO: check checksum!
154
 
155
	DEBUGF	1,"ICMP_Handler - is echo request, through device:%x\n", ebx
156
 
1159 hidnplayr 157
	mov	byte [edx + ICMP_Packet.Type], ICMP_ECHOREPLY		    ; Change Packet type to reply
158
	mov	word [edx + ICMP_Packet.Checksum], 0			    ; Set checksum to 0, needed to calculate new checksum
159
 
1171 hidnplayr 160
	call	ETH_struc2dev
161
	cmp	edi,-1
162
	je	.dump
163
	inc	[ICMP_PACKETS_RX+4*edi]
1185 hidnplayr 164
	inc	[ICMP_PACKETS_TX+4*edi]
1171 hidnplayr 165
 
1159 hidnplayr 166
; exchange dest and source address in IP header
167
; exchange dest and source MAC in ETH header
168
	mov	esi, [esp]
169
 
170
	mov	eax, dword [esi + ETH_FRAME.DstMAC]
171
	mov	ecx, dword [esi + ETH_FRAME.SrcMAC]
172
	mov	dword [esi + ETH_FRAME.SrcMAC], eax
173
	mov	dword [esi + ETH_FRAME.DstMAC], ecx
174
 
175
	mov	ax, word [esi + ETH_FRAME.DstMAC + 4]
176
	mov	cx, word [esi + ETH_FRAME.SrcMAC + 4]
177
	mov	word [esi + ETH_FRAME.SrcMAC + 4], ax
178
	mov	word [esi + ETH_FRAME.DstMAC + 4], cx
179
 
180
	mov	eax, dword [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress]
181
	mov	ecx, dword [esi + ETH_FRAME.Data + IPv4_Packet.DestinationAddress]
182
	mov	dword [esi + ETH_FRAME.Data + IPv4_Packet.DestinationAddress], eax
183
	mov	dword [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress], ecx
184
 
185
; Recalculate ip header checksum
186
	add	esi, ETH_FRAME.Data					    ; Point esi to start of IP Packet
1249 hidnplayr 187
	movzx	ecx, byte [esi + IPv4_Packet.VersionAndIHL]		    ; Calculate IP Header length by using IHL field
188
	and	ecx, 0x0000000F 					    ;
189
	shl	cx , 2
190
	push	ebx edx ecx esi
191
	xor	edx, edx
192
	call	checksum_1
193
	call	checksum_2
194
	pop	esi
195
	mov	word [esi + IPv4_Packet.HeaderChecksum], dx		    ; Store it in the IP Packet header
1159 hidnplayr 196
 
197
; Recalculate ICMP CheckSum
1249 hidnplayr 198
	movzx	eax, word[esi + IPv4_Packet.TotalLength]		    ; Find length of IP Packet
1159 hidnplayr 199
	xchg	ah , al 						    ;
1249 hidnplayr 200
	sub	eax, [esp]						     ; Now we know the length of ICMP data in eax
201
	mov	ecx, eax
202
	mov	esi, [esp + 4]
203
	xor	edx, edx
204
	call	checksum_1
205
	call	checksum_2
206
	mov	ax , dx
207
	pop	ecx edx ebx
1159 hidnplayr 208
	mov	word [edx + ICMP_Packet.Checksum], ax
209
 
1249 hidnplayr 210
	jmp	ETH_sender						    ; Send the reply
1159 hidnplayr 211
 
1171 hidnplayr 212
 
213
 
214
 
215
 
1159 hidnplayr 216
       .check_sockets:
1206 hidnplayr 217
	; TODO: validate the header & checksum.
1159 hidnplayr 218
 
219
	; Look for an open ICMP socket
220
 
221
	mov	esi, net_sockets
222
  .try_more:
223
	mov	ax , [edx + ICMP_Packet.Identifier]
224
  .next_socket:
1249 hidnplayr 225
	mov	esi, [esi + SOCKET_head.NextPtr]
1159 hidnplayr 226
	or	esi, esi
227
	jz	.dump
1249 hidnplayr 228
	cmp	[esi + SOCKET_head.Type], IP_PROTO_ICMP
1159 hidnplayr 229
	jne	.next_socket
1249 hidnplayr 230
	cmp	[esi + SOCKET_head.end + IPv4_SOCKET.end + ICMP_SOCKET.Identifier], ax
1159 hidnplayr 231
	jne	.next_socket
232
 
1171 hidnplayr 233
	call	IPv4_dest_to_dev
234
	cmp	edi,-1
235
	je	.dump
236
	inc	[ICMP_PACKETS_RX+4*edi]
237
 
1159 hidnplayr 238
	DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
239
 
1249 hidnplayr 240
	lea	ebx, [esi + SOCKET_head.lock]
1159 hidnplayr 241
	call	wait_mutex
242
 
1249 hidnplayr 243
	; Now, assign data to socket. We have socket address in esi.
1159 hidnplayr 244
	; We have ICMP Packet in edx
245
	; number of bytes in ecx
246
 
1249 hidnplayr 247
	mov	eax, esi
1159 hidnplayr 248
	pop	esi
1249 hidnplayr 249
	add	esp, 4
250
	sub	edx, esi
251
	mov	edi, edx
252
	jmp	socket_internal_receiver
1159 hidnplayr 253
 
254
       .dump:
255
	DEBUGF	1,"ICMP_Handler - dumping\n"
256
 
257
	call	kernel_free
1249 hidnplayr 258
	add	esp, 4 ; pop (balance stack)
1159 hidnplayr 259
 
260
	ret
261
 
262
 
1257 hidnplayr 263
;-----------------------------------------------------------------
1159 hidnplayr 264
;
265
; ICMP_Handler_fragments:
266
;
267
;  Called by IP_handler,
268
;  this procedure will send reply's to ICMP echo's etc
269
;
270
;  IN:  Pointer to buffer in [esp]
271
;       size of buffer in [esp+4]
272
;       pointer to device struct in ebx
273
;       ICMP Packet size in ecx
274
;       pointer to ICMP Packet data in edx
275
;  OUT: /
276
;
1257 hidnplayr 277
;-----------------------------------------------------------------
1159 hidnplayr 278
align 4
1196 hidnplayr 279
ICMP_handler_fragments:   ; works only on pure ethernet right now !
1159 hidnplayr 280
 
281
	DEBUGF	1,"ICMP_Handler_fragments - start\n"
282
 
283
	cmp	ecx, 65500
284
	jg	.dump
285
 
286
	cmp	byte [edx + ICMP_Packet.Type], ICMP_ECHO		    ; Is this an echo request? discard if not
287
	jne	.dump
288
 
289
	mov	esi, [esp]
290
 
291
	sub	ecx, ICMP_Packet.Data
292
	mov	eax, [esi + IPv4_Packet.SourceAddress]
293
	mov	ebx, [esi + IPv4_Packet.DestinationAddress]
294
	push	word [esi + IPv4_Packet.Identification]
295
 
296
	mov	di , [edx + ICMP_Packet.Identifier]
297
	shl	edi, 16
298
	mov	di , [edx + ICMP_Packet.SequenceNumber]
299
 
300
	mov	esi, edx
301
	add	esi, ICMP_Packet.Data
302
	pop	dx
303
	shl	edx, 16
304
	mov	dx , ICMP_ECHOREPLY shl 8 + 0				    ; Type + Code
305
 
1196 hidnplayr 306
	call	ICMP_create_packet
1159 hidnplayr 307
 
308
       .dump:
309
	DEBUGF	1,"ICMP_Handler_fragments - end\n"
310
 
311
	call	kernel_free
1249 hidnplayr 312
	add	esp, 4 ; pop (balance stack)
1159 hidnplayr 313
	ret
314
 
1257 hidnplayr 315
 
1159 hidnplayr 316
;-----------------------------------------------------------------
317
;
318
; Note: ICMP only works on top of IP protocol :)
319
;
320
; inputs:
321
;
322
; eax = dest ip
323
; ebx = source ip
324
; ecx = data length
325
; dh = type
326
; dl = code
327
; high 16 bits of edx = fragment id (for IP header)
328
; esi = data offset
329
; edi = identifier shl 16 + sequence number
330
;
331
;-----------------------------------------------------------------
332
align 4
1196 hidnplayr 333
ICMP_create_packet:
1159 hidnplayr 334
 
335
	DEBUGF 1,"Create ICMP Packet\n"
336
 
337
	push	esi edi edx
338
 
339
	add	ecx, ICMP_Packet.Data
340
	mov	di , IP_PROTO_ICMP
341
	shr	edx, 16
342
 
1196 hidnplayr 343
	call	IPv4_create_packet
1159 hidnplayr 344
 
345
	cmp	edi, -1
346
	je	.exit
347
 
1206 hidnplayr 348
	DEBUGF 1,"full icmp packet size: %u\n", edx
1165 hidnplayr 349
 
1159 hidnplayr 350
	pop	eax
351
	mov	word [edi + ICMP_Packet.Type], ax	; Write both type and code bytes at once
352
	pop	eax
353
	mov	[edi + ICMP_Packet.SequenceNumber], ax
354
	shr	eax, 16
355
	mov	[edi + ICMP_Packet.Identifier], ax
356
	mov	[edi + ICMP_Packet.Checksum], 0
357
 
1249 hidnplayr 358
	push	eax ebx ecx edx
359
	mov	esi, edi
360
	xor	edx, edx
361
	call	checksum_1
362
	call	checksum_2
363
	mov	[edi + ICMP_Packet.Checksum], dx
364
	pop	edx ecx ebx eax esi
1159 hidnplayr 365
 
366
	sub	ecx, ICMP_Packet.Data
367
	add	edi, ICMP_Packet.Data
368
	push	cx
369
	shr	cx , 2
370
	rep	movsd
371
	pop	cx
372
	and	cx , 3
373
	rep	movsb
374
 
1206 hidnplayr 375
	sub	edi, edx  ;; TODO: find a better way to remember start of packet
1159 hidnplayr 376
	mov	ecx, [ebx + ETH_DEVICE.transmit]
377
	push	edx edi ecx
378
	DEBUGF 1,"Sending ICMP Packet\n"
379
	ret						; Send the packet (create_packet routine outputs pointer to routine to send packet in eax)
380
 
381
  .exit:
1165 hidnplayr 382
	DEBUGF 1,"Creating ICMP Packet failed\n"
383
	add	esp, 3*4
1159 hidnplayr 384
	ret
385
 
386
 
387
 
388
 
1257 hidnplayr 389
;-----------------------------------------------------------------
1159 hidnplayr 390
;
391
; ICMP_API
392
;
393
; This function is called by system function 75
394
;
395
; IN:  subfunction number in bl
396
;      device number in bh
397
;      ecx, edx, .. depends on subfunction
398
;
399
; OUT:
400
;
1257 hidnplayr 401
;-----------------------------------------------------------------
1159 hidnplayr 402
align 4
403
ICMP_API:
404
 
405
	movzx	eax, bh
406
	shl	eax, 2
407
 
408
	test	bl, bl
409
	jz	.packets_tx	; 0
410
	dec	bl
411
	jz	.packets_rx	; 1
412
 
413
.error:
414
	mov	eax, -1
415
	ret
416
 
417
.packets_tx:
418
	add	eax, ICMP_PACKETS_TX
419
	mov	eax, [eax]
420
	ret
421
 
422
.packets_rx:
423
	add	eax, ICMP_PACKETS_RX
424
	mov	eax, [eax]
425
	ret