From e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Fri, 28 Aug 2015 09:58:54 +0800 Subject: Add qemu 2.4.0 Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang --- qemu/roms/SLOF/clients/net-snk/app/netlib/bootp.c | 254 ++++++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 qemu/roms/SLOF/clients/net-snk/app/netlib/bootp.c (limited to 'qemu/roms/SLOF/clients/net-snk/app/netlib/bootp.c') diff --git a/qemu/roms/SLOF/clients/net-snk/app/netlib/bootp.c b/qemu/roms/SLOF/clients/net-snk/app/netlib/bootp.c new file mode 100644 index 000000000..1bc6efe5b --- /dev/null +++ b/qemu/roms/SLOF/clients/net-snk/app/netlib/bootp.c @@ -0,0 +1,254 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DEBUG 0 + +static char * response_buffer; + +#if DEBUG +static void +print_ip(char *ip) +{ + printf("%d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); +} +#endif + +/* IP header checksum calculation */ +static unsigned short +checksum(unsigned short *packet, int words) +{ + unsigned long checksum; + for (checksum = 0; words > 0; words--) + checksum += *packet++; + checksum = (checksum >> 16) + (checksum & 0xffff); + checksum += (checksum >> 16); + return ~checksum; +} + + +static int +send_bootp(filename_ip_t * fn_ip) +{ +#if DEBUG + int i; +#endif + unsigned int packetsize = + sizeof(struct iphdr) + sizeof(struct ethhdr) + + sizeof(struct udphdr) + sizeof(struct btphdr); + unsigned char packet[packetsize]; + struct iphdr *iph; + struct udphdr *udph; + struct btphdr *btph; + + iph = (struct iphdr *) packet; + udph = (struct udphdr *) (iph + 1); + btph = (struct btphdr *) (udph + 1); + + memset(packet, 0, packetsize); + + fill_iphdr((uint8_t *) iph, htons(packetsize - sizeof(struct ethhdr)), + IPTYPE_UDP, 0, fn_ip->server_ip); + fill_udphdr((uint8_t *) udph, + htons(sizeof(struct udphdr) + sizeof(struct btphdr)), + htons(UDPPORT_BOOTPC), htons(UDPPORT_BOOTPS)); + btph->op = 1; + btph->htype = 1; + btph->hlen = 6; + strcpy((char *) btph->file, "bla"); + memcpy(btph->chaddr, get_mac_address(), 6); + +#if DEBUG + printf("Sending packet\n"); + printf("Packet is "); + for (i = 0; i < packetsize; i++) + printf(" %02x", packet[i]); + printf(".\n"); +#endif + + send_ipv4(fn_ip->fd, packet, iph->ip_len); +#if DEBUG + printf("%d bytes transmitted over socket.\n", i); +#endif + + return 0; +} + + +static int +receive_bootp(filename_ip_t * fn_ip) +{ + int len, old_sum; + unsigned int packetsize = 2000; + unsigned char packet[packetsize]; + struct iphdr *iph; + struct udphdr *udph; + struct btphdr *btph; + +#if DEBUG + struct ethhdr *ethh; + ethh = (struct ethhdr *) packet; +#endif + + iph = (struct iphdr *) (packet + sizeof(struct ethhdr)); + udph = (struct udphdr *) (iph + 1); + btph = (struct btphdr *) (udph + 1); + + memset(packet, 0, packetsize); + + /* setting up a timer with a timeout of one second */ + set_timer(TICKS_SEC); + + do { + + /* let's receive a packet */ + len = recv(fn_ip->fd, packet, packetsize, 0); + +#if DEBUG + int j; + printf("%d bytes received, %d expected \n", len, packetsize); + if (len == 346) { + printf("Rec packet\n"); + printf("Packet is "); + for (j = 0; j < len; j++) { + if (j % 16 == 0) + printf("\n"); + printf(" %02x", packet[j]); + } + printf(".\n"); + } +#endif + if (len == 0) + continue; + + /* check if the ip checksum is correct */ + old_sum = iph->ip_sum; + iph->ip_sum = 0x00; + if (old_sum != + checksum((unsigned short *) iph, sizeof(struct iphdr) >> 1)) + /* checksum failed */ + continue; + /* is it a udp packet */ + if (iph->ip_p != IPTYPE_UDP) + continue; + /* check if the source port and destination port and the packet + * say that it is a bootp answer */ + if (udph->uh_dport != htons(UDPPORT_BOOTPC) || udph->uh_sport != htons(UDPPORT_BOOTPS)) + continue; + /* check if it is a Boot Reply */ + if (btph->op != 2) + continue; + /* Comparing our mac address with the one in the bootp reply */ + if (memcmp(get_mac_address(), btph->chaddr, ETH_ALEN)) + continue; + + if(response_buffer) + memcpy(response_buffer, btph, 1720); + + fn_ip->own_ip = btph->yiaddr; + fn_ip->server_ip = btph->siaddr; + strcpy((char *) fn_ip->filename, (char *) btph->file); + +#if DEBUG + printf("\nThese are the details of the bootp reply:\n"); + printf("Our IP address: "); + print_ip((char*) &fn_ip->own_ip); + printf("Next server IP address: "); + print_ip((char*) &fn_ip->server_ip); + printf("Boot file name: %s\n", btph->file); + printf("Packet is: %s\n", btph->file); + for (j = 0; j < len; j++) { + if (j % 16 == 0) + printf("\n"); + printf(" %02x", packet[j]); + } + printf(".\n"); + printf("fn_ip->own_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + get_mac_address()[0], get_mac_address()[1], + get_mac_address()[2], get_mac_address()[3], + get_mac_address()[4], get_mac_address()[5]); + printf("Header ethh->dest_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + ethh->dest_mac[0], ethh->dest_mac[1], ethh->dest_mac[2], + ethh->dest_mac[3], ethh->dest_mac[4], ethh->dest_mac[5]); + printf("Header ethh->src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + ethh->src_mac[0], ethh->src_mac[1], ethh->src_mac[2], + ethh->src_mac[3], ethh->src_mac[4], ethh->src_mac[5]); + printf("Header ethh->typ: %x\n",ethh->type); + printf("Header iph->ip_hlv: %x\n",iph->ip_hlv); + printf("Header iph->ip_len: %x\n",iph->ip_len); + printf("Header iph->ip_id: %x\n",iph->ip_id); + printf("Header iph->ip_off: %x\n",iph->ip_off); + printf("Header iph->ip_ttl: %x\n",iph->ip_ttl); + printf("Header iph->ip_p: %x\n",iph->ip_p); + printf("Header iph->ip_sum: %x\n",iph->ip_sum); + printf("Header iph->ip_src: %x\n",iph->ip_src); + printf("Header iph->ip_dst: %x\n",iph->ip_dst); + + printf("Header btph->op: %x\n",btph->op); + printf("Header btph->htype: %x\n",btph->htype); + printf("Header btph->hlen: %x\n",btph->hlen); + printf("Header btph->hops: %x\n",btph->hops); + printf("Header btph->xid: %x\n",btph->xid); + printf("Header btph->secs: %x\n",btph->secs); + printf("Header btph->ciaddr: %x\n",btph->ciaddr); + printf("Header btph->yiaddr: %x\n",btph->yiaddr); + printf("Header btph->siaddr: %x\n",btph->siaddr); + printf("Header btph->giaddr: %x\n",btph->giaddr); + + printf("Header btph->chaddr: %02x:%02x:%02x:%02x:%02x:%02x:\n", + btph->chaddr[0], btph->chaddr[1], btph->chaddr[2], + btph->chaddr[3], btph->chaddr[4], btph->chaddr[5]); +#endif + return 0; + + /* only do this for the time specified during set_timer() */ + } while (get_timer() > 0); + return -1; +} + + +int +bootp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries) +{ + int i = (int) retries+1; + fn_ip->own_ip = 0; + + printf(" "); + + response_buffer = ret_buffer; + + do { + printf("\b\b%02d", i); + if (!i--) { + printf("\nGiving up after %d bootp requests\n", + retries+1); + return -1; + } + send_bootp(fn_ip); + /* if the timer in receive_bootp expired it will return + * -1 and we will just send another bootp request just + * in case the previous one was lost. And because we don't + * trust the network cable we keep on doing this 30 times */ + } while (receive_bootp(fn_ip) != 0); + printf("\b\b\b"); + return 0; +} -- cgit 1.2.3-korg