~ubuntu-branches/ubuntu/hardy/klibc/hardy-updates

« back to all changes in this revision

Viewing changes to ipconfig/bootp_proto.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeff Bailey
  • Date: 2006-01-04 20:24:52 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104202452-ec4v3n829rymukuv
Tags: 1.1.15-0ubuntu1
* New upstream version.

* Patch to fix compilation on parisc64 kernels.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * ipconfig/bootp_proto.c
3
 
 *
4
 
 * BOOTP packet protocol handling.
5
 
 */
6
 
#include <sys/types.h>
7
 
#include <linux/types.h>        /* for __u8 */
8
 
#include <sys/uio.h>
9
 
#include <stdio.h>
10
 
#include <stdlib.h>
11
 
#include <string.h>
12
 
#include <time.h>
13
 
#include <unistd.h>
14
 
#include <netinet/in.h>
15
 
 
16
 
#include "ipconfig.h"
17
 
#include "netdev.h"
18
 
#include "bootp_packet.h"
19
 
#include "bootp_proto.h"
20
 
#include "packet.h"
21
 
 
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 */
32
 
};
33
 
 
34
 
/*
35
 
 * Send a plain bootp request packet with options
36
 
 */
37
 
int bootp_send_request(struct netdev *dev)
38
 
{
39
 
        struct bootp_hdr bootp;
40
 
        struct iovec iov[] = {
41
 
                /* [0] = ip + udp headers */
42
 
                [1] = { &bootp, sizeof(bootp) },
43
 
                [2] = { bootp_options, 312 }
44
 
        };
45
 
 
46
 
        memset(&bootp, 0, sizeof(struct bootp_hdr));
47
 
 
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);
55
 
 
56
 
        DEBUG(("-> bootp xid 0x%08x secs 0x%08x ",
57
 
               bootp.xid, ntohs(bootp.secs)));
58
 
 
59
 
        return packet_send(dev, iov, 2);
60
 
}
61
 
 
62
 
/*
63
 
 * Parse a bootp reply packet
64
 
 */
65
 
int
66
 
bootp_parse(struct netdev *dev, struct bootp_hdr *hdr, __u8 *exts, int extlen)
67
 
{
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';
79
 
 
80
 
        if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 &&
81
 
            exts[2] == 83 && exts[3] == 99) {
82
 
                __u8 *ext;
83
 
 
84
 
                for (ext = exts + 4; ext - exts < extlen; ) {
85
 
                        __u8 len, opt = *ext++;
86
 
                        if (opt == 0)
87
 
                                continue;
88
 
 
89
 
                        len = *ext++;
90
 
 
91
 
                        switch (opt) {
92
 
                        case 1: /* subnet mask */
93
 
                                memcpy(&dev->ip_netmask, ext, len > 4 ? 4 : len);
94
 
                                break;
95
 
                        case 3: /* default gateway */
96
 
                                memcpy(&dev->ip_gateway, ext, len > 4 ? 4 : len);
97
 
                                break;
98
 
                        case 6: /* DNS server */
99
 
                                memcpy(&dev->ip_nameserver, ext, len > 8 ? 8 : len);
100
 
                                break;
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';
106
 
                                break;
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';
112
 
                                break;
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';
118
 
                                break;
119
 
                        case 26: /* interface MTU */
120
 
                                if ( len == 2  )
121
 
                                        dev->mtu = (ext[0] << 8) + ext[1];
122
 
                                break;
123
 
                        case 28: /* broadcast addr */
124
 
                                memcpy(&dev->ip_broadcast, ext, len > 4 ? 4 : len);
125
 
                                break;
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';
131
 
                                break;
132
 
                        }                               
133
 
 
134
 
                        ext += len;
135
 
                }
136
 
        }
137
 
 
138
 
        /*
139
 
         * Got packet.
140
 
         */
141
 
        return 1;
142
 
}
143
 
 
144
 
/*
145
 
 * Receive a bootp reply and parse packet
146
 
 */
147
 
int bootp_recv_reply(struct netdev *dev)
148
 
{
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 }
155
 
        };
156
 
        int ret;
157
 
 
158
 
        ret = packet_recv(iov, 3);
159
 
        if (ret <= 0)
160
 
                return ret;
161
 
 
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))
166
 
                return 0;
167
 
 
168
 
        ret -= sizeof(struct bootp_hdr);
169
 
 
170
 
        return bootp_parse(dev, &bootp, bootp_options, ret);
171
 
}
172
 
 
173
 
/*
174
 
 * Initialise interface for bootp.
175
 
 */
176
 
int bootp_init_if(struct netdev *dev)
177
 
{
178
 
        short flags;
179
 
 
180
 
        /*
181
 
         * Get the device flags
182
 
         */
183
 
        if (netdev_getflags(dev, &flags))
184
 
                return -1;
185
 
 
186
 
        /*
187
 
         * We can't do DHCP nor BOOTP if this device
188
 
         * doesn't support broadcast.
189
 
         */
190
 
        if (dev->mtu < 364 || (flags & IFF_BROADCAST) == 0) {
191
 
                dev->caps &= ~(CAP_BOOTP | CAP_DHCP);
192
 
                return 0;
193
 
        }
194
 
        
195
 
        /*
196
 
         * Get a random XID
197
 
         */
198
 
        dev->bootp.xid = (__u32)lrand48();
199
 
        dev->open_time = time(NULL);
200
 
 
201
 
        return 0;
202
 
}