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