4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
32 #include <sys/param.h>
34 #include <libdladm_impl.h>
38 static char dladm_rootdir
[MAXPATHLEN
] = "/";
41 dladm_status2str(dladm_status_t status
, char *buf
)
49 case DLADM_STATUS_BADARG
:
50 s
= "invalid argument";
52 case DLADM_STATUS_FAILED
:
53 s
= "operation failed";
55 case DLADM_STATUS_TOOSMALL
:
56 s
= "buffer size too small";
58 case DLADM_STATUS_NOTSUP
:
59 s
= "operation not supported";
61 case DLADM_STATUS_NOTFOUND
:
62 s
= "object not found";
64 case DLADM_STATUS_BADVAL
:
67 case DLADM_STATUS_NOMEM
:
68 s
= "insufficient memory";
70 case DLADM_STATUS_EXIST
:
71 s
= "object already exists";
73 case DLADM_STATUS_LINKINVAL
:
76 case DLADM_STATUS_PROPRDONLY
:
77 s
= "read-only property";
79 case DLADM_STATUS_BADVALCNT
:
80 s
= "invalid number of values";
82 case DLADM_STATUS_DBNOTFOUND
:
83 s
= "database not found";
85 case DLADM_STATUS_DENIED
:
86 s
= "permission denied";
88 case DLADM_STATUS_IOERR
:
91 case DLADM_STATUS_TEMPONLY
:
92 s
= "change cannot be persistent, specify -t please";
94 case DLADM_STATUS_TIMEDOUT
:
95 s
= "operation timed out";
97 case DLADM_STATUS_ISCONN
:
98 s
= "already connected";
100 case DLADM_STATUS_NOTCONN
:
103 case DLADM_STATUS_REPOSITORYINVAL
:
104 s
= "invalid configuration repository";
106 case DLADM_STATUS_MACADDRINVAL
:
107 s
= "invalid MAC address";
109 case DLADM_STATUS_KEYINVAL
:
112 case DLADM_STATUS_INVALIDMACADDRLEN
:
113 s
= "invalid MAC address length";
115 case DLADM_STATUS_INVALIDMACADDRTYPE
:
116 s
= "invalid MAC address type";
118 case DLADM_STATUS_LINKBUSY
:
121 case DLADM_STATUS_VIDINVAL
:
122 s
= "invalid VLAN identifier";
124 case DLADM_STATUS_TRYAGAIN
:
125 s
= "try again later";
127 case DLADM_STATUS_NONOTIF
:
128 s
= "link notification is not supported";
131 s
= "<unknown error>";
134 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", dgettext(TEXT_DOMAIN
, s
));
139 * Convert a unix errno to a dladm_status_t.
140 * We only convert errnos that are likely to be encountered. All others
141 * are mapped to DLADM_STATUS_FAILED.
144 dladm_errno2status(int err
)
148 return (DLADM_STATUS_OK
);
150 return (DLADM_STATUS_BADARG
);
152 return (DLADM_STATUS_EXIST
);
154 return (DLADM_STATUS_NOTFOUND
);
156 return (DLADM_STATUS_TOOSMALL
);
158 return (DLADM_STATUS_NOMEM
);
160 return (DLADM_STATUS_NOTSUP
);
162 return (DLADM_STATUS_NONOTIF
);
165 return (DLADM_STATUS_DENIED
);
167 return (DLADM_STATUS_IOERR
);
169 return (DLADM_STATUS_LINKBUSY
);
171 return (DLADM_STATUS_TRYAGAIN
);
173 return (DLADM_STATUS_FAILED
);
177 #define LOCK_DB_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
180 i_dladm_lock_db(const char *lock_file
, short type
)
185 if ((lock_fd
= open(lock_file
, O_RDWR
| O_CREAT
| O_TRUNC
,
190 lock
.l_whence
= SEEK_SET
;
194 if (fcntl(lock_fd
, F_SETLKW
, &lock
) < 0) {
197 (void) close(lock_fd
);
198 (void) unlink(lock_file
);
206 i_dladm_unlock_db(const char *lock_file
, int fd
)
213 lock
.l_type
= F_UNLCK
;
214 lock
.l_whence
= SEEK_SET
;
218 (void) fcntl(fd
, F_SETLKW
, &lock
);
220 (void) unlink(lock_file
);
224 * Given a link class, returns its class string.
227 dladm_class2str(datalink_class_t
class, char *buf
)
232 case DATALINK_CLASS_PHYS
:
235 case DATALINK_CLASS_VLAN
:
238 case DATALINK_CLASS_AGGR
:
241 case DATALINK_CLASS_VNIC
:
249 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", s
);
254 * Given a physical link media type, returns its media type string.
257 dladm_media2str(uint32_t media
, char *buf
)
308 s
= "ATM(ClassicIP)";
314 s
= "X.25(ClassicIP)";
323 s
= "100BaseVGEthernet";
326 s
= "100BaseVGTokenRing";
341 s
= "AsyncCharacter";
348 (void) snprintf(buf
, DLADM_STRSIZE
, "%s", s
);
353 i_dladm_rw_db(const char *db_file
, mode_t db_perms
,
354 dladm_status_t (*process_db
)(void *, FILE *, FILE *),
355 void *arg
, boolean_t writeop
)
357 dladm_status_t status
= DLADM_STATUS_OK
;
358 FILE *fp
, *nfp
= NULL
;
359 char lock
[MAXPATHLEN
];
360 char file
[MAXPATHLEN
];
361 char newfile
[MAXPATHLEN
];
366 * If we are called from a boot script such as net-physical,
367 * it's quite likely that the root fs is still not writable.
368 * For this case, it's ok for the lock creation to fail since
369 * no one else could be accessing our configuration file.
371 db_basename
= strrchr(db_file
, '/');
372 if (db_basename
== NULL
|| db_basename
[1] == '\0')
373 return (dladm_errno2status(EINVAL
));
375 (void) snprintf(lock
, MAXPATHLEN
, "/tmp/%s.lock", db_basename
);
376 if ((lock_fd
= i_dladm_lock_db
377 (lock
, (writeop
? F_WRLCK
: F_RDLCK
))) < 0 && errno
!= EROFS
)
378 return (dladm_errno2status(errno
));
380 (void) snprintf(file
, MAXPATHLEN
, "%s/%s", dladm_rootdir
, db_file
);
381 if ((fp
= fopen(file
, (writeop
? "r+" : "r"))) == NULL
) {
384 i_dladm_unlock_db(lock
, lock_fd
);
386 return (DLADM_STATUS_DBNOTFOUND
);
388 return (dladm_errno2status(err
));
392 (void) snprintf(newfile
, MAXPATHLEN
, "%s/%s.new",
393 dladm_rootdir
, db_file
);
394 if ((nfd
= open(newfile
, O_WRONLY
| O_CREAT
| O_TRUNC
,
397 i_dladm_unlock_db(lock
, lock_fd
);
398 return (dladm_errno2status(errno
));
401 if ((nfp
= fdopen(nfd
, "w")) == NULL
) {
404 (void) unlink(newfile
);
405 i_dladm_unlock_db(lock
, lock_fd
);
406 return (dladm_errno2status(errno
));
409 status
= (*process_db
)(arg
, fp
, nfp
);
410 if (!writeop
|| status
!= DLADM_STATUS_OK
)
414 * Configuration files need to be owned by the 'dladm' user.
415 * If we are invoked by root, the file ownership needs to be fixed.
417 if (getuid() == 0 || geteuid() == 0) {
418 if (fchown(nfd
, UID_DLADM
, GID_SYS
) < 0) {
419 status
= dladm_errno2status(errno
);
424 if (fflush(nfp
) == EOF
) {
425 status
= dladm_errno2status(errno
);
431 if (rename(newfile
, file
) < 0) {
432 (void) unlink(newfile
);
433 i_dladm_unlock_db(lock
, lock_fd
);
434 return (dladm_errno2status(errno
));
437 i_dladm_unlock_db(lock
, lock_fd
);
438 return (DLADM_STATUS_OK
);
443 if (status
!= DLADM_STATUS_OK
)
444 (void) unlink(newfile
);
447 i_dladm_unlock_db(lock
, lock_fd
);
452 dladm_set_rootdir(const char *rootdir
)
456 if (rootdir
== NULL
|| *rootdir
!= '/' ||
457 (dp
= opendir(rootdir
)) == NULL
)
458 return (DLADM_STATUS_BADARG
);
460 (void) strncpy(dladm_rootdir
, rootdir
, MAXPATHLEN
);
462 return (DLADM_STATUS_OK
);
466 dladm_valid_linkname(const char *link
)
468 size_t len
= strlen(link
);
471 if (len
+ 1 >= MAXLINKNAMELEN
)
475 * The link name cannot start with a digit and must end with a digit.
477 if ((isdigit(link
[0]) != 0) || (isdigit(link
[len
- 1]) == 0))
481 * The legal characters in a link name are:
482 * alphanumeric (a-z, A-Z, 0-9), and the underscore ('_').
484 for (cp
= link
; *cp
!= '\0'; cp
++) {
485 if ((isalnum(*cp
) == 0) && (*cp
!= '_'))