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

« back to all changes in this revision

Viewing changes to ipconfig/dhcp_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/dhcp_proto.c
3
 
 *
4
 
 * DHCP RFC 2131 and 2132
5
 
 */
6
 
#include <sys/types.h>
7
 
#include <linux/types.h>        /* for __u8 */
8
 
#include <sys/uio.h>
9
 
#include <netinet/in.h>
10
 
#include <stdio.h>
11
 
#include <string.h>
12
 
#include <time.h>
13
 
 
14
 
#include "ipconfig.h"
15
 
#include "netdev.h"
16
 
#include "bootp_packet.h"
17
 
#include "bootp_proto.h"
18
 
#include "dhcp_proto.h"
19
 
#include "packet.h"
20
 
 
21
 
static __u8 dhcp_params[] = {
22
 
        1,                      /* subnet mask */
23
 
        3,                      /* default gateway */
24
 
        6,                      /* DNS server */
25
 
        12,                     /* host name */
26
 
        15,                     /* domain name */
27
 
        17,                     /* root path */
28
 
        26,                     /* interface mtu */
29
 
        28,                     /* broadcast addr */
30
 
        40,                     /* NIS domain name (why?) */
31
 
};
32
 
 
33
 
static __u8 dhcp_discover_hdr[] = {
34
 
        99, 130, 83, 99,        /* bootp cookie */
35
 
        53, 1, DHCPDISCOVER,    /* dhcp message type */
36
 
        55, sizeof(dhcp_params),/* parameter list */
37
 
};
38
 
 
39
 
static __u8 dhcp_request_hdr[] = {
40
 
        99, 130, 83, 99,        /* boot cookie */
41
 
        53, 1, DHCPREQUEST,     /* dhcp message type */
42
 
#define SERVER_IP_OFF 9
43
 
        54, 4, 0, 0, 0, 0,      /* server IP */
44
 
#define REQ_IP_OFF 15
45
 
        50, 4, 0, 0, 0, 0,      /* requested IP address */
46
 
        55, sizeof(dhcp_params),/* parameter list */
47
 
};
48
 
 
49
 
static __u8 dhcp_end[] = {
50
 
        255,
51
 
};
52
 
 
53
 
static struct iovec dhcp_discover_iov[] = {
54
 
        /* [0] = ip + udp header */
55
 
        /* [1] = bootp header */
56
 
        [2] = { dhcp_discover_hdr, sizeof(dhcp_discover_hdr) },
57
 
        [3] = { dhcp_params, sizeof(dhcp_params) },
58
 
        [4] = { dhcp_end, sizeof(dhcp_end) }
59
 
};
60
 
 
61
 
static struct iovec dhcp_request_iov[] = {
62
 
        /* [0] = ip + udp header */
63
 
        /* [1] = bootp header */
64
 
        [2] = { dhcp_request_hdr, sizeof(dhcp_request_hdr) },
65
 
        [3] = { dhcp_params, sizeof(dhcp_params) },
66
 
        [4] = { dhcp_end, sizeof(dhcp_end) }
67
 
};
68
 
 
69
 
/*
70
 
 * Parse a DHCP response packet
71
 
 */
72
 
static int
73
 
dhcp_parse(struct netdev *dev, struct bootp_hdr *hdr, __u8 *exts, int extlen)
74
 
{
75
 
        __u8 type = 0;
76
 
        __u32 serverid = INADDR_NONE;
77
 
        int ret = 0;
78
 
 
79
 
        if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 &&
80
 
            exts[2] == 83 && exts[3] == 99) {
81
 
                __u8 *ext;
82
 
 
83
 
                for (ext = exts + 4; ext - exts < extlen; ) {
84
 
                        __u8 len, *opt = ext++;
85
 
                        if (*opt == 0)
86
 
                                continue;
87
 
 
88
 
                        len = *ext++;
89
 
 
90
 
                        ext += len;
91
 
 
92
 
                        if (*opt == 53)
93
 
                                type = opt[2];
94
 
                        if (*opt == 54)
95
 
                                memcpy(&serverid, opt + 2, 4);
96
 
                }
97
 
        }
98
 
 
99
 
        switch (type) {
100
 
        case DHCPOFFER:
101
 
                ret = bootp_parse(dev, hdr, exts, extlen);
102
 
                if (ret == 1 && serverid != INADDR_NONE)
103
 
                        dev->serverid = serverid;
104
 
                DEBUG(("\n   dhcp offer\n"));
105
 
                break;
106
 
 
107
 
        case DHCPACK:
108
 
                ret = bootp_parse(dev, hdr, exts, extlen);
109
 
                DEBUG(("\n   dhcp ack\n"));
110
 
                break;
111
 
 
112
 
        case DHCPNAK:
113
 
                ret = 2;
114
 
                DEBUG(("\n   dhcp nak\n"));
115
 
                break;
116
 
        }
117
 
        return ret;
118
 
}
119
 
 
120
 
/*
121
 
 * Receive and parse a DHCP packet
122
 
 */
123
 
static int dhcp_recv(struct netdev *dev)
124
 
{
125
 
        struct bootp_hdr bootp;
126
 
        __u8 dhcp_options[1500];
127
 
        struct iovec iov[] = {
128
 
                /* [0] = ip + udp header */
129
 
                [1] = { &bootp, sizeof(struct bootp_hdr) },
130
 
                [2] = { dhcp_options, sizeof(dhcp_options) }
131
 
        };
132
 
        int ret;
133
 
 
134
 
        ret = packet_recv(iov, 3);
135
 
        if (ret <= 0)
136
 
                return ret;
137
 
 
138
 
        DEBUG(("\n   dhcp xid %08x ", dev->bootp.xid));
139
 
 
140
 
        if (ret < sizeof(struct bootp_hdr) ||
141
 
            bootp.op != BOOTP_REPLY ||          /* RFC951 7.5 */
142
 
            bootp.xid != dev->bootp.xid ||
143
 
            memcmp(bootp.chaddr, dev->hwaddr, 16))
144
 
                return 0;
145
 
 
146
 
        ret -= sizeof(struct bootp_hdr);
147
 
 
148
 
        return dhcp_parse(dev, &bootp, dhcp_options, ret);
149
 
}
150
 
 
151
 
static int dhcp_send(struct netdev *dev, struct iovec *vec, int len)
152
 
{
153
 
        struct bootp_hdr bootp;
154
 
 
155
 
        memset(&bootp, 0, sizeof(struct bootp_hdr));
156
 
 
157
 
        bootp.op     = BOOTP_REQUEST;
158
 
        bootp.htype  = dev->hwtype;
159
 
        bootp.hlen   = dev->hwlen;
160
 
        bootp.xid    = dev->bootp.xid;
161
 
        bootp.ciaddr = dev->ip_addr;
162
 
        bootp.giaddr = dev->bootp.gateway;
163
 
        bootp.secs   = htons(time(NULL) - dev->open_time);
164
 
        memcpy(bootp.chaddr, dev->hwaddr, 16);
165
 
 
166
 
        vec[1].iov_base = &bootp;
167
 
        vec[1].iov_len = sizeof(struct bootp_hdr);
168
 
 
169
 
        DEBUG(("xid %08x secs %d ",
170
 
               bootp.xid, ntohs(bootp.secs)));
171
 
 
172
 
        return packet_send(dev, vec, len);
173
 
}
174
 
 
175
 
/*
176
 
 * Send a DHCP discover packet
177
 
 */
178
 
int dhcp_send_discover(struct netdev *dev)
179
 
{
180
 
        dev->ip_addr = INADDR_ANY;
181
 
        dev->ip_gateway = INADDR_ANY;
182
 
 
183
 
        DEBUG(("-> dhcp discover "));
184
 
        
185
 
        return dhcp_send(dev, dhcp_discover_iov, 5);
186
 
}
187
 
 
188
 
/*
189
 
 * Receive a DHCP offer packet
190
 
 */
191
 
int dhcp_recv_offer(struct netdev *dev)
192
 
{
193
 
        return dhcp_recv(dev);
194
 
}
195
 
 
196
 
/*
197
 
 * Send a DHCP request packet
198
 
 */
199
 
int dhcp_send_request(struct netdev *dev)
200
 
{
201
 
        memcpy(&dhcp_request_hdr[SERVER_IP_OFF], &dev->serverid, 4);
202
 
        memcpy(&dhcp_request_hdr[REQ_IP_OFF], &dev->ip_addr, 4);
203
 
 
204
 
        DEBUG(("-> dhcp request "));
205
 
 
206
 
        return dhcp_send(dev, dhcp_request_iov, 5);
207
 
}
208
 
 
209
 
/*
210
 
 * Receive a DHCP ack packet
211
 
 */
212
 
int dhcp_recv_ack(struct netdev *dev)
213
 
{
214
 
        return dhcp_recv(dev);
215
 
}