Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/ipconfig/dhcp_proto.c

Parent Directory Parent Directory | Revision Log Revision Log


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