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