2
* ipconfig/bootp_proto.c
4
* BOOTP packet protocol handling.
7
#include <linux/types.h> /* for __u8 */
14
#include <netinet/in.h>
18
#include "bootp_packet.h"
19
#include "bootp_proto.h"
22
static __u8 bootp_options[312] = {
23
[0] = 99, 130, 83, 99,/* RFC1048 magic cookie */
24
[4] = 1, 4, /* 4- 9 subnet mask */
25
[10] = 3, 4, /* 10- 15 default gateway */
26
[16] = 5, 8, /* 16- 25 nameserver */
27
[26] = 12, 32, /* 26- 59 host name */
28
[60] = 40, 32, /* 60- 95 nis domain name */
29
[96] = 17, 40, /* 96-137 boot path */
30
[138] = 57, 2, 1, 150, /* 138-141 extension buffer */
31
[142] = 255, /* end of list */
35
* Send a plain bootp request packet with options
37
int bootp_send_request(struct netdev *dev)
39
struct bootp_hdr bootp;
40
struct iovec iov[] = {
41
/* [0] = ip + udp headers */
42
[1] = { &bootp, sizeof(bootp) },
43
[2] = { bootp_options, 312 }
46
memset(&bootp, 0, sizeof(struct bootp_hdr));
48
bootp.op = BOOTP_REQUEST,
49
bootp.htype = dev->hwtype;
50
bootp.hlen = dev->hwlen;
51
bootp.xid = dev->bootp.xid;
52
bootp.ciaddr = dev->ip_addr;
53
bootp.secs = htons(time(NULL) - dev->open_time);
54
memcpy(bootp.chaddr, dev->hwaddr, 16);
56
DEBUG(("-> bootp xid 0x%08x secs 0x%08x ",
57
bootp.xid, ntohs(bootp.secs)));
59
return packet_send(dev, iov, 2);
63
* Parse a bootp reply packet
66
bootp_parse(struct netdev *dev, struct bootp_hdr *hdr, __u8 *exts, int extlen)
68
dev->bootp.gateway = hdr->giaddr;
69
dev->ip_addr = hdr->yiaddr;
70
dev->ip_server = hdr->siaddr;
71
dev->ip_netmask = INADDR_ANY;
72
dev->ip_broadcast = INADDR_ANY;
73
dev->ip_gateway = hdr->giaddr;
74
dev->ip_nameserver[0] = INADDR_ANY;
75
dev->ip_nameserver[1] = INADDR_ANY;
76
dev->hostname[0] = '\0';
77
dev->nisdomainname[0] = '\0';
78
dev->bootpath[0] = '\0';
80
if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 &&
81
exts[2] == 83 && exts[3] == 99) {
84
for (ext = exts + 4; ext - exts < extlen; ) {
85
__u8 len, opt = *ext++;
92
case 1: /* subnet mask */
93
memcpy(&dev->ip_netmask, ext, len > 4 ? 4 : len);
95
case 3: /* default gateway */
96
memcpy(&dev->ip_gateway, ext, len > 4 ? 4 : len);
98
case 6: /* DNS server */
99
memcpy(&dev->ip_nameserver, ext, len > 8 ? 8 : len);
101
case 12: /* host name */
102
if (len > sizeof(dev->hostname) - 1)
103
len = sizeof(dev->hostname) - 1;
104
memcpy(&dev->hostname, ext, len);
105
dev->hostname[len] = '\0';
107
case 15: /* domain name */
108
if (len > sizeof(dev->dnsdomainname) - 1)
109
len = sizeof(dev->dnsdomainname) - 1;
110
memcpy(&dev->dnsdomainname, ext, len);
111
dev->dnsdomainname[len] = '\0';
113
case 17: /* root path */
114
if (len > sizeof(dev->bootpath) - 1)
115
len = sizeof(dev->bootpath) - 1;
116
memcpy(&dev->bootpath, ext, len);
117
dev->bootpath[len] = '\0';
119
case 26: /* interface MTU */
121
dev->mtu = (ext[0] << 8) + ext[1];
123
case 28: /* broadcast addr */
124
memcpy(&dev->ip_broadcast, ext, len > 4 ? 4 : len);
126
case 40: /* NIS domain name */
127
if (len > sizeof(dev->nisdomainname) - 1)
128
len = sizeof(dev->nisdomainname) - 1;
129
memcpy(&dev->nisdomainname, ext, len);
130
dev->nisdomainname[len] = '\0';
145
* Receive a bootp reply and parse packet
147
int bootp_recv_reply(struct netdev *dev)
149
struct bootp_hdr bootp;
150
__u8 bootp_options[312];
151
struct iovec iov[] = {
152
/* [0] = ip + udp headers */
153
[1] = { &bootp, sizeof(struct bootp_hdr) },
154
[2] = { bootp_options, 312 }
158
ret = packet_recv(iov, 3);
162
if (ret < sizeof(struct bootp_hdr) ||
163
bootp.op != BOOTP_REPLY || /* RFC951 7.5 */
164
bootp.xid != dev->bootp.xid ||
165
memcmp(bootp.chaddr, dev->hwaddr, 16))
168
ret -= sizeof(struct bootp_hdr);
170
return bootp_parse(dev, &bootp, bootp_options, ret);
174
* Initialise interface for bootp.
176
int bootp_init_if(struct netdev *dev)
181
* Get the device flags
183
if (netdev_getflags(dev, &flags))
187
* We can't do DHCP nor BOOTP if this device
188
* doesn't support broadcast.
190
if (dev->mtu < 364 || (flags & IFF_BROADCAST) == 0) {
191
dev->caps &= ~(CAP_BOOTP | CAP_DHCP);
198
dev->bootp.xid = (__u32)lrand48();
199
dev->open_time = time(NULL);