17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 569bb4bb4Scarlsonj * Common Development and Distribution License (the "License"). 669bb4bb4Scarlsonj * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 223644994cSmeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #ifndef STATES_H 277c478bd9Sstevel@tonic-gate #define STATES_H 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/types.h> 307c478bd9Sstevel@tonic-gate #include <netinet/in.h> 317c478bd9Sstevel@tonic-gate #include <netinet/dhcp.h> 327c478bd9Sstevel@tonic-gate #include <libinetutil.h> 337c478bd9Sstevel@tonic-gate 34d04ccbb3Scarlsonj #include "common.h" 35d04ccbb3Scarlsonj #include "ipc_action.h" 36d04ccbb3Scarlsonj #include "async.h" 37d04ccbb3Scarlsonj #include "packet.h" 38d04ccbb3Scarlsonj #include "util.h" 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * interfaces for state transition/action functions. these functions 427c478bd9Sstevel@tonic-gate * can be found in suitably named .c files, such as inform.c, select.c, 437c478bd9Sstevel@tonic-gate * renew.c, etc. 447c478bd9Sstevel@tonic-gate */ 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #ifdef __cplusplus 477c478bd9Sstevel@tonic-gate extern "C" { 487c478bd9Sstevel@tonic-gate #endif 497c478bd9Sstevel@tonic-gate 50d04ccbb3Scarlsonj /* 51d04ccbb3Scarlsonj * DHCP state machine representation: includes all of the information used for 52d04ccbb3Scarlsonj * a state machine instance. For IPv4, this represents a single logical 53d04ccbb3Scarlsonj * interface and (usually) a leased address. For IPv6, it represents a 54d04ccbb3Scarlsonj * DUID+IAID combination. Note that if multiple DUID+IAID instances are one 55d04ccbb3Scarlsonj * day allowed per interface, this will need to become a list. 56d04ccbb3Scarlsonj */ 57d04ccbb3Scarlsonj struct dhcp_smach_s { 58d04ccbb3Scarlsonj dhcp_smach_t *dsm_next; /* Note: must be first */ 59d04ccbb3Scarlsonj dhcp_smach_t *dsm_prev; 60d04ccbb3Scarlsonj 61d04ccbb3Scarlsonj /* 62d04ccbb3Scarlsonj * The name of the state machine. This is currently just a pointer to 63d04ccbb3Scarlsonj * the controlling LIF's name, but could be otherwise. 64d04ccbb3Scarlsonj */ 65d04ccbb3Scarlsonj const char *dsm_name; 66d04ccbb3Scarlsonj dhcp_lif_t *dsm_lif; /* Controlling LIF */ 67d04ccbb3Scarlsonj uint_t dsm_hold_count; /* reference count */ 68d04ccbb3Scarlsonj 69d04ccbb3Scarlsonj dhcp_lease_t *dsm_leases; /* List of leases */ 70d04ccbb3Scarlsonj uint_t dsm_lif_wait; /* LIFs waiting on DAD */ 71d04ccbb3Scarlsonj uint_t dsm_lif_down; /* LIFs failed */ 72d04ccbb3Scarlsonj 73d04ccbb3Scarlsonj /* 74d04ccbb3Scarlsonj * each state machine can have at most one pending asynchronous 75d04ccbb3Scarlsonj * action, which is represented in a `struct async_action'. 76d04ccbb3Scarlsonj * if that asynchronous action was a result of a user request, 77d04ccbb3Scarlsonj * then the `struct ipc_action' is used to hold information 78d04ccbb3Scarlsonj * about the user request. these structures are opaque to 79d04ccbb3Scarlsonj * users of the ifslist, and the functional interfaces 80d04ccbb3Scarlsonj * provided in async.[ch] and ipc_action.[ch] should be used 81d04ccbb3Scarlsonj * to maintain them. 82d04ccbb3Scarlsonj */ 83d04ccbb3Scarlsonj 84d04ccbb3Scarlsonj ipc_action_t dsm_ia; 85d04ccbb3Scarlsonj async_action_t dsm_async; 86d04ccbb3Scarlsonj 87d04ccbb3Scarlsonj uchar_t *dsm_cid; /* client id */ 88d04ccbb3Scarlsonj uchar_t dsm_cidlen; /* client id len */ 89d04ccbb3Scarlsonj 90d04ccbb3Scarlsonj /* 91d04ccbb3Scarlsonj * current state of the machine 92d04ccbb3Scarlsonj */ 93d04ccbb3Scarlsonj 94d04ccbb3Scarlsonj DHCPSTATE dsm_state; 958ff86213Scarlsonj boolean_t dsm_droprelease; /* soon to call finished_smach */ 96d04ccbb3Scarlsonj 97d04ccbb3Scarlsonj uint16_t dsm_dflags; /* DHCP_IF_* (shared with IPC) */ 98d04ccbb3Scarlsonj 99d04ccbb3Scarlsonj uint16_t *dsm_prl; /* if non-NULL, param request list */ 100d04ccbb3Scarlsonj uint_t dsm_prllen; /* param request list len */ 101*a1196271SJames Carlson uint16_t *dsm_pil; /* if non-NULL, param ignore list */ 102*a1196271SJames Carlson uint_t dsm_pillen; /* param ignore list len */ 103d04ccbb3Scarlsonj 104d04ccbb3Scarlsonj uint_t dsm_nrouters; /* the number of default routers */ 105d04ccbb3Scarlsonj struct in_addr *dsm_routers; /* an array of default routers */ 106d04ccbb3Scarlsonj 107d04ccbb3Scarlsonj in6_addr_t dsm_server; /* our DHCP server */ 108d04ccbb3Scarlsonj uchar_t *dsm_serverid; /* server DUID for v6 */ 109d04ccbb3Scarlsonj uint_t dsm_serveridlen; /* DUID length */ 110d04ccbb3Scarlsonj 111d04ccbb3Scarlsonj /* 112d04ccbb3Scarlsonj * We retain the very first ack obtained on the state machine to 113d04ccbb3Scarlsonj * provide access to options which were originally assigned by 114d04ccbb3Scarlsonj * the server but may not have been included in subsequent 115d04ccbb3Scarlsonj * acks, as there are servers which do this and customers have 116d04ccbb3Scarlsonj * had unsatisfactory results when using our agent with them. 117d04ccbb3Scarlsonj * ipc_event() in agent.c provides a fallback to the original 118d04ccbb3Scarlsonj * ack when the current ack doesn't have the information 119d04ccbb3Scarlsonj * requested. 120d04ccbb3Scarlsonj * 121d04ccbb3Scarlsonj * Note that neither of these is actually a list of packets. There's 122d04ccbb3Scarlsonj * exactly one packet here, so use free_pkt_entry. 123d04ccbb3Scarlsonj */ 124d04ccbb3Scarlsonj PKT_LIST *dsm_ack; 125d04ccbb3Scarlsonj PKT_LIST *dsm_orig_ack; 126d04ccbb3Scarlsonj 127d04ccbb3Scarlsonj /* 128d04ccbb3Scarlsonj * other miscellaneous variables set or needed in the process 129d04ccbb3Scarlsonj * of acquiring a lease. 130d04ccbb3Scarlsonj */ 131d04ccbb3Scarlsonj 132d04ccbb3Scarlsonj int dsm_offer_wait; /* seconds between sending offers */ 133d04ccbb3Scarlsonj iu_timer_id_t dsm_offer_timer; /* timer associated with offer wait */ 134d04ccbb3Scarlsonj 135d04ccbb3Scarlsonj /* 136d04ccbb3Scarlsonj * time we sent the DISCOVER relative to dsm_neg_hrtime, so that the 137d04ccbb3Scarlsonj * REQUEST can have the same pkt->secs. 138d04ccbb3Scarlsonj */ 139d04ccbb3Scarlsonj 140d04ccbb3Scarlsonj uint16_t dsm_disc_secs; 141d04ccbb3Scarlsonj 142d04ccbb3Scarlsonj /* 143d04ccbb3Scarlsonj * this is a chain of packets which have been received on this 144d04ccbb3Scarlsonj * state machine over some interval of time. the packets may have 145d04ccbb3Scarlsonj * to meet some criteria in order to be put on this list. in 146d04ccbb3Scarlsonj * general, packets are put on this list through recv_pkt() 147d04ccbb3Scarlsonj */ 148d04ccbb3Scarlsonj 149d04ccbb3Scarlsonj PKT_LIST *dsm_recv_pkt_list; 150d04ccbb3Scarlsonj 151d04ccbb3Scarlsonj /* 152d04ccbb3Scarlsonj * these three fields are initially zero, and get incremented 153d04ccbb3Scarlsonj * as the ifslist goes from INIT -> BOUND. if and when the 154d04ccbb3Scarlsonj * ifslist moves to the RENEWING state, these fields are 155d04ccbb3Scarlsonj * reset, so they always either indicate the number of packets 156d04ccbb3Scarlsonj * sent, received, and declined while obtaining the current 157d04ccbb3Scarlsonj * lease (if BOUND), or the number of packets sent, received, 158d04ccbb3Scarlsonj * and declined while attempting to obtain a future lease 159d04ccbb3Scarlsonj * (if any other state). 160d04ccbb3Scarlsonj */ 161d04ccbb3Scarlsonj 162d04ccbb3Scarlsonj uint32_t dsm_sent; 163d04ccbb3Scarlsonj uint32_t dsm_received; 164d04ccbb3Scarlsonj uint32_t dsm_bad_offers; 165d04ccbb3Scarlsonj 166d04ccbb3Scarlsonj /* 167d04ccbb3Scarlsonj * dsm_send_pkt.pkt is dynamically allocated to be as big a 168d04ccbb3Scarlsonj * packet as we can send out on this state machine. the remainder 169d04ccbb3Scarlsonj * of this information is needed to make it easy to handle 170d04ccbb3Scarlsonj * retransmissions. note that other than dsm_bad_offers, all 171d04ccbb3Scarlsonj * of these fields are maintained internally in send_pkt(), 172d04ccbb3Scarlsonj * and consequently should never need to be modified by any 173d04ccbb3Scarlsonj * other functions. 174d04ccbb3Scarlsonj */ 175d04ccbb3Scarlsonj 176d04ccbb3Scarlsonj dhcp_pkt_t dsm_send_pkt; 177d04ccbb3Scarlsonj union { 178d04ccbb3Scarlsonj struct sockaddr_in v4; 179d04ccbb3Scarlsonj struct sockaddr_in6 v6; 180d04ccbb3Scarlsonj } dsm_send_dest; 181d04ccbb3Scarlsonj 182d04ccbb3Scarlsonj /* 183d04ccbb3Scarlsonj * For v4, dsm_send_tcenter is used to track the central timer value in 184d04ccbb3Scarlsonj * milliseconds (4000, 8000, 16000, 32000, 64000), and dsm_send_timeout 185d04ccbb3Scarlsonj * is that value plus the +/- 1000 millisecond fuzz. 186d04ccbb3Scarlsonj * 187d04ccbb3Scarlsonj * For v6, dsm_send_tcenter is the MRT (maximum retransmit timer) 188d04ccbb3Scarlsonj * value, and dsm_send_timeout must be set to the IRT (initial 189d04ccbb3Scarlsonj * retransmit timer) value by the sender. 190d04ccbb3Scarlsonj */ 191d04ccbb3Scarlsonj uint_t dsm_send_timeout; 192d04ccbb3Scarlsonj uint_t dsm_send_tcenter; 193d04ccbb3Scarlsonj stop_func_t *dsm_send_stop_func; 194d04ccbb3Scarlsonj uint32_t dsm_packet_sent; 195d04ccbb3Scarlsonj iu_timer_id_t dsm_retrans_timer; 196d04ccbb3Scarlsonj 197d04ccbb3Scarlsonj /* 198d04ccbb3Scarlsonj * The host name we've been asked to request is remembered 199d04ccbb3Scarlsonj * here between the DISCOVER and the REQUEST. (v4 only) 200d04ccbb3Scarlsonj */ 201d04ccbb3Scarlsonj char *dsm_reqhost; 202d04ccbb3Scarlsonj 203d04ccbb3Scarlsonj /* 204d04ccbb3Scarlsonj * V4 and V6 use slightly different timers. For v4, we must count 205d04ccbb3Scarlsonj * seconds from the point where we first try to configure the 206d04ccbb3Scarlsonj * interface. For v6, only seconds while performing a transaction 207d04ccbb3Scarlsonj * matter. 208d04ccbb3Scarlsonj * 209d04ccbb3Scarlsonj * In v4, `dsm_neg_hrtime' represents the time since DHCP started 210d04ccbb3Scarlsonj * configuring the interface, and is used for computing the pkt->secs 211d04ccbb3Scarlsonj * field in v4. In v6, it represents the time since the current 212d04ccbb3Scarlsonj * transaction (if any) was started, and is used for the ELAPSED_TIME 213d04ccbb3Scarlsonj * option. 214d04ccbb3Scarlsonj * 215d04ccbb3Scarlsonj * `dsm_newstart_monosec' represents the time the ACKed REQUEST was 216d04ccbb3Scarlsonj * sent, which represents the start time of a new batch of leases. 217d04ccbb3Scarlsonj * When the lease time actually begins (and thus becomes current), 218d04ccbb3Scarlsonj * `dsm_curstart_monosec' is set to `dsm_newstart_monosec'. 219d04ccbb3Scarlsonj */ 220d04ccbb3Scarlsonj hrtime_t dsm_neg_hrtime; 221d04ccbb3Scarlsonj monosec_t dsm_newstart_monosec; 222d04ccbb3Scarlsonj monosec_t dsm_curstart_monosec; 223d04ccbb3Scarlsonj 224d04ccbb3Scarlsonj int dsm_script_fd; 225d04ccbb3Scarlsonj pid_t dsm_script_pid; 226d04ccbb3Scarlsonj pid_t dsm_script_helper_pid; 227d04ccbb3Scarlsonj const char *dsm_script_event; 228d04ccbb3Scarlsonj iu_event_id_t dsm_script_event_id; 229d04ccbb3Scarlsonj void *dsm_callback_arg; 230d04ccbb3Scarlsonj script_callback_t *dsm_script_callback; 231cfb9c9abScarlsonj 232cfb9c9abScarlsonj iu_timer_id_t dsm_start_timer; 233d04ccbb3Scarlsonj }; 234d04ccbb3Scarlsonj 235d04ccbb3Scarlsonj #define dsm_isv6 dsm_lif->lif_pif->pif_isv6 236d04ccbb3Scarlsonj #define dsm_hwtype dsm_lif->lif_pif->pif_hwtype 237d04ccbb3Scarlsonj 238d04ccbb3Scarlsonj struct dhcp_lease_s { 239d04ccbb3Scarlsonj dhcp_lease_t *dl_next; /* Note: must be first */ 240d04ccbb3Scarlsonj dhcp_lease_t *dl_prev; 241d04ccbb3Scarlsonj 242d04ccbb3Scarlsonj dhcp_smach_t *dl_smach; /* back pointer to state machine */ 243d04ccbb3Scarlsonj dhcp_lif_t *dl_lifs; /* LIFs configured by this lease */ 244d04ccbb3Scarlsonj uint_t dl_nlifs; /* Number of configured LIFs */ 245d04ccbb3Scarlsonj uint_t dl_hold_count; /* reference counter */ 246d04ccbb3Scarlsonj boolean_t dl_removed; /* Set if removed from list */ 247d04ccbb3Scarlsonj boolean_t dl_stale; /* not updated by Renew/bind */ 248d04ccbb3Scarlsonj 249d04ccbb3Scarlsonj /* 250d04ccbb3Scarlsonj * the following fields are set when a lease is acquired, and 251d04ccbb3Scarlsonj * may be updated over the lifetime of the lease. they are 252d04ccbb3Scarlsonj * all reset by reset_smach(). 253d04ccbb3Scarlsonj */ 254d04ccbb3Scarlsonj 255d04ccbb3Scarlsonj dhcp_timer_t dl_t1; /* relative renewal start time, hbo */ 256d04ccbb3Scarlsonj dhcp_timer_t dl_t2; /* relative rebinding start time, hbo */ 257d04ccbb3Scarlsonj }; 258d04ccbb3Scarlsonj 259d04ccbb3Scarlsonj /* The IU event callback functions */ 260e704a8f2Smeem iu_eh_callback_t dhcp_acknak_global; 261e704a8f2Smeem iu_eh_callback_t dhcp_packet_lif; 262d04ccbb3Scarlsonj 263d04ccbb3Scarlsonj /* Common state-machine related routines throughout dhcpagent */ 264d04ccbb3Scarlsonj boolean_t dhcp_adopt(void); 265d04ccbb3Scarlsonj void dhcp_adopt_complete(dhcp_smach_t *); 266d04ccbb3Scarlsonj boolean_t dhcp_bound(dhcp_smach_t *, PKT_LIST *); 267d04ccbb3Scarlsonj void dhcp_bound_complete(dhcp_smach_t *); 268d04ccbb3Scarlsonj int dhcp_drop(dhcp_smach_t *, void *); 269d04ccbb3Scarlsonj void dhcp_deprecate(iu_tq_t *, void *); 2707c478bd9Sstevel@tonic-gate void dhcp_expire(iu_tq_t *, void *); 271d04ccbb3Scarlsonj boolean_t dhcp_extending(dhcp_smach_t *); 272d04ccbb3Scarlsonj void dhcp_inform(dhcp_smach_t *); 273d04ccbb3Scarlsonj void dhcp_init_reboot(dhcp_smach_t *); 2747c478bd9Sstevel@tonic-gate void dhcp_rebind(iu_tq_t *, void *); 275d04ccbb3Scarlsonj int dhcp_release(dhcp_smach_t *, void *); 2767c478bd9Sstevel@tonic-gate void dhcp_renew(iu_tq_t *, void *); 2777c478bd9Sstevel@tonic-gate void dhcp_requesting(iu_tq_t *, void *); 278d04ccbb3Scarlsonj void dhcp_restart(dhcp_smach_t *); 279d04ccbb3Scarlsonj void dhcp_selecting(dhcp_smach_t *); 280cfb9c9abScarlsonj boolean_t set_start_timer(dhcp_smach_t *); 281d04ccbb3Scarlsonj void send_declines(dhcp_smach_t *); 282d04ccbb3Scarlsonj void send_v6_request(dhcp_smach_t *); 283d04ccbb3Scarlsonj boolean_t save_server_id(dhcp_smach_t *, PKT_LIST *); 284d04ccbb3Scarlsonj void server_unicast_option(dhcp_smach_t *, PKT_LIST *); 285d04ccbb3Scarlsonj 286d04ccbb3Scarlsonj /* State machine support functions in states.c */ 287d04ccbb3Scarlsonj dhcp_smach_t *insert_smach(dhcp_lif_t *, int *); 288d04ccbb3Scarlsonj void hold_smach(dhcp_smach_t *); 289d04ccbb3Scarlsonj void release_smach(dhcp_smach_t *); 2903589885cScarlsonj void remove_smach(dhcp_smach_t *); 291d04ccbb3Scarlsonj dhcp_smach_t *next_smach(dhcp_smach_t *, boolean_t); 292d04ccbb3Scarlsonj dhcp_smach_t *primary_smach(boolean_t); 293*a1196271SJames Carlson dhcp_smach_t *info_primary_smach(boolean_t); 294d04ccbb3Scarlsonj void make_primary(dhcp_smach_t *); 295d04ccbb3Scarlsonj dhcp_smach_t *lookup_smach(const char *, boolean_t); 296d04ccbb3Scarlsonj dhcp_smach_t *lookup_smach_by_uindex(uint16_t, dhcp_smach_t *, boolean_t); 297d04ccbb3Scarlsonj dhcp_smach_t *lookup_smach_by_xid(uint32_t, dhcp_smach_t *, boolean_t); 298d04ccbb3Scarlsonj dhcp_smach_t *lookup_smach_by_event(iu_event_id_t); 299d04ccbb3Scarlsonj void finished_smach(dhcp_smach_t *, int); 300d04ccbb3Scarlsonj boolean_t set_smach_state(dhcp_smach_t *, DHCPSTATE); 301d04ccbb3Scarlsonj int get_smach_cid(dhcp_smach_t *); 302d04ccbb3Scarlsonj boolean_t verify_smach(dhcp_smach_t *); 303d04ccbb3Scarlsonj uint_t smach_count(void); 304d04ccbb3Scarlsonj void reset_smach(dhcp_smach_t *); 305d04ccbb3Scarlsonj void refresh_smachs(iu_eh_t *, int, void *); 306d04ccbb3Scarlsonj void refresh_smach(dhcp_smach_t *); 307d04ccbb3Scarlsonj void nuke_smach_list(void); 308d04ccbb3Scarlsonj boolean_t schedule_smach_timer(dhcp_smach_t *, int, uint32_t, 309d04ccbb3Scarlsonj iu_tq_callback_t *); 310d04ccbb3Scarlsonj void cancel_offer_timer(dhcp_smach_t *); 3113644994cSmeem void cancel_smach_timers(dhcp_smach_t *); 312cfb9c9abScarlsonj void discard_default_routes(dhcp_smach_t *); 313d04ccbb3Scarlsonj void remove_default_routes(dhcp_smach_t *); 314e704a8f2Smeem boolean_t is_bound_state(DHCPSTATE); 315d04ccbb3Scarlsonj 316d04ccbb3Scarlsonj /* Lease-related support functions in states.c */ 317d04ccbb3Scarlsonj dhcp_lease_t *insert_lease(dhcp_smach_t *); 318d04ccbb3Scarlsonj void hold_lease(dhcp_lease_t *); 319d04ccbb3Scarlsonj void release_lease(dhcp_lease_t *); 320d04ccbb3Scarlsonj void remove_lease(dhcp_lease_t *); 321d04ccbb3Scarlsonj void deprecate_leases(dhcp_smach_t *); 322d04ccbb3Scarlsonj void cancel_lease_timers(dhcp_lease_t *); 323d04ccbb3Scarlsonj boolean_t schedule_lease_timer(dhcp_lease_t *, dhcp_timer_t *, 324d04ccbb3Scarlsonj iu_tq_callback_t *); 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate #ifdef __cplusplus 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate #endif 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate #endif /* STATES_H */ 331