xref: /onnv-gate/usr/src/cmd/cmd-inet/sbin/dhcpagent/states.h (revision 9633:309290318ad0)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52546Scarlsonj  * Common Development and Distribution License (the "License").
62546Scarlsonj  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
229508SPeter.Memishian@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #ifndef	STATES_H
270Sstevel@tonic-gate #define	STATES_H
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <netinet/in.h>
310Sstevel@tonic-gate #include <netinet/dhcp.h>
320Sstevel@tonic-gate #include <libinetutil.h>
330Sstevel@tonic-gate 
343431Scarlsonj #include "common.h"
353431Scarlsonj #include "ipc_action.h"
363431Scarlsonj #include "async.h"
373431Scarlsonj #include "packet.h"
383431Scarlsonj #include "util.h"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * interfaces for state transition/action functions.  these functions
420Sstevel@tonic-gate  * can be found in suitably named .c files, such as inform.c, select.c,
430Sstevel@tonic-gate  * renew.c, etc.
440Sstevel@tonic-gate  */
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #ifdef	__cplusplus
470Sstevel@tonic-gate extern "C" {
480Sstevel@tonic-gate #endif
490Sstevel@tonic-gate 
503431Scarlsonj /*
513431Scarlsonj  * DHCP state machine representation: includes all of the information used for
523431Scarlsonj  * a state machine instance.  For IPv4, this represents a single logical
533431Scarlsonj  * interface and (usually) a leased address.  For IPv6, it represents a
543431Scarlsonj  * DUID+IAID combination.  Note that if multiple DUID+IAID instances are one
553431Scarlsonj  * day allowed per interface, this will need to become a list.
563431Scarlsonj  */
573431Scarlsonj struct dhcp_smach_s {
584106Scarlsonj 	dhcp_smach_t	*dsm_next;	/* Note: must be first */
594106Scarlsonj 	dhcp_smach_t	*dsm_prev;
603431Scarlsonj 
613431Scarlsonj 	/*
623431Scarlsonj 	 * The name of the state machine.  This is currently just a pointer to
633431Scarlsonj 	 * the controlling LIF's name, but could be otherwise.
643431Scarlsonj 	 */
654106Scarlsonj 	const char	*dsm_name;
664106Scarlsonj 	dhcp_lif_t	*dsm_lif;	/* Controlling LIF */
674106Scarlsonj 	uint_t		dsm_hold_count;	/* reference count */
683431Scarlsonj 
694106Scarlsonj 	dhcp_lease_t	*dsm_leases;	/* List of leases */
704106Scarlsonj 	uint_t		dsm_lif_wait;	/* LIFs waiting on DAD */
714106Scarlsonj 	uint_t		dsm_lif_down;	/* LIFs failed */
723431Scarlsonj 
733431Scarlsonj 	/*
743431Scarlsonj 	 * each state machine can have at most one pending asynchronous
753431Scarlsonj 	 * action, which is represented in a `struct async_action'.
763431Scarlsonj 	 * if that asynchronous action was a result of a user request,
773431Scarlsonj 	 * then the `struct ipc_action' is used to hold information
783431Scarlsonj 	 * about the user request.  these structures are opaque to
793431Scarlsonj 	 * users of the ifslist, and the functional interfaces
803431Scarlsonj 	 * provided in async.[ch] and ipc_action.[ch] should be used
813431Scarlsonj 	 * to maintain them.
823431Scarlsonj 	 */
833431Scarlsonj 
844106Scarlsonj 	ipc_action_t	dsm_ia;
854106Scarlsonj 	async_action_t	dsm_async;
863431Scarlsonj 
873431Scarlsonj 	uchar_t		*dsm_cid;	/* client id */
883431Scarlsonj 	uchar_t		dsm_cidlen;	/* client id len */
893431Scarlsonj 
903431Scarlsonj 	/*
913431Scarlsonj 	 * current state of the machine
923431Scarlsonj 	 */
933431Scarlsonj 
944106Scarlsonj 	DHCPSTATE	dsm_state;
956508Scarlsonj 	boolean_t	dsm_droprelease;  /* soon to call finished_smach */
963431Scarlsonj 
973431Scarlsonj 	uint16_t	dsm_dflags;	/* DHCP_IF_* (shared with IPC) */
983431Scarlsonj 
993431Scarlsonj 	uint16_t	*dsm_prl;	/* if non-NULL, param request list */
1003431Scarlsonj 	uint_t		dsm_prllen;	/* param request list len */
101*9633Sjames.d.carlson@sun.com 	uint16_t	*dsm_pil;	/* if non-NULL, param ignore list */
102*9633Sjames.d.carlson@sun.com 	uint_t		dsm_pillen;	/* param ignore list len */
1033431Scarlsonj 
1043431Scarlsonj 	uint_t		dsm_nrouters;	/* the number of default routers */
1053431Scarlsonj 	struct in_addr	*dsm_routers;	/* an array of default routers */
1063431Scarlsonj 
1073431Scarlsonj 	in6_addr_t	dsm_server;	/* our DHCP server */
1083431Scarlsonj 	uchar_t		*dsm_serverid;	/* server DUID for v6 */
1093431Scarlsonj 	uint_t		dsm_serveridlen; /* DUID length */
1103431Scarlsonj 
1113431Scarlsonj 	/*
1123431Scarlsonj 	 * We retain the very first ack obtained on the state machine to
1133431Scarlsonj 	 * provide access to options which were originally assigned by
1143431Scarlsonj 	 * the server but may not have been included in subsequent
1153431Scarlsonj 	 * acks, as there are servers which do this and customers have
1163431Scarlsonj 	 * had unsatisfactory results when using our agent with them.
1173431Scarlsonj 	 * ipc_event() in agent.c provides a fallback to the original
1183431Scarlsonj 	 * ack when the current ack doesn't have the information
1193431Scarlsonj 	 * requested.
1203431Scarlsonj 	 *
1213431Scarlsonj 	 * Note that neither of these is actually a list of packets.  There's
1223431Scarlsonj 	 * exactly one packet here, so use free_pkt_entry.
1233431Scarlsonj 	 */
1243431Scarlsonj 	PKT_LIST	*dsm_ack;
1253431Scarlsonj 	PKT_LIST	*dsm_orig_ack;
1263431Scarlsonj 
1273431Scarlsonj 	/*
1283431Scarlsonj 	 * other miscellaneous variables set or needed in the process
1293431Scarlsonj 	 * of acquiring a lease.
1303431Scarlsonj 	 */
1313431Scarlsonj 
1323431Scarlsonj 	int		dsm_offer_wait;	/* seconds between sending offers */
1333431Scarlsonj 	iu_timer_id_t	dsm_offer_timer; /* timer associated with offer wait */
1343431Scarlsonj 
1353431Scarlsonj 	/*
1363431Scarlsonj 	 * time we sent the DISCOVER relative to dsm_neg_hrtime, so that the
1373431Scarlsonj 	 * REQUEST can have the same pkt->secs.
1383431Scarlsonj 	 */
1393431Scarlsonj 
1404106Scarlsonj 	uint16_t	dsm_disc_secs;
1413431Scarlsonj 
1423431Scarlsonj 	/*
1433431Scarlsonj 	 * this is a chain of packets which have been received on this
1443431Scarlsonj 	 * state machine over some interval of time.  the packets may have
1453431Scarlsonj 	 * to meet some criteria in order to be put on this list.  in
1463431Scarlsonj 	 * general, packets are put on this list through recv_pkt()
1473431Scarlsonj 	 */
1483431Scarlsonj 
1494106Scarlsonj 	PKT_LIST	*dsm_recv_pkt_list;
1503431Scarlsonj 
1513431Scarlsonj 	/*
1523431Scarlsonj 	 * these three fields are initially zero, and get incremented
1533431Scarlsonj 	 * as the ifslist goes from INIT -> BOUND.  if and when the
1543431Scarlsonj 	 * ifslist moves to the RENEWING state, these fields are
1553431Scarlsonj 	 * reset, so they always either indicate the number of packets
1563431Scarlsonj 	 * sent, received, and declined while obtaining the current
1573431Scarlsonj 	 * lease (if BOUND), or the number of packets sent, received,
1583431Scarlsonj 	 * and declined while attempting to obtain a future lease
1593431Scarlsonj 	 * (if any other state).
1603431Scarlsonj 	 */
1613431Scarlsonj 
1624106Scarlsonj 	uint32_t	dsm_sent;
1634106Scarlsonj 	uint32_t	dsm_received;
1644106Scarlsonj 	uint32_t	dsm_bad_offers;
1653431Scarlsonj 
1663431Scarlsonj 	/*
1673431Scarlsonj 	 * dsm_send_pkt.pkt is dynamically allocated to be as big a
1683431Scarlsonj 	 * packet as we can send out on this state machine.  the remainder
1693431Scarlsonj 	 * of this information is needed to make it easy to handle
1703431Scarlsonj 	 * retransmissions.  note that other than dsm_bad_offers, all
1713431Scarlsonj 	 * of these fields are maintained internally in send_pkt(),
1723431Scarlsonj 	 * and consequently should never need to be modified by any
1733431Scarlsonj 	 * other functions.
1743431Scarlsonj 	 */
1753431Scarlsonj 
1764106Scarlsonj 	dhcp_pkt_t	dsm_send_pkt;
1773431Scarlsonj 	union {
1783431Scarlsonj 		struct sockaddr_in v4;
1793431Scarlsonj 		struct sockaddr_in6 v6;
1803431Scarlsonj 	} dsm_send_dest;
1813431Scarlsonj 
1823431Scarlsonj 	/*
1833431Scarlsonj 	 * For v4, dsm_send_tcenter is used to track the central timer value in
1843431Scarlsonj 	 * milliseconds (4000, 8000, 16000, 32000, 64000), and dsm_send_timeout
1853431Scarlsonj 	 * is that value plus the +/- 1000 millisecond fuzz.
1863431Scarlsonj 	 *
1873431Scarlsonj 	 * For v6, dsm_send_tcenter is the MRT (maximum retransmit timer)
1883431Scarlsonj 	 * value, and dsm_send_timeout must be set to the IRT (initial
1893431Scarlsonj 	 * retransmit timer) value by the sender.
1903431Scarlsonj 	 */
1914106Scarlsonj 	uint_t		dsm_send_timeout;
1924106Scarlsonj 	uint_t		dsm_send_tcenter;
1934106Scarlsonj 	stop_func_t	*dsm_send_stop_func;
1944106Scarlsonj 	uint32_t	dsm_packet_sent;
1954106Scarlsonj 	iu_timer_id_t	dsm_retrans_timer;
1963431Scarlsonj 
1973431Scarlsonj 	/*
1983431Scarlsonj 	 * The host name we've been asked to request is remembered
1993431Scarlsonj 	 * here between the DISCOVER and the REQUEST.  (v4 only)
2003431Scarlsonj 	 */
2013431Scarlsonj 	char		*dsm_reqhost;
2023431Scarlsonj 
2033431Scarlsonj 	/*
2043431Scarlsonj 	 * V4 and V6 use slightly different timers.  For v4, we must count
2053431Scarlsonj 	 * seconds from the point where we first try to configure the
2063431Scarlsonj 	 * interface.  For v6, only seconds while performing a transaction
2073431Scarlsonj 	 * matter.
2083431Scarlsonj 	 *
2093431Scarlsonj 	 * In v4, `dsm_neg_hrtime' represents the time since DHCP started
2103431Scarlsonj 	 * configuring the interface, and is used for computing the pkt->secs
2113431Scarlsonj 	 * field in v4.  In v6, it represents the time since the current
2123431Scarlsonj 	 * transaction (if any) was started, and is used for the ELAPSED_TIME
2133431Scarlsonj 	 * option.
2143431Scarlsonj 	 *
2153431Scarlsonj 	 * `dsm_newstart_monosec' represents the time the ACKed REQUEST was
2163431Scarlsonj 	 * sent, which represents the start time of a new batch of leases.
2173431Scarlsonj 	 * When the lease time actually begins (and thus becomes current),
2183431Scarlsonj 	 * `dsm_curstart_monosec' is set to `dsm_newstart_monosec'.
2193431Scarlsonj 	 */
2204106Scarlsonj 	hrtime_t	dsm_neg_hrtime;
2214106Scarlsonj 	monosec_t	dsm_newstart_monosec;
2224106Scarlsonj 	monosec_t	dsm_curstart_monosec;
2233431Scarlsonj 
2244106Scarlsonj 	int		dsm_script_fd;
2254106Scarlsonj 	pid_t		dsm_script_pid;
2264106Scarlsonj 	pid_t		dsm_script_helper_pid;
2274106Scarlsonj 	const char	*dsm_script_event;
2284106Scarlsonj 	iu_event_id_t	dsm_script_event_id;
2294106Scarlsonj 	void		*dsm_callback_arg;
2304106Scarlsonj 	script_callback_t *dsm_script_callback;
2314106Scarlsonj 
2324106Scarlsonj 	iu_timer_id_t	dsm_start_timer;
2333431Scarlsonj };
2343431Scarlsonj 
2353431Scarlsonj #define	dsm_isv6	dsm_lif->lif_pif->pif_isv6
2363431Scarlsonj #define	dsm_hwtype	dsm_lif->lif_pif->pif_hwtype
2373431Scarlsonj 
2383431Scarlsonj struct dhcp_lease_s {
2393431Scarlsonj 	dhcp_lease_t	*dl_next;	/* Note: must be first */
2403431Scarlsonj 	dhcp_lease_t	*dl_prev;
2413431Scarlsonj 
2423431Scarlsonj 	dhcp_smach_t	*dl_smach;	/* back pointer to state machine */
2433431Scarlsonj 	dhcp_lif_t	*dl_lifs;	/* LIFs configured by this lease */
2443431Scarlsonj 	uint_t		dl_nlifs;	/* Number of configured LIFs */
2453431Scarlsonj 	uint_t		dl_hold_count;	/* reference counter */
2463431Scarlsonj 	boolean_t	dl_removed;	/* Set if removed from list */
2473431Scarlsonj 	boolean_t	dl_stale;	/* not updated by Renew/bind */
2483431Scarlsonj 
2493431Scarlsonj 	/*
2503431Scarlsonj 	 * the following fields are set when a lease is acquired, and
2513431Scarlsonj 	 * may be updated over the lifetime of the lease.  they are
2523431Scarlsonj 	 * all reset by reset_smach().
2533431Scarlsonj 	 */
2543431Scarlsonj 
2553431Scarlsonj 	dhcp_timer_t	dl_t1;		/* relative renewal start time, hbo */
2563431Scarlsonj 	dhcp_timer_t	dl_t2;		/* relative rebinding start time, hbo */
2573431Scarlsonj };
2583431Scarlsonj 
2593431Scarlsonj /* The IU event callback functions */
2605381Smeem iu_eh_callback_t	dhcp_acknak_global;
2615381Smeem iu_eh_callback_t	dhcp_packet_lif;
2623431Scarlsonj 
2633431Scarlsonj /* Common state-machine related routines throughout dhcpagent */
2643431Scarlsonj boolean_t	dhcp_adopt(void);
2653431Scarlsonj void		dhcp_adopt_complete(dhcp_smach_t *);
2663431Scarlsonj boolean_t	dhcp_bound(dhcp_smach_t *, PKT_LIST *);
2673431Scarlsonj void		dhcp_bound_complete(dhcp_smach_t *);
2683431Scarlsonj int		dhcp_drop(dhcp_smach_t *, void *);
2693431Scarlsonj void		dhcp_deprecate(iu_tq_t *, void *);
2700Sstevel@tonic-gate void		dhcp_expire(iu_tq_t *, void *);
2713431Scarlsonj boolean_t	dhcp_extending(dhcp_smach_t *);
2723431Scarlsonj void		dhcp_inform(dhcp_smach_t *);
2733431Scarlsonj void		dhcp_init_reboot(dhcp_smach_t *);
2740Sstevel@tonic-gate void		dhcp_rebind(iu_tq_t *, void *);
2753431Scarlsonj int		dhcp_release(dhcp_smach_t *, void *);
2760Sstevel@tonic-gate void		dhcp_renew(iu_tq_t *, void *);
2770Sstevel@tonic-gate void		dhcp_requesting(iu_tq_t *, void *);
2783431Scarlsonj void		dhcp_restart(dhcp_smach_t *);
2793431Scarlsonj void		dhcp_selecting(dhcp_smach_t *);
2804106Scarlsonj boolean_t	set_start_timer(dhcp_smach_t *);
2813431Scarlsonj void		send_declines(dhcp_smach_t *);
2823431Scarlsonj void		send_v6_request(dhcp_smach_t *);
2833431Scarlsonj boolean_t	save_server_id(dhcp_smach_t *, PKT_LIST *);
2843431Scarlsonj void		server_unicast_option(dhcp_smach_t *, PKT_LIST *);
2853431Scarlsonj 
2863431Scarlsonj /* State machine support functions in states.c */
2873431Scarlsonj dhcp_smach_t	*insert_smach(dhcp_lif_t *, int *);
2883431Scarlsonj void		hold_smach(dhcp_smach_t *);
2893431Scarlsonj void		release_smach(dhcp_smach_t *);
2903522Scarlsonj void		remove_smach(dhcp_smach_t *);
2913431Scarlsonj dhcp_smach_t	*next_smach(dhcp_smach_t *, boolean_t);
2923431Scarlsonj dhcp_smach_t	*primary_smach(boolean_t);
293*9633Sjames.d.carlson@sun.com dhcp_smach_t	*info_primary_smach(boolean_t);
2943431Scarlsonj void		make_primary(dhcp_smach_t *);
2953431Scarlsonj dhcp_smach_t	*lookup_smach(const char *, boolean_t);
2963431Scarlsonj dhcp_smach_t	*lookup_smach_by_uindex(uint16_t, dhcp_smach_t *, boolean_t);
2973431Scarlsonj dhcp_smach_t	*lookup_smach_by_xid(uint32_t, dhcp_smach_t *, boolean_t);
2983431Scarlsonj dhcp_smach_t	*lookup_smach_by_event(iu_event_id_t);
2993431Scarlsonj void		finished_smach(dhcp_smach_t *, int);
3003431Scarlsonj boolean_t	set_smach_state(dhcp_smach_t *, DHCPSTATE);
3013431Scarlsonj int		get_smach_cid(dhcp_smach_t *);
3023431Scarlsonj boolean_t	verify_smach(dhcp_smach_t *);
3033431Scarlsonj uint_t		smach_count(void);
3043431Scarlsonj void		reset_smach(dhcp_smach_t *);
3053431Scarlsonj void		refresh_smachs(iu_eh_t *, int, void *);
3063431Scarlsonj void		refresh_smach(dhcp_smach_t *);
3073431Scarlsonj void		nuke_smach_list(void);
3083431Scarlsonj boolean_t	schedule_smach_timer(dhcp_smach_t *, int, uint32_t,
3093431Scarlsonj 		    iu_tq_callback_t *);
3103431Scarlsonj void		cancel_offer_timer(dhcp_smach_t *);
3119508SPeter.Memishian@Sun.COM void		cancel_smach_timers(dhcp_smach_t *);
3124106Scarlsonj void		discard_default_routes(dhcp_smach_t *);
3133431Scarlsonj void		remove_default_routes(dhcp_smach_t *);
3145381Smeem boolean_t	is_bound_state(DHCPSTATE);
3153431Scarlsonj 
3163431Scarlsonj /* Lease-related support functions in states.c */
3173431Scarlsonj dhcp_lease_t	*insert_lease(dhcp_smach_t *);
3183431Scarlsonj void		hold_lease(dhcp_lease_t *);
3193431Scarlsonj void		release_lease(dhcp_lease_t *);
3203431Scarlsonj void		remove_lease(dhcp_lease_t *);
3213431Scarlsonj void		deprecate_leases(dhcp_smach_t *);
3223431Scarlsonj void		cancel_lease_timers(dhcp_lease_t *);
3233431Scarlsonj boolean_t	schedule_lease_timer(dhcp_lease_t *, dhcp_timer_t *,
3243431Scarlsonj 		    iu_tq_callback_t *);
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate #ifdef	__cplusplus
3270Sstevel@tonic-gate }
3280Sstevel@tonic-gate #endif
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate #endif	/* STATES_H */
331