/*
* 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
* 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
*/
/*
*/
/*
* Data-Link Provider Interface (Version 2)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <stropts.h>
#include <errno.h>
#include <alloca.h>
#include <sys/sysmacros.h>
#include <ctype.h>
#include <net/if_types.h>
#include <libdladm.h>
#include <libdllink.h>
#include <libdlpi.h>
#include <libintl.h>
#include <libinetutil.h>
#include <libnetcfg.h>
#include <dirent.h>
#include <zone.h>
#include "libdlpi_impl.h"
static int i_dlpi_style1_open(dlpi_impl_t *);
static int i_dlpi_style2_open(dlpi_impl_t *);
static int i_dlpi_attach(dlpi_impl_t *);
static void i_dlpi_passive(dlpi_impl_t *);
size_t, int);
size_t, int);
static void i_dlpi_deletenotifyid(dlpi_impl_t *);
struct i_dlpi_walklink_arg {
void *arg;
};
static int
{
}
/*ARGSUSED*/
void
{
struct dirent *d;
if (flags & DLPI_DEVIPNET) {
return;
if (d->d_name[0] == '.')
continue;
break;
}
} else {
/*
* Rather than have libdlpi take the libdladm handle,
* open the handle here.
*/
!= DLADM_STATUS_OK)
return;
}
}
int
{
/*
* Validate linkname and retrieve the DLPI provier name and PPA.
*/
if (retval != DLPI_SUCCESS)
return (retval);
/*
* Ensure flags values are sane.
*/
return (DLPI_EINVAL);
/* Allocate a new dlpi_impl_t. */
return (DL_SYSERR);
/* Copy linkname provided to the function. */
sizeof (dip->dli_linkname)) {
return (DLPI_ELINKNAMEINVAL);
}
/* Copy provider name. */
/*
* Special case: DLPI_SERIAL flag is set to indicate a synchronous
* serial line interface (see syncinit(1M), syncstat(1M),
* syncloop(1M)), which is not a DLPI link.
*/
return (retval);
}
return (retval);
}
if (retval == DLPI_ENOTSTYLE2) {
/*
* The error code indicates not to continue the
* style-2 open. Change the error code back to
* DL_SYSERR, so that one would know the cause
* of failure from errno.
*/
}
if (retval != DLPI_SUCCESS) {
return (retval);
}
}
return (DLPI_ERAWNOTSUP);
}
return (DLPI_EIPNETINFONOTSUP);
}
/*
* We intentionally do not care if this request fails, as this
* indicates the underlying DLPI device does not support Native mode
* (pre-GLDV3 device drivers).
*/
}
return (DLPI_SUCCESS);
}
void
{
}
}
}
/*
* NOTE: The version argument must be less than the max supported value
* and is used to determine the fields of the dlpi_info_t structure. See
* dlpi_info(3DLPI).
*/
int
{
int retval;
return (DLPI_EINHANDLE);
return (DLPI_EINVAL);
sizeof (dlpi_info_vers1_t) : sizeof (dlpi_info_t));
/* Set QoS range parameters to default unsupported value. */
/* Set QoS parameters to default unsupported value. */
if (retval != DLPI_SUCCESS)
return (retval);
return (DLPI_EVERNOTSUP);
return (DLPI_EMODENOTSUP);
/* Check and save QoS selection information, if any. */
if (datalen > sizeof (dl_qos_cl_sel1_t) ||
return (DLPI_EBADMSG);
return (DLPI_EMODENOTSUP);
}
/* Check and save QoS range information, if any. */
if (datalen > sizeof (dl_qos_cl_range1_t) ||
return (DLPI_EBADMSG);
return (DLPI_EMODENOTSUP);
}
/* Check and save physical address and SAP information. */
return (DL_BADADDR);
return (DLPI_EBADMSG);
if (dip->dli_sapbefore)
else
}
/* Check and save broadcast address information, if any. */
return (DLPI_EBADMSG);
return (DL_BADADDR);
}
/* Information retrieved from the handle. */
return (DLPI_SUCCESS);
}
/*
* This function parses 'linkname' and stores the 'provider' name and 'PPA'.
*/
int
{
}
static int
{
/*
* the linkname and retreive the DLPI provider name and PPA we strip the
* zonename prefix (if any) and call dlpi_parselink to retrieve the DLPI
* provider name and PPA.
*/
return (DLPI_ELINKNAMEINVAL);
/*
* Validate linkname and retrieve the DLPI provier name and PPA.
*/
}
/*
* This function takes a provider name and a PPA and stores a full linkname
* as 'linkname'. If 'provider' already is a full linkname 'provider' name
* is stored in 'linkname'.
*/
int
{
return (DLPI_ELINKNAMEINVAL);
ppa);
} else {
}
return (DLPI_SUCCESS);
}
int
{
int retval;
return (DLPI_EINHANDLE);
/*
* If 'sap' is DLPI_ANY_SAP, bind to SAP 2 on token ring, else 0 on
* other interface types (SAP 0 has special significance on token ring).
*/
if (sap == DLPI_ANY_SAP)
else
bindreqp->dl_conn_mgmt = 0;
bindreqp->dl_max_conind = 0;
bindreqp->dl_xidtest_flg = 0;
if (retval != DLPI_SUCCESS)
return (retval);
/*
* Received a DLPI_BIND_ACK, now verify that the bound SAP
* is equal to the SAP requested. Some DLPI MAC type may bind
* to a different SAP than requested, in this case 'boundsap'
* returns the actual bound SAP. For the case where 'boundsap'
* is NULL and 'sap' is not DLPI_ANY_SAP, dlpi_bind fails.
*/
return (DLPI_FAILURE);
else
return (DLPI_EUNAVAILSAP);
}
return (DLPI_SUCCESS);
}
int
{
return (DLPI_EINHANDLE);
}
/*
* This function is invoked by dlpi_enabmulti() or dlpi_disabmulti() and
*/
static int
{
return (DLPI_EINHANDLE);
if (addrlen > DLPI_PHYSADDR_MAX)
return (DLPI_EINVAL);
}
int
{
}
int
{
}
/*
* This function is invoked by dlpi_promiscon() or dlpi_promiscoff(). Based
* 'level'.
*/
static int
{
return (DLPI_EINHANDLE);
}
int
{
}
int
{
}
int
{
int retval;
return (DLPI_EINHANDLE);
return (DLPI_EINVAL);
if (retval != DLPI_SUCCESS)
return (retval);
/* Received DL_PHYS_ADDR_ACK, store the physical address and length. */
if (datalen > DLPI_PHYSADDR_MAX)
return (DL_BADADDR);
if (dataoff < DL_PHYS_ADDR_ACK_SIZE ||
return (DLPI_EBADMSG);
} else {
}
return (DLPI_SUCCESS);
}
int
{
return (DLPI_EINHANDLE);
return (DLPI_EINVAL);
}
int
{
return (DLPI_EINHANDLE);
return (DLPI_EINVAL);
/* Set priority to default priority range. */
/* Use SAP value if specified otherwise use bound SAP value. */
} else {
}
/*
* Since `daddrp' only has the link-layer destination address,
* we must prepend or append the SAP (according to dli_sapbefore)
* to make a full DLPI address.
*/
if (dip->dli_sapbefore) {
} else {
dip->dli_saplen);
}
}
int
{
int retval;
return (DLPI_EINHANDLE);
/*
* If handle is in raw mode ignore everything except total message
* length.
*/
return (retval);
}
return (retval);
/*
* If DLPI link provides source address, store source address in
* 'saddrp' and source length in 'saddrlenp', else set saddrlenp to 0.
*/
if (*saddrlenp < DLPI_PHYSADDR_MAX)
return (DLPI_EINVAL);
if (dataoff < DL_UNITDATA_IND_SIZE ||
return (DLPI_EBADMSG);
if (*saddrlenp > DLPI_PHYSADDR_MAX)
return (DL_BADADDR);
if (dip->dli_sapbefore)
} else {
*saddrlenp = 0;
}
}
/*
* If destination address requested, check and save destination
* address, if any.
*/
if (dataoff < DL_UNITDATA_IND_SIZE ||
return (DLPI_EBADMSG);
return (DL_BADADDR);
if (dip->dli_sapbefore)
} else {
recvp->dri_destaddrlen = 0;
}
}
return (DLPI_SUCCESS);
}
int
{
int retval;
return (DLPI_EINHANDLE);
if (retval != DLPI_SUCCESS)
return (retval);
if (dip->dli_note_processing)
return (DLPI_FAILURE);
return (DLPI_EINVAL);
if ((~DLPI_NOTIFICATION_TYPES & notes) ||
!(notes & DLPI_NOTIFICATION_TYPES))
return (DLPI_ENOTEINVAL);
notifyreqp->dl_timelimit = 0;
if (retval == DL_NOTSUPPORTED)
return (DLPI_ENOTENOTSUP);
if (retval != DLPI_SUCCESS)
return (retval);
return (DL_SYSERR);
/* Register notification information. */
/* Insert notification node at head */
return (DLPI_SUCCESS);
}
int
{
return (DLPI_EINHANDLE);
/* Walk the notifyentry list to find matching id. */
return (DLPI_ENOTEIDINVAL);
/* Delete node if callbacks are not being processed. */
if (!dip->dli_note_processing)
return (DLPI_SUCCESS);
}
int
{
}
int
{
return (DLPI_EINHANDLE);
return (DLPI_SUCCESS);
}
const char *
{
}
/*
* Returns DLPI style stored in the handle.
* Note: This function is used for test purposes only. Do not remove without
* fixing the DLPI testsuite.
*/
{
}
{
switch (dlpitype) {
case DL_ETHER:
return (ARPHRD_ETHER);
case DL_FRAME:
return (ARPHRD_FRAME);
case DL_ATM:
return (ARPHRD_ATM);
case DL_IPATM:
return (ARPHRD_IPATM);
case DL_HDLC:
return (ARPHRD_HDLC);
case DL_FC:
return (ARPHRD_FC);
case DL_CSMACD: /* ieee 802 networks */
case DL_TPB:
case DL_TPR:
case DL_METRO:
case DL_FDDI:
return (ARPHRD_IEEE802);
case DL_IB:
return (ARPHRD_IB);
case DL_IPV4:
case DL_IPV6:
return (ARPHRD_TUNNEL);
}
return (0);
}
{
switch (dlpitype) {
case DL_ETHER:
return (IFT_ETHER);
case DL_ATM:
return (IFT_ATM);
case DL_CSMACD:
return (IFT_ISO88023);
case DL_TPB:
return (IFT_ISO88024);
case DL_TPR:
return (IFT_ISO88025);
case DL_FDDI:
return (IFT_FDDI);
case DL_IB:
return (IFT_IB);
case DL_OTHER:
return (IFT_OTHER);
}
return (0);
}
/*
* This function attempts to open a device under the following namespaces:
* /dev - if DLPI_DEVONLY is specified, or if there is no
*
* In particular, if DLPI_DEVIPNET is not specified, this function is used to
* with style1 being B_TRUE, and if that fails and the return value is not
* DLPI_ENOTSTYLE2, the function will again be called with style1 being
* B_FALSE (style-1 open attempt first, then style-2 open attempt).
*
* If DLPI_DEVONLY is specified, both attempt will try to open the /dev node
* directly.
*
* Otherwise, for style-1 attempt, the function will try to open the style-1
* Note that the fallback and the subsequent style-2 attempt will not happen if:
* is a known device name or its VLAN PPA hack name. (for example, assuming
* as VLAN 1 over the bge0 device should be named as net1000.
*
* DLPI_ENOTSTYLE2 will be returned in case 2 and 3 to indicate not to proceed
* the second style-2 open attempt.
*/
static int
{
int oflags;
if (flags & DLPI_DEVIPNET) {
return (DLPI_SUCCESS);
else
/*
* This is not a valid style-1 name. It could be "ip" module
* for example. Fallback to open the /dev node.
*/
&ppa) != DLPI_SUCCESS) {
goto fallback;
}
/*
*/
} else {
/*
*/
provider);
}
return (DLPI_SUCCESS);
/*
* We don't fallback to open the /dev node when it returns
* error codes other than ENOENT. In that case, DLPI_ENOTSTYLE2
* is returned to indicate not to continue the style-2 open.
*/
return (DLPI_ENOTSTYLE2);
/*
* the given name is a device name or its VLAN PPA hack name
* of a known link. If the answer is yes, and this link
* supports vanity naming, then the link (or the VLAN) should
* name (for example, when bge0 is renamed to net0). In this
* we should not fallback to open the /dev/<devname> node.
*/
/* open libdladm handle rather than taking it as input */
!= DLADM_STATUS_OK)
goto fallback;
DLADM_OPT_ACTIVE)) == DLADM_STATUS_OK &&
!dpa.dp_novanity) {
return (DLPI_ENOTSTYLE2);
}
}
}
return (DLPI_SUCCESS);
}
/*
* Open a style 1 link. PPA is implicitly attached.
*/
static int
{
int fd;
if (retval != DLPI_SUCCESS)
return (retval);
save_errno = errno;
errno = save_errno;
}
return (retval);
}
/*
* Open a style 2 link. PPA must be explicitly attached.
*/
static int
{
int fd;
if (retval != DLPI_SUCCESS)
return (retval);
/*
* Special case: DLPI_SERIAL flag (synchronous serial lines) is not a
* DLPI link so attach and ignore rest.
*/
goto attach;
goto failure;
/*
* Succeeded opening the link and verified it is style2. Now attach to
* PPA only if DLPI_NOATTACH is not set.
*/
return (DLPI_SUCCESS);
return (DLPI_SUCCESS);
save_errno = errno;
errno = save_errno;
return (retval);
}
/*
* Verify with DLPI that the link is the expected DLPI 'style' device,
* dlpi_info sets the DLPI style in the DLPI handle.
*/
static int
{
int retval;
return (retval);
}
/*
* For DLPI style 2 providers, an explicit attach of PPA is required.
*/
static int
{
/*
* Special case: DLPI_SERIAL flag (synchronous serial lines)
* is not a DLPI link so ignore DLPI style.
*/
return (DLPI_ENOTSTYLE2);
}
/*
* Enable DLPI passive mode on a DLPI handle. We intentionally do not care
* if this request fails, as this indicates the underlying DLPI device does
* not support link aggregation (pre-GLDV3 device drivers), and thus will
* DLPI primitives like DL_BIND_REQ. For further info see dlpi(7p).
*/
static void
{
}
/*
* for this function are:
* dlpi_impl_t *dip: internal dlpi handle to open stream
* const dlpi_msg_t *dlreqp: request message structure
* void *databuf: data buffer
* size_t datalen: data buffer len
* int flags: flags to set for putmsg()
* Returns DLPI_SUCCESS if putmsg() succeeds, otherwise DL_SYSERR on failure.
*/
static int
{
int retval;
}
}
/*
* for this function are:
* dlpi_impl_t *dip: internal dlpi handle
* int msec: timeout to wait for message
* dlpi_msg_t *dlreplyp: reply message structure, the message size
* member on return stores actual size received
* t_uscalar_t dlreqprim: requested primitive
* t_uscalar_t dlreplyprim:acknowledged primitive in response to request
* size_t dlreplyminsz: minimum size of acknowledged primitive size
* void *databuf: data buffer
* size_t *datalenp: data buffer len
* size_t *totdatalenp: total data received. Greater than 'datalenp' if
* actual data received is larger than 'databuf'
* Function returns DLPI_SUCCESS if requested message is retrieved
* otherwise returns error code or timeouts. If a notification arrives on
* the stream the callback is notified. However, error returned during the
* handling of notification is ignored as it would be confusing to actual caller
* of this function.
*/
static int
{
int retval;
int flags;
/*
* dlreplyp and databuf can be NULL at the same time, to force a check
* for pending events on the DLPI link instance; dlpi_enabnotify(3DLPI).
* this will be true more so for DLPI_RAW mode with notifications
* enabled.
*/
return (DLPI_EINVAL);
for (;;) {
if (!infinite)
default:
return (DL_SYSERR);
break;
case 0:
return (DLPI_ETIMEDOUT);
case -1:
return (DL_SYSERR);
}
flags = 0;
return (DL_SYSERR);
if (totdatalenp != NULL)
/*
* The supplied DLPI_CHUNKSIZE sized buffers are large enough
* to retrieve all valid DLPI responses in one iteration.
* If MORECTL or MOREDATA is set, we are not interested in the
* remainder of the message. Temporary buffers are used to
* drain the remainder of this message.
* The special case we have to account for is if
* a higher priority messages is enqueued whilst handling
* this condition. We use a change in the flags parameter
* returned by getmsg() to indicate the message has changed.
*/
sizeof (bufc);
&flags)) < 0)
return (DL_SYSERR);
if (totdatalenp != NULL)
/*
* In the special case of higher priority
* message received, the low priority message
* received earlier is discarded, if no data
* or control message is left.
*/
break;
}
}
/*
* Check if DL_NOTIFY_IND message received. If there is one,
* notify the callback function(s) and continue processing the
* requested message.
*/
/* process properly-formed DL_NOTIFY_IND messages */
}
goto update_timer;
}
/*
* If we were expecting a data message, and we got one, set
* *datalenp. If we aren't waiting on a control message, then
* we're done.
*/
break;
}
/*
* If we were expecting a control message, and the message
* we received is at least big enough to be a DLPI message,
* then verify it's a reply to something we sent. If it
* is a reply to something we sent, also verify its size.
*/
return (DLPI_EBADMSG);
break;
return (DLPI_EBADMSG);
/* Is it ours? */
break;
}
}
if (!infinite) {
if (msec <= 0)
return (DLPI_ETIMEDOUT);
}
}
return (DLPI_SUCCESS);
}
/*
* Common routine invoked by all DLPI control routines. The inputs for this
* function are:
* dlpi_impl_t *dip: internal dlpi handle
* const dlpi_msg_t *dlreqp: request message structure
* dlpi_msg_t *dlreplyp: reply message structure
* size_t dlreplyminsz: minimum size of reply primitive
* int flags: flags to be set to send a message
* This routine succeeds if the message is an expected request/acknowledged
* message. However, if DLPI notification has been enabled via
* dlpi_enabnotify(), DL_NOTIFY_IND messages are handled before handling
* expected messages. Otherwise, any other unexpected asynchronous messages will
* be discarded.
*/
static int
{
int retval;
/* Put the requested primitive on the stream. */
if (retval != DLPI_SUCCESS)
return (retval);
/* Retrieve acknowledged message for requested primitive. */
if (retval != DLPI_SUCCESS)
return (retval);
/*
* If primitive is DL_ERROR_ACK, set errno.
*/
}
return (retval);
}
/*
* DLPI error codes.
*/
static const char *dlpi_errlist[] = {
"bad LSAP selector", /* DL_BADSAP 0x00 */
"DLSAP address in improper format or invalid", /* DL_BADADDR 0x01 */
"improper permissions for request", /* DL_ACCESS 0x02 */
"primitive issued in improper state", /* DL_OUTSTATE 0x03 */
NULL, /* DL_SYSERR 0x04 */
"sequence number not from outstanding DL_CONN_IND",
/* DL_BADCORR 0x05 */
"user data exceeded provider limit", /* DL_BADDATA 0x06 */
"requested service not supplied by provider",
/* DL_UNSUPPORTED 0x07 */
"specified PPA was invalid", /* DL_BADPPA 0x08 */
"primitive received not known by provider", /* DL_BADPRIM 0x09 */
"QoS parameters contained invalid values",
/* DL_BADQOSPARAM 0x0a */
"QoS structure type is unknown/unsupported", /* DL_BADQOSTYPE 0x0b */
"token used not an active stream", /* DL_BADTOKEN 0x0c */
"attempted second bind with dl_max_conind", /* DL_BOUND 0x0d */
"physical link initialization failed", /* DL_INITFAILED 0x0e */
"provider couldn't allocate alternate address", /* DL_NOADDR 0x0f */
"physical link not initialized", /* DL_NOTINIT 0x10 */
"previous data unit could not be delivered",
/* DL_UNDELIVERABLE 0x11 */
"primitive is known but unsupported",
/* DL_NOTSUPPORTED 0x12 */
"limit exceeded", /* DL_TOOMANY 0x13 */
"promiscuous mode not enabled", /* DL_NOTENAB 0x14 */
"other streams for PPA in post-attached", /* DL_BUSY 0x15 */
"automatic handling XID&TEST unsupported", /* DL_NOAUTO 0x16 */
"automatic handling of XID unsupported", /* DL_NOXIDAUTO 0x17 */
"automatic handling of TEST unsupported", /* DL_NOTESTAUTO 0x18 */
"automatic handling of XID response", /* DL_XIDAUTO 0x19 */
"automatic handling of TEST response", /* DL_TESTAUTO 0x1a */
"pending outstanding connect indications" /* DL_PENDING 0x1b */
};
/*
* libdlpi error codes.
*/
static const char *libdlpi_errlist[] = {
"DLPI operation succeeded", /* DLPI_SUCCESS */
"invalid argument", /* DLPI_EINVAL */
"invalid DLPI linkname", /* DLPI_ELINKNAMEINVAL */
"DLPI link does not exist", /* DLPI_ENOLINK */
"bad DLPI link", /* DLPI_EBADLINK */
"invalid DLPI handle", /* DLPI_EINHANDLE */
"DLPI operation timed out", /* DLPI_ETIMEDOUT */
"unsupported DLPI version", /* DLPI_EVERNOTSUP */
"unsupported DLPI connection mode", /* DLPI_EMODENOTSUP */
"unavailable DLPI SAP", /* DLPI_EUNAVAILSAP */
"DLPI operation failed", /* DLPI_FAILURE */
"DLPI style-2 node reports style-1", /* DLPI_ENOTSTYLE2 */
"bad DLPI message", /* DLPI_EBADMSG */
"DLPI raw mode not supported", /* DLPI_ERAWNOTSUP */
"DLPI notification not supported by link",
/* DLPI_ENOTENOTSUP */
"invalid DLPI notification type", /* DLPI_ENOTEINVAL */
"invalid DLPI notification id", /* DLPI_ENOTEIDINVAL */
"DLPI_IPNETINFO not supported" /* DLPI_EIPNETINFONOTSUP */
};
const char *
{
DLPI_SUCCESS]));
else
}
/*
*/
{ DL_TPB, "Token Bus" },
{ DL_TPR, "Token Ring" },
{ DL_METRO, "Metro Net" },
{ DL_ETHER, "Ethernet" },
{ DL_HDLC, "HDLC" },
{ DL_CHAR, "Sync Character" },
{ DL_CTCA, "CTCA" },
{ DL_FDDI, "FDDI" },
{ DL_FRAME, "Frame Relay (LAPF)" },
{ DL_MPFRAME, "MP Frame Relay" },
{ DL_ASYNC, "Async Character" },
{ DL_IPX25, "X.25 (Classic IP)" },
{ DL_LOOP, "Software Loopback" },
{ DL_FC, "Fiber Channel" },
{ DL_ATM, "ATM" },
{ DL_IPATM, "ATM (Classic IP)" },
{ DL_X25, "X.25 (LAPB)" },
{ DL_ISDN, "ISDN" },
{ DL_HIPPI, "HIPPI" },
{ DL_100VG, "100BaseVG Ethernet" },
{ DL_100VGTPR, "100BaseVG Token Ring" },
{ DL_ETH_CSMA, "Ethernet/IEEE 802.3" },
{ DL_100BT, "100BaseT" },
{ DL_IB, "Infiniband" },
{ DL_IPV4, "IPv4 Tunnel" },
{ DL_IPV6, "IPv6 Tunnel" },
{ DL_WIFI, "IEEE 802.11" },
{ DL_IPNET, "IPNET" }
};
const char *
{
int i;
for (i = 0; i < NELEMS(dlpi_mactypes); i++) {
return (dlpi_mactypes[i].dm_desc);
}
return ("Unknown MAC Type");
}
/*
* Each table entry comprises a DLPI primitive and the maximum buffer
*/
{ DL_INFO_REQ, DL_INFO_REQ_SIZE },
{ DL_BIND_REQ, DL_BIND_REQ_SIZE },
DLPI_SAPLEN_MAX)) },
};
/*
* Refers to the dlpi_primsizes[] table to return corresponding maximum
* buffer size.
*/
static size_t
{
int i;
for (i = 0; i < NELEMS(dlpi_primsizes); i++) {
return (dlpi_primsizes[i].dp_primsz);
}
return (sizeof (t_uscalar_t));
}
/*
* sap values vary in length and are in host byte order, build sap value
* by writing saplen bytes, so that the sap value is left aligned.
*/
static uint_t
{
int i;
#ifdef _LITTLE_ENDIAN
for (i = saplen - 1; i >= 0; i--) {
#else
for (i = 0; i < saplen; i++) {
#endif
sap <<= 8;
}
return (sap);
}
/*
* Copy sap value to a buffer in host byte order. saplen is the number of
* bytes to copy.
*/
static void
{
#ifdef _LITTLE_ENDIAN
#else
#endif
}
/*
* Fill notification payload and callback each registered functions.
* Delete nodes if any was called while processing.
*/
static int
{
switch (note) {
case DL_NOTE_SPEED:
break;
case DL_NOTE_SDU_SIZE:
break;
case DL_NOTE_FC_MODE:
return (DLPI_EBADMSG);
}
break;
case DL_NOTE_ETSBAT:
return (DLPI_EBADMSG);
}
break;
case DL_NOTE_PHYS_ADDR:
/*
* libdlpi currently only supports notifications for
* DL_CURR_PHYS_ADDR.
*/
return (DLPI_ENOTENOTSUP);
return (DLPI_EBADMSG);
if (dataoff < DL_NOTIFY_IND_SIZE)
return (DLPI_EBADMSG);
return (DL_BADADDR);
break;
}
deletenode = B_TRUE;
}
/* Walk the notifyentry list to unregister marked entries. */
if (deletenode)
return (DLPI_SUCCESS);
}
/*
* Find registered notification.
*/
static boolean_t
{
return (B_TRUE);
}
return (B_FALSE);
}
/*
* Walk the list of notifications and deleted nodes marked to be deleted.
*/
static void
{
} else {
}
}
}