summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-inet/sbin/dhcpagent/interface.h
blob: 446adfb36f8d3334a94a51153af462a8a7bc46cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	INTERFACE_H
#define	INTERFACE_H

/*
 * Interface.[ch] encapsulate all of the agent's knowledge of network
 * interfaces from the DHCP agent's perspective.  See interface.c for
 * documentation on how to use the exported functions.  Note that there are not
 * functional interfaces for manipulating all of the fields in a PIF or LIF --
 * please read the comments in the structure definitions below for the rules on
 * accessing various fields.
 */

#ifdef	__cplusplus
extern "C" {
#endif

#include <netinet/in.h>
#include <net/if.h>			/* IFNAMSIZ */
#include <sys/types.h>
#include <netinet/dhcp.h>
#include <dhcpagent_ipc.h>
#include <libinetutil.h>

#include "common.h"
#include "util.h"

#define	V4_PART_OF_V6(v6)	v6._S6_un._S6_u32[3]

struct dhcp_pif_s {
	dhcp_pif_t	*pif_next;	/* Note: must be first */
	dhcp_pif_t	*pif_prev;
	dhcp_lif_t	*pif_lifs;	/* pointer to logical interface list */
	uint32_t	pif_index;	/* interface index */
	uint16_t	pif_max;	/* largest DHCP packet on this if */
	uchar_t		*pif_hwaddr;	/* our link-layer address */
	uchar_t		pif_hwlen;	/* our link-layer address len */
	uchar_t		pif_hwtype;	/* type of link-layer */
	boolean_t	pif_isv6;
	boolean_t	pif_running;	/* interface is running */
	uint_t		pif_hold_count;	/* reference count */
	char		pif_name[LIFNAMSIZ];
	char		pif_grifname[LIFNAMSIZ];
	uint32_t	pif_grindex;	/* interface index for pif_grifname */
	boolean_t	pif_under_ipmp;	/* is an ipmp underlying interface */
};

struct dhcp_lif_s {
	dhcp_lif_t	*lif_next;	/* Note: must be first */
	dhcp_lif_t	*lif_prev;
	dhcp_pif_t	*lif_pif;	/* backpointer to parent physical if */
	dhcp_smach_t	*lif_smachs;	/* pointer to list of state machines */
	dhcp_lease_t	*lif_lease;	/* backpointer to lease holding LIF */
	uint64_t	lif_flags;	/* Interface flags (IFF_*) */
	int		lif_sock_ip_fd;	/* Bound to addr.BOOTPC for src addr */
	iu_event_id_t	lif_packet_id;	/* event packet id */
	uint_t		lif_max;	/* maximum IP message size */
	uint_t		lif_hold_count;	/* reference count */
	boolean_t	lif_dad_wait;	/* waiting for DAD resolution */
	boolean_t	lif_removed;	/* removed from list */
	boolean_t	lif_plumbed;	/* interface plumbed by dhcpagent */
	boolean_t	lif_expired;	/* lease has evaporated */
	const char	*lif_declined;	/* reason to refuse this address */
	uint32_t	lif_iaid;	/* unique and stable identifier */
	iu_event_id_t	lif_iaid_id;	/* for delayed writes to /etc */

	/*
	 * While in any states except ADOPTING, INIT, INFORMATION and
	 * INFORM_SENT, the following three fields are equal to what we believe
	 * the current address, netmask, and broadcast address on the interface
	 * to be.  This is so we can detect if the user changes them and
	 * abandon the interface.
	 */

	in6_addr_t	lif_v6addr;	/* our IP address */
	in6_addr_t	lif_v6mask;	/* our netmask */
	in6_addr_t	lif_v6peer;	/* our broadcast or peer address */

	dhcp_timer_t	lif_preferred;	/* lease preferred timer (v6 only) */
	dhcp_timer_t	lif_expire;	/* lease expire timer */

	char		lif_name[LIFNAMSIZ];
};
#define	lif_addr	V4_PART_OF_V6(lif_v6addr)
#define	lif_netmask	V4_PART_OF_V6(lif_v6mask)
#define	lif_peer	V4_PART_OF_V6(lif_v6peer)
#define	lif_broadcast	V4_PART_OF_V6(lif_v6peer)

/* used by expired_lif_state to express state of DHCP interfaces */
typedef enum dhcp_expire_e {
	DHCP_EXP_NOLIFS,
	DHCP_EXP_NOEXP,
	DHCP_EXP_ALLEXP,
	DHCP_EXP_SOMEEXP
} dhcp_expire_t;

/*
 * A word on memory management and LIFs and PIFs:
 *
 * Since LIFs are often passed as context to callback functions, they cannot be
 * freed when the interface they represent is dropped or released (or when
 * those callbacks finally go off, they will be hosed).  To handle this
 * situation, the structures are reference counted.  Here are the rules for
 * managing these counts:
 *
 * A PIF is created through insert_pif().  Along with initializing the PIF,
 * this puts a hold on the PIF.  A LIF is created through insert_lif().  This
 * also initializes the LIF and places a hold on it.  The caller's hold on the
 * underlying PIF is transferred to the LIF.
 *
 * Whenever a lease is released or dropped (implicitly or explicitly),
 * remove_lif() is called, which sets the lif_removed flag and removes the
 * interface from the internal list of managed interfaces.  Lastly,
 * remove_lif() calls release_lif() to remove the hold acquired in
 * insert_lif().  If this decrements the hold count on the interface to zero,
 * then free() is called and the hold on the PIF is dropped.  If there are
 * holds other than the hold acquired in insert_lif(), the hold count will
 * still be > 0, and the interface will remain allocated (though dormant).
 *
 * Whenever a callback is scheduled against a LIF, another hold must be put on
 * the ifslist through hold_lif().
 *
 * Whenever a callback is called back against a LIF, release_lif() must be
 * called to decrement the hold count, which may end up freeing the LIF if the
 * hold count becomes zero.
 *
 * Since some callbacks may take a long time to get called back (such as
 * timeout callbacks for lease expiration, etc), it is sometimes more
 * appropriate to cancel the callbacks and call release_lif() if the
 * cancellation succeeds.  This is done in remove_lif() for the lease preferred
 * and expire callbacks.
 *
 * In general, a callback may also call verify_lif() when it gets called back
 * in addition to release_lif(), to make sure that the interface is still in
 * fact under the dhcpagent's control.  To make coding simpler, there is a
 * third function, verify_smach(), which performs both the release_lif() and
 * the verify_lif() on all LIFs controlled by a state machine.
 */

extern dhcp_pif_t *v4root;
extern dhcp_pif_t *v6root;

dhcp_pif_t	*insert_pif(const char *, boolean_t, int *);
void		hold_pif(dhcp_pif_t *);
void		release_pif(dhcp_pif_t *);
dhcp_pif_t	*lookup_pif_by_uindex(uint16_t, dhcp_pif_t *, boolean_t);
dhcp_pif_t	*lookup_pif_by_name(const char *, boolean_t);
void		pif_status(dhcp_pif_t *, boolean_t);

dhcp_lif_t	*insert_lif(dhcp_pif_t *, const char *, int *);
void		hold_lif(dhcp_lif_t *);
void		release_lif(dhcp_lif_t *);
void		remove_lif(dhcp_lif_t *);
dhcp_lif_t	*lookup_lif_by_name(const char *, const dhcp_pif_t *);
boolean_t	verify_lif(const dhcp_lif_t *);
dhcp_lif_t	*plumb_lif(dhcp_pif_t *, const in6_addr_t *);
void		unplumb_lif(dhcp_lif_t *);
dhcp_lif_t	*attach_lif(const char *, boolean_t, int *);
int		set_lif_dhcp(dhcp_lif_t *);
void		set_lif_deprecated(dhcp_lif_t *);
boolean_t	clear_lif_deprecated(dhcp_lif_t *);
boolean_t	open_ip_lif(dhcp_lif_t *, in_addr_t, boolean_t);
void		close_ip_lif(dhcp_lif_t *);
void		lif_mark_decline(dhcp_lif_t *, const char *);
boolean_t	schedule_lif_timer(dhcp_lif_t *, dhcp_timer_t *,
		    iu_tq_callback_t *);
void		cancel_lif_timers(dhcp_lif_t *);
dhcp_expire_t	expired_lif_state(dhcp_smach_t *);
dhcp_lif_t	*find_expired_lif(dhcp_smach_t *);

uint_t		get_max_mtu(boolean_t);
void		remove_v6_strays(void);

#ifdef	__cplusplus
}
#endif

#endif	/* INTERFACE_H */