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 */
|