|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2004, 2008 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: ! 13: ! 14: #include <stdio.h> ! 15: #include <string.h> ! 16: #include <sys/socket.h> ! 17: #include <time.h> ! 18: ! 19: #include <ethernet.h> ! 20: #include <ipv4.h> ! 21: #include <udp.h> ! 22: #include <dhcp.h> ! 23: ! 24: #define DEBUG 0 ! 25: ! 26: static char * response_buffer; ! 27: ! 28: void ! 29: print_ip(char *ip) ! 30: { ! 31: printf("%d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); ! 32: } ! 33: ! 34: ! 35: /* IP header checksum calculation */ ! 36: unsigned short ! 37: checksum(unsigned short *packet, int words) ! 38: { ! 39: unsigned long checksum; ! 40: for (checksum = 0; words > 0; words--) ! 41: checksum += *packet++; ! 42: checksum = (checksum >> 16) + (checksum & 0xffff); ! 43: checksum += (checksum >> 16); ! 44: return ~checksum; ! 45: } ! 46: ! 47: ! 48: static int ! 49: send_bootp(filename_ip_t * fn_ip) ! 50: { ! 51: #if DEBUG ! 52: int i; ! 53: #endif ! 54: unsigned int packetsize = ! 55: sizeof(struct iphdr) + sizeof(struct ethhdr) + ! 56: sizeof(struct udphdr) + sizeof(struct btphdr); ! 57: unsigned char packet[packetsize]; ! 58: struct iphdr *iph; ! 59: struct udphdr *udph; ! 60: struct btphdr *btph; ! 61: ! 62: iph = (struct iphdr *) packet; ! 63: udph = (struct udphdr *) (iph + 1); ! 64: btph = (struct btphdr *) (udph + 1); ! 65: ! 66: memset(packet, 0, packetsize); ! 67: ! 68: fill_iphdr((uint8_t *) iph, htons(packetsize - sizeof(struct ethhdr)), ! 69: IPTYPE_UDP, 0, fn_ip->server_ip); ! 70: fill_udphdr((uint8_t *) udph, ! 71: htons(sizeof(struct udphdr) + sizeof(struct btphdr)), ! 72: htons(UDPPORT_BOOTPC), htons(UDPPORT_BOOTPS)); ! 73: btph->op = 1; ! 74: btph->htype = 1; ! 75: btph->hlen = 6; ! 76: strcpy((char *) btph->file, "bla"); ! 77: memcpy(btph->chaddr, get_mac_address(), 6); ! 78: ! 79: #if DEBUG ! 80: printf("Sending packet\n"); ! 81: printf("Packet is "); ! 82: for (i = 0; i < packetsize; i++) ! 83: printf(" %02x", packet[i]); ! 84: printf(".\n"); ! 85: #endif ! 86: ! 87: send_ipv4(packet, iph->ip_len); ! 88: #if DEBUG ! 89: printf("%d bytes transmitted over socket.\n", i); ! 90: #endif ! 91: ! 92: return 0; ! 93: } ! 94: ! 95: ! 96: static int ! 97: receive_bootp(filename_ip_t * fn_ip) ! 98: { ! 99: int len, old_sum; ! 100: unsigned int packetsize = 2000; ! 101: unsigned char packet[packetsize]; ! 102: struct ethhdr *ethh; ! 103: struct iphdr *iph; ! 104: struct udphdr *udph; ! 105: struct btphdr *btph; ! 106: ! 107: ethh = (struct ethhdr *) packet; ! 108: iph = (struct iphdr *) (packet + sizeof(struct ethhdr)); ! 109: udph = (struct udphdr *) (iph + 1); ! 110: btph = (struct btphdr *) (udph + 1); ! 111: ! 112: memset(packet, 0, packetsize); ! 113: ! 114: /* setting up a timer with a timeout of one second */ ! 115: set_timer(TICKS_SEC); ! 116: ! 117: do { ! 118: ! 119: /* let's receive a packet */ ! 120: len = recv(0, packet, packetsize, 0); ! 121: ! 122: #if DEBUG ! 123: int j; ! 124: printf("%d bytes received, %d expected \n", len, packetsize); ! 125: if (len == 346) { ! 126: printf("Rec packet\n"); ! 127: printf("Packet is "); ! 128: for (j = 0; j < len; j++) { ! 129: if (j % 16 == 0) ! 130: printf("\n"); ! 131: printf(" %02x", packet[j]); ! 132: } ! 133: printf(".\n"); ! 134: } ! 135: #endif ! 136: /* check if the ip checksum is correct */ ! 137: old_sum = iph->ip_sum; ! 138: iph->ip_sum = 0x00; ! 139: if (old_sum != ! 140: checksum((unsigned short *) iph, sizeof(struct iphdr) >> 1)) ! 141: /* checksum failed */ ! 142: continue; ! 143: /* is it a udp packet */ ! 144: if (iph->ip_p != IPTYPE_UDP) ! 145: continue; ! 146: /* check if the source port and destination port and the packet ! 147: * say that it is a bootp answer */ ! 148: if (udph->uh_dport != htons(UDPPORT_BOOTPC) || udph->uh_sport != htons(UDPPORT_BOOTPS)) ! 149: continue; ! 150: /* check if it is a Boot Reply */ ! 151: if (btph->op != 2) ! 152: continue; ! 153: /* Comparing our mac address with the one in the bootp reply */ ! 154: if (memcmp(get_mac_address(), btph->chaddr, ETH_ALEN)) ! 155: continue; ! 156: ! 157: if(response_buffer) ! 158: memcpy(response_buffer, btph, 1720); ! 159: ! 160: fn_ip->own_ip = btph->yiaddr; ! 161: fn_ip->server_ip = btph->siaddr; ! 162: strcpy((char *) fn_ip->filename, (char *) btph->file); ! 163: ! 164: #if DEBUG ! 165: printf("\nThese are the details of the bootp reply:\n"); ! 166: printf("Our IP address: "); ! 167: print_ip((char*) &fn_ip->own_ip); ! 168: printf("Next server IP address: "); ! 169: print_ip((char*) &fn_ip->server_ip); ! 170: printf("Boot file name: %s\n", btph->file); ! 171: printf("Packet is: %s\n", btph->file); ! 172: for (j = 0; j < len; j++) { ! 173: if (j % 16 == 0) ! 174: printf("\n"); ! 175: printf(" %02x", packet[j]); ! 176: } ! 177: printf(".\n"); ! 178: printf("fn_ip->own_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", ! 179: get_mac_address()[0], get_mac_address()[1], ! 180: get_mac_address()[2], get_mac_address()[3], ! 181: get_mac_address()[4], get_mac_address()[5]); ! 182: printf("Header ethh->dest_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", ! 183: ethh->dest_mac[0], ethh->dest_mac[1], ethh->dest_mac[2], ! 184: ethh->dest_mac[3], ethh->dest_mac[4], ethh->dest_mac[5]); ! 185: printf("Header ethh->src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", ! 186: ethh->src_mac[0], ethh->src_mac[1], ethh->src_mac[2], ! 187: ethh->src_mac[3], ethh->src_mac[4], ethh->src_mac[5]); ! 188: printf("Header ethh->typ: %x\n",ethh->type); ! 189: printf("Header iph->ip_hlv: %x\n",iph->ip_hlv); ! 190: printf("Header iph->ip_len: %x\n",iph->ip_len); ! 191: printf("Header iph->ip_id: %x\n",iph->ip_id); ! 192: printf("Header iph->ip_off: %x\n",iph->ip_off); ! 193: printf("Header iph->ip_ttl: %x\n",iph->ip_ttl); ! 194: printf("Header iph->ip_p: %x\n",iph->ip_p); ! 195: printf("Header iph->ip_sum: %x\n",iph->ip_sum); ! 196: printf("Header iph->ip_src: %x\n",iph->ip_src); ! 197: printf("Header iph->ip_dst: %x\n",iph->ip_dst); ! 198: ! 199: printf("Header btph->op: %x\n",btph->op); ! 200: printf("Header btph->htype: %x\n",btph->htype); ! 201: printf("Header btph->hlen: %x\n",btph->hlen); ! 202: printf("Header btph->hops: %x\n",btph->hops); ! 203: printf("Header btph->xid: %x\n",btph->xid); ! 204: printf("Header btph->secs: %x\n",btph->secs); ! 205: printf("Header btph->ciaddr: %x\n",btph->ciaddr); ! 206: printf("Header btph->yiaddr: %x\n",btph->yiaddr); ! 207: printf("Header btph->siaddr: %x\n",btph->siaddr); ! 208: printf("Header btph->giaddr: %x\n",btph->giaddr); ! 209: ! 210: printf("Header btph->chaddr: %02x:%02x:%02x:%02x:%02x:%02x:\n", ! 211: btph->chaddr[0], btph->chaddr[1], btph->chaddr[2], ! 212: btph->chaddr[3], btph->chaddr[4], btph->chaddr[5]); ! 213: ! 214: #endif ! 215: return 0; ! 216: ! 217: /* only do this for the time specified during set_timer() */ ! 218: } while (get_timer() > 0); ! 219: return -1; ! 220: } ! 221: ! 222: ! 223: int ! 224: bootp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries) ! 225: { ! 226: int i = (int) retries+1; ! 227: fn_ip->own_ip = 0; ! 228: ! 229: printf(" "); ! 230: ! 231: response_buffer = ret_buffer; ! 232: ! 233: do { ! 234: printf("\b\b%02d", i); ! 235: if (!i--) { ! 236: printf("\nGiving up after %d bootp requests\n", ! 237: retries+1); ! 238: return -1; ! 239: } ! 240: send_bootp(fn_ip); ! 241: /* if the timer in receive_bootp expired it will return ! 242: * -1 and we will just send another bootp request just ! 243: * in case the previous one was lost. And because we don't ! 244: * trust the network cable we keep on doing this 30 times */ ! 245: } while (receive_bootp(fn_ip) != 0); ! 246: printf("\b\b\b"); ! 247: return 0; ! 248: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.