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