/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef STATES_H #define STATES_H #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include "common.h" #include "ipc_action.h" #include "async.h" #include "packet.h" #include "util.h" /* * interfaces for state transition/action functions. these functions * can be found in suitably named .c files, such as inform.c, select.c, * renew.c, etc. */ #ifdef __cplusplus extern "C" { #endif /* * DHCP state machine representation: includes all of the information used for * a state machine instance. For IPv4, this represents a single logical * interface and (usually) a leased address. For IPv6, it represents a * DUID+IAID combination. Note that if multiple DUID+IAID instances are one * day allowed per interface, this will need to become a list. */ struct dhcp_smach_s { dhcp_smach_t *dsm_next; /* Note: must be first */ dhcp_smach_t *dsm_prev; /* * The name of the state machine. This is currently just a pointer to * the controlling LIF's name, but could be otherwise. */ const char *dsm_name; dhcp_lif_t *dsm_lif; /* Controlling LIF */ uint_t dsm_hold_count; /* reference count */ dhcp_lease_t *dsm_leases; /* List of leases */ uint_t dsm_lif_wait; /* LIFs waiting on DAD */ uint_t dsm_lif_down; /* LIFs failed */ boolean_t dsm_using_dlpi; /* * each state machine can have at most one pending asynchronous * action, which is represented in a `struct async_action'. * if that asynchronous action was a result of a user request, * then the `struct ipc_action' is used to hold information * about the user request. these structures are opaque to * users of the ifslist, and the functional interfaces * provided in async.[ch] and ipc_action.[ch] should be used * to maintain them. */ ipc_action_t dsm_ia; async_action_t dsm_async; uchar_t *dsm_cid; /* client id */ uchar_t dsm_cidlen; /* client id len */ /* * current state of the machine */ DHCPSTATE dsm_state; uint16_t dsm_dflags; /* DHCP_IF_* (shared with IPC) */ uint16_t *dsm_prl; /* if non-NULL, param request list */ uint_t dsm_prllen; /* param request list len */ uint_t dsm_nrouters; /* the number of default routers */ struct in_addr *dsm_routers; /* an array of default routers */ in6_addr_t dsm_server; /* our DHCP server */ uchar_t *dsm_serverid; /* server DUID for v6 */ uint_t dsm_serveridlen; /* DUID length */ /* * We retain the very first ack obtained on the state machine to * provide access to options which were originally assigned by * the server but may not have been included in subsequent * acks, as there are servers which do this and customers have * had unsatisfactory results when using our agent with them. * ipc_event() in agent.c provides a fallback to the original * ack when the current ack doesn't have the information * requested. * * Note that neither of these is actually a list of packets. There's * exactly one packet here, so use free_pkt_entry. */ PKT_LIST *dsm_ack; PKT_LIST *dsm_orig_ack; /* * other miscellaneous variables set or needed in the process * of acquiring a lease. */ int dsm_offer_wait; /* seconds between sending offers */ iu_timer_id_t dsm_offer_timer; /* timer associated with offer wait */ /* * time we sent the DISCOVER relative to dsm_neg_hrtime, so that the * REQUEST can have the same pkt->secs. */ uint16_t dsm_disc_secs; /* * this is a chain of packets which have been received on this * state machine over some interval of time. the packets may have * to meet some criteria in order to be put on this list. in * general, packets are put on this list through recv_pkt() */ PKT_LIST *dsm_recv_pkt_list; /* * these three fields are initially zero, and get incremented * as the ifslist goes from INIT -> BOUND. if and when the * ifslist moves to the RENEWING state, these fields are * reset, so they always either indicate the number of packets * sent, received, and declined while obtaining the current * lease (if BOUND), or the number of packets sent, received, * and declined while attempting to obtain a future lease * (if any other state). */ uint32_t dsm_sent; uint32_t dsm_received; uint32_t dsm_bad_offers; /* * dsm_send_pkt.pkt is dynamically allocated to be as big a * packet as we can send out on this state machine. the remainder * of this information is needed to make it easy to handle * retransmissions. note that other than dsm_bad_offers, all * of these fields are maintained internally in send_pkt(), * and consequently should never need to be modified by any * other functions. */ dhcp_pkt_t dsm_send_pkt; union { struct sockaddr_in v4; struct sockaddr_in6 v6; } dsm_send_dest; /* * For v4, dsm_send_tcenter is used to track the central timer value in * milliseconds (4000, 8000, 16000, 32000, 64000), and dsm_send_timeout * is that value plus the +/- 1000 millisecond fuzz. * * For v6, dsm_send_tcenter is the MRT (maximum retransmit timer) * value, and dsm_send_timeout must be set to the IRT (initial * retransmit timer) value by the sender. */ uint_t dsm_send_timeout; uint_t dsm_send_tcenter; stop_func_t *dsm_send_stop_func; uint32_t dsm_packet_sent; iu_timer_id_t dsm_retrans_timer; /* * The host name we've been asked to request is remembered * here between the DISCOVER and the REQUEST. (v4 only) */ char *dsm_reqhost; /* * V4 and V6 use slightly different timers. For v4, we must count * seconds from the point where we first try to configure the * interface. For v6, only seconds while performing a transaction * matter. * * In v4, `dsm_neg_hrtime' represents the time since DHCP started * configuring the interface, and is used for computing the pkt->secs * field in v4. In v6, it represents the time since the current * transaction (if any) was started, and is used for the ELAPSED_TIME * option. * * `dsm_newstart_monosec' represents the time the ACKed REQUEST was * sent, which represents the start time of a new batch of leases. * When the lease time actually begins (and thus becomes current), * `dsm_curstart_monosec' is set to `dsm_newstart_monosec'. */ hrtime_t dsm_neg_hrtime; monosec_t dsm_newstart_monosec; monosec_t dsm_curstart_monosec; int dsm_script_fd; pid_t dsm_script_pid; pid_t dsm_script_helper_pid; const char *dsm_script_event; iu_event_id_t dsm_script_event_id; void *dsm_callback_arg; script_callback_t *dsm_script_callback; }; #define dsm_isv6 dsm_lif->lif_pif->pif_isv6 #define dsm_hwtype dsm_lif->lif_pif->pif_hwtype struct dhcp_lease_s { dhcp_lease_t *dl_next; /* Note: must be first */ dhcp_lease_t *dl_prev; dhcp_smach_t *dl_smach; /* back pointer to state machine */ dhcp_lif_t *dl_lifs; /* LIFs configured by this lease */ uint_t dl_nlifs; /* Number of configured LIFs */ uint_t dl_hold_count; /* reference counter */ boolean_t dl_removed; /* Set if removed from list */ boolean_t dl_stale; /* not updated by Renew/bind */ /* * the following fields are set when a lease is acquired, and * may be updated over the lifetime of the lease. they are * all reset by reset_smach(). */ dhcp_timer_t dl_t1; /* relative renewal start time, hbo */ dhcp_timer_t dl_t2; /* relative rebinding start time, hbo */ }; /* The IU event callback functions */ iu_eh_callback_t dhcp_acknak_common; iu_eh_callback_t dhcp_acknak_lif; iu_eh_callback_t dhcp_collect_dlpi; /* Common state-machine related routines throughout dhcpagent */ boolean_t dhcp_adopt(void); void dhcp_adopt_complete(dhcp_smach_t *); boolean_t dhcp_bound(dhcp_smach_t *, PKT_LIST *); void dhcp_bound_complete(dhcp_smach_t *); int dhcp_drop(dhcp_smach_t *, void *); void dhcp_deprecate(iu_tq_t *, void *); void dhcp_expire(iu_tq_t *, void *); boolean_t dhcp_extending(dhcp_smach_t *); void dhcp_inform(dhcp_smach_t *); void dhcp_init_reboot(dhcp_smach_t *); void dhcp_rebind(iu_tq_t *, void *); int dhcp_release(dhcp_smach_t *, void *); void dhcp_renew(iu_tq_t *, void *); void dhcp_requesting(iu_tq_t *, void *); void dhcp_restart(dhcp_smach_t *); void dhcp_selecting(dhcp_smach_t *); void dhcp_start(iu_tq_t *, void *); void send_declines(dhcp_smach_t *); void send_v6_request(dhcp_smach_t *); boolean_t save_server_id(dhcp_smach_t *, PKT_LIST *); void server_unicast_option(dhcp_smach_t *, PKT_LIST *); /* State machine support functions in states.c */ dhcp_smach_t *insert_smach(dhcp_lif_t *, int *); void hold_smach(dhcp_smach_t *); void release_smach(dhcp_smach_t *); dhcp_smach_t *next_smach(dhcp_smach_t *, boolean_t); dhcp_smach_t *primary_smach(boolean_t); void make_primary(dhcp_smach_t *); dhcp_smach_t *lookup_smach(const char *, boolean_t); dhcp_smach_t *lookup_smach_by_uindex(uint16_t, dhcp_smach_t *, boolean_t); dhcp_smach_t *lookup_smach_by_xid(uint32_t, dhcp_smach_t *, boolean_t); dhcp_smach_t *lookup_smach_by_event(iu_event_id_t); void finished_smach(dhcp_smach_t *, int); boolean_t set_smach_state(dhcp_smach_t *, DHCPSTATE); int get_smach_cid(dhcp_smach_t *); boolean_t verify_smach(dhcp_smach_t *); uint_t smach_count(void); void reset_smach(dhcp_smach_t *); void refresh_smachs(iu_eh_t *, int, void *); void refresh_smach(dhcp_smach_t *); void nuke_smach_list(void); boolean_t schedule_smach_timer(dhcp_smach_t *, int, uint32_t, iu_tq_callback_t *); void cancel_offer_timer(dhcp_smach_t *); void remove_default_routes(dhcp_smach_t *); /* Lease-related support functions in states.c */ dhcp_lease_t *insert_lease(dhcp_smach_t *); void hold_lease(dhcp_lease_t *); void release_lease(dhcp_lease_t *); void remove_lease(dhcp_lease_t *); void deprecate_leases(dhcp_smach_t *); void cancel_lease_timers(dhcp_lease_t *); boolean_t schedule_lease_timer(dhcp_lease_t *, dhcp_timer_t *, iu_tq_callback_t *); #ifdef __cplusplus } #endif #endif /* STATES_H */