Subversion Repositories Kolibri OS

Rev

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