PERFORCE change 120256 for review

Alexey Tarasov taleks at FreeBSD.org
Wed May 23 14:54:54 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=120256

Change 120256 by taleks at taleks_th on 2007/05/23 14:54:46

	pxe_arp: added client entry to arp_table. pxe_core: small cosmetic changes + DHCP related function for future use. pxe_icmp: rewritten using pxe_ip. pxe_ip: added routing related functions, added pxe_ip_send() function for ip based protocols.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/Makefile#3 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_arp.c#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_arp.h#4 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#10 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.c#6 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.h#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_ip.c#5 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_ip.h#4 edit

Differences ...

==== //depot/projects/soc2007/taleks-pxe_http/Makefile#3 (text+ko) ====

@@ -12,7 +12,8 @@
 # the location of libstand
 CFLAGS+=	-I${.CURDIR}/../../../../lib/libstand/
 
-# debug flag
-CFLAGS+=	-DPXE_DEBUG
+#debug flag
+#CFLAGS+=	-DPXE_DEBUG
+#CFLAGS+=	-DPXE_DEBUG_HELL
 
 .include <bsd.lib.mk>

==== //depot/projects/soc2007/taleks-pxe_http/pxe_arp.c#4 (text+ko) ====

@@ -5,7 +5,8 @@
 #include "pxe_core.h"
 #include "pxe_mem.h"
 
-static PXE_ARP_ENTRY		arp_table[MAX_ARP_ENTRIES];
+/* last entry used for PXE client ip/mac */
+static PXE_ARP_ENTRY		arp_table[MAX_ARP_ENTRIES + 1];
 static PXE_ARP_PACK_DATA	packet_to_send;	
 static int			arp_usage = 0;
 
@@ -23,7 +24,7 @@
 	printf("pxe_arp_init() started.\n");
 	
 	if (packet_to_send.hdr.hsize != 0) {
-		printf("Pxe_arp_init() already inited.\n");
+		printf("pxe_arp_init() already initialized.\n");
 		return;
 	}
 #endif
@@ -37,9 +38,14 @@
 	packet_to_send.hdr.hsize = 6;	/* Ethernet MAC size */
 	packet_to_send.hdr.psize = 4;	/* ip4 size */
 	packet_to_send.hdr.operation = le2be16(PXE_ARPOP_REQUEST);
+
 	/* filling source related data: client ip & MAC */	
 	pxe_memcpy(pxe_get_mymac(), packet_to_send.body.src_hwaddr, 6);	
 	packet_to_send.body.src_paddr = pxe_get_myip32();
+	
+	/* filling entry for own ip/mac*/	
+	pxe_memcpy(pxe_get_mymac(), arp_table[MAX_ARP_ENTRIES].mac, 6);	
+	arp_table[MAX_ARP_ENTRIES].ip4.ip  = pxe_get_myip32();
     
 	/* setting broadcast target address */
 	pxe_memset(packet_to_send.body.target_hwaddr, 0xff, 6); 
@@ -58,13 +64,13 @@
 {
 	int entry = 0;
 	
-	for (; entry < MAX_ARP_ENTRIES; ++entry) {
+	for (; entry < MAX_ARP_ENTRIES + 1; ++entry) {
 
 		if (arp_table[entry].ip4.ip == ip)
 			return (const MAC_ADDR *)&(arp_table[entry].mac);
 	}
 
-	return NULL;
+	return (NULL);
 }
 
 /*
@@ -80,60 +86,69 @@
 int
 pxe_arp_protocol(PXE_PACKET *pack, uint8_t function, void *data)
 {
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("pxe_arp_protocol() started.\n");
 #endif
-	const PXE_ARP_PACK_DATA *arp_reply = (const PXE_ARP_PACK_DATA *)pack->raw_data;
+	PXE_ARP_PACK_DATA *arp_reply = (PXE_ARP_PACK_DATA *)pack->raw_data;
+
 
-#ifdef PXE_DEBUG
 	if (arp_reply->hdr.operation == le2be16(PXE_ARPOP_REQUEST) ) {
 	
-		uint8_t		*mac = arp_reply->body.src_hwaddr;
-		uint8_t		*mac2 = arp_reply->body.target_hwaddr;		
-		PXE_IPADDR	ip4;
-		PXE_IPADDR	ip42;		
+		uint8_t		*mac_src = arp_reply->body.src_hwaddr;
+		uint8_t		*mac_dst = arp_reply->body.target_hwaddr;		
+		PXE_IPADDR	ip4_src;
+		PXE_IPADDR	ip4_dst;		
 
-		ip4.ip = arp_reply->body.src_paddr;
-		ip42.ip = arp_reply->body.target_paddr;
+		ip4_src.ip = arp_reply->body.src_paddr;
+		ip4_dst.ip = arp_reply->body.target_paddr;
 		
-		printf("arp request from %x:%x:%x:%x:%x:%x/%d.%d.%d.%d/%x\n\t to: %x:%x:%x:%x:%x:%x/%d.%d.%d.%d/%x\n",
-		    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
-		    ip4.octet[0], ip4.octet[1], ip4.octet[2], ip4.octet[3], ip4.ip,
-		    mac2[0], mac2[1], mac2[2], mac2[3], mac2[4], mac2[5],
-		    ip42.octet[0], ip42.octet[1], ip42.octet[2], ip42.octet[3], ip42.ip		    
+#ifdef PXE_DEBUG		
+		printf("arp request from %x:%x:%x:%x:%x:%x/%d.%d.%d.%d\n\t to: %x:%x:%x:%x:%x:%x/%d.%d.%d.%d\n",
+		    mac_src[0], mac_src[1], mac_src[2], mac_src[3], mac_src[4], mac_src[5],
+		    ip4_src.octet[0], ip4_src.octet[1], ip4_src.octet[2], ip4_src.octet[3],
+		    mac_dst[0], mac_dst[1], mac_dst[2], mac_dst[3], mac_dst[4], mac_dst[5],
+		    ip4_dst.octet[0], ip4_dst.octet[1], ip4_dst.octet[2], ip4_dst.octet[3]
 		);
+#endif		
+
+		/* somebody is looking for us */
+		if (ip4_dst.ip == arp_table[MAX_ARP_ENTRIES].ip4.ip) {
 		
-		printf("Sending  arp reply.");
+			pxe_memcpy(arp_reply->body.src_hwaddr, packet_to_send.body.target_hwaddr, 6);
+			packet_to_send.body.target_paddr = arp_reply->body.src_paddr;
+			packet_to_send.hdr.operation = le2be16(PXE_ARPOP_REPLY);
 		
-		pxe_memcpy(arp_reply->body.src_hwaddr, packet_to_send.body.target_hwaddr, 6);
-		packet_to_send.body.target_paddr = arp_reply->body.src_paddr;
-		packet_to_send.hdr.operation = le2be16(PXE_ARPOP_REPLY);
-		
-		PXE_PACKET	pack;
+			PXE_PACKET	pack;
 	
-		pack.raw_size = sizeof(PXE_ARP_PACK_DATA);
-		pack.raw_data = &packet_to_send;
-		pack.raw_data = &packet_to_send;
-		pack.data = &packet_to_send.hdr;
-	    	pack.protocol = PXE_PROTOCOL_ARP;
-		pack.dest_mac = (const MAC_ADDR *)&packet_to_send.body.target_hwaddr[0];
-		pack.flags = PXE_SINGLE;
+			pack.raw_size = sizeof(PXE_ARP_PACK_DATA);
+			pack.raw_data = &packet_to_send;
+			pack.data = &packet_to_send.hdr;
+			pack.data_size = sizeof(PXE_ARP_PACK_DATA) - MEDIAHDR_LEN_ETH;		
+		    	pack.protocol = PXE_PROTOCOL_ARP;
+			pack.dest_mac = (const MAC_ADDR *)&packet_to_send.body.target_hwaddr[0];
+			pack.flags = PXE_SINGLE;
 		
-		if (!pxe_core_transmit(&pack)) {
-		    printf("Reply to arp request failed.\n");
+			if (!pxe_core_transmit(&pack)) {
+			        printf("pxe_arp_protocol(): reply to arp request failed.\n");
+			}
+
+			/* cleaning packet_to_send back to initiakl state */
+			pxe_memset(packet_to_send.body.target_hwaddr, 0xff, 6);
+			packet_to_send.hdr.operation = le2be16(PXE_ARPOP_REQUEST);
 		}
-
-		/* cleaning packet_to_send back to initiakl state */
-		pxe_memset(packet_to_send.body.target_hwaddr, 0xff, 6);
-		packet_to_send.hdr.operation = le2be16(PXE_ARPOP_REQUEST);
 		
-		return 0;
-	}
+		 /* we may cache information about packet sender */
+#ifdef PXE_ARP_SNIFF
+		/* just to skip operation filter below */
+		arp_reply->hdr.operation = le2be16(PXE_ARPOP_REPLY);
 #else
-	if (arp_reply->hdr.operation != le2be16(PXE_ARPOP_REPLY) ) /* we don't need answer for requests. May be. */
-		return 0;
+		return (0);		
 #endif
+	}
 
+	if (arp_reply->hdr.operation != le2be16(PXE_ARPOP_REPLY) ) /* we don't need anything except replies on that stage */
+		return (0); 
+		
 
 	
 	/* if arp_usage exceeds MAX_ARP_ENTRIES, occurs rewriting of earlier placed ARP entries.
@@ -152,18 +167,18 @@
 		    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
 		);
 #endif
-		return 0;
+		return (0);
 	}
 	
 	pxe_memcpy(&arp_reply->body.src_hwaddr, &arp_table[arp_usage % MAX_ARP_ENTRIES].mac, 6);
 	arp_table[arp_usage % MAX_ARP_ENTRIES].ip4.ip = arp_reply->body.src_paddr;
 	++arp_usage;
 
-#ifdef PXE_DEBUG	
-	printf("arp reply: arp usage = %d\n", arp_usage);
+#ifdef PXE_DEBUG_HELL	
+	printf("pxe_arp_protocol(): arp usage = %d\n", arp_usage);
 #endif
 	
-	return 0; /* inform pxe_get_packet() we don't need this packet more. */
+	return (0); /* inform pxe_get_packet() we don't need this packet more. */
 }
 
 /*
@@ -227,7 +242,7 @@
 
 	while (1) {
 #ifdef PXE_DEBUG			
-		printf(".");
+		twiddle();
 #endif
 		if (pxe_core_recv_packets()) {        	/* means some packet was received */
 			
@@ -242,13 +257,13 @@
 
 		if (timeToDie == 0) {	
 
-#ifdef PXE_DEBUG			
-			printf(".. request timeout\n");
+#ifdef PXE_DEBUG_HELL
+			printf(".");
 #endif 
 			--trysLeft;
 			if (trysLeft == 0) { 	/* have not recieved anything, return nothing */
 
-				printf("\nARP sending timeout.\n");
+				printf("\npxe_arp_ip4mac(): ARP reply timeout.\n");
 				return (NULL);
 			}
 
@@ -260,7 +275,7 @@
 		}
 
 		/* sleep(1); */
-		delay(500000);
+		delay(1000000);
 		--timeToDie;
 	}
 

==== //depot/projects/soc2007/taleks-pxe_http/pxe_arp.h#4 (text+ko) ====

@@ -17,9 +17,12 @@
 /* max MAC<->ip4 bindings to store */
 #define MAX_ARP_ENTRIES	4
 /* max try count to send/recieve ARP request/reply */
-#define PXE_MAX_ARP_TRY	5
+#define PXE_MAX_ARP_TRY	3
 /* max timeout in seconds */
-#define PXE_TIME_TO_DIE 60
+#define PXE_TIME_TO_DIE 10
+
+/* define to anable caching incoming packet sender information*/
+#define PXE_ARP_SNIFF
 
 typedef struct pxe_arp_entry {
 	PXE_IPADDR	ip4;

==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#10 (text+ko) ====

@@ -17,7 +17,7 @@
  */
 
 /* NOTE: to think about using of this buffers */
-#define	PXE_BUFFER_SIZE		0x2000
+#define	PXE_BUFFER_SIZE		0x1000
 #define	PXE_TFTP_BUFFER_SIZE	512
 static uint8_t      scratch_buffer[PXE_BUFFER_SIZE];
 static uint8_t      data_buffer[PXE_BUFFER_SIZE];
@@ -67,6 +67,54 @@
         return (status);
 }
 
+
+void
+print_dhcp_options(uint8_t *opts) 
+{
+	uint8_t	*p=opts;
+	uint8_t	code = opts[0];
+	uint8_t	len = 0;
+	
+	printf("DHCP options:\n");
+    
+        while (code != 255) {
+	
+		++p;
+		len = 1 + (*p);
+		printf("code %d, len %d: ", code, len);
+		
+		switch (code) {
+		case 0:	/* pad */
+			len = 0;
+			break;	
+	    
+		case 1:	/* netmask */
+			printf("netmask: %d.%d.%d.%d\n", *(p+1), *(p+2), *(p+3), *(p+4));
+			break;
+			
+		case 3: /* routers */
+			printf("first router: %d.%d.%d.%d\n", *(p+1), *(p+2), *(p+3), *(p+4));
+			break;
+			
+		case 5: /* nameserver */
+			printf("first nameserver: %d.%d.%d.%d\n", *(p+1), *(p+2), *(p+3), *(p+4));
+			break;
+			
+		default:
+			break;
+		};
+	
+		printf("\n");
+		p += len;
+		code = *p;
+		len = 0;
+		
+		if (p - opts > BOOTP_DHCPVEND)
+		    break;
+	}
+}
+
+
 /*
  * performs UNDI initialization  call during pxe_core_init()
  * out:
@@ -190,13 +238,13 @@
 	       pxe_p->EntryPointSP.segment,
 	       pxe_p->EntryPointSP.offset);
 
+	__pxe_entry_seg = pxe->EntryPointSP.segment;
+	__pxe_entry_off = pxe->EntryPointSP.offset;
+	
 	gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer;
 	pxe_memset(gci_p, 0, sizeof(*gci_p));
 	gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY;
 
-	__pxe_entry_seg = pxe->EntryPointSP.segment;
-	__pxe_entry_off = pxe->EntryPointSP.offset;
-	
 	if (!pxe_core_call(PXENV_GET_CACHED_INFO)) {
 	}
 
@@ -257,13 +305,22 @@
 	printf("my ip: %d.%d.%d.%d\n", nic_ip.octet[0], nic_ip.octet[1], nic_ip.octet[2], nic_ip.octet[3]);
 						/* my MAC */
 	pxe_memcpy(&bootplayer.CAddr, &nic_mac, MAC_ADDR_LEN);
-	printf("my MAC: %x:%x:%x:%x:%x:%x\n", nic_mac[0], nic_mac[1], nic_mac[2], nic_mac[3], nic_mac[4], nic_mac[5]);
+	printf("my MAC: %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", nic_mac[0], nic_mac[1], nic_mac[2], nic_mac[3], nic_mac[4], nic_mac[5]);
 
+	pxe_arp_init();
+	pxe_icmp_init();
+	
+	pxe_ip_route_init(0x0100a8c0);	/* NOTE: setting default route 192.168.0.1
+					 * need to determiny gateway by getting info drom DHCP packets,
+					 * but cached packets for some resons have no gip set. So,
+					 * after implementing of UDP, need to return to this point and
+					 * get info sending DHCP  requests.
+					 */
+		
 #ifdef PXE_DEBUG
 	printf("pxe_core_init(): ended.\n");
 #endif	
 
-	delay(5000000);
 	return (1);
 }
 
@@ -348,7 +405,7 @@
 pxe_core_remove_isr()
 {
 
-	bzero(&v86, sizeof(v86));
+	pxe_memset(&v86, 0, sizeof(v86));
 
 	v86.ctl  = V86_ADDR | V86_CALLF | V86_FLAGS;
 	v86.addr = (VTOPSEG(__isr_remove) << 16) | VTOPOFF(__isr_remove);
@@ -386,7 +443,7 @@
 
 /*
  *  function code is taken from bangpxe_call(), /sys/boot/libi386/pxe.c
- *  needs pxe_srs.s wrapper and vm86int() support.
+ *  needs pxe_isr.s wrapper and vm86int() support.
  *  in:
  *	func - PXE function number
  *  out:
@@ -397,7 +454,7 @@
 pxe_core_call(int func)
 {
 
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("pxe_core_call(): func = 0x%x...", func);
 #endif
 	pxe_memset(&v86, 0, sizeof(v86));
@@ -413,7 +470,7 @@
 	int call_status = v86.eax;
 	int status = *((uint16_t *)scratch_buffer);
 	
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 	printf("%s (0x%x)\n", (call_status == 0) ? "?OK" : "?NOK", status );
 #endif
 
@@ -461,7 +518,7 @@
 	    (undi_send->XmitFlag == XMT_DESTADDR) ? "to" : "bcast",
 	    (*pack->dest_mac)[0], (*pack->dest_mac)[1], (*pack->dest_mac)[2],
 	    (*pack->dest_mac)[3], (*pack->dest_mac)[4], (*pack->dest_mac)[5],
-	    undi_send->Protocol, pack->raw_size
+	    undi_send->Protocol, pack->data_size
 	);
 #endif
 	
@@ -489,6 +546,9 @@
 		    break;
 	}
 
+	if (status)
+		++packets_sent;
+		
 	return (status);
 }
 
@@ -557,7 +617,9 @@
 int
 pxe_core_get_packet(int func, t_PXENV_UNDI_ISR *undi_isr )
 {
+#ifdef PXE_DEBUG_HELL
 	printf("get_packet(): started with func %d\n", func);
+#endif
 	
 	undi_isr->FuncFlag = func;
 	int count = 0;
@@ -567,14 +629,14 @@
 		undi_isr->Status = 0;
 
 		if (!pxe_core_call(PXENV_UNDI_ISR)) {
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("get_packet(): failed.\n");
 #endif		
 		}
 
 		if (undi_isr->Status != 0) {
 			/* something gone wrong */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("get_packet(): fail status =  0x%x.\n", undi_isr->Status);
 #endif					
 			return (0);
@@ -582,15 +644,15 @@
 
 		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) {
 			/* nothing to de */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("get_packet(): all is already done.\n");
 #endif					
-			break;
+			return (0);
 		}
 
 		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) {
 			/* NIC is busy, wait */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("get_packet(): device is busy.\n");
 #endif					
 			++count;
@@ -604,7 +666,7 @@
 
 		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_RECIEVE) {
 			/* that's what we are waiting for */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("get_packet(): got packet!.\n");
 #endif					
 			break;
@@ -612,7 +674,7 @@
 
 		if (undi_isr->FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
 			/* transmitted packet */
-#ifdef PXE_DEBUG
+#ifdef PXE_DEBUG_HELL
 			printf("get_packet(): transmit packet.\n");
 #endif					
 			return (0);
@@ -640,7 +702,6 @@
 	int	protocol = 0;     /* protocol */
 	int	received = 0;     /* bytes received to buffer */
 
-	void	*frame_data = NULL;/* pointer to frame data */
 	int	frame_size = 0;    /* size of frame */
 	int	drop_flag = 0;
 	int	processed_packets = 0;
@@ -666,7 +727,7 @@
 packet_start:
 
 	drop_flag = 0;
-	bzero(undi_isr, sizeof(*undi_isr));
+	pxe_memset(undi_isr, 0, sizeof(t_PXENV_UNDI_ISR));
 	
 	if (0 == pxe_core_get_packet(func, undi_isr)) {
 		return (processed_packets);
@@ -677,11 +738,11 @@
 	frame_size = undi_isr->FrameLength;
 
 	if ( (frame_size == 0) && (buffer_size == 0)) {	/* no packet, it seems  'all is done' */
-	    return (processed_packets);
+		return (processed_packets);
 	}
 	
 #ifdef PXE_DEBUG
-	printf("recv_packets(): size = %d, proto = %d, frame_length = %d\n.", buffer_size, protocol, frame_size);
+	printf("recv_packets(): size = %d, proto = %d, frame_length = %d bytes\n.", buffer_size, protocol, frame_size);
 #endif		
 
 	/* we are interested in ARP & IP packets */
@@ -699,7 +760,7 @@
 		pxe_core_copy(	undi_isr->Frame.segment, undi_isr->Frame.offset,
 			VTOPSEG(data_buffer), VTOPOFF(data_buffer), frame_size);
 	} else {
-		printf("pxe_core_recv_packets(): not enough buffer size (%d bytes) for frame size %d bytes.",
+		printf("pxe_core_recv_packets(): not enough buffer size (%d bytes) for frame size %d bytes.\n",
 		    PXE_BUFFER_SIZE, frame_size);
 
 		drop_flag = 1;		/* drop this packet */
@@ -712,7 +773,7 @@
 
 	if (!drop_flag) {
 
-		PXE_IP_HDR *iphdr = (PXE_IP_HDR *)data_buffer;
+		PXE_IP_HDR *iphdr = (PXE_IP_HDR *)(data_buffer + MEDIAHDR_LEN_ETH);
 
 		dummy_pack.protocol = protocol;
 		dummy_pack.state = PXE_PACKET_STATE_USING;
@@ -912,16 +973,26 @@
 }
 
 /*
+ * commits choosed packet, free used structures
+ */
+void
+pxe_core_commit(PXE_PACKET *pack)
+{
+
+	pxe_mutex_own(&core_mutex, PXE_OWNER_CORE);
+	pack->state = PXE_PACKET_STATE_FREE;
+	pxe_mutex_free(&core_mutex, PXE_OWNER_CORE);
+}
+
+/*
  * drops choosed packet
  */
 void
 pxe_core_drop(PXE_PACKET *pack)
 {
 
-	pxe_mutex_own(&core_mutex, PXE_OWNER_CORE);
-	pack->state = PXE_PACKET_STATE_FREE;
 	++packets_dropped;
-	pxe_mutex_free(&core_mutex, PXE_OWNER_CORE);
+	pxe_core_commit(pack);
 }
 
 /*

==== //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.c#6 (text+ko) ====

@@ -1,5 +1,6 @@
 #include <stand.h>
 
+#include "pxe_arp.h"
 #include "pxe_conv.h"
 #include "pxe_core.h"
 #include "pxe_icmp.h"
@@ -7,7 +8,10 @@
 
 
 /* used in echo replying */
-static pinging = 0;
+static PXE_IPADDR	pinging;		/* ip to accept replies from */
+static uint16_t		seq_number;		/* next sequence number to accept */
+static uint16_t		last_accepted = 0xffff;	/* last sequence number accepted */
+static int		echo_flags = 0;
 
 int
 pxe_icmp_callback(PXE_PACKET *pack, uint8_t function, void *data)
@@ -28,20 +32,25 @@
 
 	/* icmp header*/
 	PXE_IP_HDR	*iphdr = (PXE_IP_HDR *)pack->data;
-	size_t	iphdr_len = (iphdr->ver_ihl & 0x0f) * 4;
-	size_t	data_size = iphdr->length - iphdr_len - sizeof(PXE_IP_HDR);
-	PXE_ICMP_HDR *icmphdr = (PXE_ICMP_HDR *)(pack->data + sizeof(PXE_IP_HDR) + iphdr_len);
+	size_t		iphdr_len = (iphdr->ver_ihl & 0x0f) * 4;
+	size_t		data_size = be2le16(iphdr->length) - iphdr_len - sizeof(PXE_ICMP_HDR);
+	PXE_ICMP_HDR	*icmphdr = (PXE_ICMP_HDR *)(pack->data + iphdr_len);
 
+#ifdef PXE_DEBUG
+	printf("pxe_icmp_callback(): data size %d bytes, total %d bytes, type: %d\n", data_size, pack->data_size, icmphdr->type);
+#endif
 	/* TODO: verify checksum */
 
 	/* reply */
-	PXE_PACKET *pack_out = NULL;
-	PXE_IP_HDR *reply_iphdr = NULL;
-	PXE_ICMP_HDR  *reply_icmphdr = NULL;
-	size_t     reply_size = sizeof(PXE_IP_HDR) + sizeof(PXE_ICMP_HDR) + data_size;
+	PXE_IP_HDR	*reply_iphdr = NULL;
+	PXE_ICMP_HDR	*reply_icmphdr = NULL;
+	size_t		reply_size = sizeof(PXE_IP_HDR) + sizeof(PXE_ICMP_HDR)
+				    + data_size;
 
+	uint16_t	reply_number = be2le32(icmphdr->seq_num);
+	
 	/* we are interested only in echo related packets*/
-	switch(icmphdr->code) {
+	switch(icmphdr->type) {
 	case PXE_ICMP_ECHO_REQUEST:
 	case PXE_ICMP_ECHO_REPLY:
  /*	case PXE_ICMP_DEST_UNREACHABLE:
@@ -52,52 +61,61 @@
 		return (0);   /* instruct pxe core to drop packet*/
 	};
 
-	if (icmphdr->code == PXE_ICMP_ECHO_REPLY) {
-		if (pinging == be2le32(iphdr->src_ip))
-			printf("\necho reply from %x, seq=%ld.",
-			    iphdr->src_ip, icmphdr->seq_num);
-		else /* we are not interested in this reply*/
-			printf("\nlame echo reply from %x, seq=%ld.",
-			    iphdr->src_ip, icmphdr->seq_num);
+
+	if (icmphdr->type == PXE_ICMP_ECHO_REPLY) {
+
+		if ( (reply_number != seq_number) && (icmphdr->code != 0)) {
+#ifdef PXE_DEBUG		
+			printf("pxe_icmp_callback(): skipping %d sequence number, cause %d is expected\n", reply_number, seq_number);
+#endif
+			return (0);	/* ignore this packet */
+		}
+		
+		uint16_t	id = (uint16_t)(seq_number*seq_number);
+		if (icmphdr->packet_id != id) {
+			if (echo_flags)
+				printf("pxe_icmp_callback(): skipping packet cause id 0x%x, but 0x%x is expected\n", icmphdr->packet_id, id);
+				
+			return (0);
+		}
+
+		if (pinging.ip == iphdr->src_ip) {
+
+/*			uint16_t sum_orig = icmphdr->checksum;
+			icmphdr->checksum = 0;
+			uint16_t sum = ~pxe_ip_checksum(icmphdr, sizeof(PXE_ICMP_HDR) + data_size);
+			
+			printf("checksums: 0x%x %s 0x%x\n", sum_orig, (sum_orig == sum) ? "==" : "!=", sum );
+*/
+			if (echo_flags) {
+				printf("pxe_ping(): echo reply from %d.%d.%d.%d, seq=%ld ",
+				    pinging.octet[0], pinging.octet[1],
+				    pinging.octet[2], pinging.octet[3], seq_number );
+			}
+			
+			last_accepted = seq_number;	/* notify pxe_ping() code that we received reply */
+		}
+			    
 		return (0);
 	}
+
 	/* all we need now is echo reply */
 
-	pack_out = pxe_core_alloc_packet(reply_size);
 
-	if (pack_out == NULL) {
-		/* TO THINK: failed to allocate packet,
-		 * may be it's better to use
-		 * statically allocated packet.
-		 */
-		return (0);
-	}
+	/* using buffer of recieved packet to avoid additional memory copy operations */
 
-	reply_iphdr = (PXE_IP_HDR *)pack_out->data;
-	reply_icmphdr = (PXE_ICMP_HDR *)(reply_iphdr + 1);
+	reply_iphdr = (PXE_IP_HDR *)pack->data;
+	reply_icmphdr = (PXE_ICMP_HDR *)(pack->data + iphdr_len);
 
 	reply_icmphdr->type = PXE_ICMP_ECHO_REPLY;
-
-	/* copying same values */
-	reply_icmphdr->code = icmphdr->code;
-	reply_icmphdr->seq_num = icmphdr->seq_num;
-	reply_icmphdr->packet_id = icmphdr->packet_id;
 	reply_icmphdr->checksum = 0;
 	reply_icmphdr->checksum =
-	    ~(le2be16(pxe_ip_checksum(reply_icmphdr, sizeof(PXE_ICMP_HDR))));
-
-	pxe_ip_hdr(pack_out->data, iphdr->src_ip, 0x01, reply_size, 0);
-
-	/* copying all data from request packet to reply packet,
-	 * starting after headers
-	 */
-	pxe_memcpy(reply_icmphdr + 1, pack->data + iphdr_len + sizeof(PXE_ICMP_HDR),
-	    data_size);
+	        ~pxe_ip_checksum(reply_icmphdr, sizeof(PXE_ICMP_HDR) + data_size);
+		
+	if (!pxe_ip_send(pack->data, iphdr->src_ip, 0x01, pack->data_size, 1) && echo_flags) {
+		printf("pxe_ping(): failed to send echo reply.\n");
+	}
 
-	pxe_core_transmit(pack_out);
-/*	pxe_core_commit(pack);
-	return (1); /* instruct core we are interested in it, so save data */
-
 	return (0);	/* drop it, we don't need this packet more.
 			 * this is a little bit ugly, may be
 			 * using of more return codes will be more flexible
@@ -108,7 +126,7 @@
 pxe_icmp_init()
 {
 
-	/* register protocol in pxe protocols table. */
+	/* register protocol in pxe_core protocols table. */
 	/* 0x01 - ICMP protocol */
 	pxe_core_register(0x01, pxe_icmp_callback);
 
@@ -116,61 +134,81 @@
 }
 
 int
-pxe_ping(PXE_IPADDR *ip, int count)
+pxe_ping(PXE_IPADDR *ip, int count, int flags)
 {
-	int     scount = 0;
-
-	/* creating packet */
+	seq_number = 0;
+	last_accepted = 0xffff;
+	echo_flags = flags;
+	
+	
+	/* creating data storage for packet */
+	uint8_t		data[sizeof(PXE_IP_HDR) + sizeof(PXE_ICMP_HDR) + 32];
+	
 	size_t		pack_size = sizeof(PXE_IP_HDR) + sizeof(PXE_ICMP_HDR) + 32;
-	PXE_PACKET	*pack = pxe_core_alloc_packet(pack_size);
 	PXE_IP_HDR	*iphdr = NULL;
 	PXE_ICMP_HDR	*icmphdr = NULL;
+	uint32_t	wait_time = 0;
+	int		scount = 0;
 
-	if (pack == NULL) {    /* failed to alloc packet */
-		return (0);
-	}
+	if (flags)
+		printf("pxe_ping(): pinging %d.%d.%d.%d, 32 bytes\n", ip->octet[0], ip->octet[1], ip->octet[2], ip->octet[3]);
+	
+	pinging.ip = ip->ip;
 
-	printf("\nping: %x, bytes=32", ip->ip);
-	pinging = ip->ip;
-
-	iphdr = (PXE_IP_HDR *)pack->data;
-	icmphdr = (PXE_ICMP_HDR *)(pack->data + sizeof(PXE_IP_HDR));
+	iphdr = (PXE_IP_HDR *)data;
+	icmphdr = (PXE_ICMP_HDR *)(data + sizeof(PXE_IP_HDR));
 
 	/* base icmp header side*/
 	icmphdr->type = PXE_ICMP_ECHO_REQUEST;
-	icmphdr->code = 1;
+	icmphdr->code = 0;
 
-/*	icmphdr->seq_num = scount;
-	icmphdr->packet_id = scount*scount;
-*/
+	while (seq_number < count) {
 
-/*	icmphdr->checksum = 0;
-	reply_icmphdr->checksum =
-	    ~(le2be16(pxe_ip_checksum(icmphdr, sizeof(pxe_icmp))));
-*/
+		++seq_number;
+		
+		icmphdr->seq_num = le2be16(seq_number);
+		icmphdr->packet_id = (uint16_t)(seq_number*seq_number); /* is this good idea? */
 
-	/* ip header side */
-	pxe_create_ip_hdr(pack->data, ip->ip, 0x01, pack_size, 0);
-
-
-	while (scount < count) {
-
-		icmphdr->seq_num = scount;
-		icmphdr->packet_id = scount*scount; /* is this good idea? */
-
 		/* recalc for every packet */
 		icmphdr->checksum = 0;
 		icmphdr->checksum =
-		    ~(le2be16(pxe_ip_checksum(icmphdr, sizeof(PXE_ICMP_HDR))));
+		    ~(pxe_ip_checksum(icmphdr, sizeof(PXE_ICMP_HDR) + 32));
+
+	    	if (!pxe_ip_send(data, ip->ip, 0x01, pack_size, 1) && echo_flags) {
+			printf("pxe_ping(): failed to send echo reply.\n");
+		}	
+
+		/* echo reply waiting */
+		wait_time = 0;
+		
+		while (wait_time < PXE_ICMP_TIMEOUT) {
+			
+			twiddle();
+			wait_time += 10;
+			
+			if (!pxe_core_recv_packets()) {
+				delay(10000);
+			}
+			
+			if (last_accepted == seq_number) {
+				if (flags)
+					printf("< %d ms\n", wait_time);
 
-		pxe_core_transmit(pack);
+				++scount;
+				break;
+			}
 
-		/* TODO: timeout checking */
+		}
 
-		++scount;
+		if ( (last_accepted != seq_number) && flags)
+			printf("ping timeout.\n");
+		
+		/* wait a little, to avoid ICMP flood */
+		delay(500000);
 	}
 
-	pinging = 0;
-
+	pinging.ip = 0;
+	echo_flags = 0;
+	
 	return (scount);
 }

==== //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.h#5 (text+ko) ====

@@ -11,13 +11,15 @@
 
 /* ICMP header */
 typedef struct pxe_icmp_hdr {
-    uint8_t type;	/* type of ICMP  packet */
-    uint8_t code;	/* code, used to identify session */
-    uint16_t checksum;	/* ICMP header checksum */
-    uint16_t packet_id;	/* for echo */
-    uint16_t seq_num;   /* for echo */
+    uint8_t	type;		/* type of ICMP  packet */
+    uint8_t	code;		/* code, used to identify session */
+    uint16_t	checksum;	/* ICMP header checksum */
+    uint16_t	packet_id;	/* for echo */
+    uint16_t	seq_num;	/* for echo */
 } __packed PXE_ICMP_HDR;
 
+/* timeout in milliseconds */
+#define PXE_ICMP_TIMEOUT	5000
 /* pxe_ping - send icmp echo request packets to host
  *    in:
  *       ip      - host ip address

==== //depot/projects/soc2007/taleks-pxe_http/pxe_ip.c#5 (text+ko) ====

@@ -1,5 +1,163 @@
+#include "pxe_core.h"
 #include "pxe_ip.h"
+#include "pxe_icmp.h"
+
+static PXE_IP_ROUTE_ENTRY	route_table[PXE_MAX_ROUTES];
+static int			all_routes = 0;
+static uint16_t 		packet_id = 1;
+void
+pxe_ip_route_init(uint32_t def_gw)
+{
+
+        if (all_routes)	/* already inited */
+		return;
+		
+	/* add default gw */
+	pxe_ip_route_default(def_gw);
+	all_routes += 1;
+
+	PXE_IPADDR	myip;
+	myip.ip = pxe_get_myip32();
+	
+	/* make route for local network */
+	uint32_t	mask = pxe_ip_get_netmask(myip.ip);
+	
+	if (mask == 0) {
+		printf("pxe_ip_route_init(): my ip is class D or class E, don't know how understand this.\n");
+		return;
+	}
+	
+	pxe_ip_route_add(myip.ip, mask, 0);
+}
+
+
+uint32_t
+pxe_ip_get_netmask(uint32_t ip)
+{
+	uint8_t		net_class = (ip & 0x000000F0) >> 4;
+	
+	if ( (net_class & 0x0c) == 0x0c) {	/* class C */
+		return (0x00ffffff);
+	}
+	else if ((net_class & 0x08) == 0x08) {	/* class B */
+	        return (0x0000ffff);
+	}
+	else if ((net_class & 0x08) == 0x00) {	/* class A */
+	        return (0x000000ff);
+	}
+	
+	/* D & E classes are not supported yet... */
+	return (0);
+}
+
+int
+pxe_ip_route_add(uint32_t net, uint32_t mask, uint32_t gw)
+{
+	PXE_IPADDR net_ip, gw_ip;
+	
+	net_ip.ip = (net & mask);
+	gw_ip.ip = gw;
+	
+	printf("pxe_ip_route_add(): adding net %d.%d.%d.%d mask %8.8x gw ",
+	    net_ip.octet[0], net_ip.octet[1], net_ip.octet[2], net_ip.octet[3], le2be32(mask)
+	);
+	
+	if (gw)
+	    printf("%d.%d.%d.%d\n", gw_ip.octet[0], gw_ip.octet[1], gw_ip.octet[2], gw_ip.octet[3]);
+	else
+	    printf("pxenet0\n");
+	
+	if (all_routes == PXE_MAX_ROUTES) {
+		printf("pxe_ip_route_add(): failed, cause routing table is full.\n");
+		return (0);
+	}
+
+	if (gw && (pxe_ping(&gw_ip, 3, 0) == 0) ) {
+		printf("pxe_ip_route_add(): failed, cause gateway is unreachable.\n");
+		return (1);
+	}
+	
+        route_table[all_routes].net = (net & mask);
+	route_table[all_routes].mask = mask;
+	route_table[all_routes].gw = gw;
+	
+	++all_routes;
+	
+	return (1);
+}
+
+int
+pxe_ip_route_del(uint32_t net, uint32_t mask, uint32_t gw)
+{
+	PXE_IPADDR net_ip, gw_ip;
+	int route_index = 1;
+	
+	net_ip.ip = (net & mask);
+	gw_ip.ip = gw;
+	
+	printf("pxe_ip_route_add(): deleting net %d.%d.%d.%d mask %8.8x gw %d.%d.%d.%d\n",
+	    net_ip.octet[0], net_ip.octet[1], net_ip.octet[2], net_ip.octet[3], le2be32(mask),
+	    gw_ip.octet[0], gw_ip.octet[1], gw_ip.octet[2], gw_ip.octet[3]
+	);
+	
+	
+	for ( ; route_index < all_routes; ++route_index) {
+	        
+		if ((route_table[route_index].net == net_ip.ip) &&
+	    	    (route_table[route_index].gw == gw) &&
+		    (route_table[route_index].mask == mask)) 
+		{
+		
+			--all_routes;    		
+			
+			if (route_index == all_routes)
+				return (1);
+			
+			/* shift routes */
+			int shift_index = route_index;
+			
+			for ( ; shift_index < all_routes; ++shift_index) {

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list