2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#ifndef _DHCPAGENT_IPC_H
2N/A#define _DHCPAGENT_IPC_H
2N/A
2N/A#include <sys/socket.h>
2N/A#include <net/if.h> /* LIFNAMSIZ */
2N/A#include <stddef.h>
2N/A#include <limits.h>
2N/A#include <sys/types.h>
2N/A#include <sys/time.h>
2N/A#include <netinet/dhcp.h>
2N/A#include <dhcp_impl.h>
2N/A
2N/A/*
2N/A * dhcpagent_ipc.[ch] comprise the interface used to perform
2N/A * interprocess communication with the agent. see dhcpagent_ipc.c for
2N/A * documentation on how to use the exported functions.
2N/A */
2N/A
2N/A#ifdef __cplusplus
2N/Aextern "C" {
2N/A#endif
2N/A
2N/A/*
2N/A * Solaris 10 Branded Zones also use this, so it cannot be changed to
2N/A * /usr/sbin/dhcpagent
2N/A */
2N/A#define DHCP_AGENT_PATH "/sbin/dhcpagent"
2N/A#define DHCP_IPC_LISTEN_BACKLOG 30
2N/A#define IPPORT_DHCPAGENT 4999
2N/A#define DHCP_IPC_MAX_WAIT 15 /* max seconds to wait to start agent */
2N/A
2N/A/*
2N/A * return values which should be used by programs which talk to the
2N/A * agent (for uniformity).
2N/A */
2N/A
2N/A#define DHCP_EXIT_SUCCESS 0
2N/A#define DHCP_EXIT_FAILURE 2
2N/A#define DHCP_EXIT_BADARGS 3
2N/A#define DHCP_EXIT_TIMEOUT 4
2N/A#define DHCP_EXIT_SYSTEM 6
2N/A
2N/A/*
2N/A * opaque types for requests and replies. users of this api do not
2N/A * need to understand their contents.
2N/A */
2N/A
2N/Atypedef struct dhcp_ipc_request dhcp_ipc_request_t;
2N/Atypedef struct dhcp_ipc_reply dhcp_ipc_reply_t;
2N/A
2N/A/* payloads that can be passed in a request or reply */
2N/A
2N/Atypedef enum {
2N/A DHCP_TYPE_OPTION,
2N/A DHCP_TYPE_STATUS,
2N/A DHCP_TYPE_OPTNUM,
2N/A DHCP_TYPE_NONE,
2N/A DHCP_TYPE_REQHOST
2N/A} dhcp_data_type_t;
2N/A
2N/A/*
2N/A * requests that can be sent to the agent
2N/A *
2N/A * code in dhcpagent relies on the numeric values of these
2N/A * requests -- but there's no sane reason to change them anyway.
2N/A *
2N/A * If any commands are changed, added, or removed, see the ipc_typestr[]
2N/A * array in dhcpagent_ipc.c.
2N/A */
2N/A
2N/Atypedef enum {
2N/A DHCP_DROP, DHCP_EXTEND, DHCP_PING, DHCP_RELEASE,
2N/A DHCP_START, DHCP_STATUS, DHCP_INFORM, DHCP_GET_TAG,
2N/A DHCP_NIPC, /* number of supported requests */
2N/A DHCP_PRIMARY = 0x100,
2N/A DHCP_V6 = 0x200
2N/A} dhcp_ipc_type_t;
2N/A
2N/A/* structure passed with the DHCP_GET_TAG request */
2N/A
2N/Atypedef struct {
2N/A uint_t category;
2N/A uint_t code;
2N/A uint_t size;
2N/A} dhcp_optnum_t;
2N/A
2N/A#define DHCP_IPC_CMD(type) ((type) & 0x00ff)
2N/A#define DHCP_IPC_FLAGS(type) ((type) & 0xff00)
2N/A
2N/A/* special timeout values for dhcp_ipc_make_request() */
2N/A
2N/A#define DHCP_IPC_WAIT_FOREVER (-1)
2N/A#define DHCP_IPC_WAIT_DEFAULT (-2)
2N/A
2N/A/*
2N/A * errors that can be returned from the provided functions.
2N/A * note: keep in sync with dhcp_ipc_strerror()
2N/A */
2N/A
2N/Aenum {
2N/A /* System call errors must be kept contiguous */
2N/A DHCP_IPC_SUCCESS, DHCP_IPC_E_SOCKET, DHCP_IPC_E_FCNTL,
2N/A DHCP_IPC_E_READ, DHCP_IPC_E_ACCEPT, DHCP_IPC_E_CLOSE,
2N/A DHCP_IPC_E_BIND, DHCP_IPC_E_LISTEN, DHCP_IPC_E_MEMORY,
2N/A DHCP_IPC_E_CONNECT, DHCP_IPC_E_WRITEV, DHCP_IPC_E_POLL,
2N/A
2N/A /* All others follow */
2N/A DHCP_IPC_E_TIMEOUT, DHCP_IPC_E_SRVFAILED, DHCP_IPC_E_EOF,
2N/A DHCP_IPC_E_INVIF, DHCP_IPC_E_INT, DHCP_IPC_E_PERM,
2N/A DHCP_IPC_E_OUTSTATE, DHCP_IPC_E_PEND, DHCP_IPC_E_BOOTP,
2N/A DHCP_IPC_E_CMD_UNKNOWN, DHCP_IPC_E_UNKIF, DHCP_IPC_E_PROTO,
2N/A DHCP_IPC_E_FAILEDIF, DHCP_IPC_E_NOPRIMARY, DHCP_IPC_E_DOWNIF,
2N/A DHCP_IPC_E_NOIPIF, DHCP_IPC_E_NOVALUE, DHCP_IPC_E_RUNNING
2N/A};
2N/A
2N/A/*
2N/A * low-level public dhcpagent ipc functions -- these are for use by
2N/A * programs that need to communicate with the dhcpagent. these will
2N/A * remain relatively stable.
2N/A */
2N/A
2N/Aextern const char *dhcp_ipc_strerror(int);
2N/Aextern dhcp_ipc_request_t *dhcp_ipc_alloc_request(dhcp_ipc_type_t, const char *,
2N/A const void *, uint32_t, dhcp_data_type_t);
2N/Aextern void *dhcp_ipc_get_data(dhcp_ipc_reply_t *, size_t *,
2N/A dhcp_data_type_t *);
2N/Aextern int dhcp_ipc_make_request(dhcp_ipc_request_t *,
2N/A dhcp_ipc_reply_t **, int32_t);
2N/Aextern const char *dhcp_ipc_type_to_string(dhcp_ipc_type_t);
2N/A
2N/A/*
2N/A * high-level public dhcpagent ipc functions
2N/A */
2N/A
2N/Aextern int dhcp_ipc_getinfo(dhcp_optnum_t *, DHCP_OPT **, int32_t);
2N/A
2N/A/*
2N/A * private dhcpagent ipc "server side" functions -- these are only for
2N/A * use by dhcpagent(1M) and are subject to change.
2N/A */
2N/A
2N/Aextern int dhcp_ipc_init(int *);
2N/Aextern int dhcp_ipc_accept(int, int *, int *);
2N/Aextern int dhcp_ipc_recv_request(int, dhcp_ipc_request_t **, int);
2N/Aextern dhcp_ipc_reply_t *dhcp_ipc_alloc_reply(dhcp_ipc_request_t *, int,
2N/A const void *, uint32_t, dhcp_data_type_t);
2N/Aextern int dhcp_ipc_send_reply(int, dhcp_ipc_reply_t *);
2N/Aextern int dhcp_ipc_close(int);
2N/A
2N/A/*
2N/A * values for if_state in the dhcp_status_t
2N/A *
2N/A * code in this library and dhcpagent rely on the numeric values of these
2N/A * requests -- but there's no sane reason to change them anyway.
2N/A */
2N/A
2N/Atypedef enum {
2N/A INIT, /* nothing done yet */
2N/A SELECTING, /* sent DISCOVER, waiting for OFFERs */
2N/A REQUESTING, /* sent REQUEST, waiting for ACK/NAK */
2N/A PRE_BOUND, /* have ACK, setting up interface */
2N/A BOUND, /* have a valid lease */
2N/A RENEWING, /* have lease, but trying to renew */
2N/A REBINDING, /* have lease, but trying to rebind */
2N/A INFORMATION, /* sent INFORM, received ACK */
2N/A INIT_REBOOT, /* attempt to use cached ACK/Reply */
2N/A ADOPTING, /* attempting to adopt */
2N/A INFORM_SENT, /* sent INFORM, awaiting ACK */
2N/A DECLINING, /* sent v6 Decline, awaiting Reply */
2N/A RELEASING, /* sent v6 Release, awaiting Reply */
2N/A DHCP_NSTATES /* total number of states */
2N/A} DHCPSTATE;
2N/A
2N/A/* values for if_dflags in the dhcp_status_t */
2N/A
2N/A#define DHCP_IF_PRIMARY 0x0100 /* interface is primary interface */
2N/A#define DHCP_IF_BUSY 0x0200 /* asynchronous command pending */
2N/A#define DHCP_IF_BOOTP 0x0400 /* interface is using bootp */
2N/A#define DHCP_IF_REMOVED 0x0800 /* interface is going away */
2N/A#define DHCP_IF_FAILED 0x1000 /* interface configuration problem */
2N/A#define DHCP_IF_V6 0x2000 /* DHCPv6 interface */
2N/A
2N/A/*
2N/A * structure passed with the DHCP_STATUS replies
2N/A *
2N/A * when parsing a dhcp_status_t, `version' should always be checked
2N/A * if there is a need to access any fields which were not defined in
2N/A * version 1 of this structure.
2N/A *
2N/A * as new fields are added to the dhcp_status_t, they should be
2N/A * appended to the structure and the version number incremented.
2N/A */
2N/A
2N/Atypedef struct dhcp_status {
2N/A uint8_t version; /* version of this structure */
2N/A
2N/A char if_name[LIFNAMSIZ];
2N/A DHCPSTATE if_state; /* state of interface; see above */
2N/A
2N/A time_t if_began; /* time lease began (absolute) */
2N/A time_t if_t1; /* renewing time (absolute) */
2N/A time_t if_t2; /* rebinding time (absolute) */
2N/A time_t if_lease; /* lease expiration time (absolute) */
2N/A
2N/A uint16_t if_dflags; /* DHCP flags on this if; see above */
2N/A
2N/A /*
2N/A * these three fields are initially zero, and get incremented
2N/A * as if_state goes from INIT -> BOUND (or INIT ->
2N/A * INFORMATION). if and when the interface moves to the
2N/A * RENEWING state, these fields are reset, so they always
2N/A * either indicate the number of packets sent, received, and
2N/A * declined while obtaining the current lease (if BOUND), or
2N/A * the number of packets sent, received, and declined while
2N/A * attempting to obtain a future lease (if any other state).
2N/A */
2N/A
2N/A uint32_t if_sent;
2N/A uint32_t if_recv;
2N/A uint32_t if_bad_offers;
2N/A
2N/A /*
2N/A * if_cid contains the client identifier, either obtained
2N/A * from the config file or generated by the dhcpagent.
2N/A * if_cidlen contains the length of if_cid.
2N/A */
2N/A uint32_t if_cidlen;
2N/A uchar_t if_cid[UCHAR_MAX];
2N/A char if_reqhost[MAXNAMELEN];
2N/A} dhcp_status_t;
2N/A
2N/A#define DHCP_STATUS_VER 3 /* current version of dhcp_status_t */
2N/A#define DHCP_STATUS_VER1_SIZE (offsetof(dhcp_status_t, if_bad_offers) + \
2N/A sizeof (uint32_t))
2N/A#define DHCP_STATUS_VER2_SIZE (offsetof(dhcp_status_t, if_cid) + UCHAR_MAX)
2N/A#define DHCP_STATUS_VER3_SIZE (offsetof(dhcp_status_t, if_reqhost) + \
2N/A MAXNAMELEN)
2N/A
2N/A/*
2N/A * the remainder of this file contains implementation-specific
2N/A * artifacts which may change. note that a `dhcp_ipc_request_t' and a
2N/A * `dhcp_ipc_reply_t' are incomplete types as far as consumers of this
2N/A * api are concerned. use these details at your own risk.
2N/A */
2N/A
2N/Atypedef hrtime_t dhcp_ipc_id_t;
2N/A
2N/A/*
2N/A * note: the first 4 fields of the dhcp_ipc_request_t and dhcp_ipc_reply_t
2N/A * are intentionally identical; code in dhcpagent_ipc.c counts on it!
2N/A */
2N/A
2N/Astruct dhcp_ipc_request {
2N/A dhcp_ipc_type_t message_type; /* type of request */
2N/A dhcp_ipc_id_t ipc_id; /* per-socket unique request id */
2N/A dhcp_data_type_t data_type; /* type of payload */
2N/A uint32_t data_length; /* size of actual data in the buffer */
2N/A char ifname[LIFNAMSIZ];
2N/A int32_t timeout; /* timeout in seconds */
2N/A uchar_t buffer[1]; /* dynamically extended */
2N/A};
2N/A
2N/Astruct dhcp_ipc_reply {
2N/A dhcp_ipc_type_t message_type; /* same message type as request */
2N/A dhcp_ipc_id_t ipc_id; /* same id as request */
2N/A dhcp_data_type_t data_type; /* type of payload */
2N/A uint32_t data_length; /* size of actual data in the buffer */
2N/A uint32_t return_code; /* did the request succeed? */
2N/A uchar_t buffer[1]; /* dynamically extended */
2N/A};
2N/A
2N/A/*
2N/A * since ansi c won't let us define arrays with 0 elements, the
2N/A * size of the ipc request/reply structures is off-by-1; use macros.
2N/A */
2N/A
2N/A#define DHCP_IPC_REPLY_SIZE (sizeof (dhcp_ipc_reply_t) - 1)
2N/A#define DHCP_IPC_REQUEST_SIZE (sizeof (dhcp_ipc_request_t) - 1)
2N/A
2N/A#define DHCP_IPC_DEFAULT_WAIT 120 /* seconds */
2N/A
2N/A#ifdef __cplusplus
2N/A}
2N/A#endif
2N/A
2N/A#endif /* _DHCPAGENT_IPC_H */