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