4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include <sys/types.h>
30 #include <netinet/in.h>
31 #include <netinet/dhcp.h>
32 #include <libinetutil.h>
35 #include "ipc_action.h"
41 * interfaces for state transition/action functions. these functions
42 * can be found in suitably named .c files, such as inform.c, select.c,
51 * DHCP state machine representation: includes all of the information used for
52 * a state machine instance. For IPv4, this represents a single logical
53 * interface and (usually) a leased address. For IPv6, it represents a
54 * DUID+IAID combination. Note that if multiple DUID+IAID instances are one
55 * day allowed per interface, this will need to become a list.
58 dhcp_smach_t
*dsm_next
; /* Note: must be first */
59 dhcp_smach_t
*dsm_prev
;
62 * The name of the state machine. This is currently just a pointer to
63 * the controlling LIF's name, but could be otherwise.
66 dhcp_lif_t
*dsm_lif
; /* Controlling LIF */
67 uint_t dsm_hold_count
; /* reference count */
69 dhcp_lease_t
*dsm_leases
; /* List of leases */
70 uint_t dsm_lif_wait
; /* LIFs waiting on DAD */
71 uint_t dsm_lif_down
; /* LIFs failed */
74 * each state machine can have at most one pending asynchronous
75 * action, which is represented in a `struct async_action'.
76 * if that asynchronous action was a result of a user request,
77 * then the `struct ipc_action' is used to hold information
78 * about the user request. these structures are opaque to
79 * users of the ifslist, and the functional interfaces
80 * provided in async.[ch] and ipc_action.[ch] should be used
85 async_action_t dsm_async
;
87 uchar_t
*dsm_cid
; /* client id */
88 uchar_t dsm_cidlen
; /* client id len */
91 * current state of the machine
95 boolean_t dsm_droprelease
; /* soon to call finished_smach */
97 uint16_t dsm_dflags
; /* DHCP_IF_* (shared with IPC) */
99 uint16_t *dsm_prl
; /* if non-NULL, param request list */
100 uint_t dsm_prllen
; /* param request list len */
101 uint16_t *dsm_pil
; /* if non-NULL, param ignore list */
102 uint_t dsm_pillen
; /* param ignore list len */
104 uint_t dsm_nrouters
; /* the number of default routers */
105 struct in_addr
*dsm_routers
; /* an array of default routers */
107 in6_addr_t dsm_server
; /* our DHCP server */
108 uchar_t
*dsm_serverid
; /* server DUID for v6 */
109 uint_t dsm_serveridlen
; /* DUID length */
112 * We retain the very first ack obtained on the state machine to
113 * provide access to options which were originally assigned by
114 * the server but may not have been included in subsequent
115 * acks, as there are servers which do this and customers have
116 * had unsatisfactory results when using our agent with them.
117 * ipc_event() in agent.c provides a fallback to the original
118 * ack when the current ack doesn't have the information
121 * Note that neither of these is actually a list of packets. There's
122 * exactly one packet here, so use free_pkt_entry.
125 PKT_LIST
*dsm_orig_ack
;
128 * other miscellaneous variables set or needed in the process
129 * of acquiring a lease.
132 int dsm_offer_wait
; /* seconds between sending offers */
133 iu_timer_id_t dsm_offer_timer
; /* timer associated with offer wait */
136 * time we sent the DISCOVER relative to dsm_neg_hrtime, so that the
137 * REQUEST can have the same pkt->secs.
140 uint16_t dsm_disc_secs
;
143 * this is a chain of packets which have been received on this
144 * state machine over some interval of time. the packets may have
145 * to meet some criteria in order to be put on this list. in
146 * general, packets are put on this list through recv_pkt()
149 PKT_LIST
*dsm_recv_pkt_list
;
152 * these three fields are initially zero, and get incremented
153 * as the ifslist goes from INIT -> BOUND. if and when the
154 * ifslist moves to the RENEWING state, these fields are
155 * reset, so they always either indicate the number of packets
156 * sent, received, and declined while obtaining the current
157 * lease (if BOUND), or the number of packets sent, received,
158 * and declined while attempting to obtain a future lease
159 * (if any other state).
163 uint32_t dsm_received
;
164 uint32_t dsm_bad_offers
;
167 * dsm_send_pkt.pkt is dynamically allocated to be as big a
168 * packet as we can send out on this state machine. the remainder
169 * of this information is needed to make it easy to handle
170 * retransmissions. note that other than dsm_bad_offers, all
171 * of these fields are maintained internally in send_pkt(),
172 * and consequently should never need to be modified by any
176 dhcp_pkt_t dsm_send_pkt
;
178 struct sockaddr_in v4
;
179 struct sockaddr_in6 v6
;
183 * For v4, dsm_send_tcenter is used to track the central timer value in
184 * milliseconds (4000, 8000, 16000, 32000, 64000), and dsm_send_timeout
185 * is that value plus the +/- 1000 millisecond fuzz.
187 * For v6, dsm_send_tcenter is the MRT (maximum retransmit timer)
188 * value, and dsm_send_timeout must be set to the IRT (initial
189 * retransmit timer) value by the sender.
191 uint_t dsm_send_timeout
;
192 uint_t dsm_send_tcenter
;
193 stop_func_t
*dsm_send_stop_func
;
194 uint32_t dsm_packet_sent
;
195 iu_timer_id_t dsm_retrans_timer
;
198 * The host name we've been asked to request is remembered
199 * here between the DISCOVER and the REQUEST. (v4 only)
204 * V4 and V6 use slightly different timers. For v4, we must count
205 * seconds from the point where we first try to configure the
206 * interface. For v6, only seconds while performing a transaction
209 * In v4, `dsm_neg_hrtime' represents the time since DHCP started
210 * configuring the interface, and is used for computing the pkt->secs
211 * field in v4. In v6, it represents the time since the current
212 * transaction (if any) was started, and is used for the ELAPSED_TIME
215 * `dsm_newstart_monosec' represents the time the ACKed REQUEST was
216 * sent, which represents the start time of a new batch of leases.
217 * When the lease time actually begins (and thus becomes current),
218 * `dsm_curstart_monosec' is set to `dsm_newstart_monosec'.
220 hrtime_t dsm_neg_hrtime
;
221 monosec_t dsm_newstart_monosec
;
222 monosec_t dsm_curstart_monosec
;
225 pid_t dsm_script_pid
;
226 pid_t dsm_script_helper_pid
;
227 const char *dsm_script_event
;
228 iu_event_id_t dsm_script_event_id
;
229 void *dsm_callback_arg
;
230 script_callback_t
*dsm_script_callback
;
232 iu_timer_id_t dsm_start_timer
;
235 #define dsm_isv6 dsm_lif->lif_pif->pif_isv6
236 #define dsm_hwtype dsm_lif->lif_pif->pif_hwtype
238 struct dhcp_lease_s
{
239 dhcp_lease_t
*dl_next
; /* Note: must be first */
240 dhcp_lease_t
*dl_prev
;
242 dhcp_smach_t
*dl_smach
; /* back pointer to state machine */
243 dhcp_lif_t
*dl_lifs
; /* LIFs configured by this lease */
244 uint_t dl_nlifs
; /* Number of configured LIFs */
245 uint_t dl_hold_count
; /* reference counter */
246 boolean_t dl_removed
; /* Set if removed from list */
247 boolean_t dl_stale
; /* not updated by Renew/bind */
250 * the following fields are set when a lease is acquired, and
251 * may be updated over the lifetime of the lease. they are
252 * all reset by reset_smach().
255 dhcp_timer_t dl_t1
; /* relative renewal start time, hbo */
256 dhcp_timer_t dl_t2
; /* relative rebinding start time, hbo */
259 /* The IU event callback functions */
260 iu_eh_callback_t dhcp_acknak_global
;
261 iu_eh_callback_t dhcp_packet_lif
;
263 /* Common state-machine related routines throughout dhcpagent */
264 boolean_t
dhcp_adopt(void);
265 void dhcp_adopt_complete(dhcp_smach_t
*);
266 boolean_t
dhcp_bound(dhcp_smach_t
*, PKT_LIST
*);
267 void dhcp_bound_complete(dhcp_smach_t
*);
268 int dhcp_drop(dhcp_smach_t
*, void *);
269 void dhcp_deprecate(iu_tq_t
*, void *);
270 void dhcp_expire(iu_tq_t
*, void *);
271 boolean_t
dhcp_extending(dhcp_smach_t
*);
272 void dhcp_inform(dhcp_smach_t
*);
273 void dhcp_init_reboot(dhcp_smach_t
*);
274 void dhcp_rebind(iu_tq_t
*, void *);
275 int dhcp_release(dhcp_smach_t
*, void *);
276 void dhcp_renew(iu_tq_t
*, void *);
277 void dhcp_requesting(iu_tq_t
*, void *);
278 void dhcp_restart(dhcp_smach_t
*);
279 void dhcp_selecting(dhcp_smach_t
*);
280 boolean_t
set_start_timer(dhcp_smach_t
*);
281 void send_declines(dhcp_smach_t
*);
282 void send_v6_request(dhcp_smach_t
*);
283 boolean_t
save_server_id(dhcp_smach_t
*, PKT_LIST
*);
284 void server_unicast_option(dhcp_smach_t
*, PKT_LIST
*);
286 /* State machine support functions in states.c */
287 dhcp_smach_t
*insert_smach(dhcp_lif_t
*, int *);
288 void hold_smach(dhcp_smach_t
*);
289 void release_smach(dhcp_smach_t
*);
290 void remove_smach(dhcp_smach_t
*);
291 dhcp_smach_t
*next_smach(dhcp_smach_t
*, boolean_t
);
292 dhcp_smach_t
*primary_smach(boolean_t
);
293 dhcp_smach_t
*info_primary_smach(boolean_t
);
294 void make_primary(dhcp_smach_t
*);
295 dhcp_smach_t
*lookup_smach(const char *, boolean_t
);
296 dhcp_smach_t
*lookup_smach_by_uindex(uint16_t, dhcp_smach_t
*, boolean_t
);
297 dhcp_smach_t
*lookup_smach_by_xid(uint32_t, dhcp_smach_t
*, boolean_t
);
298 dhcp_smach_t
*lookup_smach_by_event(iu_event_id_t
);
299 void finished_smach(dhcp_smach_t
*, int);
300 boolean_t
set_smach_state(dhcp_smach_t
*, DHCPSTATE
);
301 int get_smach_cid(dhcp_smach_t
*);
302 boolean_t
verify_smach(dhcp_smach_t
*);
303 uint_t
smach_count(void);
304 void reset_smach(dhcp_smach_t
*);
305 void refresh_smachs(iu_eh_t
*, int, void *);
306 void refresh_smach(dhcp_smach_t
*);
307 void nuke_smach_list(void);
308 boolean_t
schedule_smach_timer(dhcp_smach_t
*, int, uint32_t,
310 void cancel_offer_timer(dhcp_smach_t
*);
311 void cancel_smach_timers(dhcp_smach_t
*);
312 void discard_default_routes(dhcp_smach_t
*);
313 void remove_default_routes(dhcp_smach_t
*);
314 boolean_t
is_bound_state(DHCPSTATE
);
316 /* Lease-related support functions in states.c */
317 dhcp_lease_t
*insert_lease(dhcp_smach_t
*);
318 void hold_lease(dhcp_lease_t
*);
319 void release_lease(dhcp_lease_t
*);
320 void remove_lease(dhcp_lease_t
*);
321 void deprecate_leases(dhcp_smach_t
*);
322 void cancel_lease_timers(dhcp_lease_t
*);
323 boolean_t
schedule_lease_timer(dhcp_lease_t
*, dhcp_timer_t
*,
330 #endif /* STATES_H */