1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef INTERFACE_H 27 #define INTERFACE_H 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 /* 32 * Interface.[ch] encapsulate all of the agent's knowledge of network 33 * interfaces from the DHCP agent's perspective. See interface.c for 34 * documentation on how to use the exported functions. Note that there are not 35 * functional interfaces for manipulating all of the fields in a PIF or LIF -- 36 * please read the comments in the structure definitions below for the rules on 37 * accessing various fields. 38 */ 39 40 #ifdef __cplusplus 41 extern "C" { 42 #endif 43 44 #include <netinet/in.h> 45 #include <net/if.h> /* IFNAMSIZ */ 46 #include <sys/types.h> 47 #include <netinet/dhcp.h> 48 #include <dhcpagent_ipc.h> 49 #include <libinetutil.h> 50 51 #include "common.h" 52 #include "util.h" 53 54 #define V4_PART_OF_V6(v6) v6._S6_un._S6_u32[3] 55 56 struct dhcp_pif_s { 57 dhcp_pif_t *pif_next; /* Note: must be first */ 58 dhcp_pif_t *pif_prev; 59 dhcp_lif_t *pif_lifs; /* pointer to logical interface list */ 60 uint32_t pif_index; /* interface index */ 61 uint16_t pif_max; /* largest DHCP packet on this if */ 62 uchar_t *pif_hwaddr; /* our link-layer address */ 63 uchar_t pif_hwlen; /* our link-layer address len */ 64 uchar_t pif_hwtype; /* type of link-layer */ 65 boolean_t pif_isv6; 66 boolean_t pif_running; /* interface is running */ 67 int pif_dlpi_fd; 68 int pif_dlpi_count; 69 iu_event_id_t pif_dlpi_id; /* event id for ack/nak/offer */ 70 uint_t pif_hold_count; /* reference count */ 71 72 /* 73 * The destination address is the broadcast address of the interface, 74 * in DLPI terms (which means it includes both a link-layer broadcast 75 * address and a SAP, and the order depends on the requirements of the 76 * underlying driver). We store it as a token like this because it's 77 * generally how we need to use it. 78 */ 79 80 uchar_t *pif_daddr; /* our destination address */ 81 uchar_t pif_dlen; /* our destination address len */ 82 83 uint_t pif_saplen; /* the SAP len */ 84 boolean_t pif_sap_before; /* does SAP come before address? */ 85 char pif_name[LIFNAMSIZ]; 86 }; 87 88 struct dhcp_lif_s { 89 dhcp_lif_t *lif_next; /* Note: must be first */ 90 dhcp_lif_t *lif_prev; 91 dhcp_pif_t *lif_pif; /* backpointer to parent physical if */ 92 dhcp_smach_t *lif_smachs; /* pointer to list of state machines */ 93 dhcp_lease_t *lif_lease; /* backpointer to lease holding LIF */ 94 uint64_t lif_flags; /* Interface flags (IFF_*) */ 95 int lif_sock_ip_fd; /* Bound to addr.BOOTPC for src addr */ 96 iu_event_id_t lif_acknak_id; /* event acknak id */ 97 uint_t lif_max; /* maximum IP message size */ 98 uint_t lif_hold_count; /* reference count */ 99 boolean_t lif_dad_wait; /* waiting for DAD resolution */ 100 boolean_t lif_removed; /* removed from list */ 101 boolean_t lif_plumbed; /* interface plumbed by dhcpagent */ 102 boolean_t lif_expired; /* lease has evaporated */ 103 const char *lif_declined; /* reason to refuse this address */ 104 uint32_t lif_iaid; /* unique and stable identifier */ 105 iu_event_id_t lif_iaid_id; /* for delayed writes to /etc */ 106 107 /* 108 * While in any states except ADOPTING, INIT, INFORMATION and 109 * INFORM_SENT, the following three fields are equal to what we believe 110 * the current address, netmask, and broadcast address on the interface 111 * to be. This is so we can detect if the user changes them and 112 * abandon the interface. 113 */ 114 115 in6_addr_t lif_v6addr; /* our IP address */ 116 in6_addr_t lif_v6mask; /* our netmask */ 117 in6_addr_t lif_v6peer; /* our broadcast or peer address */ 118 119 dhcp_timer_t lif_preferred; /* lease preferred timer (v6 only) */ 120 dhcp_timer_t lif_expire; /* lease expire timer */ 121 122 char lif_name[LIFNAMSIZ]; 123 }; 124 #define lif_addr V4_PART_OF_V6(lif_v6addr) 125 #define lif_netmask V4_PART_OF_V6(lif_v6mask) 126 #define lif_peer V4_PART_OF_V6(lif_v6peer) 127 #define lif_broadcast V4_PART_OF_V6(lif_v6peer) 128 129 /* used by expired_lif_state to express state of DHCP interfaces */ 130 typedef enum dhcp_expire_e { 131 DHCP_EXP_NOLIFS, 132 DHCP_EXP_NOEXP, 133 DHCP_EXP_ALLEXP, 134 DHCP_EXP_SOMEEXP 135 } dhcp_expire_t; 136 137 /* 138 * A word on memory management and LIFs and PIFs: 139 * 140 * Since LIFs are often passed as context to callback functions, they cannot be 141 * freed when the interface they represent is dropped or released (or when 142 * those callbacks finally go off, they will be hosed). To handle this 143 * situation, the structures are reference counted. Here are the rules for 144 * managing these counts: 145 * 146 * A PIF is created through insert_pif(). Along with initializing the PIF, 147 * this puts a hold on the PIF. A LIF is created through insert_lif(). This 148 * also initializes the LIF and places a hold on it. The caller's hold on the 149 * underlying PIF is transferred to the LIF. 150 * 151 * Whenever a lease is released or dropped (implicitly or explicitly), 152 * remove_lif() is called, which sets the lif_removed flag and removes the 153 * interface from the internal list of managed interfaces. Lastly, 154 * remove_lif() calls release_lif() to remove the hold acquired in 155 * insert_lif(). If this decrements the hold count on the interface to zero, 156 * then free() is called and the hold on the PIF is dropped. If there are 157 * holds other than the hold acquired in insert_lif(), the hold count will 158 * still be > 0, and the interface will remain allocated (though dormant). 159 * 160 * Whenever a callback is scheduled against a LIF, another hold must be put on 161 * the ifslist through hold_lif(). 162 * 163 * Whenever a callback is called back against a LIF, release_lif() must be 164 * called to decrement the hold count, which may end up freeing the LIF if the 165 * hold count becomes zero. 166 * 167 * Since some callbacks may take a long time to get called back (such as 168 * timeout callbacks for lease expiration, etc), it is sometimes more 169 * appropriate to cancel the callbacks and call release_lif() if the 170 * cancellation succeeds. This is done in remove_lif() for the lease preferred 171 * and expire callbacks. 172 * 173 * In general, a callback may also call verify_lif() when it gets called back 174 * in addition to release_lif(), to make sure that the interface is still in 175 * fact under the dhcpagent's control. To make coding simpler, there is a 176 * third function, verify_smach(), which performs both the release_lif() and 177 * the verify_lif() on all LIFs controlled by a state machine. 178 */ 179 180 extern dhcp_pif_t *v4root; 181 extern dhcp_pif_t *v6root; 182 183 dhcp_pif_t *insert_pif(const char *, boolean_t, int *); 184 void hold_pif(dhcp_pif_t *); 185 void release_pif(dhcp_pif_t *); 186 dhcp_pif_t *lookup_pif_by_index(uint_t, boolean_t); 187 dhcp_pif_t *lookup_pif_by_uindex(uint16_t, dhcp_pif_t *, boolean_t); 188 dhcp_pif_t *lookup_pif_by_name(const char *, boolean_t); 189 boolean_t open_dlpi_pif(dhcp_pif_t *); 190 void close_dlpi_pif(dhcp_pif_t *); 191 void pif_status(dhcp_pif_t *, boolean_t); 192 193 dhcp_lif_t *insert_lif(dhcp_pif_t *, const char *, int *); 194 void hold_lif(dhcp_lif_t *); 195 void release_lif(dhcp_lif_t *); 196 void remove_lif(dhcp_lif_t *); 197 dhcp_lif_t *lookup_lif_by_name(const char *, const dhcp_pif_t *); 198 boolean_t verify_lif(const dhcp_lif_t *); 199 dhcp_lif_t *plumb_lif(dhcp_pif_t *, const in6_addr_t *); 200 void unplumb_lif(dhcp_lif_t *); 201 dhcp_lif_t *attach_lif(const char *, boolean_t, int *); 202 int set_lif_dhcp(dhcp_lif_t *, boolean_t); 203 void set_lif_deprecated(dhcp_lif_t *); 204 boolean_t clear_lif_deprecated(dhcp_lif_t *); 205 boolean_t open_ip_lif(dhcp_lif_t *); 206 void close_ip_lif(dhcp_lif_t *); 207 void lif_mark_decline(dhcp_lif_t *, const char *); 208 boolean_t schedule_lif_timer(dhcp_lif_t *, dhcp_timer_t *, 209 iu_tq_callback_t *); 210 void cancel_lif_timers(dhcp_lif_t *); 211 dhcp_expire_t expired_lif_state(dhcp_smach_t *); 212 dhcp_lif_t *find_expired_lif(dhcp_smach_t *); 213 214 uint_t get_max_mtu(boolean_t); 215 void remove_v6_strays(void); 216 217 #ifdef __cplusplus 218 } 219 #endif 220 221 #endif /* INTERFACE_H */ 222