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