summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdlpi/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdlpi/common')
-rw-r--r--usr/src/lib/libdlpi/common/libdlpi.c154
-rw-r--r--usr/src/lib/libdlpi/common/libdlpi.h56
-rw-r--r--usr/src/lib/libdlpi/common/mapfile-vers3
3 files changed, 162 insertions, 51 deletions
diff --git a/usr/src/lib/libdlpi/common/libdlpi.c b/usr/src/lib/libdlpi/common/libdlpi.c
index b95ff3fd93..f403135b6a 100644
--- a/usr/src/lib/libdlpi/common/libdlpi.c
+++ b/usr/src/lib/libdlpi/common/libdlpi.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,13 +44,15 @@
#include <ctype.h>
#include <net/if_types.h>
#include <netinet/arp.h>
+#include <libdladm.h>
+#include <libdllink.h>
#include <libdlpi.h>
#include <libintl.h>
#include <libinetutil.h>
#include "libdlpi_impl.h"
-static int i_dlpi_open(const char *, int *, uint_t);
+static int i_dlpi_open(const char *, int *, uint_t, boolean_t);
static int i_dlpi_style1_open(dlpi_impl_t *);
static int i_dlpi_style2_open(dlpi_impl_t *);
static int i_dlpi_checkstyle(dlpi_impl_t *, t_uscalar_t);
@@ -74,6 +76,33 @@ static int i_dlpi_notifyind_process(dlpi_impl_t *, dl_notify_ind_t *);
static boolean_t i_dlpi_notifyidexists(dlpi_impl_t *, dlpi_notifyent_t *);
static void i_dlpi_deletenotifyid(dlpi_impl_t *);
+struct i_dlpi_walklink_arg {
+ dlpi_walkfunc_t *fn;
+ void *arg;
+};
+
+static int
+i_dlpi_walk_link(const char *name, void *arg)
+{
+ struct i_dlpi_walklink_arg *warg = arg;
+
+ return ((warg->fn(name, warg->arg)) ? DLADM_WALK_TERMINATE :
+ DLADM_WALK_CONTINUE);
+}
+
+/*ARGSUSED*/
+void
+dlpi_walk(dlpi_walkfunc_t *fn, void *arg, uint_t flags)
+{
+ struct i_dlpi_walklink_arg warg;
+
+ warg.fn = fn;
+ warg.arg = arg;
+
+ (void) dladm_walk(i_dlpi_walk_link, &warg, DATALINK_CLASS_ALL,
+ DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
+}
+
int
dlpi_open(const char *linkname, dlpi_handle_t *dhp, uint_t flags)
{
@@ -101,6 +130,8 @@ dlpi_open(const char *linkname, dlpi_handle_t *dhp, uint_t flags)
dip->dli_oflags = flags;
dip->dli_notifylistp = NULL;
dip->dli_note_processing = B_FALSE;
+ if (getenv("DLPI_DEVONLY") != NULL)
+ dip->dli_oflags |= DLPI_DEVONLY;
for (cnt = 0; cnt != dip->dli_mod_cnt; cnt++) {
(void) strlcpy(dip->dli_modlist[cnt], ifsp.ifsp_mods[cnt],
@@ -133,8 +164,19 @@ dlpi_open(const char *linkname, dlpi_handle_t *dhp, uint_t flags)
return (retval);
}
- if (i_dlpi_style1_open(dip) != DLPI_SUCCESS) {
- if ((retval = i_dlpi_style2_open(dip)) != DLPI_SUCCESS) {
+ if ((retval = i_dlpi_style1_open(dip)) != DLPI_SUCCESS) {
+ 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.
+ */
+ retval = DL_SYSERR;
+ } else {
+ retval = i_dlpi_style2_open(dip);
+ }
+ if (retval != DLPI_SUCCESS) {
free(dip);
return (retval);
}
@@ -939,35 +981,98 @@ dlpi_iftype(uint_t dlpitype)
}
/*
- * This function attempts to open linkname under the following namespaces:
- * - /dev
- * - /devices
- * If open doesn't succeed and link doesn't exist (ENOENT), this function
- * returns DLPI_ENOLINK, otherwise returns DL_SYSERR.
+ * This function attempts to open a device under the following namespaces:
+ * /dev/net - if a data-link with the specified name exists
+ * /dev - if DLPI_DEVONLY is specified, or if there is no
+ * data-link with the specified name (could be /dev/ip)
+ *
+ * In particular, this function is used to open a data-link node, or some
+ * special node, such as "/dev/ip" node. It is usually be called firstly
+ * 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
+ * /dev/net node, and perhaps fallback to open the style-1 /dev node if the
+ * give name is not a data-link name (e.g., it is /dev/ip). Note that the
+ * fallback and the subsequent style-2 attempt will not happen if:
+ * 1. style-1 opening of the /dev/net node succeeds;
+ * 2. style-1 opening of the /dev/net node fails with errno other than ENOENT,
+ * which means that the specific /dev/net node exist, but the attempt fails
+ * for some other reason;
+ * 3. style-1 openning of the /dev/net fails with ENOENT, but the name is
+ * a known device name or its VLAN PPA hack name. (for example, assuming
+ * device bge0 is renamed to net0, opening /dev/net/bge1000 would return
+ * ENOENT, but we should not fallback to open /dev/bge1000 in this case,
+ * 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
-i_dlpi_open(const char *provider, int *fd, uint_t flags)
+i_dlpi_open(const char *provider, int *fd, uint_t flags, boolean_t style1)
{
char path[MAXPATHLEN];
int oflags;
+ errno = ENOENT;
oflags = O_RDWR;
if (flags & DLPI_EXCL)
oflags |= O_EXCL;
- (void) snprintf(path, sizeof (path), "/dev/%s", provider);
+ if (style1 && !(flags & DLPI_DEVONLY)) {
+ char driver[DLPI_LINKNAME_MAX];
+ char device[DLPI_LINKNAME_MAX];
+ datalink_id_t linkid;
+ uint_t ppa;
- if ((*fd = open(path, oflags)) != -1)
- return (DLPI_SUCCESS);
+ /*
+ * This is not a valid style-1 name. It could be "ip" module
+ * for example. Fallback to open the /dev node.
+ */
+ if (dlpi_parselink(provider, driver, &ppa) != DLPI_SUCCESS)
+ goto fallback;
- /*
- * On diskless boot, it's possible the /dev links have not yet
- * been created; fallback to /devices. When /dev links are
- * created on demand, this code can be removed.
- */
- (void) snprintf(path, sizeof (path), "/devices/pseudo/clone@0:%s",
- provider);
+ (void) snprintf(path, sizeof (path), "/dev/net/%s", provider);
+ if ((*fd = open(path, oflags)) != -1)
+ 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.
+ */
+ if (errno != ENOENT)
+ return (DLPI_ENOTSTYLE2);
+ /*
+ * We didn't find the /dev/net node. Then we check whether
+ * 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
+ * also have its /dev/net node but perhaps with another vanity
+ * name (for example, when bge0 is renamed to net0). In this
+ * case, although attempt to open the /dev/net/<devname> fails,
+ * we should not fallback to open the /dev/<devname> node.
+ */
+ (void) snprintf(device, DLPI_LINKNAME_MAX, "%s%d", driver,
+ ppa >= 1000 ? ppa % 1000 : ppa);
+
+ if (dladm_dev2linkid(device, &linkid) == DLADM_STATUS_OK) {
+ dladm_phys_attr_t dpa;
+
+ if ((dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE)) ==
+ DLADM_STATUS_OK && !dpa.dp_novanity) {
+ return (DLPI_ENOTSTYLE2);
+ }
+ }
+ }
+
+fallback:
+ (void) snprintf(path, sizeof (path), "/dev/%s", provider);
if ((*fd = open(path, oflags)) != -1)
return (DLPI_SUCCESS);
@@ -988,8 +1093,9 @@ i_dlpi_style1_open(dlpi_impl_t *dip)
* where modules need to be pushed onto the device stream, open only
* device name, otherwise open the full linkname.
*/
- retval = i_dlpi_open((dip->dli_mod_cnt != 0) ? dip->dli_provider :
- dip->dli_linkname, &fd, dip->dli_oflags);
+ retval = i_dlpi_open((dip->dli_mod_cnt != 0) ?
+ dip->dli_provider : dip->dli_linkname, &fd,
+ dip->dli_oflags, B_TRUE);
if (retval != DLPI_SUCCESS) {
dip->dli_mod_pushed = 0;
@@ -1048,9 +1154,9 @@ i_dlpi_style2_open(dlpi_impl_t *dip)
*/
if (dip->dli_mod_pushed == 0) {
if ((retval = i_dlpi_open(dip->dli_provider, &fd,
- dip->dli_oflags)) != DLPI_SUCCESS)
+ dip->dli_oflags, B_FALSE)) != DLPI_SUCCESS) {
return (retval);
-
+ }
dip->dli_fd = fd;
} else if (dip->dli_mod_pushed == dip->dli_mod_cnt) {
if (i_dlpi_remove_ppa(dip->dli_modlist[dip->dli_mod_cnt - 1])
diff --git a/usr/src/lib/libdlpi/common/libdlpi.h b/usr/src/lib/libdlpi/common/libdlpi.h
index 93037e1dc5..5b9b1caba5 100644
--- a/usr/src/lib/libdlpi/common/libdlpi.h
+++ b/usr/src/lib/libdlpi/common/libdlpi.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -43,6 +43,7 @@ extern "C" {
/*
* Maximum link name length, including terminating NUL, in bytes.
+ * Must be no larger than MAXLINKNAMELEN (see <sys/param.h>).
*/
#define DLPI_LINKNAME_MAX 32
@@ -55,12 +56,13 @@ extern "C" {
* Flag values for dlpi_open(); those not documented in dlpi_open(3DLPI)
* are Consolidation Private and subject to change or removal.
*/
-#define DLPI_EXCL 0x0001 /* Exclusive open */
+#define DLPI_EXCL 0x0001 /* Exclusive open */
#define DLPI_PASSIVE 0x0002 /* Open DLPI link in passive mode */
#define DLPI_RAW 0x0004 /* Open DLPI link in raw mode */
#define DLPI_SERIAL 0x0008 /* Synchronous serial line interface */
#define DLPI_NOATTACH 0x0010 /* Do not attach PPA */
-#define DLPI_NATIVE 0x0020 /* Open DLPI link in Native mode */
+#define DLPI_NATIVE 0x0020 /* Open DLPI link in native mode */
+#define DLPI_DEVONLY 0x0040 /* Open DLPI link under /dev only */
/*
* Timeout to be used in DLPI-related operations, in seconds.
@@ -74,25 +76,24 @@ extern "C" {
* <sys/dlpi.h>.
*/
enum {
- DLPI_SUCCESS = 10000, /* DLPI operation succeeded */
- DLPI_EINVAL, /* invalid argument */
- DLPI_ELINKNAMEINVAL, /* invalid DLPI linkname */
- DLPI_ENOLINK, /* DLPI link does not exist */
- DLPI_EBADLINK, /* bad DLPI link */
- DLPI_EINHANDLE, /* invalid DLPI handle */
- DLPI_ETIMEDOUT, /* DLPI operation timed out */
- DLPI_EVERNOTSUP, /* unsupported DLPI Version */
- DLPI_EMODENOTSUP, /* unsupported DLPI connection mode */
- DLPI_EUNAVAILSAP, /* unavailable DLPI SAP */
- DLPI_FAILURE, /* DLPI operation failed */
- DLPI_ENOTSTYLE2, /* DLPI style-2 node reports style-1 */
- DLPI_EBADMSG, /* bad DLPI message */
- DLPI_ERAWNOTSUP, /* DLPI raw mode not supported */
- DLPI_ENOTEINVAL, /* invalid DLPI notification type */
- DLPI_ENOTENOTSUP, /* DLPI notification not supported */
- /* by link */
- DLPI_ENOTEIDINVAL, /* invalid DLPI notification id */
- DLPI_ERRMAX /* Highest + 1 libdlpi error code */
+ DLPI_SUCCESS = 10000, /* DLPI operation succeeded */
+ DLPI_EINVAL, /* invalid argument */
+ DLPI_ELINKNAMEINVAL, /* invalid DLPI linkname */
+ DLPI_ENOLINK, /* DLPI link does not exist */
+ DLPI_EBADLINK, /* bad DLPI link */
+ DLPI_EINHANDLE, /* invalid DLPI handle */
+ DLPI_ETIMEDOUT, /* DLPI operation timed out */
+ DLPI_EVERNOTSUP, /* unsupported DLPI Version */
+ DLPI_EMODENOTSUP, /* unsupported DLPI connection mode */
+ DLPI_EUNAVAILSAP, /* unavailable DLPI SAP */
+ DLPI_FAILURE, /* DLPI operation failed */
+ DLPI_ENOTSTYLE2, /* DLPI style-2 node reports style-1 */
+ DLPI_EBADMSG, /* bad DLPI message */
+ DLPI_ERAWNOTSUP, /* DLPI raw mode not supported */
+ DLPI_ENOTEINVAL, /* invalid DLPI notification type */
+ DLPI_ENOTENOTSUP, /* DLPI notification not supported by link */
+ DLPI_ENOTEIDINVAL, /* invalid DLPI notification id */
+ DLPI_ERRMAX /* Highest + 1 libdlpi error code */
};
/*
@@ -157,10 +158,10 @@ typedef struct {
} dni_data;
} dlpi_notifyinfo_t;
-#define dni_speed dni_data.dniu_speed
-#define dni_size dni_data.dniu_size
-#define dni_physaddr dni_data.dniu_addr.physaddr
-#define dni_physaddrlen dni_data.dniu_addr.physaddrlen
+#define dni_speed dni_data.dniu_speed
+#define dni_size dni_data.dniu_size
+#define dni_physaddr dni_data.dniu_addr.physaddr
+#define dni_physaddrlen dni_data.dniu_addr.physaddrlen
typedef struct __dlpi_handle *dlpi_handle_t;
@@ -179,6 +180,9 @@ extern const char *dlpi_mactype(uint_t);
extern const char *dlpi_strerror(int);
extern const char *dlpi_linkname(dlpi_handle_t);
+typedef boolean_t dlpi_walkfunc_t(const char *, void *);
+
+extern void dlpi_walk(dlpi_walkfunc_t *, void *, uint_t);
extern int dlpi_open(const char *, dlpi_handle_t *, uint_t);
extern void dlpi_close(dlpi_handle_t);
extern int dlpi_info(dlpi_handle_t, dlpi_info_t *, uint_t);
diff --git a/usr/src/lib/libdlpi/common/mapfile-vers b/usr/src/lib/libdlpi/common/mapfile-vers
index aeaf161539..39ecc29922 100644
--- a/usr/src/lib/libdlpi/common/mapfile-vers
+++ b/usr/src/lib/libdlpi/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -49,6 +49,7 @@ SUNW_1.1 { # first release of libdlpi, Solaris 11
dlpi_set_timeout;
dlpi_strerror;
dlpi_unbind;
+ dlpi_walk;
};
SUNWprivate {
global: