libdladm.c revision a776d98e5f349dbb7f5a47eca48f50e6117adcb7
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling * Common Development and Distribution License (the "License").
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct media_type_desc {
fa9e4066f08beec538e775443c5be79dd423fcabahrens#define MEDIATYPECOUNT (sizeof (media_type_table) / sizeof (media_type_t))
fa9e4066f08beec538e775443c5be79dd423fcabahrenstypedef struct {
66e2aacc02a4625d105fb249ad16c27e79604ff2gw#define LPTYPES (sizeof (link_protect_types) / sizeof (link_protect_t))
3baa08fc5b6bea08a475b0cfe3ad161d74c5864bek * Don't open DLMGMT_DOOR now. dlmgmtd(1M) is not able to
3baa08fc5b6bea08a475b0cfe3ad161d74c5864bek * open the door when the dladm handle is opened because the
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * door hasn't been created yet at that time. Thus, we must
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * open it on-demand in dladm_door_fd(). Move the open()
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * to dladm_door_fd() for all cases.
478ed9ada0b6efe1318150a700986aa47e6a926dEric Taylor if ((*handle = malloc(sizeof (struct dladm_handle))) == NULL) {
990b4856d0eaada6f8140335733a1b1771ed2746lling * If DLMGMT_DOOR hasn't been opened in the handle yet, open it.
485bbbf5450c6645352388d798251c1a89ef4c9cGeorge Wilsondladm_status2str(dladm_status_t status, char *buf)
990b4856d0eaada6f8140335733a1b1771ed2746lling const char *s;
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "invalid argument";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "operation failed";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "buffer size too small";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "operation not supported";
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson s = "object not found";
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson s = "invalid value";
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson s = "insufficient memory";
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson s = "object already exists";
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson s = "invalid link";
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson s = "read-only property";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "invalid number of values";
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh s = "database not found";
0a48a24e663a04e34e2ed4e55390ad96f178dbeatimh s = "permission denied";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "I/O error";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "change cannot be persistent";
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s = "operation timed out";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "already connected";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "not connected";
b1b8ab34de515a5e83206da22c3d7e563241b021lling s = "invalid configuration repository";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "invalid MAC address";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "invalid key";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "invalid MAC address length";
b1b8ab34de515a5e83206da22c3d7e563241b021lling s = "invalid MAC address type";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "link busy";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "invalid VLAN identifier";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "try again later";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "link notification is not supported";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "invalid time range";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "invalid MAC address value";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "MAC address reserved for use by underlying data-link";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "MAC address is already in use";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "invalid factory MAC address slot";
4201a95e0468170d576f82c3aa63afecf718497aRic Aleshire s = "factory MAC address slot already used";
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright s = "all factory MAC address slots are in use";
a227b7f4f323ad89c40a86c430a5e891504a8e8bhs s = "factory MAC address slots not supported";
a227b7f4f323ad89c40a86c430a5e891504a8e8bhs s = "Invalid MAC address prefix value";
e09fa4dacfb671e707d50a55ae9b5cc191e1b8cbNeil Perrin s = "Invalid MAC address prefix length";
e09fa4dacfb671e707d50a55ae9b5cc191e1b8cbNeil Perrin s = "non-existent processor ID";
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s = "could not determine processor status";
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s = "processor not online";
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright s = "too many elements specified";
743a77ed89085d3c232c4a2f65ab4e19576839e2Alan Wright s = "invalid range";
3baa08fc5b6bea08a475b0cfe3ad161d74c5864bek s = "database not found";
3baa08fc5b6bea08a475b0cfe3ad161d74c5864bek s = "database parse error";
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante s = "property parse error";
55da60b91d96984f12de050ce428373ea25c7f35Mark J Musante s = "attribute parse error";
3baa08fc5b6bea08a475b0cfe3ad161d74c5864bek s = "flow database error";
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock s = "flow database open error";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "flow database parse error";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "flow property database parse error";
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s = "flow add error";
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens s = "flow walk error";
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens s = "a flow with identical attributes exists";
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby s = "flow(s) with incompatible attributes exists";
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick s = "link still has flows";
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum s = "persistent flow with the same name exists";
6e0cbcaa0c6f2bc34634a4cc17b099f9ecef03d1Matthew Ahrens s = "invalid IP address";
b1b8ab34de515a5e83206da22c3d7e563241b021lling s = "invalid IP prefix length";
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens s = "invalid IP protocol";
cb04b8739c50e3e6d12e89b790fa7b8d0d899865Mark J Musante s = "invalid port number";
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm s = "invalid dsfield";
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm s = "invalid dsfield mask";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "MTU check failed, use lower MTU or -f option";
44cd46cadd9aab751dae6a4023c1cb5bf316d274billm s = "invalid property";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "minimum value for maxbw is 1200K";
cde58dbc6a23d4d38db7c8866312be83221c765fMatthew Ahrens s = "request hw rings failed";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "change must be persistent";
990b4856d0eaada6f8140335733a1b1771ed2746lling s = "optional software not installed";
a9799022bd90b13722204e80112efaa5bf573099ck s = "invalid IP tunnel type";
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan s = "IP tunnel type required";
088f389458728c464569a5506b58070254fa4f7dahrens s = "invalid local IP tunnel address";
d0f3f37e7f24f68fdbd85386c60e576883622762Mark Shellenbaum s = "invalid remote IP tunnel address";
f94275ce205810a201404c5f35f4cc96057022b1Adam Leventhal s = "address already in use";
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick s = "pool and cpus property are mutually exclusive";
6e1f5caa9321646aa4212d48e32a0d241866d85dNeil Perrin s = "invalid IB phys link";
cde58dbc6a23d4d38db7c8866312be83221c765fMatthew Ahrens s = "port is down";
cb04b8739c50e3e6d12e89b790fa7b8d0d899865Mark J Musante s = "partition already exists";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "PKEY is not present on the port";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "invalid PKEY";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "IB internal resource not available";
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw s = "invalid PKEY table size";
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum s = "local or remote port requires transport";
e7437265dc2a4920c197ed4337665539d358b22cahrens s = "MTU check failed, MTU outside of device's supported range";
de8267e0f723ed2c38ea9def92d465f69a300f56timh s = "<unknown error>";
0a586cea3ceec7e5e50e7e54c745082a7a333ac2Mark Shellenbaum (void) snprintf(buf, DLADM_STRSIZE, "%s", dgettext(TEXT_DOMAIN, s));
c8ee1847e300c992c76cf25d6c165e6ccf64a113Victor Latushkin * Convert a unix errno to a dladm_status_t.
c8ee1847e300c992c76cf25d6c165e6ccf64a113Victor Latushkin * We only convert errnos that are likely to be encountered. All others
c8ee1847e300c992c76cf25d6c165e6ccf64a113Victor Latushkin * are mapped to DLADM_STATUS_FAILED.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * percentages not supported for now,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * see RFE 6540675
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* check for overflow */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Convert bandwidth in bps to a string in Mbps. For values greater
fa9e4066f08beec538e775443c5be79dd423fcabahrens * than 1Mbps or 1000000, print a whole Mbps value. For values that
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock * have fractional Mbps in whole Kbps, print the bandwidth in a manner
fa9e4066f08beec538e775443c5be79dd423fcabahrens * similar to a floating point format.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * bps string
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2000 0.002
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 431000 0.431
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1000000 1
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1030000 1.030
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * 100000000 100
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockconst char *
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (kbps != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(buf, DLADM_STRSIZE, "%5u.%03u", mbps,
99653d4ee642c6528e88224f12409a5f23060994eschrock#define LOCK_DB_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((lock_fd = open(lock_file, O_RDWR | O_CREAT | O_TRUNC,
46a2abf27af40eda17a3f97e79eda1aef4e3c3c8eschrock return (-1);
46a2abf27af40eda17a3f97e79eda1aef4e3c3c8eschrock return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Given a link class, returns its class string.
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Lingconst char *
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling const char *s;
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "phys";
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "vlan";
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "aggr";
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "vnic";
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "etherstub";
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "iptun";
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "simnet";
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling s = "bridge";
fa9e4066f08beec538e775443c5be79dd423fcabahrens s = "part";
fa9e4066f08beec538e775443c5be79dd423fcabahrens s = "unknown";
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Given a physical link media type, returns its media type string.
fa9e4066f08beec538e775443c5be79dd423fcabahrensconst char *
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling const char *s = "--";
9eb19f4d61679ca0382def038665019234458eddGeorge Wilson * Given a physical link media type string, returns its media type constant.
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylori_dladm_rw_db(dladm_handle_t handle, const char *db_file, mode_t db_perms,
573ca77e53dd31dcaebef023e7eb41969e6896c1George Wilson dladm_status_t (*process_db)(dladm_handle_t, void *, FILE *, FILE *),
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If we are called from a boot script such as net-physical,
fa9e4066f08beec538e775443c5be79dd423fcabahrens * it's quite likely that the root fs is still not writable.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For this case, it's ok for the lock creation to fail since
fa9e4066f08beec538e775443c5be79dd423fcabahrens * no one else could be accessing our configuration file.
3f9d6ad73e45c6823b409f93b0c8d4f62861d2d5Lin Ling (void) snprintf(lock, MAXPATHLEN, "/tmp/%s.lock", db_basename);
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock (lock, (writeop ? F_WRLCK : F_RDLCK))) < 0 && errno != EROFS)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) snprintf(file, MAXPATHLEN, "%s/%s", dladm_rootdir, db_file);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if ((fp = fopen(file, (writeop ? "r+" : "r"))) == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((nfd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC,
148434217c040ea38dc844384f6ba68d9b325906Matthew Ahrens /* Set permissions on file to db_perms */
1195e687f1c03c8d57417b5999578922e20a3554Mark J Musante * Configuration files need to be owned by the 'dladm' user and
99d5e173470cf967aa87653364ed614299e7b511Tim Haley * 'netadm' group.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock (void) strncpy(dladm_rootdir, rootdir, MAXPATHLEN);
4b964ada391d44b89d97e7e930e6a9a136e0a2f4George Wilson const char *cp;
f9af39bacaaa0f9dda3b75ff6858b9f3988a39afGeorge Wilson * The link name cannot start with a digit and must end with a digit.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if ((isdigit(link[0]) != 0) || (isdigit(link[len - 1]) == 0))
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * The legal characters in a link name are:
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * alphanumeric (a-z, A-Z, 0-9), underscore ('_'), and '.'.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if ((isalnum(*cp) == 0) && (*cp != '_') && (*cp != '.'))
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Convert priority string to a value.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrockdladm_str2pri(char *token, mac_priority_level_t *pri)
088f389458728c464569a5506b58070254fa4f7dahrens strncasecmp(token, "medium", strlen("medium")) == 0) {
8f18d1fadf6a0c20fac9ff7259a5368faa3c3bfbGeorge Wilson strncasecmp(token, "high", strlen("high")) == 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Convert priority value to a string.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksconst char *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const char *s;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks switch (pri) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "medium";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks s = "high";
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (void) snprintf(buf, DLADM_STRSIZE, "%s", dgettext(TEXT_DOMAIN, s));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Convert protect string to a value.
1195e687f1c03c8d57417b5999578922e20a3554Mark J Musante for (i = 0; i < LPTYPES; i++) {
for (i = 0; i < LPTYPES; i++) {
return (buf);
return (buf);
return (buf);
*cnt = c;
int len, i;
return (DLADM_STATUS_BADVAL);
return (DLADM_STATUS_OK);
for (i = 0; i < len; i++) {
char c = buf[i];
if (match) {
goto fail;
goto fail;
if (novalues)
goto fail;
goto fail;
return (DLADM_STATUS_OK);
fail:
return (DLADM_STATUS_FAILED);
char *endp;
switch (type) {
case MAC_PROPVAL_UINT32: {
return (DLADM_STATUS_NOMEM);
errno = 0;
return (DLADM_STATUS_BADRANGE);
return (DLADM_STATUS_BADRANGE);
return (DLADM_STATUS_BADRANGE);
return (DLADM_STATUS_BADVAL);
return (status);
case MAC_PROPVAL_UINT32: {
if (k > *nelem) {
*nelem = k;
return (status);
case MAC_PROPVAL_UINT32: {
return (EINVAL);
uint32cmp(const void *a, const void *b)
switch (type) {
case MAC_PROPVAL_UINT32: {
return (DLADM_STATUS_NOMEM);
return (DLADM_STATUS_NOMEM);
for (i = 0; i < nelem; i++)
return (DLADM_STATUS_BADRANGE);
return (status);