libdlpi.c revision 210db2243d3b5ca39c96a4c34c6d9453ddfbeaa9
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 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 <sys/sysmacros.h>
#include <ctype.h>
#include <libdlpi.h>
#include <libdladm.h>
typedef enum dlpi_multi_op {
DLPI_MULTI_DISABLE = 0,
typedef enum dlpi_promisc_op {
DLPI_PROMISC_OFF = 0,
const char *i_dlpi_mac_type[] = {
"Token Bus", /* 0x01 */
"Token Ring", /* 0x02 */
"Metro Net", /* 0x03 */
"Ethernet", /* 0x04 */
"HDLC", /* 0x05 */
"Sync Character", /* 0x06 */
"CTCA", /* 0x07 */
"FDDI", /* 0x08 */
"unknown" /* 0x09 */
"Frame Relay (LAPF)", /* 0x0a */
"MP Frame Relay", /* 0x0b */
"Async Character", /* 0x0c */
"X.25 (Classic IP)", /* 0x0d */
"Software Loopback", /* 0x0e */
"undefined", /* 0x0f */
"Fiber Channel", /* 0x10 */
"ATM", /* 0x11 */
"ATM (Classic IP)", /* 0x12 */
"X.25 (LAPB)", /* 0x13 */
"ISDN", /* 0x14 */
"HIPPI", /* 0x15 */
"100BaseVG Ethernet", /* 0x16 */
"100BaseVG Token Ring", /* 0x17 */
"100BaseT", /* 0x19 */
"Infiniband" /* 0x1a */
};
static int i_dlpi_ifrm_num(char *, unsigned int *);
const char *
{
return ("ERROR");
return (i_dlpi_mac_type[type]);
}
static int
{
}
static int
{
int res;
int flags = 0;
default:
goto failed;
goto failed;
}
}
goto failed;
}
}
break;
case 0:
/*FALLTHRU*/
case -1:
goto failed;
}
return (0);
return (-1);
}
int
{
char devname[MAXPATHLEN];
char path[MAXPATHLEN];
int fd;
return (fd);
provider);
return (fd);
}
return (-1);
}
int
dlpi_close(int fd)
{
}
int
{
int rc = -1;
union DL_qos_types *uqtp;
return (-1);
goto done;
goto done;
if (size < DL_INFO_ACK_SIZE) {
goto done;
}
goto done;
}
if (dliap->dl_qos_offset != 0) {
goto done;
}
uqtp = (union DL_qos_types *)
goto done;
}
}
if (dliap->dl_qos_range_offset != 0) {
goto done;
}
uqtp = (union DL_qos_types *)
goto done;
}
}
if (dliap->dl_addr_offset != 0) {
if (dliap->dl_addr_length == 0) {
goto done;
}
}
if (dliap->dl_brdcst_addr_offset != 0) {
if (dliap->dl_brdcst_addr_length == 0) {
goto done;
}
if (brdcst_addrlenp != NULL)
if (brdcst_addrp != NULL)
(void) memcpy(brdcst_addrp,
}
rc = 0; /* success */
done:
return (rc);
}
int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
size = 0;
return (-1);
goto done;
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_OK_ACK:
if (size < DL_OK_ACK_SIZE) {
goto done;
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_BADPPA:
break;
case DL_ACCESS:
break;
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
size = 0;
return (-1);
goto done;
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_OK_ACK:
if (size < DL_OK_ACK_SIZE) {
goto done;
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
size = 0;
return (-1);
goto done;
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_BIND_ACK:
if (size < DL_BIND_ACK_SIZE) {
goto done;
}
if (max_conn_ind != NULL)
if (dlbap->dl_addr_offset != 0) {
if (dlbap->dl_addr_length == 0) {
goto done;
}
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_BADADDR:
break;
case DL_INITFAILED:
case DL_NOTINIT:
break;
case DL_ACCESS:
break;
case DL_NOADDR:
break;
case DL_UNSUPPORTED:
case DL_NOAUTO:
case DL_NOXIDAUTO:
case DL_NOTESTAUTO:
break;
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
size = 0;
return (-1);
goto done;
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_OK_ACK:
if (size < DL_OK_ACK_SIZE) {
goto done;
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
static int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
sizeof (dl_disabmulti_req_t);
opsize += addr_length;
size = 0;
return (-1);
if (op == DLPI_MULTI_ENABLE) {
} else {
}
goto done;
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_OK_ACK:
if (size < DL_OK_ACK_SIZE) {
goto done;
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_BADADDR:
break;
case DL_TOOMANY:
break;
case DL_NOTSUPPORTED:
break;
case DL_NOTENAB:
break;
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
int
{
addr_length));
}
int
{
addr_length));
}
static int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
sizeof (dl_promiscoff_req_t);
size = 0;
return (-1);
if (op == DLPI_PROMISC_ON) {
goto done;
} else {
goto done;
}
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_OK_ACK:
if (size < DL_OK_ACK_SIZE) {
goto done;
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_NOTSUPPORTED:
case DL_UNSUPPORTED:
break;
case DL_NOTENAB:
break;
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
int
{
}
int
{
}
int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
size = 0;
return (-1);
goto done;
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_PHYS_ADDR_ACK:
if (size < DL_PHYS_ADDR_ACK_SIZE) {
goto done;
}
if (dlpaap->dl_addr_offset != 0) {
if (dlpaap->dl_addr_length == 0) {
goto done;
}
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
int
{
int rc = -1;
union DL_primitives *buf;
union DL_primitives *udlp;
size = 0;
return (-1);
goto done;
goto done;
if (size < sizeof (t_uscalar_t)) {
goto done;
}
switch (udlp->dl_primitive) {
case DL_OK_ACK:
if (size < DL_OK_ACK_SIZE) {
goto done;
}
break;
case DL_ERROR_ACK:
if (size < DL_ERROR_ACK_SIZE) {
goto done;
}
case DL_BADADDR:
break;
case DL_NOTSUPPORTED:
break;
case DL_SYSERR:
break;
default:
break;
}
goto done;
default:
goto done;
}
rc = 0; /* success */
done:
return (rc);
}
void
{
union DL_primitives *buf;
return;
/*
* We don't care about the outcome of this operation. We at least
* don't want to return until the operation completes or the
* timeout expires.
*/
}
static int
{
int fd;
int cnt;
/* Open device */
diap->mod_pushed = 0;
return (-1);
} else {
}
/*
* Try to push modules (if any) onto the device stream
*/
return (-1);
}
}
goto failed;
goto failed;
return (fd);
(void) dlpi_close(fd);
return (-1);
}
static int
{
int fd;
/*
* If style 1 open failed, we need to determine how far it got and
* finish up the open() call as a style 2 open
*
* If no modules were pushed (mod_pushed == 0), then we need to
* strip off the ppa off the device name and open it as a style 2
* device
*
* If the pushing of the last module failed, we need to strip off the
* ppa from that module and try pushing it as a style 2 module
*
* Otherwise we failed during the push of an intermediate module and
* must fail out and close the device.
*
* And if style1 did not fail (i.e. we called style2 open directly),
* just open the device
*/
if (diap->style1_failed) {
if (!diap->mod_pushed) {
return (-1);
return (-1);
if (i_dlpi_ifrm_num(
return (-1);
diap->mod_pushed--;
} else {
return (-1);
}
} else {
return (-1);
}
/*
* Try and push modules (if any) onto the device stream
*/
goto failed;
}
NULL) == -1)
goto failed;
goto failed;
goto failed;
return (fd);
(void) dlpi_close(fd);
return (-1);
}
static int
{
int cnt = 0; /* number of modules to push */
char *nxtmod;
char *p;
int len;
/* if lun is specified fail (backwards compat) */
return (-1);
/* save copy of original device name */
return (-1);
/* initialize ppa */
/* get provider name and ppa from ifname */
if (!isdigit(*p)) {
break;
}
}
sizeof (modbuf))
return (-1);
/* parse '.' delimited module list */
/* null-terminate interface name (device) */
*modlist = '\0';
modlist++;
if (*modlist == '\0')
return (-1);
if (nxtmod) {
*nxtmod = '\0';
nxtmod++;
}
return (-1);
cnt++;
}
}
return (-1);
return (0);
}
int
{
int fd;
return (-1);
}
if (!force_style2) {
return (fd);
}
return (-1);
return (fd);
}
int
{
return (-1);
}
return (-1);
return (0);
}
/*
* attempt to remove ppa from end of file name
* return -1 if none found
* return ppa if found and remove the ppa from the filename
*/
static int
{
int i;
uint_t p = 0;
unsigned int m = 1;
p += (fname[i] - '0')*m;
m *= 10;
i--;
}
if (m == 1) {
return (-1);
}
*ppa = p;
return (0);
}