Date: Wed, 23 May 2007 14:54:53 GMT From: Alexey Tarasov <taleks@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 120256 for review Message-ID: <200705231454.l4NEsr5U023223@repoman.freebsd.org>
index | next in thread | raw e-mail
http://perforce.freebsd.org/chv.cgi?CH=120256 Change 120256 by taleks@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) <<<home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200705231454.l4NEsr5U023223>
