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
;;                                                                 ;;
1249 hidnplayr 6
;;  IPv4.INC                                                       ;;
1159 hidnplayr 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
 
1206 hidnplayr 19
$Revision: 1473 $
1159 hidnplayr 20
 
21
; IP underlying protocols numbers
22
 
23
ETHER_IPv4	equ 0x0008	; Reversed from 0800 for intel
24
 
25
MAX_FRAGMENTS	equ 16
26
MAX_IP		equ MAX_NET_DEVICES
27
 
28
struct	IPv4_Packet
29
	.VersionAndIHL		db  ?  ; Version[0-3 bits] and IHL(header length)[4-7 bits]
30
	.TypeOfService		db  ?
31
	.TotalLength		dw  ?
32
	.Identification 	dw  ?
33
	.FlagsAndFragmentOffset dw  ?  ; Flags[0-2] and FragmentOffset[3-15]
34
	.TimeToLive		db  ?  ;
35
	.Protocol		db  ?
36
	.HeaderChecksum 	dw  ?
37
	.SourceAddress		dd  ?
38
	.DestinationAddress	dd  ?
39
	.DataOrOptional:
40
ends
41
 
42
struct	FRAGMENT_slot
43
	.ttl			dw  ?  ; Time to live for this entry, 0 for empty slot's
44
	.id			dw  ?  ; Identification field from IP header
45
	.SrcIP			dd  ?  ; .. from IP header
46
	.DstIP			dd  ?  ; .. from IP header
47
	.ptr			dd  ?  ; Pointer to first packet
48
	.size:
49
ends
50
 
51
struct	FRAGMENT_entry		       ; This structure will replace the ethernet header in fragmented ip packets
52
	.PrevPtr		dd  ?  ; Pointer to previous fragment entry  (-1 for first packet)
53
	.NextPtr		dd  ?  ; Pointer to next fragment entry (-1 for last packet)
54
	.Owner			dd  ?  ; Pointer to structure of driver
1249 hidnplayr 55
				rb  2  ; to match ethernet header size          ; TODO: fix this hack
1159 hidnplayr 56
	.Data:			       ; Ip header begins here (we will need the IP header to re-construct the complete packet)
57
ends
58
 
59
align 4
60
uglobal
61
	BROADCAST	dd  ?
62
	IP_LIST 	rd  MAX_IP
63
	SUBNET_LIST	rd  MAX_IP
64
	DNS_LIST	rd  MAX_IP
65
	GATEWAY_LIST	rd  MAX_IP
66
	IP_PACKETS_TX	rd  MAX_IP
67
	IP_PACKETS_RX	rd  MAX_IP
68
	FRAGMENT_LIST	rb  MAX_FRAGMENTS*FRAGMENT_slot.size
69
endg
70
 
71
 
72
;-----------------------------------------------------------------
73
;
74
; IPv4_init
75
;
76
;  This function resets all IP variables
77
;
78
;  IN:  /
79
;  OUT: /
80
;
81
;-----------------------------------------------------------------
82
align 4
83
IPv4_init:
84
 
85
	or	eax, -1
86
	mov	edi, BROADCAST
1200 hidnplayr 87
	mov	ecx, 4*MAX_IP+1
1159 hidnplayr 88
	rep	stosd
89
 
90
	xor	eax, eax
91
	mov	edi, FRAGMENT_LIST
92
	mov	ecx, FRAGMENT_slot.size*MAX_FRAGMENTS/4 + 2*MAX_IP
93
	rep	stosd
94
 
95
	ret
96
 
97
 
98
 
99
;-----------------------------------------------------------------
100
;
1249 hidnplayr 101
; IPv4_Handler:
1159 hidnplayr 102
;
1249 hidnplayr 103
;  Will check if IP Packet isnt damaged
1159 hidnplayr 104
;  and call appropriate handler. (TCP/UDP/ICMP/..)
105
;
106
;  It will also re-construct fragmented packets
107
;
108
;  IN:  Pointer to buffer in [esp]
109
;       size of buffer in [esp+4]
110
;       pointer to device struct in ebx
111
;       pointer to IP Packet data in edx
112
;  OUT: /
113
;
114
;-----------------------------------------------------------------
115
align 4
1473 hidnplayr 116
IPv4_handler:	 ; TODO: implement handler for IP options
1257 hidnplayr 117
		 ; TODO2: add code for IPv4 sockets (raw sockets)
1159 hidnplayr 118
 
119
	DEBUGF	1,"IP_Handler - start\n"
120
 
121
 
1473 hidnplayr 122
;-------------------------------------------
123
; Check if the packet still has time to live
1159 hidnplayr 124
 
1473 hidnplayr 125
	cmp	byte [edx + IPv4_Packet.TimeToLive], 0
126
	je	.dump
127
 
128
;--------------------------------------
129
; First, check if IP packet has options
130
 
131
	movzx	eax, [edx + IPv4_Packet.VersionAndIHL]
132
	and	al , 0x0f					; get IHL(header length)
133
	cmp	al , 0x05					; IHL!= 5*4(20 bytes)
134
	jnz	.has_options
135
 
136
 
137
;-------------------------------
138
; Now, re-calcualte the checksum
139
 
1249 hidnplayr 140
	; Re-calculate checksum
1473 hidnplayr 141
	push	edx ebx
1249 hidnplayr 142
	mov	esi, edx
1473 hidnplayr 143
	call	checksum_ip_header
144
	pop	ebx edx
1249 hidnplayr 145
 
1473 hidnplayr 146
	; now see if it was correct
147
	cmp	[edx + IPv4_Packet.HeaderChecksum], 0
1249 hidnplayr 148
	jne	.dump						; if checksum isn't valid then dump packet
149
 
1473 hidnplayr 150
	DEBUGF	1,"IPv4 Checksum is correct\n"
1254 hidnplayr 151
 
1473 hidnplayr 152
;-------------------------------------------------------
153
; Time to find out what interface this packet belongs to
154
 
155
; Therefore we will scan the current list of IP's
156
 
1159 hidnplayr 157
	mov	eax, [edx + IPv4_Packet.DestinationAddress]
158
	mov	edi, BROADCAST
159
	mov	ecx, MAX_IP+1
1473 hidnplayr 160
 
161
  .find_ip_loop:
162
	cmp	eax, dword [edi]
1159 hidnplayr 163
	jz	.ip_ok
1473 hidnplayr 164
	add	edi, 4
165
	dec	ecx
166
	jnz	.find_ip_loop
1159 hidnplayr 167
 
1473 hidnplayr 168
	; it was not on the list, perhaps it's a loopback ?
1159 hidnplayr 169
	not	eax
170
	test	eax, 127 shl 24 ; 127.x.x.x
171
	jz	.ip_ok
172
 
1473 hidnplayr 173
	;  TODO: we need to check for broadcasts (other then 255.255.255.255)
1159 hidnplayr 174
 
1473 hidnplayr 175
	DEBUGF	2,"Destination address does not match!\n"
176
 
1159 hidnplayr 177
	jmp	.dump
178
 
1473 hidnplayr 179
 
180
;---------------------------------------------------
181
; Now we can update stats and find the device number
182
 
1159 hidnplayr 183
  .ip_ok:
1171 hidnplayr 184
	call	ETH_struc2dev					; TODO: make this work on other protocols too!
185
	inc	[IP_PACKETS_RX+4*edi]
1473 hidnplayr 186
	DEBUGF	1,"Packet comes from %u.%u.%u.%u\n",\
1159 hidnplayr 187
	[edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
188
 
189
 
190
 
191
 
1473 hidnplayr 192
;----------------------------------
193
; Check if the packet is fragmented
1159 hidnplayr 194
 
1473 hidnplayr 195
	test	[edx + IPv4_Packet.FlagsAndFragmentOffset], 1 shl 5	; Is 'more fragments' flag set ?
196
	jnz	.has_fragments						; If so, we definately have a fragmented packet
1159 hidnplayr 197
 
1473 hidnplayr 198
	test	[edx + IPv4_Packet.FlagsAndFragmentOffset], 0xff1f	; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
199
	jnz	.is_last_fragment
200
 
201
 
202
 
203
;-------------------------------------------------------------------
204
; No, it's just a regular IP packet, pass it to the higher protocols
205
 
206
  .handle_it:							; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
1159 hidnplayr 207
	movzx	eax, byte [edx + IPv4_Packet.VersionAndIHL]	; Calculate Header length by using IHL field
208
	and	eax, 0x0000000F 				;
209
	shl	eax, 2						;
210
	movzx	ecx, word [edx + IPv4_Packet.TotalLength]	; Calculate length of encapsulated Packet
211
	xchg	cl , ch 					;
212
	sub	ecx, eax					;
213
 
214
	add	eax, edx
215
	push	eax
1473 hidnplayr 216
 
217
	mov	esi, [edx + IPv4_Packet.SourceAddress]		; These values might be of interest to the higher protocols
218
	mov	edi, [edx + IPv4_Packet.DestinationAddress]	;
1159 hidnplayr 219
	mov	al , [edx + IPv4_Packet.Protocol]
220
	pop	edx						; Offset to data (tcp/udp/icmp/.. Packet)
221
 
222
	cmp	al , IP_PROTO_TCP
1249 hidnplayr 223
	je	TCP_handler
1159 hidnplayr 224
 
225
	cmp	al , IP_PROTO_UDP
1196 hidnplayr 226
	je	UDP_handler
1159 hidnplayr 227
 
228
	cmp	al , IP_PROTO_ICMP
1196 hidnplayr 229
	je	ICMP_handler
1159 hidnplayr 230
 
1473 hidnplayr 231
	DEBUGF	2,"unknown Internet protocol: %u\n", al
1159 hidnplayr 232
 
233
  .dump:
1473 hidnplayr 234
	DEBUGF	2,"IP_Handler - dumping\n"
1159 hidnplayr 235
;        inc     [dumped_rx_count]
236
	call	kernel_free
237
	add	esp, 4						; pop (balance stack)
238
	ret
239
 
240
 
1473 hidnplayr 241
;---------------------------
242
; Fragmented packet handler
243
 
244
 
245
  .has_fragments:
246
	movzx	eax, [edx + IPv4_Packet.FlagsAndFragmentOffset]
247
	xchg	al , ah
1159 hidnplayr 248
	shl	ax , 3
1473 hidnplayr 249
 
1159 hidnplayr 250
	DEBUGF	1,"Fragmented packet, offset:%u, id:%x\n", ax, [edx + IPv4_Packet.Identification]:4
251
 
252
	test	ax , ax 					; Is this the first packet of the fragment?
1473 hidnplayr 253
	jz	.is_first_fragment
1159 hidnplayr 254
 
1473 hidnplayr 255
 
256
;-------------------------------------------------------
257
; We have a fragmented IP packet, but it's not the first
258
 
259
	DEBUGF	1,"Middle fragmented packet received!\n"
260
 
261
	call	IPv4_find_fragment_slot
262
	cmp	esi, -1
263
	je	.dump
264
 
265
	mov	word [esi + FRAGMENT_slot.ttl], 15		; Reset the ttl
266
	mov	esi, [esi + FRAGMENT_slot.ptr]
267
	or	edi, -1
268
  .find_last_entry:						; The following routine will try to find the last entry
269
	cmp	edi, [esi + FRAGMENT_entry.PrevPtr]
270
	jne	.destroy_slot					; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
271
	mov	edi, esi
272
	mov	esi, [esi + FRAGMENT_entry.NextPtr]
273
	cmp	esi, -1
274
	jne	.find_last_entry
275
								; We found the last entry (pointer is now in edi)
276
								; We are going to overwrite the ethernet header in received packet with a FRAGMENT_entry structure
277
 
278
	pop	eax						; pointer to packet
279
	mov	[edi + FRAGMENT_entry.NextPtr], eax		; update pointer of previous entry to the new entry
280
	mov	[eax + FRAGMENT_entry.NextPtr], -1
281
	mov	[eax + FRAGMENT_entry.PrevPtr], edi
282
	mov	[eax + FRAGMENT_entry.Owner], ebx
283
 
284
	add	esp, 4
285
	ret
286
 
287
 
288
;------------------------------------
289
; We have received the first fragment
290
 
291
  .is_first_fragment:
1159 hidnplayr 292
	DEBUGF	1,"First fragmented packet received!\n"
293
								; try to locate a free slot..
294
	mov	ecx, MAX_FRAGMENTS
295
	mov	esi, FRAGMENT_LIST
1473 hidnplayr 296
  .find_free_slot:
1159 hidnplayr 297
	cmp	word [esi + FRAGMENT_slot.ttl], 0
298
	je	.found_free_slot
299
	add	esi, FRAGMENT_slot.size
300
	loop	.find_free_slot
301
	jmp	.dump						; If no free slot was found, dump the packet
302
 
1473 hidnplayr 303
  .found_free_slot:						; We found a free slot, let's fill in the FRAGMENT_slot structure
1159 hidnplayr 304
	mov	word [esi + FRAGMENT_slot.ttl], 15		; RFC recommends 15 secs as ttl
305
	mov	ax , word [edx + IPv4_Packet.Identification]
306
	mov	word [esi + FRAGMENT_slot.id], ax
307
	mov	eax, dword [edx + IPv4_Packet.SourceAddress]
308
	mov	dword [esi + FRAGMENT_slot.SrcIP], eax
309
	mov	eax, dword [edx + IPv4_Packet.DestinationAddress]
310
	mov	dword [esi + FRAGMENT_slot.DstIP], eax
311
	pop	eax
312
	mov	dword [esi + FRAGMENT_slot.ptr], eax
313
								; Now, replace ethernet header in original buffer with a FRAGMENT_entry structure
314
	mov	[eax + FRAGMENT_entry.NextPtr], -1
315
	mov	[eax + FRAGMENT_entry.PrevPtr], -1
316
	mov	[eax + FRAGMENT_entry.Owner], ebx
317
 
318
	add	esp, 4						; balance stack and exit
319
	ret
320
 
321
 
1473 hidnplayr 322
;-----------------------------------
323
; We have received the last fragment
1159 hidnplayr 324
 
1473 hidnplayr 325
  .is_last_fragment:
326
	DEBUGF	1,"Last fragmented packet received!\n"
1159 hidnplayr 327
 
1473 hidnplayr 328
	call	IPv4_find_fragment_slot
1159 hidnplayr 329
	cmp	esi, -1
330
	je	.dump
331
 
332
	mov	esi, [esi + FRAGMENT_slot.ptr]			; We found the first entry, let's calculate total size of the packet in eax, so we can allocate a buffer
333
	push	esi
1473 hidnplayr 334
	xor	eax, eax
1159 hidnplayr 335
	or	edi, -1
1473 hidnplayr 336
 
337
  .count_bytes:
1159 hidnplayr 338
	cmp	[esi + FRAGMENT_entry.PrevPtr], edi
1473 hidnplayr 339
	jne	.destroy_slot_pop						  ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
1159 hidnplayr 340
	mov	cx, word [esi + FRAGMENT_entry.Data + IPv4_Packet.TotalLength]	  ; Add total length
341
	xchg	cl, ch
342
	DEBUGF	1,"Packet size: %u\n", cx
343
	add	ax, cx
344
	movzx	cx, byte [esi + FRAGMENT_entry.Data + IPv4_Packet.VersionAndIHL]  ; Sub Header length
345
	and	cx, 0x000F
346
	shl	cx, 2
347
	DEBUGF	1,"Header size: %u\n", cx
348
	sub	ax, cx
349
	mov	edi, esi
350
	mov	esi, [esi + FRAGMENT_entry.NextPtr]
351
	cmp	esi, -1
352
	jne	.count_bytes
353
 
354
	mov	esi, [esp+4]  ;;;
355
	mov	[edi + FRAGMENT_entry.NextPtr], esi			       ; Add this packet to the chain, this simplifies the following code
356
	mov	[esi + FRAGMENT_entry.NextPtr], -1
357
	mov	[esi + FRAGMENT_entry.PrevPtr], edi
358
	mov	[esi + FRAGMENT_entry.Owner], ebx
359
 
360
	mov	cx, [edx + IPv4_Packet.TotalLength]			       ; Note: This time we dont substract Header length
361
	xchg	cl , ch
362
	DEBUGF	1,"Packet size: %u\n", cx
363
	add	ax , cx
364
	DEBUGF	1,"Total Received data size: %u\n", eax
365
 
366
	push	eax
367
	mov	ax , [edx + IPv4_Packet.FlagsAndFragmentOffset]
368
	xchg	al , ah
369
	shl	ax , 3
370
	add	cx , ax
371
	pop	eax
372
	DEBUGF	1,"Total Fragment size: %u\n", ecx
373
 
374
	cmp	ax, cx
375
	jne	.destroy_slot_pop
376
 
377
	push	eax
378
	push	eax
379
	call	kernel_alloc
380
	test	eax, eax
381
	je	.destroy_slot_pop							; If we dont have enough space to allocate the buffer, discard all packets in slot
382
	mov	edx, [esp+4]								; Get pointer to first fragment entry back in edx
383
 
1473 hidnplayr 384
  .rebuild_packet_loop:
1159 hidnplayr 385
	movzx	ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.FlagsAndFragmentOffset]	; Calculate the fragment offset
1473 hidnplayr 386
	xchg	cl , ch 									;  intel byte order
1159 hidnplayr 387
	shl	cx , 3										;   multiply by 8 and clear first 3 bits
388
	DEBUGF	1,"Fragment offset: %u\n", cx
389
 
390
	lea	edi, [eax + ecx]								; Notice that edi will be equal to eax for first fragment
391
	movzx	ebx, byte [edx + FRAGMENT_entry.Data + IPv4_Packet.VersionAndIHL]		; Find header size (in ebx) of fragment
392
	and	bx , 0x000F									;
393
	shl	bx , 2										;
394
 
395
	lea	esi, [edx + FRAGMENT_entry.Data]						; Set esi to the correct begin of fragment
396
	movzx	ecx, word [edx + FRAGMENT_entry.Data + IPv4_Packet.TotalLength] 		; Calculate total length of fragment
397
	xchg	cl, ch										;  intel byte order
398
 
399
	cmp	edi, eax									; Is this packet the first fragment ?
400
	je	.first_fragment
401
	sub	cx, bx										; If not, dont copy the header
402
	add	esi, ebx									;
1473 hidnplayr 403
  .first_fragment:
1159 hidnplayr 404
 
405
	push	cx										; First copy dword-wise, then byte-wise
406
	shr	cx, 2										;
407
	rep	movsd										;
408
	pop	cx										;
409
	and	cx, 3										;
410
	rep	movsb										;
411
 
412
	push	eax
413
	push	edx										; Push pointer to fragment onto stack
1473 hidnplayr 414
	mov	ebx, [edx + FRAGMENT_entry.Owner]						; we need to remeber the owner, in case this is the last packet
1159 hidnplayr 415
	mov	edx, [edx + FRAGMENT_entry.NextPtr]						; Set edx to the next pointer
416
	call	kernel_free									; free the previous fragment buffer (this uses the value from stack)
417
	pop	eax
418
	cmp	edx, -1 									; Check if it is last fragment in chain
419
	jne	.rebuild_packet_loop
420
 
421
	pop	ecx										;
422
	xchg	cl, ch
423
	mov	edx, eax
424
	mov	word [edx + IPv4_Packet.TotalLength], cx
425
	add	esp, 8
426
 
1473 hidnplayr 427
	xchg	cl, ch		    ;
428
 
429
	push	ecx		   ;;;;
430
	push	eax		   ;;;;
431
 
432
;        mov     esi, edx           ;  This prints the IP packet to the debug board (usefull when using serial output debug..)
1159 hidnplayr 433
;                                   ;
434
;       @@:                         ;
435
;        lodsb                      ;
436
;        DEBUGF  1,"%x ", eax:2     ;
437
;        loop    @r                 ;
438
 
1473 hidnplayr 439
	jmp	.handle_it	    ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
1249 hidnplayr 440
 
1473 hidnplayr 441
  .destroy_slot_pop:
442
	add	esp, 4
443
  .destroy_slot:
444
	DEBUGF	1,"Destroy fragment slot!\n"
445
	; TODO!
446
	jmp	.dump
1249 hidnplayr 447
 
448
 
1159 hidnplayr 449
 
450
 
1473 hidnplayr 451
;-----------------------------------
452
; The IP packet has some options
1159 hidnplayr 453
 
1473 hidnplayr 454
  .has_options:
455
	jmp	.dump
1159 hidnplayr 456
 
457
 
1166 hidnplayr 458
 
1159 hidnplayr 459
 
460
 
461
 
462
;-----------------------------------------------------------------
463
;
464
; find fragment slot
465
;
466
; IN: pointer to fragmented packet in edx         ; TODO: the RFC says we should check protocol too
467
; OUT: pointer to slot in edi, -1 on error
468
;
469
;-----------------------------------------------------------------
1473 hidnplayr 470
align 4
471
IPv4_find_fragment_slot:
1159 hidnplayr 472
 
473
	push	eax ebx ecx edx
474
	mov	ax , word [edx + IPv4_Packet.Identification]
475
	mov	ecx, MAX_FRAGMENTS
476
	mov	esi, FRAGMENT_LIST
477
	mov	ebx, dword [edx + IPv4_Packet.SourceAddress]
478
	mov	edx, dword [edx + IPv4_Packet.DestinationAddress]
479
  .find_slot:
480
	cmp	word [esi + FRAGMENT_slot.id], ax
481
	jne	.try_next
482
	cmp	dword [esi + FRAGMENT_slot.SrcIP], ebx
483
	jne	.try_next
484
	cmp	dword [esi + FRAGMENT_slot.DstIP], edx
485
	je	.found_slot
486
  .try_next:
487
	add	esi, FRAGMENT_slot.size
488
	loop	.find_slot
1473 hidnplayr 489
;        pop     edx ebx
1159 hidnplayr 490
	or	esi, -1
491
;        ret
492
 
493
  .found_slot:
494
	pop	edx ecx ebx eax
495
	ret
496
 
497
 
498
;-----------------------------------------------------------------
499
;
500
; Decrease TimeToLive of all fragment slots
501
;
502
; IN: /
503
; OUT: /
504
;
505
;-----------------------------------------------------------------
506
align 4
507
IPv4_decrease_fragment_ttls:
508
 
509
	mov	esi, FRAGMENT_LIST
510
	mov	ecx, MAX_FRAGMENTS
511
  .loop:
512
	cmp	[esi + FRAGMENT_slot.ttl], 0
513
	je	.try_next
514
	dec	[esi + FRAGMENT_slot.ttl]
515
	jnz	.try_next
516
	DEBUGF 1,"Fragment slot timed-out!\n"
517
	; TODO: clear all entry's of timed-out slot
518
  .try_next:
519
	add	esi, 4
520
	loop	.loop
521
	ret
522
 
523
 
524
 
525
 
526
 
527
;-----------------------------------------------------------------
528
;
529
; Create_IPv4_Packet
530
;
531
; IN: eax = dest ip
532
;     ebx = source ip
533
;     ecx = data length
534
;     dx  = fragment id
535
;     di  = protocol
536
;
1249 hidnplayr 537
; OUT: eax = pointer to buffer start
538
;      ebx = pointer to device struct (needed for sending procedure)
1159 hidnplayr 539
;      ecx = unchanged (packet size of embedded data)
1249 hidnplayr 540
;      edx = size of complete buffer
1159 hidnplayr 541
;      esi = pointer to sending procedure
1249 hidnplayr 542
;      edi = pointer to start of data (-1 on error)
1159 hidnplayr 543
;
1257 hidnplayr 544
;----------------------------------------------------------------- ;;; TODO: create fragmented packets
1159 hidnplayr 545
align 4
1196 hidnplayr 546
IPv4_create_packet:
1159 hidnplayr 547
 
1206 hidnplayr 548
	DEBUGF 1,"Create IPv4 Packet (size=%u)\n", ecx
1159 hidnplayr 549
 
1206 hidnplayr 550
	cmp	ecx, 1480
1159 hidnplayr 551
	jg	.exit_
552
 
1251 clevermous 553
	test	ebx, ebx	      ; if dest ip = 0
1208 hidnplayr 554
	jnz	.ip_ok		      ; and local ip is valid
555
				      ; use local ip instead
556
	cmp	[IP_LIST],0xffffffff  ;
557
	je	.ip_ok		      ; TODO: find solution to send broadcast
558
				      ; on device other then device 0
559
	mov	ebx, [IP_LIST]	      ;
560
				      ;
561
  .ip_ok:			      ;
562
 
1206 hidnplayr 563
	push	ecx eax ebx dx di
564
 
1159 hidnplayr 565
	cmp	eax, -1
566
	je	.broadcast		  ; If it is broadcast, just send
567
 
1196 hidnplayr 568
	call	ARP_IP_to_MAC
1159 hidnplayr 569
 
1196 hidnplayr 570
	cmp	eax, -1
1206 hidnplayr 571
	je	.not_found
1196 hidnplayr 572
 
1206 hidnplayr 573
	push	ebx
1196 hidnplayr 574
	push	ax
575
 
576
	jmp	.send
577
 
1159 hidnplayr 578
  .broadcast:
1196 hidnplayr 579
	push	word -1
580
	push	dword -1
1159 hidnplayr 581
 
582
  .send:
583
	call	IPv4_dest_to_dev
1171 hidnplayr 584
	inc	[IP_PACKETS_TX+4*edi]
1206 hidnplayr 585
	mov	edx, [ETH_DRV_LIST + 4*edi]
586
	lea	eax, [edx + ETH_DEVICE.mac]
587
	mov	ebx, esp
588
	mov	ecx, [esp+18]	 ;; 18 or  22 ??
1159 hidnplayr 589
	add	ecx, IPv4_Packet.DataOrOptional
590
	mov	di , ETHER_IPv4
1249 hidnplayr 591
	call	ETH_create_packet		   ; TODO: figure out a way to make this work with other protocols too
1206 hidnplayr 592
	add	esp, 6
1159 hidnplayr 593
	cmp	edi, -1
594
	je	.exit
595
 
596
	mov	[edi + IPv4_Packet.VersionAndIHL], 0x45   ; IPv4, normal length (no Optional header)
597
	mov	[edi + IPv4_Packet.TypeOfService], 0
598
	xchg	ch, cl
599
	mov	[edi + IPv4_Packet.TotalLength], cx
600
	mov	[edi + IPv4_Packet.FlagsAndFragmentOffset], 0x0000
601
	mov	[edi + IPv4_Packet.TimeToLive], 128
602
	mov	[edi + IPv4_Packet.HeaderChecksum], 0
603
	pop	cx
604
	mov	[edi + IPv4_Packet.Protocol], cl
605
	pop	cx
606
	mov	[edi + IPv4_Packet.Identification], cx
607
	pop	ecx
608
	mov	[edi + IPv4_Packet.SourceAddress], ecx
609
	pop	ecx
610
	mov	[edi + IPv4_Packet.DestinationAddress], ecx
611
 
1473 hidnplayr 612
	push	eax edx esi
1249 hidnplayr 613
	mov	esi, edi
1473 hidnplayr 614
	call	checksum_ip_header
615
	pop	esi edx eax ecx
1159 hidnplayr 616
	add	edi, IPv4_Packet.DataOrOptional
617
 
1249 hidnplayr 618
	DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx
1159 hidnplayr 619
 
620
	ret
621
 
1206 hidnplayr 622
 
623
  .not_found:
624
	DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n"
1249 hidnplayr 625
	; TODO: QUEUE the packet to resend later!
1159 hidnplayr 626
  .exit:
1206 hidnplayr 627
	add	esp, 16
1159 hidnplayr 628
  .exit_:
1165 hidnplayr 629
	DEBUGF 1,"Create IPv4 Packet - failed\n"
1159 hidnplayr 630
	or	edi, -1
631
	ret
632
 
633
 
634
 
1206 hidnplayr 635
 
1159 hidnplayr 636
;---------------------------------------------------------------------------
637
;
638
; IPv4_dest_to_dev
639
;
640
; IN: Destination IP in eax
641
; OUT: device id in edi
642
;
643
;---------------------------------------------------------------------------
644
align 4
645
IPv4_dest_to_dev:
646
 
647
	DEBUGF 1,"IPv4 destination to device: "
648
 
649
	xor	edi, edi
650
	mov	ecx, MAX_IP
651
 
652
  .loop:
653
	mov	ebx, [IP_LIST+edi]		; we dont need to worry about non exisiting ip interfaces
654
	and	ebx, [SUBNET_LIST+edi]		; they have IP and SUBNET set to all one's, so they will have no match except 255.255.255.255
655
						; (only a moron would insert that ip into this function..)
656
	mov	edx, eax
657
	and	edx, [SUBNET_LIST+edi]
658
 
659
	cmp	ebx, edx
660
	je	.found_it
661
 
662
	add	edi, 4
663
	loop	.loop
664
 
665
	xor	edi, edi	; if none found, use device 0 as default device
666
 
667
  .found_it:
668
	shr	edi, 2
669
 
1473 hidnplayr 670
	DEBUGF	1,"%u\n",edi
1159 hidnplayr 671
 
672
	ret
673
 
674
 
675
 
676
;---------------------------------------------------------------------------
677
;
678
; IPv4_get_frgmnt_num
679
;
680
; IN: /
681
; OUT: fragment number in ax
682
;
683
;---------------------------------------------------------------------------
684
align 4
685
IPv4_get_frgmnt_num:
686
	xor	ax, ax	;;; TODO: replace this with real code
687
 
688
	ret
689
 
690
 
691
;---------------------------------------------------------------------------
692
;
693
; IPv4_API
694
;
695
; This function is called by system function 75
696
;
697
; IN:  subfunction number in bl
698
;      device number in bh
699
;      ecx, edx, .. depends on subfunction
700
;
701
; OUT:
702
;
703
;---------------------------------------------------------------------------
704
align 4
705
IPv4_API:
706
 
707
	movzx	eax, bh
708
	shl	eax, 2
709
 
710
	test	bl, bl
711
	jz	.packets_tx	; 0
712
	dec	bl
713
	jz	.packets_rx	; 1
714
	dec	bl
715
	jz	.read_ip	; 2
716
	dec	bl
717
	jz	.write_ip	; 3
718
	dec	bl
719
	jz	.read_dns	; 4
720
	dec	bl
721
	jz	.write_dns	; 5
722
	dec	bl
723
	jz	.read_subnet	; 6
724
	dec	bl
725
	jz	.write_subnet	; 7
726
	dec	bl
727
	jz	.read_gateway	; 8
728
	dec	bl
729
	jz	.write_gateway	; 9
730
 
1473 hidnplayr 731
  .error:
1159 hidnplayr 732
	mov	eax, -1
733
	ret
734
 
1473 hidnplayr 735
  .packets_tx:
1159 hidnplayr 736
	add	eax, IP_PACKETS_TX
737
	mov	eax, [eax]
738
	ret
739
 
1473 hidnplayr 740
  .packets_rx:
1159 hidnplayr 741
	add	eax, IP_PACKETS_RX
742
	mov	eax, [eax]
743
	ret
744
 
1473 hidnplayr 745
  .read_ip:
1159 hidnplayr 746
	add	eax, IP_LIST
747
	mov	eax, [eax]
748
	ret
749
 
1473 hidnplayr 750
  .write_ip:
1159 hidnplayr 751
	add	eax, IP_LIST
752
	mov	[eax], ecx
753
	xor	eax, eax
754
	ret
755
 
1473 hidnplayr 756
  .read_dns:
1159 hidnplayr 757
	add	eax, DNS_LIST
758
	mov	eax, [eax]
759
	ret
760
 
1473 hidnplayr 761
  .write_dns:
1159 hidnplayr 762
	add	eax, DNS_LIST
763
	mov	[eax], ecx
764
	xor	eax, eax
765
	ret
766
 
1473 hidnplayr 767
  .read_subnet:
1159 hidnplayr 768
	add	eax, SUBNET_LIST
769
	mov	eax, [eax]
770
	ret
771
 
1473 hidnplayr 772
  .write_subnet:
1159 hidnplayr 773
	add	eax, SUBNET_LIST
774
	mov	[eax], ecx
775
	xor	eax, eax
776
	ret
777
 
1473 hidnplayr 778
  .read_gateway:
1159 hidnplayr 779
	add	eax, GATEWAY_LIST
780
	mov	eax, [eax]
781
	ret
782
 
1473 hidnplayr 783
  .write_gateway:
1159 hidnplayr 784
	add	eax, GATEWAY_LIST
785
	mov	[eax], ecx
786
	xor	eax, eax
787
	ret
788