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