]>
git.ipfire.org Git - thirdparty/dhcp.git/blob - server/bootp.c
3 BOOTP Protocol support. */
6 * Copyright (c) 1995, 1996 The Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38 * Enterprises. To learn more about the Internet Software Consortium,
39 * see ``http://www.vix.com/isc''. To learn more about Vixie
40 * Enterprises, see ``http://www.vix.com''.
44 static char copyright
[] =
45 "@(#) Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
51 struct packet
*packet
;
55 struct host_decl
*host
= (struct host_decl
*)0;
56 struct packet outgoing
;
57 struct dhcp_packet raw
;
58 struct sockaddr_in to
;
60 struct tree_cache
*options
[256];
61 struct subnet
*subnet
;
63 struct iaddr ip_address
;
66 note ("BOOTREQUEST from %s via %s",
67 print_hw_addr (packet
-> raw
-> htype
,
68 packet
-> raw
-> hlen
,
69 packet
-> raw
-> chaddr
),
70 packet
-> raw
-> giaddr
.s_addr
71 ? inet_ntoa (packet
-> raw
-> giaddr
)
72 : packet
-> interface
-> name
);
76 locate_network (packet
);
78 hp
= find_hosts_by_haddr (packet
-> raw
-> htype
,
79 packet
-> raw
-> chaddr
,
80 packet
-> raw
-> hlen
);
82 lease
= find_lease (packet
, packet
-> shared_network
);
84 /* Find an IP address in the host_decl that matches the
86 if (hp
&& packet
-> shared_network
)
87 subnet
= find_host_for_network (&hp
, &ip_address
,
88 packet
-> shared_network
);
90 subnet
= (struct subnet
*)0;
93 /* We didn't find an applicable host declaration.
94 Just in case we may be able to dynamically assign
95 an address, see if there's a host declaration
96 that doesn't have an ip address associated with it. */
98 for (; hp
; hp
= hp
-> n_ipaddr
) {
99 if (!hp
-> fixed_addr
) {
105 /* If the packet is from a host we don't know and there
106 are no dynamic bootp addresses on the network it came
107 in on, drop it on the floor. */
108 if (!(packet
-> shared_network
&&
109 packet
-> shared_network
-> dynamic_bootp
)) {
111 note ("No applicable record for BOOTP host %s",
112 print_hw_addr (packet
-> raw
-> htype
,
113 packet
-> raw
-> hlen
,
114 packet
-> raw
-> chaddr
));
118 /* If a lease has already been assigned to this client
119 and it's still okay to use dynamic bootp on
120 that lease, reassign it. */
122 /* If this lease can be used for dynamic bootp,
124 if ((lease
-> flags
& DYNAMIC_BOOTP_OK
)) {
126 /* If it's not a DYNAMIC_BOOTP lease,
127 release it before reassigning it
128 so that we don't get a lease
130 if (!(lease
-> flags
& BOOTP_LEASE
))
131 release_lease (lease
);
133 lease
-> host
= host
;
134 ack_lease (packet
, lease
, 0, 0);
138 /* If dynamic BOOTP is no longer allowed for
139 this lease, set it free. */
140 release_lease (lease
);
143 /* At this point, if we don't know the network from which
144 the packet came, lose it. */
145 if (!packet
-> shared_network
)
148 /* If there are dynamic bootp addresses that might be
149 available, try to snag one. */
151 packet
-> shared_network
-> last_lease
;
152 lease
&& lease
-> ends
<= cur_time
;
153 lease
= lease
-> prev
) {
154 if ((lease
-> flags
& DYNAMIC_BOOTP_OK
)) {
155 lease
-> host
= host
;
156 ack_lease (packet
, lease
, 0, 0);
163 /* If we don't have a fixed address for it, drop it. */
165 note ("No fixed address for BOOTP host %s (%s)",
166 print_hw_addr (packet
-> raw
-> htype
,
167 packet
-> raw
-> hlen
,
168 packet
-> raw
-> chaddr
),
173 /* Set up the outgoing packet... */
174 memset (&outgoing
, 0, sizeof outgoing
);
175 memset (&raw
, 0, sizeof raw
);
178 /* Come up with a list of options that we want to send to this
179 client. Start with the per-subnet options, and then override
180 those with client-specific options. */
182 memcpy (options
, subnet
-> options
, sizeof options
);
184 for (i
= 0; i
< 256; i
++) {
185 if (hp
-> options
[i
])
186 options
[i
] = hp
-> options
[i
];
189 /* Pack the options into the buffer. Unlike DHCP, we can't
190 pack options into the filename and server name buffers. */
192 cons_options (packet
, &outgoing
, options
, 0);
195 /* Take the fields that we care about... */
197 raw
.htype
= packet
-> raw
-> htype
;
198 raw
.hlen
= packet
-> raw
-> hlen
;
199 memcpy (raw
.chaddr
, packet
-> raw
-> chaddr
, raw
.hlen
);
200 memset (&raw
.chaddr
[raw
.hlen
], 0,
201 (sizeof raw
.chaddr
) - raw
.hlen
);
202 raw
.hops
= packet
-> raw
-> hops
;
203 raw
.xid
= packet
-> raw
-> xid
;
204 raw
.secs
= packet
-> raw
-> secs
;
206 raw
.ciaddr
= packet
-> raw
-> ciaddr
;
207 memcpy (&raw
.yiaddr
, ip_address
.iabuf
, sizeof raw
.yiaddr
);
209 if (subnet
-> interface_address
.len
)
210 memcpy (&raw
.siaddr
, subnet
-> interface_address
.iabuf
, 4);
212 memcpy (&raw
.siaddr
, server_identifier
.iabuf
, 4);
214 raw
.giaddr
= packet
-> raw
-> giaddr
;
215 if (hp
-> server_name
) {
216 strncpy (raw
.sname
, hp
-> server_name
,
217 (sizeof raw
.sname
) - 1);
218 raw
.sname
[(sizeof raw
.sname
) - 1] = 0;
220 if (hp
-> filename
) {
221 strncpy (raw
.file
, hp
-> filename
,
222 (sizeof raw
.file
) - 1);
223 raw
.file
[(sizeof raw
.file
) - 1] = 0;
226 /* Set up the hardware destination address... */
227 hto
.htype
= packet
-> raw
-> htype
;
228 hto
.hlen
= packet
-> raw
-> hlen
;
229 memcpy (hto
.haddr
, packet
-> raw
-> chaddr
, hto
.hlen
);
231 /* Report what we're doing... */
232 note ("BOOTREPLY for %s to %s (%s) via %s",
233 piaddr (ip_address
), hp
-> name
,
234 print_hw_addr (packet
-> raw
-> htype
,
235 packet
-> raw
-> hlen
,
236 packet
-> raw
-> chaddr
),
237 packet
-> raw
-> giaddr
.s_addr
238 ? inet_ntoa (packet
-> raw
-> giaddr
)
239 : packet
-> interface
-> name
);
241 /* Set up the parts of the address that are in common. */
242 to
.sin_family
= AF_INET
;
244 to
.sin_len
= sizeof to
;
246 memset (to
.sin_zero
, 0, sizeof to
.sin_zero
);
248 /* If this was gatewayed, send it back to the gateway... */
249 if (raw
.giaddr
.s_addr
) {
250 to
.sin_addr
= raw
.giaddr
;
251 to
.sin_port
= server_port
;
254 result
= send_fallback (&fallback_interface
,
256 &raw
, outgoing
.packet_length
,
257 raw
.siaddr
, &to
, &hto
);
259 warn ("send_fallback: %m");
262 /* Otherwise, broadcast it on the local network. */
264 to
.sin_addr
.s_addr
= INADDR_BROADCAST
;
265 to
.sin_port
= htons (ntohs (server_port
) + 1); /* XXX */
269 result
= send_packet (packet
-> interface
,
270 packet
, &raw
, outgoing
.packet_length
,
271 raw
.siaddr
, &to
, &hto
);
273 warn ("send_packet: %m");